steakhal created this revision.
steakhal added reviewers: NoQ, vsavchenko, martong, Szelethus, ASDenysPetrov.
Herald added subscribers: manas, dkrupp, donat.nagy, mikhail.ramalho, 
a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun, whisperity.
steakhal requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D105708

Files:
  clang/include/clang/Analysis/AnalysisDeclContext.h
  clang/lib/Analysis/AnalysisDeclContext.cpp
  clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
  clang/test/Analysis/crash-trace.c

Index: clang/test/Analysis/crash-trace.c
===================================================================
--- clang/test/Analysis/crash-trace.c
+++ 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
Index: clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -209,8 +209,8 @@
       } 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 @@
   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 differently depending on
Index: clang/lib/Analysis/AnalysisDeclContext.cpp
===================================================================
--- clang/lib/Analysis/AnalysisDeclContext.cpp
+++ clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -337,6 +337,59 @@
   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 @@
       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()) {
Index: clang/include/clang/Analysis/AnalysisDeclContext.h
===================================================================
--- clang/include/clang/Analysis/AnalysisDeclContext.h
+++ clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -200,6 +200,8 @@
   /// \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);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to