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

0 commit comments

Comments
 (0)