diff --git a/clang/docs/analyzer/developer-docs/DebugChecks.rst b/clang/docs/analyzer/developer-docs/DebugChecks.rst index 767ef6565d335..b3b908941317e 100644 --- a/clang/docs/analyzer/developer-docs/DebugChecks.rst +++ b/clang/docs/analyzer/developer-docs/DebugChecks.rst @@ -9,6 +9,22 @@ The analyzer contains a number of checkers which can aid in debugging. Enable them by using the "-analyzer-checker=" flag, followed by the name of the checker. +These checkers are especially useful when analyzing a specific function, using +the `-analyze-function` flag. The flag accepts the function name for C code, +like `-analyze-function=myfunction`. +For C++ code, due to overloading, the function name must include the +parameter list, like `-analyze-function="myfunction(int, _Bool)"`. + +Note that `bool` must be spelled as `_Bool` in the parameter list. +Refer to the output of `-analyzer-display-progress` to find the fully qualified +function name. + +There are cases when this name can still collide. For example with template +function instances with non-deducible (aka. explicit) template parameters. +In such cases, prefer passing a USR instead of a function name can resolve this +ambiguity, like this: `-analyze-function="c:@S@Window@F@overloaded#I#"`. + +Use the `clang-extdef-mapping` tool to find the USR for different functions. General Analysis Dumpers ======================== diff --git a/clang/include/clang/CrossTU/CrossTranslationUnit.h b/clang/include/clang/CrossTU/CrossTranslationUnit.h index e6b608a10e61b..9e0721edfc323 100644 --- a/clang/include/clang/CrossTU/CrossTranslationUnit.h +++ b/clang/include/clang/CrossTU/CrossTranslationUnit.h @@ -180,8 +180,8 @@ class CrossTranslationUnitContext { llvm::Expected importDefinition(const VarDecl *VD, ASTUnit *Unit); - /// Get a name to identify a named decl. - static std::optional getLookupName(const NamedDecl *ND); + /// Get a name to identify a decl. + static std::optional getLookupName(const Decl *D); /// Emit diagnostics for the user for potential configuration errors. void emitCrossTUDiagnostics(const IndexError &IE); diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp index 847913d4b03fd..0287845a741ed 100644 --- a/clang/lib/CrossTU/CrossTranslationUnit.cpp +++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -252,9 +252,9 @@ CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI) CrossTranslationUnitContext::~CrossTranslationUnitContext() {} std::optional -CrossTranslationUnitContext::getLookupName(const NamedDecl *ND) { +CrossTranslationUnitContext::getLookupName(const Decl *D) { SmallString<128> DeclUSR; - bool Ret = index::generateUSRForDecl(ND, DeclUSR); + bool Ret = index::generateUSRForDecl(D, DeclUSR); if (Ret) return {}; return std::string(DeclUSR); diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 53466e7a75b0f..e9ba374851726 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -659,8 +659,11 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { AnalysisConsumer::AnalysisMode AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) { if (!Opts.AnalyzeSpecificFunction.empty() && - AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction) + AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction && + cross_tu::CrossTranslationUnitContext::getLookupName(D).value_or("") != + Opts.AnalyzeSpecificFunction) { return AM_None; + } // Unless -analyze-all is specified, treat decls differently depending on // where they came from: diff --git a/clang/test/Analysis/analyzeOneFunction.cpp b/clang/test/Analysis/analyzeOneFunction.cpp new file mode 100644 index 0000000000000..3a362dfd9a08c --- /dev/null +++ b/clang/test/Analysis/analyzeOneFunction.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s \ +// RUN: -analyze-function="Window::overloaded(int)" + +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s \ +// RUN: -analyze-function="c:@S@Window@F@overloaded#I#" + +// RUN: %clang_extdef_map %s | FileCheck %s +// CHECK: 27:c:@S@Window@F@overloaded#I# +// CHECK-NEXT: 27:c:@S@Window@F@overloaded#C# +// CHECK-NEXT: 27:c:@S@Window@F@overloaded#d# + +void clang_analyzer_warnIfReached(); + +struct Window { + void overloaded(double) { clang_analyzer_warnIfReached(); } // not analyzed, thus not reachable + void overloaded(char) { clang_analyzer_warnIfReached(); } // not analyzed, thus not reachable + void overloaded(int) { clang_analyzer_warnIfReached(); } // expected-warning {{REACHABLE}} +};