Skip to content

Commit ef4471e

Browse files
authored
[analyzer] Teach -analyze-function about USRs, extend documentation (#161666)
This flag is really convinient in most cases. It's easy to figure out what value to pass for most cases. However, it can sometimes match too many times, like for template functions that has non-decuded (aka. explicitly specified) template parameters - because they don't appear in the parameter list, thus they are not accounted for in the current logic. It would be nice to improve `getFunctionName` but I'd say to just settle on using USRs. So this PR enables passing USRs to the flag, while keeping previous behavior.
1 parent df65494 commit ef4471e

File tree

5 files changed

+42
-5
lines changed

5 files changed

+42
-5
lines changed

clang/docs/analyzer/developer-docs/DebugChecks.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ The analyzer contains a number of checkers which can aid in debugging. Enable
99
them by using the "-analyzer-checker=" flag, followed by the name of the
1010
checker.
1111

12+
These checkers are especially useful when analyzing a specific function, using
13+
the `-analyze-function` flag. The flag accepts the function name for C code,
14+
like `-analyze-function=myfunction`.
15+
For C++ code, due to overloading, the function name must include the
16+
parameter list, like `-analyze-function="myfunction(int, _Bool)"`.
17+
18+
Note that `bool` must be spelled as `_Bool` in the parameter list.
19+
Refer to the output of `-analyzer-display-progress` to find the fully qualified
20+
function name.
21+
22+
There are cases when this name can still collide. For example with template
23+
function instances with non-deducible (aka. explicit) template parameters.
24+
In such cases, prefer passing a USR instead of a function name can resolve this
25+
ambiguity, like this: `-analyze-function="c:@S@Window@F@overloaded#I#"`.
26+
27+
Use the `clang-extdef-mapping` tool to find the USR for different functions.
1228

1329
General Analysis Dumpers
1430
========================

clang/include/clang/CrossTU/CrossTranslationUnit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ class CrossTranslationUnitContext {
180180
llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD,
181181
ASTUnit *Unit);
182182

183-
/// Get a name to identify a named decl.
184-
static std::optional<std::string> getLookupName(const NamedDecl *ND);
183+
/// Get a name to identify a decl.
184+
static std::optional<std::string> getLookupName(const Decl *D);
185185

186186
/// Emit diagnostics for the user for potential configuration errors.
187187
void emitCrossTUDiagnostics(const IndexError &IE);

clang/lib/CrossTU/CrossTranslationUnit.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI)
252252
CrossTranslationUnitContext::~CrossTranslationUnitContext() {}
253253

254254
std::optional<std::string>
255-
CrossTranslationUnitContext::getLookupName(const NamedDecl *ND) {
255+
CrossTranslationUnitContext::getLookupName(const Decl *D) {
256256
SmallString<128> DeclUSR;
257-
bool Ret = index::generateUSRForDecl(ND, DeclUSR);
257+
bool Ret = index::generateUSRForDecl(D, DeclUSR);
258258
if (Ret)
259259
return {};
260260
return std::string(DeclUSR);

clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,11 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
659659
AnalysisConsumer::AnalysisMode
660660
AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
661661
if (!Opts.AnalyzeSpecificFunction.empty() &&
662-
AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction)
662+
AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction &&
663+
cross_tu::CrossTranslationUnitContext::getLookupName(D).value_or("") !=
664+
Opts.AnalyzeSpecificFunction) {
663665
return AM_None;
666+
}
664667

665668
// Unless -analyze-all is specified, treat decls differently depending on
666669
// where they came from:
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s \
2+
// RUN: -analyze-function="Window::overloaded(int)"
3+
4+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s \
5+
// RUN: -analyze-function="c:@S@Window@F@overloaded#I#"
6+
7+
// RUN: %clang_extdef_map %s | FileCheck %s
8+
// CHECK: 27:c:@S@Window@F@overloaded#I#
9+
// CHECK-NEXT: 27:c:@S@Window@F@overloaded#C#
10+
// CHECK-NEXT: 27:c:@S@Window@F@overloaded#d#
11+
12+
void clang_analyzer_warnIfReached();
13+
14+
struct Window {
15+
void overloaded(double) { clang_analyzer_warnIfReached(); } // not analyzed, thus not reachable
16+
void overloaded(char) { clang_analyzer_warnIfReached(); } // not analyzed, thus not reachable
17+
void overloaded(int) { clang_analyzer_warnIfReached(); } // expected-warning {{REACHABLE}}
18+
};

0 commit comments

Comments
 (0)