[LV] Add test showing debug output for loops with uncountable BTCs.
[llvm-project.git] / clang / unittests / StaticAnalyzer / BugReportInterestingnessTest.cpp
blob70a58026da95fc856a70d1a5905d92bf4e403d7e
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "Reusables.h"
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/PathSensitive/AnalysisManager.h"
15 #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
18 #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
19 #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
20 #include "clang/Tooling/Tooling.h"
21 #include "gtest/gtest.h"
23 using namespace clang;
24 using namespace ento;
25 using namespace llvm;
27 namespace {
29 class InterestingnessTestChecker : public Checker<check::PreCall> {
30 BugType BT_TestBug;
32 using HandlerFn = std::function<void(const InterestingnessTestChecker *,
33 const CallEvent &, CheckerContext &)>;
35 CallDescriptionMap<HandlerFn> Handlers = {
36 {{CDM::SimpleFunc, {"setInteresting"}, 1},
37 &InterestingnessTestChecker::handleInteresting},
38 {{CDM::SimpleFunc, {"setNotInteresting"}, 1},
39 &InterestingnessTestChecker::handleNotInteresting},
40 {{CDM::SimpleFunc, {"check"}, 1},
41 &InterestingnessTestChecker::handleCheck},
42 {{CDM::SimpleFunc, {"bug"}, 1}, &InterestingnessTestChecker::handleBug},
45 void handleInteresting(const CallEvent &Call, CheckerContext &C) const;
46 void handleNotInteresting(const CallEvent &Call, CheckerContext &C) const;
47 void handleCheck(const CallEvent &Call, CheckerContext &C) const;
48 void handleBug(const CallEvent &Call, CheckerContext &C) const;
50 public:
51 InterestingnessTestChecker()
52 : BT_TestBug(this, "InterestingnessTestBug", "Test") {}
54 void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
55 const HandlerFn *Handler = Handlers.lookup(Call);
56 if (!Handler)
57 return;
59 (*Handler)(this, Call, C);
63 } // namespace
65 void InterestingnessTestChecker::handleInteresting(const CallEvent &Call,
66 CheckerContext &C) const {
67 SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();
68 assert(Sym);
69 C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {
70 BR.markInteresting(Sym);
71 return "";
72 }));
75 void InterestingnessTestChecker::handleNotInteresting(const CallEvent &Call,
76 CheckerContext &C) const {
77 SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();
78 assert(Sym);
79 C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {
80 BR.markNotInteresting(Sym);
81 return "";
82 }));
85 void InterestingnessTestChecker::handleCheck(const CallEvent &Call,
86 CheckerContext &C) const {
87 SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();
88 assert(Sym);
89 C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {
90 if (BR.isInteresting(Sym))
91 return "Interesting";
92 else
93 return "NotInteresting";
94 }));
97 void InterestingnessTestChecker::handleBug(const CallEvent &Call,
98 CheckerContext &C) const {
99 ExplodedNode *N = C.generateErrorNode();
100 C.emitReport(
101 std::make_unique<PathSensitiveBugReport>(BT_TestBug, "test bug", N));
104 namespace {
106 class TestAction : public ASTFrontendAction {
107 ExpectedDiagsTy ExpectedDiags;
109 public:
110 TestAction(ExpectedDiagsTy &&ExpectedDiags)
111 : ExpectedDiags(std::move(ExpectedDiags)) {}
113 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
114 StringRef File) override {
115 std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
116 CreateAnalysisConsumer(Compiler);
117 AnalysisConsumer->AddDiagnosticConsumer(new VerifyPathDiagnosticConsumer(
118 std::move(ExpectedDiags), Compiler.getSourceManager()));
119 AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
120 Registry.addChecker<InterestingnessTestChecker>("test.Interestingness",
121 "Description", "");
123 Compiler.getAnalyzerOpts().CheckersAndPackages = {
124 {"test.Interestingness", true}};
125 return std::move(AnalysisConsumer);
129 } // namespace
131 TEST(BugReportInterestingness, Symbols) {
132 EXPECT_TRUE(tooling::runToolOnCode(
133 std::make_unique<TestAction>(ExpectedDiagsTy{
134 {{15, 7},
135 "test bug",
136 "test bug",
137 "test.Interestingness",
138 "InterestingnessTestBug",
139 "Test",
141 {{8, 7}, "Interesting", {{{8, 7}, {8, 14}}}},
142 {{10, 7}, "NotInteresting", {{{10, 7}, {10, 14}}}},
143 {{12, 7}, "Interesting", {{{12, 7}, {12, 14}}}},
144 {{14, 7}, "NotInteresting", {{{14, 7}, {14, 14}}}},
145 {{15, 7}, "test bug", {{{15, 7}, {15, 12}}}},
146 }}}),
148 void setInteresting(int);
149 void setNotInteresting(int);
150 void check(int);
151 void bug(int);
153 void f(int A) {
154 check(A);
155 setInteresting(A);
156 check(A);
157 setNotInteresting(A);
158 check(A);
159 setInteresting(A);
160 check(A);
161 bug(A);
164 "input.cpp"));