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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181561 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Adrian Prantl 2013-05-09 23:16:27 +00:00
Родитель 192b030c8a
Коммит 0a050f7d56
3 изменённых файлов: 80 добавлений и 0 удалений

Просмотреть файл

@ -1232,6 +1232,23 @@ CodeGenModule::shouldEmitFunction(const FunctionDecl *F) {
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(GlobalDecl GD) {
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))

Просмотреть файл

@ -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.

Просмотреть файл

@ -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() { }