diff --git a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp --- a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp +++ b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp @@ -16,7 +16,9 @@ #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" #include "clang/Tooling/Tooling.h" +#include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" +#include namespace clang { namespace ento { @@ -60,7 +62,7 @@ public: void checkLocation(SVal Loc, bool IsLoad, const Stmt *S, CheckerContext &C) const { - auto UnaryOp = dyn_cast(S); + const auto *UnaryOp = dyn_cast(S); if (UnaryOp && !IsLoad) { EXPECT_FALSE(UnaryOp->isIncrementOp()); } @@ -85,62 +87,90 @@ // Unsatisfied checker dependency //===----------------------------------------------------------------------===// -class PrerequisiteChecker : public Checker { +class CheckerRegistrationOrderPrinter + : public Checker> { + std::unique_ptr BT = + std::make_unique(this, "Registration order"); + public: - void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, - BugReporter &BR) const { - BR.EmitBasicReport(D, this, "Prerequisite", categories::LogicError, - "This is the prerequisite checker", - PathDiagnosticLocation(D, Mgr.getSourceManager()), {}); + void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { + ExplodedNode *N = nullptr; + N = C.generateErrorNode(); + llvm::SmallString<200> Buf; + llvm::raw_svector_ostream OS(Buf); + C.getAnalysisManager() + .getCheckerManager() + ->getCheckerRegistry() + .printEnabledCheckerList(OS); + // Strip a newline off. + auto R = + std::make_unique(*BT, OS.str().drop_back(1), N); + C.emitReport(std::move(R)); } }; -void registerPrerequisiteChecker(CheckerManager &mgr) { - mgr.registerChecker(); +void registerCheckerRegistrationOrderPrinter(CheckerManager &mgr) { + mgr.registerChecker(); } -bool shouldRegisterPrerequisiteChecker(const CheckerManager &mgr) { - return false; +bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) { + return true; } -class DependentChecker : public Checker { -public: - void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, - BugReporter &BR) const { - BR.EmitBasicReport(D, this, "Dependent", categories::LogicError, - "This is the Dependent Checker", - PathDiagnosticLocation(D, Mgr.getSourceManager()), {}); +void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) { + Registry.addChecker(registerCheckerRegistrationOrderPrinter, + shouldRegisterCheckerRegistrationOrderPrinter, + "custom.RegistrationOrder", "Description", "", false); +} + +#define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG) \ + class CHECKER_NAME : public Checker> { \ + std::unique_ptr BT = \ + std::make_unique(this, DIAG_MSG); \ + \ + public: \ + void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {} \ + }; \ + \ + void register##CHECKER_NAME(CheckerManager &mgr) { \ + mgr.registerChecker(); \ + } \ + \ + bool shouldRegister##CHECKER_NAME(const CheckerManager &mgr) { \ + return true; \ + } \ + void add##CHECKER_NAME(CheckerRegistry &Registry) { \ + Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME, \ + "custom." #CHECKER_NAME, "Description", "", false); \ } -}; -void registerDependentChecker(CheckerManager &mgr) { - mgr.registerChecker(); -} +UNITTEST_CHECKER(StrongDep, "Strong") +UNITTEST_CHECKER(Dep, "Dep") -bool shouldRegisterDependentChecker(const CheckerManager &mgr) { - return true; +bool shouldRegisterStrongFALSE(const CheckerManager &mgr) { + return false; } -void addDependentChecker(AnalysisASTConsumer &AnalysisConsumer, - AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dependent", true}}; + +void addDep(AnalysisASTConsumer &AnalysisConsumer, + AnalyzerOptions &AnOpts) { + AnOpts.CheckersAndPackages = {{"custom.Dep", true}, + {"custom.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker(registerPrerequisiteChecker, - shouldRegisterPrerequisiteChecker, - "custom.Prerequisite", "Description", "", false); - Registry.addChecker(registerDependentChecker, - shouldRegisterDependentChecker, - "custom.Dependent", "Description", "", false); - Registry.addDependency("custom.Dependent", "custom.Prerequisite"); - }); + Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE, + "custom.Strong", "Description", "", false); + addStrongDep(Registry); + addDep(Registry); + addCheckerRegistrationOrderPrinter(Registry); + Registry.addDependency("custom.Dep", "custom.Strong"); + }); } -TEST(RegisterDependentCheckers, RegisterChecker) { +TEST(RegisterDeps, UnsatisfiedDependency) { std::string Diags; - EXPECT_TRUE(runCheckerOnCode("void f() {;}", Diags)); - EXPECT_EQ(Diags, ""); + EXPECT_TRUE(runCheckerOnCode("void f() {int i;}", Diags)); + EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.RegistrationOrder\n"); } - } // namespace } // namespace ento } // namespace clang