diff options
Diffstat (limited to 'clang-tools-extra')
-rw-r--r-- | clang-tools-extra/clang-tidy/ClangTidy.cpp | 30 | ||||
-rw-r--r-- | clang-tools-extra/clang-tidy/ClangTidy.h | 4 | ||||
-rw-r--r-- | clang-tools-extra/clang-tidy/ClangTidyOptions.h | 1 | ||||
-rw-r--r-- | clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp | 8 | ||||
-rw-r--r-- | clang-tools-extra/test/clang-tidy/temporaries.cpp | 26 |
5 files changed, 56 insertions, 13 deletions
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index c9395497bcb..0445710eaa2 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -173,8 +173,9 @@ private: } // 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 @@ clang::ASTConsumer *ClangTidyASTConsumerFactory::CreateASTConsumer( 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 @@ void ClangTidyCheck::setName(StringRef Name) { std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) { SmallVector<ClangTidyError, 8> Errors; clang::tidy::ClangTidyContext Context(&Errors, Options); - ClangTidyASTConsumerFactory Factory(Context); + ClangTidyASTConsumerFactory Factory(Context, Options); return Factory.getCheckNames(); } @@ -326,7 +332,7 @@ void runClangTidy(const ClangTidyOptions &Options, ClangTidyASTConsumerFactory *ConsumerFactory; }; - Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context))); + Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context, Options))); } void handleErrors(SmallVectorImpl<ClangTidyError> &Errors, bool Fix) { diff --git a/clang-tools-extra/clang-tidy/ClangTidy.h b/clang-tools-extra/clang-tidy/ClangTidy.h index a7ba04c4592..8d71eeb37ad 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.h +++ b/clang-tools-extra/clang-tidy/ClangTidy.h @@ -94,7 +94,8 @@ class ClangTidyCheckFactories; 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 @@ private: ClangTidyContext &Context; ast_matchers::MatchFinder Finder; std::unique_ptr<ClangTidyCheckFactories> CheckFactories; + ClangTidyOptions Options; }; /// \brief Fills the list of check names that are enabled when the provided diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h index 84dc2c22709..0e3cacf4587 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -18,6 +18,7 @@ struct ClangTidyOptions { ClangTidyOptions() : EnableChecksRegex(".*") {} std::string EnableChecksRegex; std::string DisableChecksRegex; + bool AnalyzeTemporaryDtors; }; } // end namespace tidy diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index 9284a8b038a..3d5c312fe7d 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -46,12 +46,20 @@ static cl::opt<bool> ListChecks("list-checks", cl::desc("List all enabled checks and exit."), cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt<bool> 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) { diff --git a/clang-tools-extra/test/clang-tidy/temporaries.cpp b/clang-tools-extra/test/clang-tidy/temporaries.cpp new file mode 100644 index 00000000000..a90ef63a56b --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/temporaries.cpp @@ -0,0 +1,26 @@ +// RUN: clang-tidy -checks=clang-analyzer-core.NullDereference -disable-checks='' -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 + +struct NoReturnDtor { + ~NoReturnDtor() __attribute__((noreturn)); +}; + +extern bool check(const NoReturnDtor &); + +// CHECK-NOT: warning +void testNullPointerDereferencePositive() { + int *value = 0; + // CHECK: [[@LINE+1]]:10: warning: Dereference of null pointer (loaded from variable 'value') [clang-analyzer-core.NullDereference] + *value = 1; +} + +// CHECK-NOT: warning +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; + } +} |