Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 5434fc2

Browse files
committed
Revert "Revert "Revert "Revert "DebugInfo: Omit debug info for dynamic classes in TUs that do not have the vtable for that class""""
This reverts commit r188687 (reverts r188642 (reverts 188600 (reverts 188576))). With added test coverage & fix for -gline-tables-only. Thanks Michael Gottesman for reverting this patch when it demonstrated problems & providing a reproduction/details to help me track this down. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188739 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 13b572c commit 5434fc2

File tree

5 files changed

+172
-43
lines changed

5 files changed

+172
-43
lines changed

Diff for: lib/CodeGen/CGDebugInfo.cpp

+86-29
Original file line numberDiff line numberDiff line change
@@ -644,8 +644,24 @@ llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
644644

645645
if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
646646
if (!RD->isDependentType()) {
647-
llvm::DIType Ty = getOrCreateLimitedType(
648-
CGM.getContext().getRecordType(RD)->castAs<RecordType>(), getOrCreateMainFile());
647+
llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));
648+
llvm::DICompositeType Ty(getOrCreateLimitedType(
649+
CGM.getContext().getRecordType(RD)->castAs<RecordType>(),
650+
getOrCreateMainFile()));
651+
if (!Ty.getTypeArray().getNumElements()) {
652+
if (T) {
653+
llvm::DIArray PrevMem = T.getTypeArray();
654+
unsigned NumElements = PrevMem.getNumElements();
655+
if (NumElements == 1 && !PrevMem.getElement(0))
656+
NumElements = 0;
657+
SmallVector<llvm::Value *, 16> EltTys;
658+
EltTys.reserve(NumElements);
659+
for (unsigned i = 0; i != NumElements; ++i)
660+
EltTys.push_back(PrevMem.getElement(i));
661+
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
662+
Ty.setTypeArray(Elements);
663+
}
664+
}
649665
return llvm::DIDescriptor(Ty);
650666
}
651667
}
@@ -865,7 +881,7 @@ CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
865881
}
866882
}
867883

868-
/// CollectRecordStaticField - Helper for CollectRecordFields.
884+
/// Helper for CollectRecordFields.
869885
llvm::DIDerivedType
870886
CGDebugInfo::CreateRecordStaticField(const VarDecl *Var,
871887
llvm::DIType RecordTy) {
@@ -948,7 +964,7 @@ void CGDebugInfo::CollectRecordFields(const RecordDecl *record,
948964
for (RecordDecl::decl_iterator I = record->decls_begin(),
949965
E = record->decls_end(); I != E; ++I)
950966
if (const VarDecl *V = dyn_cast<VarDecl>(*I))
951-
elements.push_back(CreateRecordStaticField(V, RecordTy));
967+
elements.push_back(getOrCreateStaticDataMemberDeclaration(V, RecordTy));
952968
else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {
953969
CollectRecordNormalField(field, layout.getFieldOffset(fieldNo),
954970
tunit, elements, RecordTy);
@@ -1123,8 +1139,14 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
11231139
if (D->isImplicit())
11241140
continue;
11251141

1126-
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
1127-
EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
1142+
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
1143+
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator MI =
1144+
SPCache.find(Method->getCanonicalDecl());
1145+
if (MI == SPCache.end())
1146+
EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
1147+
else
1148+
EltTys.push_back(MI->second);
1149+
}
11281150
}
11291151
}
11301152

@@ -1408,10 +1430,20 @@ void CGDebugInfo::completeType(const RecordDecl *RD) {
14081430
}
14091431

14101432
void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
1433+
if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
1434+
if (CXXDecl->isDynamicClass())
1435+
return;
1436+
14111437
QualType Ty = CGM.getContext().getRecordType(RD);
14121438
llvm::DIType T = getTypeOrNull(Ty);
1413-
if (!T || !T.isForwardDecl())
1439+
if (T && T.isForwardDecl())
1440+
completeClassData(RD);
1441+
}
1442+
1443+
void CGDebugInfo::completeClassData(const RecordDecl *RD) {
1444+
if (DebugKind <= CodeGenOptions::DebugLineTablesOnly)
14141445
return;
1446+
QualType Ty = CGM.getContext().getRecordType(RD);
14151447
void* TyPtr = Ty.getAsOpaquePtr();
14161448
if (CompletedTypeCache.count(TyPtr))
14171449
return;
@@ -1424,14 +1456,23 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
14241456
/// CreateType - get structure or union type.
14251457
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, bool Declaration) {
14261458
RecordDecl *RD = Ty->getDecl();
1459+
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
14271460
// Limited debug info should only remove struct definitions that can
14281461
// safely be replaced by a forward declaration in the source code.
1429-
if (DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration &&
1430-
!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) {
1462+
if ((DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration &&
1463+
!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
1464+
(CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())) {
14311465
llvm::DIDescriptor FDContext =
14321466
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
14331467
llvm::DIType RetTy = getOrCreateRecordFwdDecl(RD, FDContext);
1434-
return RetTy;
1468+
// FIXME: This is conservatively correct. If we return a non-forward decl
1469+
// that's not a full definition (such as those created by
1470+
// createContextChain) then getOrCreateType will record is as a complete
1471+
// type and we'll never record all its members. But this means we're
1472+
// emitting full debug info in TUs where GCC successfully emits a partial
1473+
// definition of the type.
1474+
if (RetTy.isForwardDecl())
1475+
return RetTy;
14351476
}
14361477

14371478
return CreateTypeDefinition(Ty);
@@ -1469,6 +1510,7 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
14691510

14701511
// Convert all the elements.
14711512
SmallVector<llvm::Value *, 16> EltTys;
1513+
// what about nested types?
14721514

14731515
// Note: The split of CXXDecl information here is intentional, the
14741516
// gdb tests will depend on a certain ordering at printout. The debug
@@ -2310,7 +2352,7 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
23102352
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
23112353
MI = SPCache.find(FD->getCanonicalDecl());
23122354
if (MI == SPCache.end()) {
2313-
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
2355+
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {
23142356
llvm::DICompositeType T(S);
23152357
llvm::DISubprogram SP = CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T);
23162358
T.addMember(SP);
@@ -3025,19 +3067,35 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
30253067
DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
30263068
}
30273069

3028-
/// getStaticDataMemberDeclaration - If D is an out-of-class definition of
3029-
/// a static data member of a class, find its corresponding in-class
3030-
/// declaration.
3031-
llvm::DIDerivedType CGDebugInfo::getStaticDataMemberDeclaration(const VarDecl *D) {
3032-
if (D->isStaticDataMember()) {
3033-
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
3034-
MI = StaticDataMemberCache.find(D->getCanonicalDecl());
3035-
if (MI != StaticDataMemberCache.end())
3036-
// Verify the info still exists.
3037-
if (llvm::Value *V = MI->second)
3038-
return llvm::DIDerivedType(cast<llvm::MDNode>(V));
3070+
/// If D is an out-of-class definition of a static data member of a class, find
3071+
/// its corresponding in-class declaration.
3072+
llvm::DIDerivedType
3073+
CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
3074+
if (!D->isStaticDataMember())
3075+
return llvm::DIDerivedType();
3076+
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
3077+
StaticDataMemberCache.find(D->getCanonicalDecl());
3078+
if (MI != StaticDataMemberCache.end()) {
3079+
assert(MI->second && "Static data member declaration should still exist");
3080+
return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
3081+
}
3082+
llvm::DICompositeType Ctxt(
3083+
getContextDescriptor(cast<Decl>(D->getDeclContext())));
3084+
llvm::DIDerivedType T = CreateRecordStaticField(D, Ctxt);
3085+
Ctxt.addMember(T);
3086+
return T;
3087+
}
3088+
3089+
llvm::DIDerivedType
3090+
CGDebugInfo::getOrCreateStaticDataMemberDeclaration(const VarDecl *D,
3091+
llvm::DICompositeType Ctxt) {
3092+
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
3093+
StaticDataMemberCache.find(D->getCanonicalDecl());
3094+
if (MI != StaticDataMemberCache.end()) {
3095+
assert(MI->second && "Static data member declaration should still exist");
3096+
return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
30393097
}
3040-
return llvm::DIDerivedType();
3098+
return CreateRecordStaticField(D, Ctxt);
30413099
}
30423100

30433101
/// EmitGlobalVariable - Emit information about a global variable.
@@ -3069,11 +3127,10 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
30693127
LinkageName = StringRef();
30703128
llvm::DIDescriptor DContext =
30713129
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
3072-
llvm::DIGlobalVariable GV =
3073-
DBuilder.createStaticVariable(DContext, DeclName, LinkageName, Unit,
3074-
LineNo, getOrCreateType(T, Unit),
3075-
Var->hasInternalLinkage(), Var,
3076-
getStaticDataMemberDeclaration(D));
3130+
llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
3131+
DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
3132+
Var->hasInternalLinkage(), Var,
3133+
getOrCreateStaticDataMemberDeclarationOrNull(D));
30773134
DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV)));
30783135
}
30793136

@@ -3121,7 +3178,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
31213178
return;
31223179
llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
31233180
Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init,
3124-
getStaticDataMemberDeclaration(cast<VarDecl>(VD)));
3181+
getOrCreateStaticDataMemberDeclarationOrNull(cast<VarDecl>(VD)));
31253182
DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV)));
31263183
}
31273184

Diff for: lib/CodeGen/CGDebugInfo.h

+8-5
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ class CGDebugInfo {
291291

292292
void completeType(const RecordDecl *RD);
293293
void completeRequiredType(const RecordDecl *RD);
294-
294+
void completeClassData(const RecordDecl *RD);
295295

296296
private:
297297
/// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
@@ -354,10 +354,13 @@ class CGDebugInfo {
354354
/// declaration for the given method definition.
355355
llvm::DISubprogram getFunctionDeclaration(const Decl *D);
356356

357-
/// getStaticDataMemberDeclaration - Return debug info descriptor to
358-
/// describe in-class static data member declaration for the given
359-
/// out-of-class definition.
360-
llvm::DIDerivedType getStaticDataMemberDeclaration(const VarDecl *D);
357+
/// Return debug info descriptor to describe in-class static data member
358+
/// declaration for the given out-of-class definition.
359+
llvm::DIDerivedType
360+
getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D);
361+
llvm::DIDerivedType
362+
getOrCreateStaticDataMemberDeclaration(const VarDecl *D,
363+
llvm::DICompositeType Ctxt);
361364

362365
/// getFunctionName - Get function name for the given FunctionDecl. If the
363366
/// name is constructred on demand (e.g. C++ destructor) then the name

Diff for: lib/CodeGen/CGVTables.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,9 @@ CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) {
828828
VFTContext->getVFPtrOffsets(RD);
829829
}
830830

831+
if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
832+
DI->completeClassData(RD);
833+
831834
// First off, check whether we've already emitted the v-table and
832835
// associated stuff.
833836
llvm::GlobalVariable *VTable = GetAddrOfVTable(RD);

Diff for: test/CodeGenCXX/debug-info-class.cpp

+67-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,39 @@ class B {
1313
virtual ~B();
1414
};
1515

16+
B::~B() {
17+
}
18+
1619
struct C {
20+
static int s;
21+
virtual ~C();
22+
};
23+
24+
C::~C() {
25+
}
26+
27+
struct D {
28+
D();
29+
virtual ~D();
30+
void func() {
31+
}
32+
};
33+
34+
struct E {
35+
E();
36+
virtual ~E();
37+
virtual void func() {
38+
}
39+
};
40+
41+
struct F {
42+
struct inner {
43+
};
44+
static const int i = 2;
45+
virtual ~F();
46+
};
47+
48+
struct G {
1749
virtual void func();
1850
struct inner {
1951
int j;
@@ -29,10 +61,17 @@ struct A {
2961
}
3062
};
3163

64+
void f1() {
65+
D x;
66+
x.func();
67+
E y;
68+
int i = F::i;
69+
F::inner z;
70+
}
3271

3372
int main(int argc, char **argv) {
3473
B b;
35-
C::inner c_i;
74+
G::inner c_i;
3675
if (argc) {
3776
A a;
3877
}
@@ -49,15 +88,34 @@ int main(int argc, char **argv) {
4988
// CHECK: DW_TAG_structure_type ] [foo]
5089
// CHECK: DW_TAG_class_type ] [bar]
5190
// CHECK: DW_TAG_union_type ] [baz]
52-
// CHECK: DW_TAG_structure_type ] [A]
53-
// CHECK: HdrSize
5491
// CHECK: DW_TAG_class_type ] [B]
5592
// CHECK: metadata !"_vptr$B", {{.*}}, i32 64, metadata !{{.*}}} ; [ DW_TAG_member ]
56-
// CHECK: metadata [[C_INNER_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [inner] {{.*}} [def]
93+
94+
// CHECK: [[C:![0-9]*]] = {{.*}} metadata [[C_MEM:![0-9]*]], i32 0, metadata [[C]], null} ; [ DW_TAG_structure_type ] [C] {{.*}} [def]
95+
// CHECK: [[C_MEM]] = metadata !{metadata [[C_VPTR:![0-9]*]], metadata [[C_S:![0-9]*]], metadata [[C_DTOR:![0-9]*]]}
96+
// CHECK: [[C_VPTR]] = {{.*}} ; [ DW_TAG_member ] [_vptr$C] {{.*}} [artificial]
97+
// CHECK: [[C_S]] = {{.*}} ; [ DW_TAG_member ] [s] {{.*}} [static] [from int]
98+
// CHECK: [[C_DTOR]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [~C]
99+
100+
// CHECK: ; [ DW_TAG_structure_type ] [A]
101+
// CHECK: HdrSize
102+
// CHECK: metadata [[D_MEM:![0-9]*]], i32 0, null} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl]
103+
// CHECK: [[D_MEM]] = metadata !{metadata [[D_FUNC:![0-9]*]]}
104+
// CHECK: [[D_FUNC]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func]
105+
106+
// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I:![0-9]*]]} ; [ DW_TAG_variable ] [i]
107+
// CHECK: [[F_I]] = {{.*}} ; [ DW_TAG_member ] [i]
108+
// CHECK: [[F:![0-9]*]] = {{.*}} metadata [[F_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [F] {{.*}} [def]
109+
// CHECK: [[F_MEM]] = metadata !{metadata [[F_I]]}
110+
111+
// CHECK: null, i32 0, null} ; [ DW_TAG_structure_type ] [E] {{.*}} [decl]
112+
113+
// CHECK: metadata [[G_INNER_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [inner] [line 50, {{.*}} [def]
57114
// Context chains (in Clang -flimit-debug-info and in GCC generally) contain
58115
// definitions without members (& without a vbase 'containing type'):
59-
// CHECK: null, i32 0, null, null} ; [ DW_TAG_structure_type ] [C] {{.*}} [def]
60-
// CHECK: [[C_INNER_MEM]] = metadata !{metadata [[C_INNER_I:![0-9]*]]}
61-
// CHECK: [[C_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int]
62-
// CHECK: ![[EXCEPTLOC]] = metadata !{i32 40,
63-
// CHECK: ![[RETLOC]] = metadata !{i32 39,
116+
// CHECK: null, i32 0, null, null} ; [ DW_TAG_structure_type ] [G] {{.*}} [def]
117+
// CHECK: [[G_INNER_MEM]] = metadata !{metadata [[G_INNER_I:![0-9]*]]}
118+
// CHECK: [[G_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int]
119+
120+
// CHECK: ![[EXCEPTLOC]] = metadata !{i32 79,
121+
// CHECK: ![[RETLOC]] = metadata !{i32 78,

Diff for: test/CodeGenCXX/debug-info-gline-tables-only.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,17 @@ class E : public C {
1313
// CHECK-NOT: DW_TAG_reference type
1414
void x(const D& d);
1515
};
16+
struct F {
17+
enum X { };
18+
void func(X);
19+
virtual ~F();
20+
};
21+
F::~F() {
22+
}
1623
}
1724

1825
// CHECK-NOT: DW_TAG_variable
1926
NS::C c;
2027
NS::D d;
2128
NS::E e;
29+
NS::F f;

0 commit comments

Comments
 (0)