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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits