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
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 2496970..7177fe2 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -644,8 +644,24 @@
if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
if (!RD->isDependentType()) {
- llvm::DIType Ty = getOrCreateLimitedType(
- CGM.getContext().getRecordType(RD)->castAs<RecordType>(), getOrCreateMainFile());
+ llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));
+ llvm::DICompositeType Ty(getOrCreateLimitedType(
+ CGM.getContext().getRecordType(RD)->castAs<RecordType>(),
+ getOrCreateMainFile()));
+ if (!Ty.getTypeArray().getNumElements()) {
+ if (T) {
+ llvm::DIArray PrevMem = T.getTypeArray();
+ unsigned NumElements = PrevMem.getNumElements();
+ if (NumElements == 1 && !PrevMem.getElement(0))
+ NumElements = 0;
+ SmallVector<llvm::Value *, 16> EltTys;
+ EltTys.reserve(NumElements);
+ for (unsigned i = 0; i != NumElements; ++i)
+ EltTys.push_back(PrevMem.getElement(i));
+ llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+ Ty.setTypeArray(Elements);
+ }
+ }
return llvm::DIDescriptor(Ty);
}
}
@@ -865,7 +881,7 @@
}
}
-/// CollectRecordStaticField - Helper for CollectRecordFields.
+/// Helper for CollectRecordFields.
llvm::DIDerivedType
CGDebugInfo::CreateRecordStaticField(const VarDecl *Var,
llvm::DIType RecordTy) {
@@ -948,7 +964,7 @@
for (RecordDecl::decl_iterator I = record->decls_begin(),
E = record->decls_end(); I != E; ++I)
if (const VarDecl *V = dyn_cast<VarDecl>(*I))
- elements.push_back(CreateRecordStaticField(V, RecordTy));
+ elements.push_back(getOrCreateStaticDataMemberDeclaration(V, RecordTy));
else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {
CollectRecordNormalField(field, layout.getFieldOffset(fieldNo),
tunit, elements, RecordTy);
@@ -1123,8 +1139,14 @@
if (D->isImplicit())
continue;
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator MI =
+ SPCache.find(Method->getCanonicalDecl());
+ if (MI == SPCache.end())
+ EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
+ else
+ EltTys.push_back(MI->second);
+ }
}
}
@@ -1408,10 +1430,20 @@
}
void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
+ if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
+ if (CXXDecl->isDynamicClass())
+ return;
+
QualType Ty = CGM.getContext().getRecordType(RD);
llvm::DIType T = getTypeOrNull(Ty);
- if (!T || !T.isForwardDecl())
+ if (T && T.isForwardDecl())
+ completeClassData(RD);
+}
+
+void CGDebugInfo::completeClassData(const RecordDecl *RD) {
+ if (DebugKind <= CodeGenOptions::DebugLineTablesOnly)
return;
+ QualType Ty = CGM.getContext().getRecordType(RD);
void* TyPtr = Ty.getAsOpaquePtr();
if (CompletedTypeCache.count(TyPtr))
return;
@@ -1424,14 +1456,23 @@
/// CreateType - get structure or union type.
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, bool Declaration) {
RecordDecl *RD = Ty->getDecl();
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
// Limited debug info should only remove struct definitions that can
// safely be replaced by a forward declaration in the source code.
- if (DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration &&
- !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) {
+ if ((DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration &&
+ !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
+ (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())) {
llvm::DIDescriptor FDContext =
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
llvm::DIType RetTy = getOrCreateRecordFwdDecl(RD, FDContext);
- return RetTy;
+ // FIXME: This is conservatively correct. If we return a non-forward decl
+ // that's not a full definition (such as those created by
+ // createContextChain) then getOrCreateType will record is as a complete
+ // type and we'll never record all its members. But this means we're
+ // emitting full debug info in TUs where GCC successfully emits a partial
+ // definition of the type.
+ if (RetTy.isForwardDecl())
+ return RetTy;
}
return CreateTypeDefinition(Ty);
@@ -1469,6 +1510,7 @@
// Convert all the elements.
SmallVector<llvm::Value *, 16> EltTys;
+ // what about nested types?
// Note: The split of CXXDecl information here is intentional, the
// gdb tests will depend on a certain ordering at printout. The debug
@@ -2310,7 +2352,7 @@
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
MI = SPCache.find(FD->getCanonicalDecl());
if (MI == SPCache.end()) {
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {
llvm::DICompositeType T(S);
llvm::DISubprogram SP = CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T);
T.addMember(SP);
@@ -3025,19 +3067,35 @@
DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
}
-/// getStaticDataMemberDeclaration - If D is an out-of-class definition of
-/// a static data member of a class, find its corresponding in-class
-/// declaration.
-llvm::DIDerivedType CGDebugInfo::getStaticDataMemberDeclaration(const VarDecl *D) {
- if (D->isStaticDataMember()) {
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
- MI = StaticDataMemberCache.find(D->getCanonicalDecl());
- if (MI != StaticDataMemberCache.end())
- // Verify the info still exists.
- if (llvm::Value *V = MI->second)
- return llvm::DIDerivedType(cast<llvm::MDNode>(V));
+/// If D is an out-of-class definition of a static data member of a class, find
+/// its corresponding in-class declaration.
+llvm::DIDerivedType
+CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
+ if (!D->isStaticDataMember())
+ return llvm::DIDerivedType();
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
+ StaticDataMemberCache.find(D->getCanonicalDecl());
+ if (MI != StaticDataMemberCache.end()) {
+ assert(MI->second && "Static data member declaration should still exist");
+ return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
}
- return llvm::DIDerivedType();
+ llvm::DICompositeType Ctxt(
+ getContextDescriptor(cast<Decl>(D->getDeclContext())));
+ llvm::DIDerivedType T = CreateRecordStaticField(D, Ctxt);
+ Ctxt.addMember(T);
+ return T;
+}
+
+llvm::DIDerivedType
+CGDebugInfo::getOrCreateStaticDataMemberDeclaration(const VarDecl *D,
+ llvm::DICompositeType Ctxt) {
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
+ StaticDataMemberCache.find(D->getCanonicalDecl());
+ if (MI != StaticDataMemberCache.end()) {
+ assert(MI->second && "Static data member declaration should still exist");
+ return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
+ }
+ return CreateRecordStaticField(D, Ctxt);
}
/// EmitGlobalVariable - Emit information about a global variable.
@@ -3069,11 +3127,10 @@
LinkageName = StringRef();
llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- llvm::DIGlobalVariable GV =
- DBuilder.createStaticVariable(DContext, DeclName, LinkageName, Unit,
- LineNo, getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var,
- getStaticDataMemberDeclaration(D));
+ llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
+ DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var,
+ getOrCreateStaticDataMemberDeclarationOrNull(D));
DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV)));
}
@@ -3121,7 +3178,7 @@
return;
llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init,
- getStaticDataMemberDeclaration(cast<VarDecl>(VD)));
+ getOrCreateStaticDataMemberDeclarationOrNull(cast<VarDecl>(VD)));
DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV)));
}