r181561 - Debug Info: Fix a problem that resulted in missing DW_AT_specifications

Adrian Prantl aprantl at apple.com
Thu May 9 16:16:28 PDT 2013


Author: adrian
Date: Thu May  9 18:16:27 2013
New Revision: 181561

URL: http://llvm.org/viewvc/llvm-project?rev=181561&view=rev
Log:
Debug Info: Fix a problem that resulted in missing DW_AT_specifications
for C++ constructors.

If the DIType for a class was generated by
CGDebugInfo::createContextChain(), the cache contains only a
limited DIType wihtout any declarations. Since EmitFunctionStart()
needs to find the canonical declaration for each method, we
construct the complete type before emitting any method.

rdar://problem/13116508

Added:
    cfe/trunk/test/CodeGenCXX/debug-info-decl-nested.cpp
Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=181561&r1=181560&r2=181561&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu May  9 18:16:27 2013
@@ -1232,6 +1232,23 @@ CodeGenModule::shouldEmitFunction(const
   return !isTriviallyRecursive(F);
 }
 
+/// If the type for the method's class was generated by
+/// CGDebugInfo::createContextChain(), the cache contains only a
+/// limited DIType without any declarations. Since EmitFunctionStart()
+/// needs to find the canonical declaration for each method, we need
+/// to construct the complete type prior to emitting the method.
+void CodeGenModule::CompleteDIClassType(const CXXMethodDecl* D) {
+  if (!D->isInstance())
+    return;
+
+  if (CGDebugInfo *DI = getModuleDebugInfo())
+    if (getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
+      const PointerType *ThisPtr =
+        cast<PointerType>(D->getThisType(getContext()));
+      DI->getOrCreateRecordType(ThisPtr->getPointeeType(), D->getLocation());
+    }
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
   const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
 
@@ -1246,6 +1263,7 @@ void CodeGenModule::EmitGlobalDefinition
       return;
 
     if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+      CompleteDIClassType(Method);
       // Make sure to emit the definition(s) before we emit the thunks.
       // This is necessary for the generation of certain thunks.
       if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Method))

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=181561&r1=181560&r2=181561&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu May  9 18:16:27 2013
@@ -1025,6 +1025,7 @@ private:
 
   void EmitNamespace(const NamespaceDecl *D);
   void EmitLinkageSpec(const LinkageSpecDecl *D);
+  void CompleteDIClassType(const CXXMethodDecl* D);
 
   /// EmitCXXConstructors - Emit constructors (base, complete) from a
   /// C++ constructor Decl.

Added: cfe/trunk/test/CodeGenCXX/debug-info-decl-nested.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-decl-nested.cpp?rev=181561&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/debug-info-decl-nested.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/debug-info-decl-nested.cpp Thu May  9 18:16:27 2013
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -std=c++11 -g -O0 -emit-llvm -g -triple x86_64-apple-darwin %s -o %t
+// RUN: cat %t | FileCheck %s -check-prefix=CHECK0
+// RUN: cat %t | FileCheck %s -check-prefix=CHECK1
+// RUN: cat %t | FileCheck %s -check-prefix=CHECK2
+//
+// This test ensures that we associate a declaration with the
+// definition of the constructor for OuterClass. The declaration is
+// necessary so the backend can emit the DW_AT_specification attribute
+// for the definition.
+//
+// rdar://problem/13116508
+
+class Foo;
+class OuterClass
+{
+  static class InnerClass {
+  public:
+    InnerClass(); // Here createContextChain() generates a limited type for OuterClass.
+  } theInnerClass;
+// CHECK0: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [private] [OuterClass]
+  OuterClass(const Foo *); // line 10
+};
+OuterClass::InnerClass OuterClass::theInnerClass; // This toplevel decl causes InnerClass to be generated.
+// CHECK0: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+1]]} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [OuterClass]
+OuterClass::OuterClass(const Foo *meta) { } // line 13
+
+
+
+
+
+class Foo1;
+class OuterClass1
+{
+  static class InnerClass1 {
+  public:
+    InnerClass1();
+  } theInnerClass1;
+// CHECK1: metadata {{.*}}, metadata ![[DECL:[0-9]+]], metadata {{.*}}, i32 [[@LINE+5]]} ; [ DW_TAG_subprogram ] [line [[@LINE+5]]] [def] [Bar]
+  void Bar(const Foo1 *);
+};
+OuterClass1::InnerClass1 OuterClass1::theInnerClass1;
+// CHECK1: [[DECL]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE-3]]] [private] [Bar]
+void OuterClass1::Bar(const Foo1 *meta) { }
+
+
+
+
+
+class Foo2;
+class OuterClass2
+{
+  static class InnerClass2 {
+  public:
+    InnerClass2();
+  } theInnerClass2;
+// CHECK2: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [private] [~OuterClass2]
+  ~OuterClass2(); // line 10
+};
+OuterClass2::InnerClass2 OuterClass2::theInnerClass2;
+// CHECK2: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+1]]} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [~OuterClass2]
+OuterClass2::~OuterClass2() { }





More information about the cfe-commits mailing list