diff options
Diffstat (limited to 'clang/lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 115 |
1 files changed, 86 insertions, 29 deletions
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<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 @@ 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<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 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, 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::completeType(const RecordDecl *RD) { } 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 @@ 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<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 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // 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::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { 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 @@ 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<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)); + } + 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 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<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 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, 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))); } |