xref: /llvm-project/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp (revision 456ee300364f4eb3337b679866bf4d84051c4556)
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