[clang] d3e14fa - [analyzer][NFC] Display the correct function name even in crash dumps
Balazs Benics via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 11 23:55:00 PDT 2021
Author: Balazs Benics
Date: 2021-07-12T09:06:46+02:00
New Revision: d3e14fafc69a07e3dab9ddb91f1d810bb5f8d7a0
URL: https://github.com/llvm/llvm-project/commit/d3e14fafc69a07e3dab9ddb91f1d810bb5f8d7a0
DIFF: https://github.com/llvm/llvm-project/commit/d3e14fafc69a07e3dab9ddb91f1d810bb5f8d7a0.diff
LOG: [analyzer][NFC] Display the correct function name even in crash dumps
The `-analyzer-display-progress` displayed the function name of the
currently analyzed function. It differs in C and C++. In C++, it
prints the argument types as well in a comma-separated list.
While in C, only the function name is displayed, without the brackets.
E.g.:
C++: foo(), foo(int, float)
C: foo
In crash traces, the analyzer dumps the location contexts, but the
string is not enough for `-analyze-function` in C++ mode.
This patch addresses the issue by dumping the proper function names
even in stack traces.
Reviewed By: NoQ
Differential Revision: https://reviews.llvm.org/D105708
Added:
Modified:
clang/include/clang/Analysis/AnalysisDeclContext.h
clang/lib/Analysis/AnalysisDeclContext.cpp
clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
clang/test/Analysis/crash-trace.c
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/AnalysisDeclContext.h b/clang/include/clang/Analysis/AnalysisDeclContext.h
index d12582f4f329..102970a1d55e 100644
--- a/clang/include/clang/Analysis/AnalysisDeclContext.h
+++ b/clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -200,6 +200,8 @@ class AnalysisDeclContext {
/// \returns Whether the root namespace of \p D is the \c std C++ namespace.
static bool isInStdNamespace(const Decl *D);
+ static std::string getFunctionName(const Decl *D);
+
private:
std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag);
diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp
index 783de6442645..d8466ac34a3d 100644
--- a/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -337,6 +337,59 @@ bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
return ND->isStdNamespace();
}
+std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ const ASTContext &Ctx = D->getASTContext();
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ OS << FD->getQualifiedNameAsString();
+
+ // In C++, there are overloads.
+
+ if (Ctx.getLangOpts().CPlusPlus) {
+ OS << '(';
+ for (const auto &P : FD->parameters()) {
+ if (P != *FD->param_begin())
+ OS << ", ";
+ OS << P->getType().getAsString();
+ }
+ OS << ')';
+ }
+
+ } else if (isa<BlockDecl>(D)) {
+ PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(D->getLocation());
+
+ if (Loc.isValid()) {
+ OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
+ << ')';
+ }
+
+ } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+
+ // FIXME: copy-pasted from CGDebugInfo.cpp.
+ OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
+ const DeclContext *DC = OMD->getDeclContext();
+ if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
+ if (OC->IsClassExtension()) {
+ OS << OC->getClassInterface()->getName();
+ } else {
+ OS << OC->getIdentifier()->getNameStart() << '('
+ << OC->getIdentifier()->getNameStart() << ')';
+ }
+ } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
+ OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
+ }
+ OS << ' ' << OMD->getSelector().getAsString() << ']';
+ }
+
+ return OS.str();
+}
+
LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
assert(
ADCMgr &&
@@ -456,7 +509,7 @@ void LocationContext::dumpStack(raw_ostream &Out) const {
Out << "\t#" << Frame << ' ';
++Frame;
if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
- Out << "Calling " << D->getQualifiedNameAsString();
+ Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
else
Out << "Calling anonymous code";
if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 33914e98b90f..03b5c04f553f 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -209,8 +209,8 @@ class AnalysisConsumer : public AnalysisASTConsumer,
} else
assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
- llvm::errs() << ": " << Loc.getFilename() << ' ' << getFunctionName(D)
- << '\n';
+ llvm::errs() << ": " << Loc.getFilename() << ' '
+ << AnalysisDeclContext::getFunctionName(D) << '\n';
}
}
@@ -568,63 +568,10 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
Mgr.reset();
}
-std::string AnalysisConsumer::getFunctionName(const Decl *D) {
- std::string Str;
- llvm::raw_string_ostream OS(Str);
-
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- OS << FD->getQualifiedNameAsString();
-
- // In C++, there are overloads.
- if (Ctx->getLangOpts().CPlusPlus) {
- OS << '(';
- for (const auto &P : FD->parameters()) {
- if (P != *FD->param_begin())
- OS << ", ";
- OS << P->getType().getAsString();
- }
- OS << ')';
- }
-
- } else if (isa<BlockDecl>(D)) {
- PresumedLoc Loc = Ctx->getSourceManager().getPresumedLoc(D->getLocation());
-
- if (Loc.isValid()) {
- OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
- << ')';
- }
-
- } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
-
- // FIXME: copy-pasted from CGDebugInfo.cpp.
- OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
- const DeclContext *DC = OMD->getDeclContext();
- if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
- OS << OID->getName();
- } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
- OS << OID->getName();
- } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
- if (OC->IsClassExtension()) {
- OS << OC->getClassInterface()->getName();
- } else {
- OS << OC->getIdentifier()->getNameStart() << '('
- << OC->getIdentifier()->getNameStart() << ')';
- }
- } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
- OS << OCD->getClassInterface()->getName() << '('
- << OCD->getName() << ')';
- }
- OS << ' ' << OMD->getSelector().getAsString() << ']';
-
- }
-
- return OS.str();
-}
-
AnalysisConsumer::AnalysisMode
AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
if (!Opts->AnalyzeSpecificFunction.empty() &&
- getFunctionName(D) != Opts->AnalyzeSpecificFunction)
+ AnalysisDeclContext::getFunctionName(D) != Opts->AnalyzeSpecificFunction)
return AM_None;
// Unless -analyze-all is specified, treat decls
diff erently depending on
diff --git a/clang/test/Analysis/crash-trace.c b/clang/test/Analysis/crash-trace.c
index 0c8c8cc6cb2e..f00db3a74ab9 100644
--- a/clang/test/Analysis/crash-trace.c
+++ b/clang/test/Analysis/crash-trace.c
@@ -1,4 +1,7 @@
-// RUN: not --crash %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection %s 2>&1 | FileCheck %s
+// RUN: not --crash %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection \
+// RUN: -x c %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-C-ONLY
+// RUN: not --crash %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection \
+// RUN: -x c++ %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-CXX-ONLY
// REQUIRES: crash-recovery
// Stack traces require back traces.
@@ -6,17 +9,22 @@
void clang_analyzer_crash(void);
-void inlined() {
+void inlined(int x, float y) {
clang_analyzer_crash();
}
void test() {
- inlined();
+ inlined(0, 0);
}
-// CHECK: 0. Program arguments: {{.*}}clang
-// CHECK-NEXT: 1. <eof> parser at end of file
-// CHECK-NEXT: 2. While analyzing stack:
-// CHECK-NEXT: #0 Calling inlined at line 14
-// CHECK-NEXT: #1 Calling test
-// CHECK-NEXT: 3. {{.*}}crash-trace.c:{{[0-9]+}}:3: Error evaluating statement
+// CHECK: 0. Program arguments: {{.*}}clang
+// CHECK-NEXT: 1. <eof> parser at end of file
+// CHECK-NEXT: 2. While analyzing stack:
+//
+// CHECK-C-ONLY-NEXT: #0 Calling inlined at line 17
+// CHECK-C-ONLY-NEXT: #1 Calling test
+//
+// CHECK-CXX-ONLY-NEXT: #0 Calling inlined(int, float) at line 17
+// CHECK-CXX-ONLY-NEXT: #1 Calling test()
+//
+// CHECK-NEXT: 3. {{.*}}crash-trace.c:{{[0-9]+}}:3: Error evaluating statement
More information about the cfe-commits
mailing list