]> granicus.if.org Git - clang/commitdiff
[codeview] Emit qualified display names if -gline-tables-only is on
authorReid Kleckner <rnk@google.com>
Thu, 30 Jun 2016 17:41:31 +0000 (17:41 +0000)
committerReid Kleckner <rnk@google.com>
Thu, 30 Jun 2016 17:41:31 +0000 (17:41 +0000)
When -gmlt is on, we don't emit namespace or class scope information,
and the CodeView emission code in LLVM can't compute the fully qualified
name. If we know LLVM won't be able to get the name right, go ahead and
emit the qualified name in the frontend.

We could change our -gmlt emission strategy to include those scopes when
emitting codeview, but that would increase memory usage and slow down
LTO and add more complexity to debug info emission.

The same problem exists when you debug a -gmlt binary with GDB, so we
should consider removing '&& EmitCodeView' from the condition here at
some point in the future after evaluating the impact on object file
size.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274246 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDebugInfo.cpp
test/CodeGenCXX/debug-info-codeview-display-name.cpp

index 723f79aee74d97b7557963f8a99c137eb3ca05d3..ab0ee6cdbe936c90201e6edae7d1270ae8de3b3b 100644 (file)
@@ -185,17 +185,27 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
   FunctionTemplateSpecializationInfo *Info =
       FD->getTemplateSpecializationInfo();
 
-  if (!Info && FII)
+  // Emit the unqualified name in normal operation. LLVM and the debugger can
+  // compute the fully qualified name from the scope chain. If we're only
+  // emitting line table info, there won't be any scope chains, so emit the
+  // fully qualified name here so that stack traces are more accurate.
+  // FIXME: Do this when emitting DWARF as well as when emitting CodeView after
+  // evaluating the size impact.
+  bool UseQualifiedName = DebugKind == codegenoptions::DebugLineTablesOnly &&
+                          CGM.getCodeGenOpts().EmitCodeView;
+
+  if (!Info && FII && !UseQualifiedName)
     return FII->getName();
 
-  // Otherwise construct human readable name for debug info.
   SmallString<128> NS;
   llvm::raw_svector_ostream OS(NS);
   PrintingPolicy Policy(CGM.getLangOpts());
   Policy.MSVCFormatting = CGM.getCodeGenOpts().EmitCodeView;
+  if (!UseQualifiedName)
+    FD->printName(OS);
+  else
+    FD->printQualifiedName(OS, Policy);
 
-  // Print the unqualified name with some template arguments.
-  FD->printName(OS);
   // Add any template specialization args.
   if (Info) {
     const TemplateArgumentList *TArgs = Info->TemplateArguments;
index 1c3682462ff19127bff8734afed9abbde7707e63..b1b5a1e9acb8e9253ee0a2aa94f55ae5c9422b96 100644 (file)
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gcodeview -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98 | \
-// RUN:  grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | FileCheck %s
+// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gcodeview -emit-llvm %s \
+// RUN:       -o - -triple=x86_64-pc-win32 -std=c++98 | \
+// RUN:    grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | \
+// RUN:    FileCheck %s --check-prefix=CHECK --check-prefix=UNQUAL
+// RUN: %clang_cc1 -fblocks -debug-info-kind=line-tables-only -gcodeview -emit-llvm %s \
+// RUN:       -o - -triple=x86_64-pc-win32 -std=c++98 | \
+// RUN:    grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | \
+// RUN:    FileCheck %s --check-prefix=CHECK --check-prefix=QUAL
 
 void freefunc() { }
 // CHECK-DAG: "freefunc"
 
 namespace N {
   int b() { return 0; }
-// CHECK-DAG: "b"
+// UNQUAL-DAG: "b"
+// QUAL-DAG: "N::b"
   namespace { void func() { } }
-// CHECK-DAG: "func"
+// UNQUAL-DAG: "func"
+// QUAL-DAG: "N::`anonymous namespace'::func"
 }
 
 void _c(void) {
@@ -19,19 +27,24 @@ void _c(void) {
 struct foo {
   int operator+(int);
   foo(){}
-// CHECK-DAG: "foo"
+// UNQUAL-DAG: "foo"
+// QUAL-DAG: "foo::foo"
 
   ~foo(){}
-// CHECK-DAG: "~foo"
+// UNQUAL-DAG: "~foo"
+// QUAL-DAG: "foo::~foo"
 
   foo(int i){}
-// CHECK-DAG: "foo"
+// UNQUAL-DAG: "foo"
+// QUAL-DAG: "foo::foo"
 
   foo(char *q){}
-// CHECK-DAG: "foo"
+// UNQUAL-DAG: "foo"
+// QUAL-DAG: "foo::foo"
 
   static foo* static_method() { return 0; }
-// CHECK-DAG: "static_method"
+// UNQUAL-DAG: "static_method"
+// QUAL-DAG: "foo::static_method"
 
 };
 
@@ -40,7 +53,8 @@ void use_foo() {
   foo::static_method();
 }
 
-// CHECK-DAG: "operator+"
+// UNQUAL-DAG: "operator+"
+// QUAL-DAG: "foo::operator+"
 int foo::operator+(int a) { return a; }
 
 // PR17371
@@ -60,11 +74,17 @@ void OverloadedNewDelete::operator delete(void *) { }
 void OverloadedNewDelete::operator delete[](void *) { }
 int OverloadedNewDelete::operator+(int x) { return x; };
 
-// CHECK-DAG: "operator new"
-// CHECK-DAG: "operator new[]"
-// CHECK-DAG: "operator delete"
-// CHECK-DAG: "operator delete[]"
-// CHECK-DAG: "operator+"
+// UNQUAL-DAG: "operator new"
+// UNQUAL-DAG: "operator new[]"
+// UNQUAL-DAG: "operator delete"
+// UNQUAL-DAG: "operator delete[]"
+// UNQUAL-DAG: "operator+"
+// QUAL-DAG: "OverloadedNewDelete::operator new"
+// QUAL-DAG: "OverloadedNewDelete::operator new[]"
+// QUAL-DAG: "OverloadedNewDelete::operator delete"
+// QUAL-DAG: "OverloadedNewDelete::operator delete[]"
+// QUAL-DAG: "OverloadedNewDelete::operator+"
+
 
 template <typename T, void (*)(void)>
 void fn_tmpl() {}