Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -94,7 +94,8 @@ class ClangTidyASTConsumerFactory { public: - ClangTidyASTConsumerFactory(ClangTidyContext &Context); + ClangTidyASTConsumerFactory(ClangTidyContext &Context, + const ClangTidyOptions &Options); ~ClangTidyASTConsumerFactory(); /// \brief Returns an ASTConsumer that runs the specified clang-tidy checks. @@ -112,6 +113,7 @@ ClangTidyContext &Context; ast_matchers::MatchFinder Finder; std::unique_ptr CheckFactories; + const ClangTidyOptions &Options; }; /// \brief Fills the list of check names that are enabled when the provided Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -173,8 +173,9 @@ } // namespace ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory( - ClangTidyContext &Context) - : Context(Context), CheckFactories(new ClangTidyCheckFactories) { + ClangTidyContext &Context, const ClangTidyOptions &Options) + : Context(Context), CheckFactories(new ClangTidyCheckFactories), + Options(Options) { for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(), E = ClangTidyModuleRegistry::end(); I != E; ++I) { @@ -207,16 +208,21 @@ if (!CheckFactories->empty()) Consumers.push_back(Finder.newASTConsumer()); - AnalyzerOptionsRef Options = Compiler.getAnalyzerOpts(); - Options->CheckersControlList = getCheckersControlList(); - if (!Options->CheckersControlList.empty()) { - Options->AnalysisStoreOpt = RegionStoreModel; - Options->AnalysisDiagOpt = PD_NONE; - Options->AnalyzeNestedBlocks = true; - Options->eagerlyAssumeBinOpBifurcation = true; + AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts(); + // FIXME: Remove this option once clang's cfg-temporary-dtors option defaults + // to true. + AnalyzerOptions->Config["cfg-temporary-dtors"] = + Options.AnalyzeTemporaryDtors ? "true" : "false"; + + AnalyzerOptions->CheckersControlList = getCheckersControlList(); + if (!AnalyzerOptions->CheckersControlList.empty()) { + AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel; + AnalyzerOptions->AnalysisDiagOpt = PD_NONE; + AnalyzerOptions->AnalyzeNestedBlocks = true; + AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true; ento::AnalysisASTConsumer *AnalysisConsumer = ento::CreateAnalysisConsumer( Compiler.getPreprocessor(), Compiler.getFrontendOpts().OutputFile, - Options, Compiler.getFrontendOpts().Plugins); + AnalyzerOptions, Compiler.getFrontendOpts().Plugins); AnalysisConsumer->AddDiagnosticConsumer( new AnalyzerDiagnosticConsumer(Context)); Consumers.push_back(AnalysisConsumer); @@ -288,7 +294,7 @@ std::vector getCheckNames(const ClangTidyOptions &Options) { SmallVector Errors; clang::tidy::ClangTidyContext Context(&Errors, Options); - ClangTidyASTConsumerFactory Factory(Context); + ClangTidyASTConsumerFactory Factory(Context, Options); return Factory.getCheckNames(); } @@ -326,7 +332,7 @@ ClangTidyASTConsumerFactory *ConsumerFactory; }; - Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context))); + Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context, Options))); } void handleErrors(SmallVectorImpl &Errors, bool Fix) { Index: clang-tidy/ClangTidyOptions.h =================================================================== --- clang-tidy/ClangTidyOptions.h +++ clang-tidy/ClangTidyOptions.h @@ -18,6 +18,7 @@ ClangTidyOptions() : EnableChecksRegex(".*") {} std::string EnableChecksRegex; std::string DisableChecksRegex; + bool AnalyzeTemporaryDtors; }; } // end namespace tidy Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -46,12 +46,20 @@ cl::desc("List all enabled checks and exit."), cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt AnalyzeTemporaryDtors( + "analyze-temporary-dtors", + cl::desc("Enable temporary destructor-aware analysis in clang-analyzer- " + "checks."), + cl::init(false), + cl::cat(ClangTidyCategory)); + int main(int argc, const char **argv) { CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory); clang::tidy::ClangTidyOptions Options; Options.EnableChecksRegex = Checks; Options.DisableChecksRegex = DisableChecks; + Options.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors; // FIXME: Allow using --list-checks without positional arguments. if (ListChecks) { Index: test/clang-tidy/temporaries.cpp =================================================================== --- /dev/null +++ test/clang-tidy/temporaries.cpp @@ -0,0 +1,20 @@ +// RUN: clang-tidy -checks=clang-analyzer-core.NullDereference -analyze-temporary-dtors %s -- > %t.log +// FileCheck complains if the input file is empty, so add a dummy line. +// RUN: echo foo >> %t.log +// RUN: FileCheck %s < %t.log + +// CHECK-NOT: warning + +struct NoReturnDtor { + ~NoReturnDtor() __attribute__((noreturn)); +}; + +extern bool check(const NoReturnDtor &); + +void testNullPointerDereference() { + int *value = 0; + if (check(NoReturnDtor())) { + // This unreachable code causes a warning if we don't run with -analyze-temporary-dtors + *value = 1; + } +}