Skip to content

Commit ea107d5

Browse files
authored
[NFC][analyzer] Use CheckerBase::getName in checker option handling (#131612)
The virtual method `ProgramPointTag::getTagDescription` had two very distinct use cases: - It is printed in the DOT graph visualization of the exploded graph (that is, a debug printout). - The checker option handling code used it to query the name of a checker, which relied on the coincidence that in `CheckerBase` this method is defined to be equivalent with `getName()`. This commit switches to using `getName` in the second use case, because this way we will be able to properly support checkers that have multiple (separately named) parts. The method `reportInvalidCheckerOptionName` is extended with an additional overload that allows specifying the `CheckerPartIdx`. The methods `getChecker*Option` could be extended analogously in the future, but they are just convenience wrappers around the variants that directly take `StringRef CheckerName`, so I'll only do this extension if it's needed.
1 parent 64cf6f9 commit ea107d5

File tree

6 files changed

+26
-51
lines changed

6 files changed

+26
-51
lines changed

clang/include/clang/Analysis/ProgramPoint.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class ProgramPointTag {
3939
public:
4040
ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
4141
virtual ~ProgramPointTag();
42+
43+
/// The description of this program point which will be displayed when the
44+
/// ExplodedGraph is dumped in DOT format for debugging.
4245
virtual StringRef getTagDescription() const = 0;
4346

4447
/// Used to implement 'isKind' in subclasses.

clang/include/clang/StaticAnalyzer/Core/Checker.h

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -516,18 +516,11 @@ class CheckerBase : public ProgramPointTag {
516516
}
517517

518518
StringRef getTagDescription() const override {
519-
// This method inherited from `ProgramPointTag` has two unrelated roles:
520-
// (1) The analyzer option handling logic uses this method to query the
521-
// name of a checker.
522-
// (2) When the `ExplodedGraph` is dumped in DOT format for debugging,
523-
// this is called to attach a description to the nodes. (This happens
524-
// for all subclasses of `ProgramPointTag`, not just checkers.)
525-
// FIXME: Application (1) should be aware of multiple parts within the same
526-
// checker class instance, so it should directly use `getName` instead of
527-
// this inherited interface which cannot support a `CheckerPartIdx`.
528-
// FIXME: Ideally application (2) should return a string that describes the
529-
// whole checker class, not just one of it parts. However, this is only for
530-
// debugging, so returning the name of one part is probably good enough.
519+
// When the ExplodedGraph is dumped for debugging (in DOT format), this
520+
// method is called to attach a description to nodes created by this
521+
// checker _class_. Ideally this should be recognizable identifier of the
522+
// whole class, but for this debugging purpose it's sufficient to use the
523+
// name of the first registered checker part.
531524
for (const auto &OptName : RegisteredNames)
532525
if (OptName)
533526
return *OptName;

clang/include/clang/StaticAnalyzer/Core/CheckerManager.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ class CheckerManager {
194194
/// Emits an error through a DiagnosticsEngine about an invalid user supplied
195195
/// checker option value.
196196
void reportInvalidCheckerOptionValue(const CheckerBase *C,
197+
StringRef OptionName,
198+
StringRef ExpectedValueDesc) const {
199+
reportInvalidCheckerOptionValue(C, DefaultPart, OptionName,
200+
ExpectedValueDesc);
201+
}
202+
203+
void reportInvalidCheckerOptionValue(const CheckerBase *C, CheckerPartIdx Idx,
197204
StringRef OptionName,
198205
StringRef ExpectedValueDesc) const;
199206

clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,7 @@ StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName,
154154
StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C,
155155
StringRef OptionName,
156156
bool SearchInParents) const {
157-
return getCheckerStringOption(
158-
C->getTagDescription(), OptionName, SearchInParents);
157+
return getCheckerStringOption(C->getName(), OptionName, SearchInParents);
159158
}
160159

161160
bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
@@ -178,8 +177,7 @@ bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
178177
bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C,
179178
StringRef OptionName,
180179
bool SearchInParents) const {
181-
return getCheckerBooleanOption(
182-
C->getTagDescription(), OptionName, SearchInParents);
180+
return getCheckerBooleanOption(C->getName(), OptionName, SearchInParents);
183181
}
184182

185183
int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
@@ -199,6 +197,5 @@ int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
199197
int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C,
200198
StringRef OptionName,
201199
bool SearchInParents) const {
202-
return getCheckerIntegerOption(
203-
C->getTagDescription(), OptionName, SearchInParents);
200+
return getCheckerIntegerOption(C->getName(), OptionName, SearchInParents);
204201
}

clang/lib/StaticAnalyzer/Core/CheckerManager.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ bool CheckerManager::hasPathSensitiveCheckers() const {
5050
}
5151

5252
void CheckerManager::reportInvalidCheckerOptionValue(
53-
const CheckerBase *C, StringRef OptionName,
53+
const CheckerBase *C, CheckerPartIdx Idx, StringRef OptionName,
5454
StringRef ExpectedValueDesc) const {
5555

5656
getDiagnostics().Report(diag::err_analyzer_checker_option_invalid_input)
57-
<< (llvm::Twine() + C->getTagDescription() + ":" + OptionName).str()
57+
<< (llvm::Twine(C->getName(Idx)) + ":" + OptionName).str()
5858
<< ExpectedValueDesc;
5959
}
6060

clang/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,25 @@ TEST(StaticAnalyzerOptions, SearchInParentPackageTests) {
3737
Opts.Config["Outer.Inner:Option2"] = "true";
3838
Opts.Config["Outer:Option2"] = "false";
3939

40-
struct CheckerOneMock : CheckerBase {
41-
StringRef getTagDescription() const override {
42-
return "Outer.Inner.CheckerOne";
43-
}
44-
};
45-
struct CheckerTwoMock : CheckerBase {
46-
StringRef getTagDescription() const override {
47-
return "Outer.Inner.CheckerTwo";
48-
}
49-
};
40+
StringRef CheckerOneName = "Outer.Inner.CheckerOne";
41+
StringRef CheckerTwoName = "Outer.Inner.CheckerTwo";
5042

5143
// CheckerTwo one has Option specified as true. It should read true regardless
5244
// of search mode.
53-
CheckerOneMock CheckerOne;
54-
EXPECT_TRUE(Opts.getCheckerBooleanOption(&CheckerOne, "Option"));
45+
EXPECT_TRUE(Opts.getCheckerBooleanOption(CheckerOneName, "Option"));
5546
// The package option is overridden with a checker option.
56-
EXPECT_TRUE(Opts.getCheckerBooleanOption(&CheckerOne, "Option", true));
47+
EXPECT_TRUE(Opts.getCheckerBooleanOption(CheckerOneName, "Option", true));
5748
// The Outer package option is overridden by the Inner package option. No
5849
// package option is specified.
59-
EXPECT_TRUE(Opts.getCheckerBooleanOption(&CheckerOne, "Option2", true));
50+
EXPECT_TRUE(Opts.getCheckerBooleanOption(CheckerOneName, "Option2", true));
6051
// No package option is specified and search in packages is turned off. We
6152
// should assert here, but we can't test that.
6253
//Opts.getCheckerBooleanOption(&CheckerOne, "Option2");
6354
//Opts.getCheckerBooleanOption(&CheckerOne, "Option2");
6455

6556
// Checker true has no option specified. It should get false when search in
6657
// parents turned on.
67-
CheckerTwoMock CheckerTwo;
68-
EXPECT_FALSE(Opts.getCheckerBooleanOption(&CheckerTwo, "Option", true));
58+
EXPECT_FALSE(Opts.getCheckerBooleanOption(CheckerTwoName, "Option", true));
6959
// In any other case, we should assert, that we cannot test unfortunately.
7060
//Opts.getCheckerBooleanOption(&CheckerTwo, "Option");
7161
//Opts.getCheckerBooleanOption(&CheckerTwo, "Option");
@@ -74,21 +64,6 @@ TEST(StaticAnalyzerOptions, SearchInParentPackageTests) {
7464
TEST(StaticAnalyzerOptions, StringOptions) {
7565
AnalyzerOptions Opts;
7666
Opts.Config["Outer.Inner.CheckerOne:Option"] = "StringValue";
77-
78-
struct CheckerOneMock : CheckerBase {
79-
StringRef getTagDescription() const override {
80-
return "Outer.Inner.CheckerOne";
81-
}
82-
};
83-
84-
CheckerOneMock CheckerOne;
85-
EXPECT_TRUE("StringValue" ==
86-
Opts.getCheckerStringOption(&CheckerOne, "Option"));
87-
}
88-
89-
TEST(StaticAnalyzerOptions, SubCheckerOptions) {
90-
AnalyzerOptions Opts;
91-
Opts.Config["Outer.Inner.CheckerOne:Option"] = "StringValue";
9267
EXPECT_TRUE("StringValue" == Opts.getCheckerStringOption(
9368
"Outer.Inner.CheckerOne", "Option"));
9469
}

0 commit comments

Comments
 (0)