1d00ed8e2SAlexander Kornienko //===- unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp ------------===//
2d00ed8e2SAlexander Kornienko //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d00ed8e2SAlexander Kornienko //
7d00ed8e2SAlexander Kornienko //===----------------------------------------------------------------------===//
8d00ed8e2SAlexander Kornienko
958884eb6SKirstóf Umann #include "CheckerRegistration.h"
10d00ed8e2SAlexander Kornienko #include "clang/Frontend/CompilerInstance.h"
11d00ed8e2SAlexander Kornienko #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
12d00ed8e2SAlexander Kornienko #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
13d00ed8e2SAlexander Kornienko #include "clang/StaticAnalyzer/Core/Checker.h"
14b6cbe6cbSKirstóf Umann #include "clang/StaticAnalyzer/Core/CheckerRegistryData.h"
15d00ed8e2SAlexander Kornienko #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
1658884eb6SKirstóf Umann #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
17d00ed8e2SAlexander Kornienko #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
1876a21502SKristof Umann #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
19d00ed8e2SAlexander Kornienko #include "clang/Tooling/Tooling.h"
20d61b1f85SKirstóf Umann #include "llvm/Support/raw_ostream.h"
21d00ed8e2SAlexander Kornienko #include "gtest/gtest.h"
22d61b1f85SKirstóf Umann #include <memory>
23d00ed8e2SAlexander Kornienko
24d00ed8e2SAlexander Kornienko namespace clang {
25d00ed8e2SAlexander Kornienko namespace ento {
26d00ed8e2SAlexander Kornienko namespace {
27d00ed8e2SAlexander Kornienko
2858884eb6SKirstóf Umann //===----------------------------------------------------------------------===//
2958884eb6SKirstóf Umann // Just a minimal test for how checker registration works with statically
3058884eb6SKirstóf Umann // linked, non TableGen generated checkers.
3158884eb6SKirstóf Umann //===----------------------------------------------------------------------===//
32cc19f921SRafael Stahl
33cc19f921SRafael Stahl class CustomChecker : public Checker<check::ASTCodeBody> {
34cc19f921SRafael Stahl public:
checkASTCodeBody(const Decl * D,AnalysisManager & Mgr,BugReporter & BR) const35cc19f921SRafael Stahl void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
36cc19f921SRafael Stahl BugReporter &BR) const {
37cc19f921SRafael Stahl BR.EmitBasicReport(D, this, "Custom diagnostic", categories::LogicError,
38cc19f921SRafael Stahl "Custom diagnostic description",
39cc19f921SRafael Stahl PathDiagnosticLocation(D, Mgr.getSourceManager()), {});
40cc19f921SRafael Stahl }
41cc19f921SRafael Stahl };
42d00ed8e2SAlexander Kornienko
addCustomChecker(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)4358884eb6SKirstóf Umann void addCustomChecker(AnalysisASTConsumer &AnalysisConsumer,
4458884eb6SKirstóf Umann AnalyzerOptions &AnOpts) {
45690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.CustomChecker", true}};
4658884eb6SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
47690ff37aSKirstóf Umann Registry.addChecker<CustomChecker>("test.CustomChecker", "Description", "");
4858884eb6SKirstóf Umann });
4958884eb6SKirstóf Umann }
5058884eb6SKirstóf Umann
TEST(RegisterCustomCheckers,RegisterChecker)51d00ed8e2SAlexander Kornienko TEST(RegisterCustomCheckers, RegisterChecker) {
52d00ed8e2SAlexander Kornienko std::string Diags;
5358884eb6SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addCustomChecker>("void f() {;}", Diags));
54690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.CustomChecker: Custom diagnostic description\n");
55d00ed8e2SAlexander Kornienko }
56d00ed8e2SAlexander Kornienko
5758884eb6SKirstóf Umann //===----------------------------------------------------------------------===//
5858884eb6SKirstóf Umann // Pretty much the same.
5958884eb6SKirstóf Umann //===----------------------------------------------------------------------===//
6058884eb6SKirstóf Umann
61cc19f921SRafael Stahl class LocIncDecChecker : public Checker<check::Location> {
62cc19f921SRafael Stahl public:
checkLocation(SVal Loc,bool IsLoad,const Stmt * S,CheckerContext & C) const63cc19f921SRafael Stahl void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
64cc19f921SRafael Stahl CheckerContext &C) const {
65d61b1f85SKirstóf Umann const auto *UnaryOp = dyn_cast<UnaryOperator>(S);
66b4e86d8aSNico Weber if (UnaryOp && !IsLoad) {
67cc19f921SRafael Stahl EXPECT_FALSE(UnaryOp->isIncrementOp());
68cc19f921SRafael Stahl }
69b4e86d8aSNico Weber }
70cc19f921SRafael Stahl };
71cc19f921SRafael Stahl
addLocIncDecChecker(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)7258884eb6SKirstóf Umann void addLocIncDecChecker(AnalysisASTConsumer &AnalysisConsumer,
7358884eb6SKirstóf Umann AnalyzerOptions &AnOpts) {
7458884eb6SKirstóf Umann AnOpts.CheckersAndPackages = {{"test.LocIncDecChecker", true}};
7558884eb6SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
7658884eb6SKirstóf Umann Registry.addChecker<CustomChecker>("test.LocIncDecChecker", "Description",
7758884eb6SKirstóf Umann "");
7858884eb6SKirstóf Umann });
79cc19f921SRafael Stahl }
80cc19f921SRafael Stahl
TEST(RegisterCustomCheckers,CheckLocationIncDec)8158884eb6SKirstóf Umann TEST(RegisterCustomCheckers, CheckLocationIncDec) {
8258884eb6SKirstóf Umann EXPECT_TRUE(
8358884eb6SKirstóf Umann runCheckerOnCode<addLocIncDecChecker>("void f() { int *p; (*p)++; }"));
84d00ed8e2SAlexander Kornienko }
8558884eb6SKirstóf Umann
866cff2e9fSAdam Balogh //===----------------------------------------------------------------------===//
876cff2e9fSAdam Balogh // Unsatisfied checker dependency
886cff2e9fSAdam Balogh //===----------------------------------------------------------------------===//
896cff2e9fSAdam Balogh
90d61b1f85SKirstóf Umann class CheckerRegistrationOrderPrinter
91d61b1f85SKirstóf Umann : public Checker<check::PreStmt<DeclStmt>> {
92d61b1f85SKirstóf Umann std::unique_ptr<BuiltinBug> BT =
93d61b1f85SKirstóf Umann std::make_unique<BuiltinBug>(this, "Registration order");
94d61b1f85SKirstóf Umann
956cff2e9fSAdam Balogh public:
checkPreStmt(const DeclStmt * DS,CheckerContext & C) const96d61b1f85SKirstóf Umann void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
97d61b1f85SKirstóf Umann ExplodedNode *N = nullptr;
98d61b1f85SKirstóf Umann N = C.generateErrorNode();
99d61b1f85SKirstóf Umann llvm::SmallString<200> Buf;
100d61b1f85SKirstóf Umann llvm::raw_svector_ostream OS(Buf);
101d61b1f85SKirstóf Umann C.getAnalysisManager()
102d61b1f85SKirstóf Umann .getCheckerManager()
103b6cbe6cbSKirstóf Umann ->getCheckerRegistryData()
104d61b1f85SKirstóf Umann .printEnabledCheckerList(OS);
105d61b1f85SKirstóf Umann // Strip a newline off.
106d61b1f85SKirstóf Umann auto R =
107d61b1f85SKirstóf Umann std::make_unique<PathSensitiveBugReport>(*BT, OS.str().drop_back(1), N);
108d61b1f85SKirstóf Umann C.emitReport(std::move(R));
1096cff2e9fSAdam Balogh }
1106cff2e9fSAdam Balogh };
1116cff2e9fSAdam Balogh
registerCheckerRegistrationOrderPrinter(CheckerManager & mgr)112d61b1f85SKirstóf Umann void registerCheckerRegistrationOrderPrinter(CheckerManager &mgr) {
113d61b1f85SKirstóf Umann mgr.registerChecker<CheckerRegistrationOrderPrinter>();
1146cff2e9fSAdam Balogh }
1156cff2e9fSAdam Balogh
shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager & mgr)116d61b1f85SKirstóf Umann bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) {
1176cff2e9fSAdam Balogh return true;
1186cff2e9fSAdam Balogh }
1196cff2e9fSAdam Balogh
addCheckerRegistrationOrderPrinter(CheckerRegistry & Registry)120d61b1f85SKirstóf Umann void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
121d61b1f85SKirstóf Umann Registry.addChecker(registerCheckerRegistrationOrderPrinter,
122d61b1f85SKirstóf Umann shouldRegisterCheckerRegistrationOrderPrinter,
123690ff37aSKirstóf Umann "test.RegistrationOrder", "Description", "", false);
124d61b1f85SKirstóf Umann }
125d61b1f85SKirstóf Umann
126d61b1f85SKirstóf Umann #define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG) \
127d61b1f85SKirstóf Umann class CHECKER_NAME : public Checker<check::PreStmt<DeclStmt>> { \
128d61b1f85SKirstóf Umann std::unique_ptr<BuiltinBug> BT = \
129d61b1f85SKirstóf Umann std::make_unique<BuiltinBug>(this, DIAG_MSG); \
130d61b1f85SKirstóf Umann \
131d61b1f85SKirstóf Umann public: \
132d61b1f85SKirstóf Umann void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {} \
133d61b1f85SKirstóf Umann }; \
134d61b1f85SKirstóf Umann \
135d61b1f85SKirstóf Umann void register##CHECKER_NAME(CheckerManager &mgr) { \
136d61b1f85SKirstóf Umann mgr.registerChecker<CHECKER_NAME>(); \
137d61b1f85SKirstóf Umann } \
138d61b1f85SKirstóf Umann \
139d61b1f85SKirstóf Umann bool shouldRegister##CHECKER_NAME(const CheckerManager &mgr) { \
140d61b1f85SKirstóf Umann return true; \
141d61b1f85SKirstóf Umann } \
142d61b1f85SKirstóf Umann void add##CHECKER_NAME(CheckerRegistry &Registry) { \
143d61b1f85SKirstóf Umann Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME, \
144690ff37aSKirstóf Umann "test." #CHECKER_NAME, "Description", "", false); \
145d61b1f85SKirstóf Umann }
146d61b1f85SKirstóf Umann
147d61b1f85SKirstóf Umann UNITTEST_CHECKER(StrongDep, "Strong")
148d61b1f85SKirstóf Umann UNITTEST_CHECKER(Dep, "Dep")
149d61b1f85SKirstóf Umann
shouldRegisterStrongFALSE(const CheckerManager & mgr)150d61b1f85SKirstóf Umann bool shouldRegisterStrongFALSE(const CheckerManager &mgr) {
151d61b1f85SKirstóf Umann return false;
152d61b1f85SKirstóf Umann }
153d61b1f85SKirstóf Umann
154d61b1f85SKirstóf Umann
addDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)155d61b1f85SKirstóf Umann void addDep(AnalysisASTConsumer &AnalysisConsumer,
1566cff2e9fSAdam Balogh AnalyzerOptions &AnOpts) {
157690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
158690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
1596cff2e9fSAdam Balogh AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
160d61b1f85SKirstóf Umann Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE,
161690ff37aSKirstóf Umann "test.Strong", "Description", "", false);
162d61b1f85SKirstóf Umann addStrongDep(Registry);
163d61b1f85SKirstóf Umann addDep(Registry);
164d61b1f85SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
165690ff37aSKirstóf Umann Registry.addDependency("test.Dep", "test.Strong");
1666cff2e9fSAdam Balogh });
1676cff2e9fSAdam Balogh }
1686cff2e9fSAdam Balogh
TEST(RegisterDeps,UnsatisfiedDependency)169d61b1f85SKirstóf Umann TEST(RegisterDeps, UnsatisfiedDependency) {
1706cff2e9fSAdam Balogh std::string Diags;
171d61b1f85SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addDep>("void f() {int i;}", Diags));
172690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.RegistrationOrder\n");
1736cff2e9fSAdam Balogh }
174e22f1c02SKirstóf Umann
175e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
176e22f1c02SKirstóf Umann // Weak checker dependencies.
177e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
178e22f1c02SKirstóf Umann
179e22f1c02SKirstóf Umann UNITTEST_CHECKER(WeakDep, "Weak")
180e22f1c02SKirstóf Umann
addWeakDepCheckerBothEnabled(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)181e22f1c02SKirstóf Umann void addWeakDepCheckerBothEnabled(AnalysisASTConsumer &AnalysisConsumer,
182e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
183690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
184690ff37aSKirstóf Umann {"test.WeakDep", true},
185690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
186e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
187e22f1c02SKirstóf Umann addWeakDep(Registry);
188e22f1c02SKirstóf Umann addDep(Registry);
189e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
190690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
191e22f1c02SKirstóf Umann });
192e22f1c02SKirstóf Umann }
193e22f1c02SKirstóf Umann
addWeakDepCheckerBothEnabledSwitched(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)194e22f1c02SKirstóf Umann void addWeakDepCheckerBothEnabledSwitched(AnalysisASTConsumer &AnalysisConsumer,
195e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
196690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
197690ff37aSKirstóf Umann {"test.WeakDep", true},
198690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
199e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
200e22f1c02SKirstóf Umann addWeakDep(Registry);
201e22f1c02SKirstóf Umann addDep(Registry);
202e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
203690ff37aSKirstóf Umann Registry.addWeakDependency("test.WeakDep", "test.Dep");
204e22f1c02SKirstóf Umann });
205e22f1c02SKirstóf Umann }
206e22f1c02SKirstóf Umann
addWeakDepCheckerDepDisabled(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)207e22f1c02SKirstóf Umann void addWeakDepCheckerDepDisabled(AnalysisASTConsumer &AnalysisConsumer,
208e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
209690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
210690ff37aSKirstóf Umann {"test.WeakDep", false},
211690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
212e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
213e22f1c02SKirstóf Umann addWeakDep(Registry);
214e22f1c02SKirstóf Umann addDep(Registry);
215e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
216690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
217e22f1c02SKirstóf Umann });
218e22f1c02SKirstóf Umann }
219e22f1c02SKirstóf Umann
addWeakDepCheckerDepUnspecified(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)220e22f1c02SKirstóf Umann void addWeakDepCheckerDepUnspecified(AnalysisASTConsumer &AnalysisConsumer,
221e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
222690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
223690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
224e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
225e22f1c02SKirstóf Umann addWeakDep(Registry);
226e22f1c02SKirstóf Umann addDep(Registry);
227e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
228690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
229e22f1c02SKirstóf Umann });
230e22f1c02SKirstóf Umann }
231e22f1c02SKirstóf Umann
232e22f1c02SKirstóf Umann UNITTEST_CHECKER(WeakDep2, "Weak2")
233e22f1c02SKirstóf Umann UNITTEST_CHECKER(Dep2, "Dep2")
234e22f1c02SKirstóf Umann
addWeakDepHasWeakDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)235e22f1c02SKirstóf Umann void addWeakDepHasWeakDep(AnalysisASTConsumer &AnalysisConsumer,
236e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
237690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
238690ff37aSKirstóf Umann {"test.WeakDep", true},
239690ff37aSKirstóf Umann {"test.WeakDep2", true},
240690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
241e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
242e22f1c02SKirstóf Umann addStrongDep(Registry);
243e22f1c02SKirstóf Umann addWeakDep(Registry);
244e22f1c02SKirstóf Umann addWeakDep2(Registry);
245e22f1c02SKirstóf Umann addDep(Registry);
246e22f1c02SKirstóf Umann addDep2(Registry);
247e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
248690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
249690ff37aSKirstóf Umann Registry.addWeakDependency("test.WeakDep", "test.WeakDep2");
250e22f1c02SKirstóf Umann });
251e22f1c02SKirstóf Umann }
252e22f1c02SKirstóf Umann
addWeakDepTransitivity(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)253e22f1c02SKirstóf Umann void addWeakDepTransitivity(AnalysisASTConsumer &AnalysisConsumer,
254e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
255690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
256690ff37aSKirstóf Umann {"test.WeakDep", false},
257690ff37aSKirstóf Umann {"test.WeakDep2", true},
258690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
259e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
260e22f1c02SKirstóf Umann addStrongDep(Registry);
261e22f1c02SKirstóf Umann addWeakDep(Registry);
262e22f1c02SKirstóf Umann addWeakDep2(Registry);
263e22f1c02SKirstóf Umann addDep(Registry);
264e22f1c02SKirstóf Umann addDep2(Registry);
265e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
266690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
267690ff37aSKirstóf Umann Registry.addWeakDependency("test.WeakDep", "test.WeakDep2");
268e22f1c02SKirstóf Umann });
269e22f1c02SKirstóf Umann }
270e22f1c02SKirstóf Umann
TEST(RegisterDeps,SimpleWeakDependency)271e22f1c02SKirstóf Umann TEST(RegisterDeps, SimpleWeakDependency) {
272e22f1c02SKirstóf Umann std::string Diags;
273e22f1c02SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerBothEnabled>(
274e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
275690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep\ntest."
276690ff37aSKirstóf Umann "Dep\ntest.RegistrationOrder\n");
277e22f1c02SKirstóf Umann Diags.clear();
278e22f1c02SKirstóf Umann
279e22f1c02SKirstóf Umann // Mind that AnalyzerOption listed the enabled checker list in the same order,
280e22f1c02SKirstóf Umann // but the dependencies are switched.
281e22f1c02SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerBothEnabledSwitched>(
282e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
283690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.Dep\ntest."
284690ff37aSKirstóf Umann "RegistrationOrder\ntest.WeakDep\n");
285e22f1c02SKirstóf Umann Diags.clear();
286e22f1c02SKirstóf Umann
287e22f1c02SKirstóf Umann // Weak dependencies dont prevent dependent checkers from being enabled.
288e22f1c02SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerDepDisabled>(
289e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
290*0213d7ecSKristóf Umann EXPECT_EQ(Diags,
291*0213d7ecSKristóf Umann "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
292e22f1c02SKirstóf Umann Diags.clear();
293e22f1c02SKirstóf Umann
294e22f1c02SKirstóf Umann // Nor will they be enabled just because a dependent checker is.
295e22f1c02SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerDepUnspecified>(
296e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
297*0213d7ecSKristóf Umann EXPECT_EQ(Diags,
298*0213d7ecSKristóf Umann "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
299e22f1c02SKirstóf Umann Diags.clear();
300e22f1c02SKirstóf Umann
301e22f1c02SKirstóf Umann EXPECT_TRUE(
302e22f1c02SKirstóf Umann runCheckerOnCode<addWeakDepTransitivity>("void f() {int i;}", Diags));
303690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep2\ntest."
304690ff37aSKirstóf Umann "Dep\ntest.RegistrationOrder\n");
305e22f1c02SKirstóf Umann Diags.clear();
306e22f1c02SKirstóf Umann
307e22f1c02SKirstóf Umann EXPECT_TRUE(
308e22f1c02SKirstóf Umann runCheckerOnCode<addWeakDepHasWeakDep>("void f() {int i;}", Diags));
309690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep2\ntest."
310690ff37aSKirstóf Umann "WeakDep\ntest.Dep\ntest.RegistrationOrder\n");
311e22f1c02SKirstóf Umann Diags.clear();
312e22f1c02SKirstóf Umann }
313e22f1c02SKirstóf Umann
314e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
315e22f1c02SKirstóf Umann // Interaction of weak and regular checker dependencies.
316e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
317e22f1c02SKirstóf Umann
addWeakDepHasStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)318e22f1c02SKirstóf Umann void addWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer,
319e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
320690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
321690ff37aSKirstóf Umann {"test.StrongDep", true},
322690ff37aSKirstóf Umann {"test.WeakDep", true},
323690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
324e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
325e22f1c02SKirstóf Umann addStrongDep(Registry);
326e22f1c02SKirstóf Umann addWeakDep(Registry);
327e22f1c02SKirstóf Umann addDep(Registry);
328e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
329690ff37aSKirstóf Umann Registry.addDependency("test.WeakDep", "test.StrongDep");
330690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
331e22f1c02SKirstóf Umann });
332e22f1c02SKirstóf Umann }
333e22f1c02SKirstóf Umann
addWeakDepAndStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)334e22f1c02SKirstóf Umann void addWeakDepAndStrongDep(AnalysisASTConsumer &AnalysisConsumer,
335e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
336690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
337690ff37aSKirstóf Umann {"test.StrongDep", true},
338690ff37aSKirstóf Umann {"test.WeakDep", true},
339690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
340e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
341e22f1c02SKirstóf Umann addStrongDep(Registry);
342e22f1c02SKirstóf Umann addWeakDep(Registry);
343e22f1c02SKirstóf Umann addDep(Registry);
344e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
345690ff37aSKirstóf Umann Registry.addDependency("test.Dep", "test.StrongDep");
346690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
347e22f1c02SKirstóf Umann });
348e22f1c02SKirstóf Umann }
349e22f1c02SKirstóf Umann
addDisabledWeakDepHasStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)350e22f1c02SKirstóf Umann void addDisabledWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer,
351e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
352690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
353690ff37aSKirstóf Umann {"test.StrongDep", true},
354690ff37aSKirstóf Umann {"test.WeakDep", false},
355690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
356e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
357e22f1c02SKirstóf Umann addStrongDep(Registry);
358e22f1c02SKirstóf Umann addWeakDep(Registry);
359e22f1c02SKirstóf Umann addDep(Registry);
360e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
361690ff37aSKirstóf Umann Registry.addDependency("test.WeakDep", "test.StrongDep");
362690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
363e22f1c02SKirstóf Umann });
364e22f1c02SKirstóf Umann }
365e22f1c02SKirstóf Umann
addDisabledWeakDepHasUnspecifiedStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)366e22f1c02SKirstóf Umann void addDisabledWeakDepHasUnspecifiedStrongDep(
367e22f1c02SKirstóf Umann AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) {
368690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
369690ff37aSKirstóf Umann {"test.WeakDep", false},
370690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
371e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
372e22f1c02SKirstóf Umann addStrongDep(Registry);
373e22f1c02SKirstóf Umann addWeakDep(Registry);
374e22f1c02SKirstóf Umann addDep(Registry);
375e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
376690ff37aSKirstóf Umann Registry.addDependency("test.WeakDep", "test.StrongDep");
377690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
378e22f1c02SKirstóf Umann });
379e22f1c02SKirstóf Umann }
380e22f1c02SKirstóf Umann
addWeakDepHasDisabledStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)381e22f1c02SKirstóf Umann void addWeakDepHasDisabledStrongDep(AnalysisASTConsumer &AnalysisConsumer,
382e22f1c02SKirstóf Umann AnalyzerOptions &AnOpts) {
383690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
384690ff37aSKirstóf Umann {"test.StrongDep", false},
385690ff37aSKirstóf Umann {"test.WeakDep", true},
386690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
387e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
388e22f1c02SKirstóf Umann addStrongDep(Registry);
389e22f1c02SKirstóf Umann addWeakDep(Registry);
390e22f1c02SKirstóf Umann addDep(Registry);
391e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
392690ff37aSKirstóf Umann Registry.addDependency("test.WeakDep", "test.StrongDep");
393690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
394e22f1c02SKirstóf Umann });
395e22f1c02SKirstóf Umann }
396e22f1c02SKirstóf Umann
addWeakDepHasUnspecifiedButLaterEnabledStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)397e22f1c02SKirstóf Umann void addWeakDepHasUnspecifiedButLaterEnabledStrongDep(
398e22f1c02SKirstóf Umann AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) {
399690ff37aSKirstóf Umann AnOpts.CheckersAndPackages = {{"test.Dep", true},
400690ff37aSKirstóf Umann {"test.Dep2", true},
401690ff37aSKirstóf Umann {"test.WeakDep", true},
402690ff37aSKirstóf Umann {"test.RegistrationOrder", true}};
403e22f1c02SKirstóf Umann AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
404e22f1c02SKirstóf Umann addStrongDep(Registry);
405e22f1c02SKirstóf Umann addWeakDep(Registry);
406e22f1c02SKirstóf Umann addDep(Registry);
407e22f1c02SKirstóf Umann addDep2(Registry);
408e22f1c02SKirstóf Umann addCheckerRegistrationOrderPrinter(Registry);
409690ff37aSKirstóf Umann Registry.addDependency("test.WeakDep", "test.StrongDep");
410690ff37aSKirstóf Umann Registry.addDependency("test.Dep2", "test.StrongDep");
411690ff37aSKirstóf Umann Registry.addWeakDependency("test.Dep", "test.WeakDep");
412e22f1c02SKirstóf Umann });
413e22f1c02SKirstóf Umann }
414e22f1c02SKirstóf Umann
TEST(RegisterDeps,DependencyInteraction)415e22f1c02SKirstóf Umann TEST(RegisterDeps, DependencyInteraction) {
416e22f1c02SKirstóf Umann std::string Diags;
417e22f1c02SKirstóf Umann EXPECT_TRUE(
418e22f1c02SKirstóf Umann runCheckerOnCode<addWeakDepHasStrongDep>("void f() {int i;}", Diags));
419690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.StrongDep\ntest."
420690ff37aSKirstóf Umann "WeakDep\ntest.Dep\ntest.RegistrationOrder\n");
421e22f1c02SKirstóf Umann Diags.clear();
422e22f1c02SKirstóf Umann
423e22f1c02SKirstóf Umann // Weak dependencies are registered before strong dependencies. This is most
424e22f1c02SKirstóf Umann // important for purely diagnostic checkers that are implemented as a part of
425e22f1c02SKirstóf Umann // purely modeling checkers, becuse the checker callback order will have to be
426e22f1c02SKirstóf Umann // established in between the modeling portion and the weak dependency.
427e22f1c02SKirstóf Umann EXPECT_TRUE(
428e22f1c02SKirstóf Umann runCheckerOnCode<addWeakDepAndStrongDep>("void f() {int i;}", Diags));
429690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep\ntest."
430690ff37aSKirstóf Umann "StrongDep\ntest.Dep\ntest.RegistrationOrder\n");
431e22f1c02SKirstóf Umann Diags.clear();
432e22f1c02SKirstóf Umann
433e22f1c02SKirstóf Umann // If a weak dependency is disabled, the checker itself can still be enabled.
434e22f1c02SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addDisabledWeakDepHasStrongDep>(
435e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
436690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.Dep\ntest."
437690ff37aSKirstóf Umann "RegistrationOrder\ntest.StrongDep\n");
438e22f1c02SKirstóf Umann Diags.clear();
439e22f1c02SKirstóf Umann
440e22f1c02SKirstóf Umann // If a weak dependency is disabled, the checker itself can still be enabled,
441e22f1c02SKirstóf Umann // but it shouldn't enable a strong unspecified dependency.
442e22f1c02SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addDisabledWeakDepHasUnspecifiedStrongDep>(
443e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
444*0213d7ecSKristóf Umann EXPECT_EQ(Diags,
445*0213d7ecSKristóf Umann "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
446e22f1c02SKirstóf Umann Diags.clear();
447e22f1c02SKirstóf Umann
448e22f1c02SKirstóf Umann // A strong dependency of a weak dependency is disabled, so neither of them
449e22f1c02SKirstóf Umann // should be enabled.
450e22f1c02SKirstóf Umann EXPECT_TRUE(runCheckerOnCode<addWeakDepHasDisabledStrongDep>(
451e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
452*0213d7ecSKristóf Umann EXPECT_EQ(Diags,
453*0213d7ecSKristóf Umann "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
454e22f1c02SKirstóf Umann Diags.clear();
455e22f1c02SKirstóf Umann
456e22f1c02SKirstóf Umann EXPECT_TRUE(
457e22f1c02SKirstóf Umann runCheckerOnCode<addWeakDepHasUnspecifiedButLaterEnabledStrongDep>(
458e22f1c02SKirstóf Umann "void f() {int i;}", Diags));
459690ff37aSKirstóf Umann EXPECT_EQ(Diags, "test.RegistrationOrder: test.StrongDep\ntest.WeakDep\ntest."
460690ff37aSKirstóf Umann "Dep\ntest.Dep2\ntest.RegistrationOrder\n");
461e22f1c02SKirstóf Umann Diags.clear();
462e22f1c02SKirstóf Umann }
46358884eb6SKirstóf Umann } // namespace
46458884eb6SKirstóf Umann } // namespace ento
46558884eb6SKirstóf Umann } // namespace clang
466