Skip to content

Commit 84eb5af

Browse files
committed
Refactor use of CheckerRegistry::addChecker()
1 parent ffe6ac4 commit 84eb5af

17 files changed

+101
-99
lines changed

clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,33 @@
3838
// function clang_registerCheckers. For example:
3939
//
4040
// extern "C"
41-
// void clang_registerCheckers (CheckerRegistry &registry) {
42-
// registry.addChecker<MainCallChecker>("example.MainCallChecker",
43-
// "Disallows calls to functions called main");
41+
// void clang_registerCheckers(CheckerRegistry &Registry) {
42+
// Registry.addChecker(
43+
// registerMainCallChecker,
44+
// shouldRegisterMainCallChecker,
45+
// "example.MainCallChecker",
46+
// "MainCallChecker",
47+
// "Example Description",
48+
// "example.mychecker.documentation.nonexistent.html",
49+
// /*isHidden=*/ false);
4450
// }
4551
//
46-
// The first method argument is the full name of the checker, including its
47-
// enclosing package. By convention, the registered name of a checker is the
48-
// name of the associated class (the template argument).
49-
// The second method argument is a short human-readable description of the
50-
// checker.
52+
// The first two arguments are the registration handling functions, which
53+
// in a simple case look like
5154
//
52-
// The clang_registerCheckers function may add any number of checkers to the
53-
// registry. If any checkers require additional initialization, use the
54-
// non-templated form of CheckerRegistry::addChecker.
55+
// void registerMainCallChecker(CheckerManager &Mgr) {
56+
// Mgr.registerChecker<MainCallChecker>();
57+
// }
58+
//
59+
// bool shouldRegisterMainCallChecker(const CheckerManager &) {
60+
// return true;
61+
// }
62+
//
63+
// The third argument is the full name of the checker (including its package),
64+
// the fourth name is the internal DebugName (by convention, the name of the
65+
// class), the fifth argument is a short documentation, the sixth argument is
66+
// an url to a documentation page, and the seventh argument should be false for
67+
// normal user-facing checkers.
5568
//
5669
// To load a checker plugin, specify the full path to the dynamic library as
5770
// the argument to the -load option in the cc1 frontend. You can then enable
@@ -60,7 +73,7 @@
6073
// clang -cc1 -load </path/to/plugin.dylib> -analyze
6174
// -analyzer-checker=<example.MainCallChecker>
6275
//
63-
// For a complete working example, see examples/analyzer-plugin.
76+
// For a complete example, see clang/lib/Analysis/plugins/SampleAnalyzer
6477

6578
#ifndef CLANG_ANALYZER_API_VERSION_STRING
6679
// FIXME: The Clang version string is not particularly granular;
@@ -119,32 +132,13 @@ class CheckerRegistry {
119132
StringRef FullName, StringRef DebugName, StringRef Desc,
120133
StringRef DocsUri, bool IsHidden);
121134

122-
/// Adds a checker to the registry. This overload doesn't take a `DebugName`
123-
/// (which usually looks like `DivZeroChecker`), so it uses the user-facing
124-
/// `FullName` (which usually looks like ``core.DivideZero`) as a debug name.
125-
/// THIS IS DEPRECATED and is only provided to preserve compatibility with
126-
/// legacy plugins.
127-
/// TODO: Eventually remove this from the codebase.
128-
void addChecker(RegisterCheckerFn Fn, ShouldRegisterFunction Sfn,
129-
StringRef FullName, StringRef Desc, StringRef DocsUri,
130-
bool IsHidden) {
131-
addChecker(Fn, Sfn, FullName, /*DebugName =*/FullName, Desc, DocsUri,
132-
IsHidden);
133-
}
134-
135-
/// Adds a checker to the registry. Use this templated overload when your
136-
/// checker does not require any custom initialization.
137-
/// This function isn't really needed and probably causes more headaches than
138-
/// the tiny convenience that it provides, but external plugins might use it,
139-
/// and there isn't a strong incentive to remove it.
140-
template <class T>
141-
void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri,
142-
bool IsHidden = false) {
143-
// Avoid MSVC's Compiler Error C2276:
144-
// http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
135+
/// Add a mock checker to the registry for testing purposes, without
136+
/// specifying metadata that is not relevant in simple tests.
137+
template <class T> void addMockChecker(StringRef FullName) {
145138
addChecker(&CheckerRegistry::initializeManager<CheckerManager, T>,
146-
&CheckerRegistry::returnTrue<T>, FullName, Desc, DocsUri,
147-
IsHidden);
139+
&CheckerRegistry::returnTrue<T>, FullName,
140+
/*DebugName=*/"TestChecker", /*Desc=*/"", /*DocsUri=*/"",
141+
/*IsHidden=*/false);
148142
}
149143

