зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
192b030c8a
Коммит
0a050f7d56
|
@ -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() { }
|
Загрузка…
Ссылка в новой задаче