From 6943dea321c6fdbc0f7dd20b30505c17d8d4e70d Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Tue, 20 Aug 2013 01:28:15 +0000 Subject: 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. llvm-svn: 188739 --- clang/lib/CodeGen/CGDebugInfo.cpp | 115 ++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 29 deletions(-) (limited to 'clang/lib/CodeGen/CGDebugInfo.cpp') diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 2496970276c..7177fe2cc32 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -644,8 +644,24 @@ llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) { if (const RecordDecl *RD = dyn_cast(Context)) { if (!RD->isDependentType()) { - llvm::DIType Ty = getOrCreateLimitedType( - CGM.getContext().getRecordType(RD)->castAs(), getOrCreateMainFile()); + llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD))); + llvm::DICompositeType Ty(getOrCreateLimitedType( + CGM.getContext().getRecordType(RD)->castAs(), + 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 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 @@ CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl, } } -/// CollectRecordStaticField - Helper for CollectRecordFields. +/// Helper for CollectRecordFields. llvm::DIDerivedType CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType RecordTy) { @@ -948,7 +964,7 @@ void CGDebugInfo::CollectRecordFields(const RecordDecl *record, for (RecordDecl::decl_iterator I = record->decls_begin(), E = record->decls_end(); I != E; ++I) if (const VarDecl *V = dyn_cast(*I)) - elements.push_back(CreateRecordStaticField(V, RecordTy)); + elements.push_back(getOrCreateStaticDataMemberDeclaration(V, RecordTy)); else if (FieldDecl *field = dyn_cast(*I)) { CollectRecordNormalField(field, layout.getFieldOffset(fieldNo), tunit, elements, RecordTy); @@ -1123,8 +1139,14 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, if (D->isImplicit()) continue; - if (const CXXMethodDecl *Method = dyn_cast(D)) - EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); + if (const CXXMethodDecl *Method = dyn_cast(D)) { + llvm::DenseMap::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::completeType(const RecordDecl *RD) { } void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { + if (const CXXRecordDecl *CXXDecl = dyn_cast(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 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { /// CreateType - get structure or union type. llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, bool Declaration) { RecordDecl *RD = Ty->getDecl(); + const CXXRecordDecl *CXXDecl = dyn_cast(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(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 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Convert all the elements. SmallVector 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::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { llvm::DenseMap::iterator MI = SPCache.find(FD->getCanonicalDecl()); if (MI == SPCache.end()) { - if (const CXXMethodDecl *MD = dyn_cast(FD)) { + if (const CXXMethodDecl *MD = dyn_cast(FD->getCanonicalDecl())) { llvm::DICompositeType T(S); llvm::DISubprogram SP = CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T); T.addMember(SP); @@ -3025,19 +3067,35 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, 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::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(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::iterator MI = + StaticDataMemberCache.find(D->getCanonicalDecl()); + if (MI != StaticDataMemberCache.end()) { + assert(MI->second && "Static data member declaration should still exist"); + return llvm::DIDerivedType(cast(MI->second)); + } + llvm::DICompositeType Ctxt( + getContextDescriptor(cast(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::iterator MI = + StaticDataMemberCache.find(D->getCanonicalDecl()); + if (MI != StaticDataMemberCache.end()) { + assert(MI->second && "Static data member declaration should still exist"); + return llvm::DIDerivedType(cast(MI->second)); } - return llvm::DIDerivedType(); + return CreateRecordStaticField(D, Ctxt); } /// EmitGlobalVariable - Emit information about a global variable. @@ -3069,11 +3127,10 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, LinkageName = StringRef(); llvm::DIDescriptor DContext = getContextDescriptor(dyn_cast(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 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, return; llvm::DIGlobalVariable GV = DBuilder.createStaticVariable( Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init, - getStaticDataMemberDeclaration(cast(VD))); + getOrCreateStaticDataMemberDeclarationOrNull(cast(VD))); DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV))); } -- cgit v1.2.3