150144
/// Makes the checker with the full name \p fullName depend on the checker

clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
44
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
55

6+
// This barebones plugin is used by clang/test/Analysis/checker-plugins.c
7+
// to test dependency handling among checkers loaded from plugins.
8+
69
using namespace clang;
710
using namespace ento;
811

@@ -16,12 +19,11 @@ struct DependendentChecker : public Checker<check::BeginFunction> {
1619
} // end anonymous namespace
1720

1821
// Register plugin!
19-
extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
20-
registry.addChecker<Dependency>("example.Dependency", "", "");
21-
registry.addChecker<DependendentChecker>("example.DependendentChecker", "",
22-
"");
22+
extern "C" void clang_registerCheckers(CheckerRegistry &Registry) {
23+
Registry.addMockChecker<Dependency>("example.Dependency");
24+
Registry.addMockChecker<DependendentChecker>("example.DependendentChecker");
2325

24-
registry.addDependency("example.DependendentChecker", "example.Dependency");
26+
Registry.addDependency("example.DependendentChecker", "example.Dependency");
2527
}
2628

2729
extern "C" const char clang_analyzerAPIVersionString[] =

clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
using namespace clang;
77
using namespace ento;
88

9+
// This barebones plugin is used by clang/test/Analysis/checker-plugins.c
10+
// to test option handling on checkers loaded from plugins.
11+
912
namespace {
1013
struct MyChecker : public Checker<check::BeginFunction> {
1114
void checkBeginFunction(CheckerContext &Ctx) const {}
@@ -26,13 +29,13 @@ bool shouldRegisterMyChecker(const CheckerManager &mgr) { return true; }
2629
} // end anonymous namespace
2730

2831
// Register plugin!
29-
extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
30-
registry.addChecker(registerMyChecker, shouldRegisterMyChecker,
31-
"example.MyChecker", "Example Description",
32+
extern "C" void clang_registerCheckers(CheckerRegistry &Registry) {
33+
Registry.addChecker(registerMyChecker, shouldRegisterMyChecker,
34+
"example.MyChecker", "MyChecker", "Example Description",
3235
"example.mychecker.documentation.nonexistent.html",
33-
/*isHidden*/false);
36+
/*isHidden*/ false);
3437

35-
registry.addCheckerOption(/*OptionType*/ "bool",
38+
Registry.addCheckerOption(/*OptionType*/ "bool",
3639
/*CheckerFullName*/ "example.MyChecker",
3740
/*OptionName*/ "ExampleOption",
3841
/*DefaultValStr*/ "false",

clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,26 @@
33
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
44
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
55

6+
// This simple plugin is used by clang/test/Analysis/checker-plugins.c
7+
// to test use a checker that is defined in a plugin.
8+
69
using namespace clang;
710
using namespace ento;
811

912
namespace {
1013
class MainCallChecker : public Checker<check::PreStmt<CallExpr>> {
11-
mutable std::unique_ptr<BugType> BT;
14+
15+
BugType BT{this, "call to main", "example analyzer plugin"};
1216

1317
public:
1418
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
1519
};
20+
21+
void registerMainCallChecker(CheckerManager &Mgr) {
22+
Mgr.registerChecker<MainCallChecker>();
23+
}
24+
25+
bool shouldRegisterMainCallChecker(const CheckerManager &) { return true; }
1626
} // end anonymous namespace
1727

1828
void MainCallChecker::checkPreStmt(const CallExpr *CE,
@@ -33,21 +43,20 @@ void MainCallChecker::checkPreStmt(const CallExpr *CE,
3343
if (!N)
3444
return;
3545

36-
if (!BT)
37-
BT.reset(new BugType(this, "call to main", "example analyzer plugin"));
38-
3946
auto report =
40-
std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
47+
std::make_unique<PathSensitiveBugReport>(BT, BT.getDescription(), N);
4148
report->addRange(Callee->getSourceRange());
4249
C.emitReport(std::move(report));
4350
}
4451
}
4552

4653
// Register plugin!
47-
extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
48-
registry.addChecker<MainCallChecker>(
49-
"example.MainCallChecker", "Disallows calls to functions called main",
50-
"");
54+
extern "C" void clang_registerCheckers(CheckerRegistry &Registry) {
55+
Registry.addChecker(registerMainCallChecker, shouldRegisterMainCallChecker,
56+
"example.MainCallChecker", "MainCallChecker",
57+
"Example Description",
58+
"example.mychecker.documentation.nonexistent.html",
59+
/*isHidden=*/false);
5160
}
5261

5362
extern "C" const char clang_analyzerAPIVersionString[] =

clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ class TestAction : public ASTFrontendAction {
119119
std::make_unique<VerifyPathDiagnosticConsumer>(
120120
std::move(ExpectedDiags), Compiler.getSourceManager()));
121121
AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
122-
Registry.addChecker<InterestingnessTestChecker>("test.Interestingness",
123-
"Description", "");
122+
Registry.addMockChecker<InterestingnessTestChecker>(
123+
"test.Interestingness");
124124
});
125125
Compiler.getAnalyzerOpts().CheckersAndPackages = {
126126
{"test.Interestingness", true}};

clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,7 @@ void addCallDescChecker(AnalysisASTConsumer &AnalysisConsumer,
620620
AnalyzerOptions &AnOpts) {
621621
AnOpts.CheckersAndPackages = {{"test.CallDescChecker", true}};
622622
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
623-
Registry.addChecker<CallDescChecker>("test.CallDescChecker", "Description",
624-
"");
623+
Registry.addMockChecker<CallDescChecker>("test.CallDescChecker");
625624
});
626625
}
627626

