Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions clang/docs/analyzer/developer-docs/DebugChecks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
========================
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/CrossTU/CrossTranslationUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ class CrossTranslationUnitContext {
llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD,
ASTUnit *Unit);

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

/// Emit diagnostics for the user for potential configuration errors.
void emitCrossTUDiagnostics(const IndexError &IE);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CrossTU/CrossTranslationUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,9 @@ CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI)
CrossTranslationUnitContext::~CrossTranslationUnitContext() {}

std::optional<std::string>
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);
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions clang/test/Analysis/analyzeOneFunction.cpp
Original file line number Diff line number Diff line change
@@ -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}}
};