1 //===- unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp ------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/Frontend/CompilerInstance.h" 11 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 12 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 13 #include "clang/StaticAnalyzer/Core/Checker.h" 14 #include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 15 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 16 #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" 17 #include "clang/Tooling/Tooling.h" 18 #include "gtest/gtest.h" 19 20 namespace clang { 21 namespace ento { 22 namespace { 23 24 class CustomChecker : public Checker<check::ASTCodeBody> { 25 public: 26 void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, 27 BugReporter &BR) const { 28 BR.EmitBasicReport(D, this, "Custom diagnostic", categories::LogicError, 29 "Custom diagnostic description", 30 PathDiagnosticLocation(D, Mgr.getSourceManager()), {}); 31 } 32 }; 33 34 class TestAction : public ASTFrontendAction { 35 class DiagConsumer : public PathDiagnosticConsumer { 36 llvm::raw_ostream &Output; 37 38 public: 39 DiagConsumer(llvm::raw_ostream &Output) : Output(Output) {} 40 void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags, 41 FilesMade *filesMade) override { 42 for (const auto *PD : Diags) 43 Output << PD->getCheckName() << ":" << PD->getShortDescription(); 44 } 45 46 StringRef getName() const override { return "Test"; } 47 }; 48 49 llvm::raw_ostream &DiagsOutput; 50 51 public: 52 TestAction(llvm::raw_ostream &DiagsOutput) : DiagsOutput(DiagsOutput) {} 53 54 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler, 55 StringRef File) override { 56 std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer = 57 CreateAnalysisConsumer(Compiler); 58 AnalysisConsumer->AddDiagnosticConsumer(new DiagConsumer(DiagsOutput)); 59 Compiler.getAnalyzerOpts()->CheckersControlList = { 60 {"custom.CustomChecker", true}}; 61 AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) { 62 Registry.addChecker<CustomChecker>("custom.CustomChecker", "Description"); 63 }); 64 return std::move(AnalysisConsumer); 65 } 66 }; 67 68 69 TEST(RegisterCustomCheckers, RegisterChecker) { 70 std::string Diags; 71 { 72 llvm::raw_string_ostream OS(Diags); 73 EXPECT_TRUE(tooling::runToolOnCode(new TestAction(OS), "void f() {;}")); 74 } 75 EXPECT_EQ(Diags, "custom.CustomChecker:Custom diagnostic description"); 76 } 77 78 } 79 } 80 } 81