clang/unittests/StaticAnalyzer/CallEventTest.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ void addCXXDeallocatorChecker(AnalysisASTConsumer &AnalysisConsumer,
5555
AnalyzerOptions &AnOpts) {
5656
AnOpts.CheckersAndPackages = {{"test.CXXDeallocator", true}};
5757
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
58-
Registry.addChecker<CXXDeallocatorChecker>("test.CXXDeallocator",
59-
"Description", "");
58+
Registry.addMockChecker<CXXDeallocatorChecker>("test.CXXDeallocator");
6059
});
6160
}
6261

clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,8 @@ void addEvalFooCheckers(AnalysisASTConsumer &AnalysisConsumer,
3333
AnOpts.CheckersAndPackages = {{"test.EvalFoo1", true},
3434
{"test.EvalFoo2", true}};
3535
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
36-
Registry.addChecker<EvalCallFoo1>("test.EvalFoo1", "EmptyDescription",
37-
"EmptyDocsUri");
38-
Registry.addChecker<EvalCallFoo2>("test.EvalFoo2", "EmptyDescription",
39-
"EmptyDocsUri");
36+
Registry.addMockChecker<EvalCallFoo1>("test.EvalFoo1");
37+
Registry.addMockChecker<EvalCallFoo2>("test.EvalFoo2");
4038
});
4139
}
4240
} // namespace

clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,26 +77,25 @@ void addExprEngineVisitPreChecker(AnalysisASTConsumer &AnalysisConsumer,
7777
AnalyzerOptions &AnOpts) {
7878
AnOpts.CheckersAndPackages = {{"ExprEngineVisitPreChecker", true}};
7979
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
80-
Registry.addChecker<ExprEngineVisitPreChecker>("ExprEngineVisitPreChecker",
81-
"Desc", "DocsURI");
80+
Registry.addMockChecker<ExprEngineVisitPreChecker>(
81+
"ExprEngineVisitPreChecker");
8282
});
8383
}
8484

8585
void addExprEngineVisitPostChecker(AnalysisASTConsumer &AnalysisConsumer,
8686
AnalyzerOptions &AnOpts) {
8787
AnOpts.CheckersAndPackages = {{"ExprEngineVisitPostChecker", true}};
8888
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
89-
Registry.addChecker<ExprEngineVisitPostChecker>(
90-
"ExprEngineVisitPostChecker", "Desc", "DocsURI");
89+
Registry.addMockChecker<ExprEngineVisitPostChecker>(
90+
"ExprEngineVisitPostChecker");
9191
});
9292
}
9393

9494
void addMemAccessChecker(AnalysisASTConsumer &AnalysisConsumer,
9595
AnalyzerOptions &AnOpts) {
9696
AnOpts.CheckersAndPackages = {{"MemAccessChecker", true}};
9797
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
98-
Registry.addChecker<MemAccessChecker>("MemAccessChecker", "Desc",
99-
"DocsURI");
98+
Registry.addMockChecker<MemAccessChecker>("MemAccessChecker");
10099
});
101100
}
102101

clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ void addFalsePositiveGenerator(AnalysisASTConsumer &AnalysisConsumer,
9292
AnOpts.CheckersAndPackages = {{"test.FalsePositiveGenerator", true},
9393
{"debug.ViewExplodedGraph", false}};
9494
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
95-
Registry.addChecker<FalsePositiveGenerator>(
96-
"test.FalsePositiveGenerator", "EmptyDescription", "EmptyDocsUri");
95+
Registry.addMockChecker<FalsePositiveGenerator>(
96+
"test.FalsePositiveGenerator");
9797
});
9898
}
9999

clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer,
4545
AnalyzerOptions &AnOpts) {
4646
AnOpts.CheckersAndPackages = {{"DescriptiveNameChecker", true}};
4747
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
48-
Registry.addChecker<DescriptiveNameChecker>("DescriptiveNameChecker",
49-
"Desc", "DocsURI");
48+
Registry.addMockChecker<DescriptiveNameChecker>("DescriptiveNameChecker");
5049
});
5150
}
5251

clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ void addNonThoroughStatefulChecker(AnalysisASTConsumer &AnalysisConsumer,
138138
AnalyzerOptions &AnOpts) {
139139
AnOpts.CheckersAndPackages = {{"test.StatefulChecker", true}};
140140
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
141-
Registry
142-
.addChecker<StatefulChecker<NonThoroughErrorNotPreventedFuncVisitor>>(
143-
"test.StatefulChecker", "Description", "");
141+
Registry.addMockChecker<
142+
StatefulChecker<NonThoroughErrorNotPreventedFuncVisitor>>(
143+
"test.StatefulChecker");
144144
});
145145
}
146146

@@ -232,8 +232,9 @@ void addThoroughStatefulChecker(AnalysisASTConsumer &AnalysisConsumer,
232232
AnalyzerOptions &AnOpts) {
233233
AnOpts.CheckersAndPackages = {{"test.StatefulChecker", true}};
234234
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
235-
Registry.addChecker<StatefulChecker<ThoroughErrorNotPreventedFuncVisitor>>(
236-
"test.StatefulChecker", "Description", "");
235+
Registry
236+
.addMockChecker<StatefulChecker<ThoroughErrorNotPreventedFuncVisitor>>(
237+
"test.StatefulChecker");
237238
});
238239
}
239240

clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ void addFlagFlipperChecker(AnalysisASTConsumer &AnalysisConsumer,
3636
AnalyzerOptions &AnOpts) {
3737
AnOpts.CheckersAndPackages = {{"test.FlipFlagOnCheckLocation", true}};
3838
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
39-
Registry.addChecker<FlipFlagOnCheckLocation>("test.FlipFlagOnCheckLocation",
40-
"Description", "");
39+
Registry.addMockChecker<FlipFlagOnCheckLocation>(
40+
"test.FlipFlagOnCheckLocation");
4141
});
4242
}
4343

clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void addCustomChecker(AnalysisASTConsumer &AnalysisConsumer,
4444
AnalyzerOptions &AnOpts) {
4545
AnOpts.CheckersAndPackages = {{"test.CustomChecker", true}};
4646
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
47-
Registry.addChecker<CustomChecker>("test.CustomChecker", "Description", "");
47+
Registry.addMockChecker<CustomChecker>("test.CustomChecker");
4848
});
4949
}
5050

@@ -73,8 +73,7 @@ void addLocIncDecChecker(AnalysisASTConsumer &AnalysisConsumer,
7373
AnalyzerOptions &AnOpts) {
7474
AnOpts.CheckersAndPackages = {{"test.LocIncDecChecker", true}};
7575
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
76-
Registry.addChecker<CustomChecker>("test.LocIncDecChecker", "Description",
77-
"");
76+
Registry.addMockChecker<CustomChecker>("test.LocIncDecChecker");
7877
});
7978
}
8079

@@ -117,9 +116,10 @@ bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) {
117116
}
118117

119118
void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
120-
Registry.addChecker(registerCheckerRegistrationOrderPrinter,
121-
shouldRegisterCheckerRegistrationOrderPrinter,
122-
"test.RegistrationOrder", "Description", "", false);
119+
Registry.addChecker(
120+
registerCheckerRegistrationOrderPrinter,
121+
shouldRegisterCheckerRegistrationOrderPrinter, "test.RegistrationOrder",
122+
"CheckerRegistrationOrderPrinter", "Description", "", false);
123123
}
124124

125125
#define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG) \
@@ -137,7 +137,8 @@ void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
137137
} \
138138
void add##CHECKER_NAME(CheckerRegistry &Registry) { \
139139
Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME, \
140-
"test." #CHECKER_NAME, "Description", "", false); \
140+
"test." #CHECKER_NAME, #CHECKER_NAME, "Description", \
141+
"", false); \
141142
}
142143

143144
UNITTEST_CHECKER(StrongDep, "Strong")
@@ -154,7 +155,7 @@ void addDep(AnalysisASTConsumer &AnalysisConsumer,
154155
{"test.RegistrationOrder", true}};
155156
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
156157
Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE,
157-
"test.Strong", "Description", "", false);
158+
"test.Strong", "StrongDep", "Description", "", false);
158159
addStrongDep(Registry);
159160
addDep(Registry);
160161
addCheckerRegistrationOrderPrinter(Registry);

0 commit comments

Comments
 (0)