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