xref: /llvm-project/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp (revision 18f219c5ac8369ec3e46c4accbb19ca51dc8bc67)
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>> {
92*18f219c5SBalazs Benics   const BugType BT{this, "Registration order"};
93d61b1f85SKirstóf Umann 
946cff2e9fSAdam Balogh public:
checkPreStmt(const DeclStmt * DS,CheckerContext & C) const95d61b1f85SKirstóf Umann   void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
96d61b1f85SKirstóf Umann     ExplodedNode *N = nullptr;
97d61b1f85SKirstóf Umann     N = C.generateErrorNode();
98d61b1f85SKirstóf Umann     llvm::SmallString<200> Buf;
99d61b1f85SKirstóf Umann     llvm::raw_svector_ostream OS(Buf);
100d61b1f85SKirstóf Umann     C.getAnalysisManager()
101d61b1f85SKirstóf Umann         .getCheckerManager()
102b6cbe6cbSKirstóf Umann         ->getCheckerRegistryData()
103d61b1f85SKirstóf Umann         .printEnabledCheckerList(OS);
104d61b1f85SKirstóf Umann     // Strip a newline off.
105d61b1f85SKirstóf Umann     auto R =
106*18f219c5SBalazs Benics         std::make_unique<PathSensitiveBugReport>(BT, OS.str().drop_back(1), N);
107d61b1f85SKirstóf Umann     C.emitReport(std::move(R));
1086cff2e9fSAdam Balogh   }
1096cff2e9fSAdam Balogh };
1106cff2e9fSAdam Balogh 
registerCheckerRegistrationOrderPrinter(CheckerManager & mgr)111d61b1f85SKirstóf Umann void registerCheckerRegistrationOrderPrinter(CheckerManager &mgr) {
112d61b1f85SKirstóf Umann   mgr.registerChecker<CheckerRegistrationOrderPrinter>();
1136cff2e9fSAdam Balogh }
1146cff2e9fSAdam Balogh 
shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager & mgr)115d61b1f85SKirstóf Umann bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) {
1166cff2e9fSAdam Balogh   return true;
1176cff2e9fSAdam Balogh }
1186cff2e9fSAdam Balogh 
addCheckerRegistrationOrderPrinter(CheckerRegistry & Registry)119d61b1f85SKirstóf Umann void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
120d61b1f85SKirstóf Umann   Registry.addChecker(registerCheckerRegistrationOrderPrinter,
121d61b1f85SKirstóf Umann                       shouldRegisterCheckerRegistrationOrderPrinter,
122690ff37aSKirstóf Umann                       "test.RegistrationOrder", "Description", "", false);
123d61b1f85SKirstóf Umann }
124d61b1f85SKirstóf Umann 
125d61b1f85SKirstóf Umann #define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG)                               \
126d61b1f85SKirstóf Umann   class CHECKER_NAME : public Checker<check::PreStmt<DeclStmt>> {              \
127d61b1f85SKirstóf Umann   public:                                                                      \
128d61b1f85SKirstóf Umann     void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {}          \
129d61b1f85SKirstóf Umann   };                                                                           \
130d61b1f85SKirstóf Umann                                                                                \
131d61b1f85SKirstóf Umann   void register##CHECKER_NAME(CheckerManager &mgr) {                           \
132d61b1f85SKirstóf Umann     mgr.registerChecker<CHECKER_NAME>();                                       \
133d61b1f85SKirstóf Umann   }                                                                            \
134d61b1f85SKirstóf Umann                                                                                \
135d61b1f85SKirstóf Umann   bool shouldRegister##CHECKER_NAME(const CheckerManager &mgr) {               \
136d61b1f85SKirstóf Umann     return true;                                                               \
137d61b1f85SKirstóf Umann   }                                                                            \
138d61b1f85SKirstóf Umann   void add##CHECKER_NAME(CheckerRegistry &Registry) {                          \
139d61b1f85SKirstóf Umann     Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME,  \
140690ff37aSKirstóf Umann                         "test." #CHECKER_NAME, "Description", "", false);      \
141d61b1f85SKirstóf Umann   }
142d61b1f85SKirstóf Umann 
143d61b1f85SKirstóf Umann UNITTEST_CHECKER(StrongDep, "Strong")
144d61b1f85SKirstóf Umann UNITTEST_CHECKER(Dep, "Dep")
145d61b1f85SKirstóf Umann 
shouldRegisterStrongFALSE(const CheckerManager & mgr)146d61b1f85SKirstóf Umann bool shouldRegisterStrongFALSE(const CheckerManager &mgr) {
147d61b1f85SKirstóf Umann   return false;
148d61b1f85SKirstóf Umann }
149d61b1f85SKirstóf Umann 
150d61b1f85SKirstóf Umann 
addDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)151d61b1f85SKirstóf Umann void addDep(AnalysisASTConsumer &AnalysisConsumer,
1526cff2e9fSAdam Balogh                   AnalyzerOptions &AnOpts) {
153690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
154690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
1556cff2e9fSAdam Balogh   AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
156d61b1f85SKirstóf Umann     Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE,
157690ff37aSKirstóf Umann                         "test.Strong", "Description", "", false);
158d61b1f85SKirstóf Umann     addStrongDep(Registry);
159d61b1f85SKirstóf Umann     addDep(Registry);
160d61b1f85SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
161690ff37aSKirstóf Umann     Registry.addDependency("test.Dep", "test.Strong");
1626cff2e9fSAdam Balogh   });
1636cff2e9fSAdam Balogh }
1646cff2e9fSAdam Balogh 
TEST(RegisterDeps,UnsatisfiedDependency)165d61b1f85SKirstóf Umann TEST(RegisterDeps, UnsatisfiedDependency) {
1666cff2e9fSAdam Balogh   std::string Diags;
167d61b1f85SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addDep>("void f() {int i;}", Diags));
168690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.RegistrationOrder\n");
1696cff2e9fSAdam Balogh }
170e22f1c02SKirstóf Umann 
171e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
172e22f1c02SKirstóf Umann // Weak checker dependencies.
173e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
174e22f1c02SKirstóf Umann 
175e22f1c02SKirstóf Umann UNITTEST_CHECKER(WeakDep, "Weak")
176e22f1c02SKirstóf Umann 
addWeakDepCheckerBothEnabled(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)177e22f1c02SKirstóf Umann void addWeakDepCheckerBothEnabled(AnalysisASTConsumer &AnalysisConsumer,
178e22f1c02SKirstóf Umann                                   AnalyzerOptions &AnOpts) {
179690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
180690ff37aSKirstóf Umann                                 {"test.WeakDep", true},
181690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
182e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
183e22f1c02SKirstóf Umann     addWeakDep(Registry);
184e22f1c02SKirstóf Umann     addDep(Registry);
185e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
186690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
187e22f1c02SKirstóf Umann   });
188e22f1c02SKirstóf Umann }
189e22f1c02SKirstóf Umann 
addWeakDepCheckerBothEnabledSwitched(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)190e22f1c02SKirstóf Umann void addWeakDepCheckerBothEnabledSwitched(AnalysisASTConsumer &AnalysisConsumer,
191e22f1c02SKirstóf Umann                                           AnalyzerOptions &AnOpts) {
192690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
193690ff37aSKirstóf Umann                                 {"test.WeakDep", true},
194690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
195e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
196e22f1c02SKirstóf Umann     addWeakDep(Registry);
197e22f1c02SKirstóf Umann     addDep(Registry);
198e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
199690ff37aSKirstóf Umann     Registry.addWeakDependency("test.WeakDep", "test.Dep");
200e22f1c02SKirstóf Umann   });
201e22f1c02SKirstóf Umann }
202e22f1c02SKirstóf Umann 
addWeakDepCheckerDepDisabled(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)203e22f1c02SKirstóf Umann void addWeakDepCheckerDepDisabled(AnalysisASTConsumer &AnalysisConsumer,
204e22f1c02SKirstóf Umann                                   AnalyzerOptions &AnOpts) {
205690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
206690ff37aSKirstóf Umann                                 {"test.WeakDep", false},
207690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
208e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
209e22f1c02SKirstóf Umann     addWeakDep(Registry);
210e22f1c02SKirstóf Umann     addDep(Registry);
211e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
212690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
213e22f1c02SKirstóf Umann   });
214e22f1c02SKirstóf Umann }
215e22f1c02SKirstóf Umann 
addWeakDepCheckerDepUnspecified(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)216e22f1c02SKirstóf Umann void addWeakDepCheckerDepUnspecified(AnalysisASTConsumer &AnalysisConsumer,
217e22f1c02SKirstóf Umann                                      AnalyzerOptions &AnOpts) {
218690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
219690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
220e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
221e22f1c02SKirstóf Umann     addWeakDep(Registry);
222e22f1c02SKirstóf Umann     addDep(Registry);
223e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
224690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
225e22f1c02SKirstóf Umann   });
226e22f1c02SKirstóf Umann }
227e22f1c02SKirstóf Umann 
228e22f1c02SKirstóf Umann UNITTEST_CHECKER(WeakDep2, "Weak2")
229e22f1c02SKirstóf Umann UNITTEST_CHECKER(Dep2, "Dep2")
230e22f1c02SKirstóf Umann 
addWeakDepHasWeakDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)231e22f1c02SKirstóf Umann void addWeakDepHasWeakDep(AnalysisASTConsumer &AnalysisConsumer,
232e22f1c02SKirstóf Umann                           AnalyzerOptions &AnOpts) {
233690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
234690ff37aSKirstóf Umann                                 {"test.WeakDep", true},
235690ff37aSKirstóf Umann                                 {"test.WeakDep2", true},
236690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
237e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
238e22f1c02SKirstóf Umann     addStrongDep(Registry);
239e22f1c02SKirstóf Umann     addWeakDep(Registry);
240e22f1c02SKirstóf Umann     addWeakDep2(Registry);
241e22f1c02SKirstóf Umann     addDep(Registry);
242e22f1c02SKirstóf Umann     addDep2(Registry);
243e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
244690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
245690ff37aSKirstóf Umann     Registry.addWeakDependency("test.WeakDep", "test.WeakDep2");
246e22f1c02SKirstóf Umann   });
247e22f1c02SKirstóf Umann }
248e22f1c02SKirstóf Umann 
addWeakDepTransitivity(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)249e22f1c02SKirstóf Umann void addWeakDepTransitivity(AnalysisASTConsumer &AnalysisConsumer,
250e22f1c02SKirstóf Umann                             AnalyzerOptions &AnOpts) {
251690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
252690ff37aSKirstóf Umann                                 {"test.WeakDep", false},
253690ff37aSKirstóf Umann                                 {"test.WeakDep2", true},
254690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
255e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
256e22f1c02SKirstóf Umann     addStrongDep(Registry);
257e22f1c02SKirstóf Umann     addWeakDep(Registry);
258e22f1c02SKirstóf Umann     addWeakDep2(Registry);
259e22f1c02SKirstóf Umann     addDep(Registry);
260e22f1c02SKirstóf Umann     addDep2(Registry);
261e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
262690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
263690ff37aSKirstóf Umann     Registry.addWeakDependency("test.WeakDep", "test.WeakDep2");
264e22f1c02SKirstóf Umann   });
265e22f1c02SKirstóf Umann }
266e22f1c02SKirstóf Umann 
TEST(RegisterDeps,SimpleWeakDependency)267e22f1c02SKirstóf Umann TEST(RegisterDeps, SimpleWeakDependency) {
268e22f1c02SKirstóf Umann   std::string Diags;
269e22f1c02SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerBothEnabled>(
270e22f1c02SKirstóf Umann       "void f() {int i;}", Diags));
271690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep\ntest."
272690ff37aSKirstóf Umann                    "Dep\ntest.RegistrationOrder\n");
273e22f1c02SKirstóf Umann   Diags.clear();
274e22f1c02SKirstóf Umann 
275e22f1c02SKirstóf Umann   // Mind that AnalyzerOption listed the enabled checker list in the same order,
276e22f1c02SKirstóf Umann   // but the dependencies are switched.
277e22f1c02SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerBothEnabledSwitched>(
278e22f1c02SKirstóf Umann       "void f() {int i;}", Diags));
279690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.Dep\ntest."
280690ff37aSKirstóf Umann                    "RegistrationOrder\ntest.WeakDep\n");
281e22f1c02SKirstóf Umann   Diags.clear();
282e22f1c02SKirstóf Umann 
283e22f1c02SKirstóf Umann   // Weak dependencies dont prevent dependent checkers from being enabled.
284e22f1c02SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerDepDisabled>(
285e22f1c02SKirstóf Umann       "void f() {int i;}", Diags));
2860213d7ecSKristóf Umann   EXPECT_EQ(Diags,
2870213d7ecSKristóf Umann             "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
288e22f1c02SKirstóf Umann   Diags.clear();
289e22f1c02SKirstóf Umann 
290e22f1c02SKirstóf Umann   // Nor will they be enabled just because a dependent checker is.
291e22f1c02SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerDepUnspecified>(
292e22f1c02SKirstóf Umann       "void f() {int i;}", Diags));
2930213d7ecSKristóf Umann   EXPECT_EQ(Diags,
2940213d7ecSKristóf Umann             "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
295e22f1c02SKirstóf Umann   Diags.clear();
296e22f1c02SKirstóf Umann 
297e22f1c02SKirstóf Umann   EXPECT_TRUE(
298e22f1c02SKirstóf Umann       runCheckerOnCode<addWeakDepTransitivity>("void f() {int i;}", Diags));
299690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep2\ntest."
300690ff37aSKirstóf Umann                    "Dep\ntest.RegistrationOrder\n");
301e22f1c02SKirstóf Umann   Diags.clear();
302e22f1c02SKirstóf Umann 
303e22f1c02SKirstóf Umann   EXPECT_TRUE(
304e22f1c02SKirstóf Umann       runCheckerOnCode<addWeakDepHasWeakDep>("void f() {int i;}", Diags));
305690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep2\ntest."
306690ff37aSKirstóf Umann                    "WeakDep\ntest.Dep\ntest.RegistrationOrder\n");
307e22f1c02SKirstóf Umann   Diags.clear();
308e22f1c02SKirstóf Umann }
309e22f1c02SKirstóf Umann 
310e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
311e22f1c02SKirstóf Umann // Interaction of weak and regular checker dependencies.
312e22f1c02SKirstóf Umann //===----------------------------------------------------------------------===//
313e22f1c02SKirstóf Umann 
addWeakDepHasStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)314e22f1c02SKirstóf Umann void addWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer,
315e22f1c02SKirstóf Umann                             AnalyzerOptions &AnOpts) {
316690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
317690ff37aSKirstóf Umann                                 {"test.StrongDep", true},
318690ff37aSKirstóf Umann                                 {"test.WeakDep", true},
319690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
320e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
321e22f1c02SKirstóf Umann     addStrongDep(Registry);
322e22f1c02SKirstóf Umann     addWeakDep(Registry);
323e22f1c02SKirstóf Umann     addDep(Registry);
324e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
325690ff37aSKirstóf Umann     Registry.addDependency("test.WeakDep", "test.StrongDep");
326690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
327e22f1c02SKirstóf Umann   });
328e22f1c02SKirstóf Umann }
329e22f1c02SKirstóf Umann 
addWeakDepAndStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)330e22f1c02SKirstóf Umann void addWeakDepAndStrongDep(AnalysisASTConsumer &AnalysisConsumer,
331e22f1c02SKirstóf Umann                             AnalyzerOptions &AnOpts) {
332690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
333690ff37aSKirstóf Umann                                 {"test.StrongDep", true},
334690ff37aSKirstóf Umann                                 {"test.WeakDep", true},
335690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
336e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
337e22f1c02SKirstóf Umann     addStrongDep(Registry);
338e22f1c02SKirstóf Umann     addWeakDep(Registry);
339e22f1c02SKirstóf Umann     addDep(Registry);
340e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
341690ff37aSKirstóf Umann     Registry.addDependency("test.Dep", "test.StrongDep");
342690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
343e22f1c02SKirstóf Umann   });
344e22f1c02SKirstóf Umann }
345e22f1c02SKirstóf Umann 
addDisabledWeakDepHasStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)346e22f1c02SKirstóf Umann void addDisabledWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer,
347e22f1c02SKirstóf Umann                                     AnalyzerOptions &AnOpts) {
348690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
349690ff37aSKirstóf Umann                                 {"test.StrongDep", true},
350690ff37aSKirstóf Umann                                 {"test.WeakDep", false},
351690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
352e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
353e22f1c02SKirstóf Umann     addStrongDep(Registry);
354e22f1c02SKirstóf Umann     addWeakDep(Registry);
355e22f1c02SKirstóf Umann     addDep(Registry);
356e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
357690ff37aSKirstóf Umann     Registry.addDependency("test.WeakDep", "test.StrongDep");
358690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
359e22f1c02SKirstóf Umann   });
360e22f1c02SKirstóf Umann }
361e22f1c02SKirstóf Umann 
addDisabledWeakDepHasUnspecifiedStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)362e22f1c02SKirstóf Umann void addDisabledWeakDepHasUnspecifiedStrongDep(
363e22f1c02SKirstóf Umann     AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) {
364690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
365690ff37aSKirstóf Umann                                 {"test.WeakDep", false},
366690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
367e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
368e22f1c02SKirstóf Umann     addStrongDep(Registry);
369e22f1c02SKirstóf Umann     addWeakDep(Registry);
370e22f1c02SKirstóf Umann     addDep(Registry);
371e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
372690ff37aSKirstóf Umann     Registry.addDependency("test.WeakDep", "test.StrongDep");
373690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
374e22f1c02SKirstóf Umann   });
375e22f1c02SKirstóf Umann }
376e22f1c02SKirstóf Umann 
addWeakDepHasDisabledStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)377e22f1c02SKirstóf Umann void addWeakDepHasDisabledStrongDep(AnalysisASTConsumer &AnalysisConsumer,
378e22f1c02SKirstóf Umann                                     AnalyzerOptions &AnOpts) {
379690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
380690ff37aSKirstóf Umann                                 {"test.StrongDep", false},
381690ff37aSKirstóf Umann                                 {"test.WeakDep", true},
382690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
383e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
384e22f1c02SKirstóf Umann     addStrongDep(Registry);
385e22f1c02SKirstóf Umann     addWeakDep(Registry);
386e22f1c02SKirstóf Umann     addDep(Registry);
387e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
388690ff37aSKirstóf Umann     Registry.addDependency("test.WeakDep", "test.StrongDep");
389690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
390e22f1c02SKirstóf Umann   });
391e22f1c02SKirstóf Umann }
392e22f1c02SKirstóf Umann 
addWeakDepHasUnspecifiedButLaterEnabledStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)393e22f1c02SKirstóf Umann void addWeakDepHasUnspecifiedButLaterEnabledStrongDep(
394e22f1c02SKirstóf Umann     AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) {
395690ff37aSKirstóf Umann   AnOpts.CheckersAndPackages = {{"test.Dep", true},
396690ff37aSKirstóf Umann                                 {"test.Dep2", true},
397690ff37aSKirstóf Umann                                 {"test.WeakDep", true},
398690ff37aSKirstóf Umann                                 {"test.RegistrationOrder", true}};
399e22f1c02SKirstóf Umann   AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
400e22f1c02SKirstóf Umann     addStrongDep(Registry);
401e22f1c02SKirstóf Umann     addWeakDep(Registry);
402e22f1c02SKirstóf Umann     addDep(Registry);
403e22f1c02SKirstóf Umann     addDep2(Registry);
404e22f1c02SKirstóf Umann     addCheckerRegistrationOrderPrinter(Registry);
405690ff37aSKirstóf Umann     Registry.addDependency("test.WeakDep", "test.StrongDep");
406690ff37aSKirstóf Umann     Registry.addDependency("test.Dep2", "test.StrongDep");
407690ff37aSKirstóf Umann     Registry.addWeakDependency("test.Dep", "test.WeakDep");
408e22f1c02SKirstóf Umann   });
409e22f1c02SKirstóf Umann }
410e22f1c02SKirstóf Umann 
TEST(RegisterDeps,DependencyInteraction)411e22f1c02SKirstóf Umann TEST(RegisterDeps, DependencyInteraction) {
412e22f1c02SKirstóf Umann   std::string Diags;
413e22f1c02SKirstóf Umann   EXPECT_TRUE(
414e22f1c02SKirstóf Umann       runCheckerOnCode<addWeakDepHasStrongDep>("void f() {int i;}", Diags));
415690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.StrongDep\ntest."
416690ff37aSKirstóf Umann                    "WeakDep\ntest.Dep\ntest.RegistrationOrder\n");
417e22f1c02SKirstóf Umann   Diags.clear();
418e22f1c02SKirstóf Umann 
419e22f1c02SKirstóf Umann   // Weak dependencies are registered before strong dependencies. This is most
420e22f1c02SKirstóf Umann   // important for purely diagnostic checkers that are implemented as a part of
421e22f1c02SKirstóf Umann   // purely modeling checkers, becuse the checker callback order will have to be
422e22f1c02SKirstóf Umann   // established in between the modeling portion and the weak dependency.
423e22f1c02SKirstóf Umann   EXPECT_TRUE(
424e22f1c02SKirstóf Umann       runCheckerOnCode<addWeakDepAndStrongDep>("void f() {int i;}", Diags));
425690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep\ntest."
426690ff37aSKirstóf Umann                    "StrongDep\ntest.Dep\ntest.RegistrationOrder\n");
427e22f1c02SKirstóf Umann   Diags.clear();
428e22f1c02SKirstóf Umann 
429e22f1c02SKirstóf Umann   // If a weak dependency is disabled, the checker itself can still be enabled.
430e22f1c02SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addDisabledWeakDepHasStrongDep>(
431e22f1c02SKirstóf Umann       "void f() {int i;}", Diags));
432690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.Dep\ntest."
433690ff37aSKirstóf Umann                    "RegistrationOrder\ntest.StrongDep\n");
434e22f1c02SKirstóf Umann   Diags.clear();
435e22f1c02SKirstóf Umann 
436e22f1c02SKirstóf Umann   // If a weak dependency is disabled, the checker itself can still be enabled,
437e22f1c02SKirstóf Umann   // but it shouldn't enable a strong unspecified dependency.
438e22f1c02SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addDisabledWeakDepHasUnspecifiedStrongDep>(
439e22f1c02SKirstóf Umann       "void f() {int i;}", Diags));
4400213d7ecSKristóf Umann   EXPECT_EQ(Diags,
4410213d7ecSKristóf Umann             "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
442e22f1c02SKirstóf Umann   Diags.clear();
443e22f1c02SKirstóf Umann 
444e22f1c02SKirstóf Umann   // A strong dependency of a weak dependency is disabled, so neither of them
445e22f1c02SKirstóf Umann   // should be enabled.
446e22f1c02SKirstóf Umann   EXPECT_TRUE(runCheckerOnCode<addWeakDepHasDisabledStrongDep>(
447e22f1c02SKirstóf Umann       "void f() {int i;}", Diags));
4480213d7ecSKristóf Umann   EXPECT_EQ(Diags,
4490213d7ecSKristóf Umann             "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
450e22f1c02SKirstóf Umann   Diags.clear();
451e22f1c02SKirstóf Umann 
452e22f1c02SKirstóf Umann   EXPECT_TRUE(
453e22f1c02SKirstóf Umann       runCheckerOnCode<addWeakDepHasUnspecifiedButLaterEnabledStrongDep>(
454e22f1c02SKirstóf Umann           "void f() {int i;}", Diags));
455690ff37aSKirstóf Umann   EXPECT_EQ(Diags, "test.RegistrationOrder: test.StrongDep\ntest.WeakDep\ntest."
456690ff37aSKirstóf Umann                    "Dep\ntest.Dep2\ntest.RegistrationOrder\n");
457e22f1c02SKirstóf Umann   Diags.clear();
458e22f1c02SKirstóf Umann }
45958884eb6SKirstóf Umann } // namespace
46058884eb6SKirstóf Umann } // namespace ento
46158884eb6SKirstóf Umann } // namespace clang
462