diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 101 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.h | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 3 |
3 files changed, 84 insertions, 33 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index d1ee2f60c8e..f7ea474daa6 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -865,7 +865,7 @@ CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl, } } -/// CollectRecordStaticField - Helper for CollectRecordFields. +/// Helper for CollectRecordFields. llvm::DIDerivedType CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType RecordTy) { @@ -951,7 +951,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); @@ -1122,8 +1122,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 +1414,18 @@ 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()) - return; + if (T && T.isForwardDecl()) + completeClassData(RD); +} + +void CGDebugInfo::completeClassData(const RecordDecl *RD) { + QualType Ty = CGM.getContext().getRecordType(RD); void* TyPtr = Ty.getAsOpaquePtr(); if (CompletedTypeCache.count(TyPtr)) return; @@ -1424,14 +1438,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); @@ -1466,6 +1489,13 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Convert all the elements. SmallVector<llvm::Value *, 16> EltTys; + llvm::DIArray PrevMem = FwdDecl.getTypeArray(); + unsigned NumElements = PrevMem.getNumElements(); + if (NumElements == 1 && !PrevMem.getElement(0)) + NumElements = 0; + EltTys.reserve(NumElements); + for (unsigned i = 0; i != NumElements; ++i) + EltTys.push_back(PrevMem.getElement(i)); // Note: The split of CXXDecl information here is intentional, the // gdb tests will depend on a certain ordering at printout. The debug @@ -2291,7 +2321,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); @@ -2997,19 +3027,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. @@ -3041,11 +3087,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))); } @@ -3093,7 +3138,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))); } diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 39436e18a72..51a937bfced 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -290,7 +290,7 @@ public: void completeType(const RecordDecl *RD); void completeRequiredType(const RecordDecl *RD); - + void completeClassData(const RecordDecl *RD); private: /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. @@ -353,10 +353,13 @@ private: /// declaration for the given method definition. llvm::DISubprogram getFunctionDeclaration(const Decl *D); - /// getStaticDataMemberDeclaration - Return debug info descriptor to - /// describe in-class static data member declaration for the given - /// out-of-class definition. - llvm::DIDerivedType getStaticDataMemberDeclaration(const VarDecl *D); + /// Return debug info descriptor to describe in-class static data member + /// declaration for the given out-of-class definition. + llvm::DIDerivedType + getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D); + llvm::DIDerivedType + getOrCreateStaticDataMemberDeclaration(const VarDecl *D, + llvm::DICompositeType Ctxt); /// getFunctionName - Get function name for the given FunctionDecl. If the /// name is constructred on demand (e.g. C++ destructor) then the name diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index c7bb54e0699..6649578fc09 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -828,6 +828,9 @@ CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { VFTContext->getVFPtrOffsets(RD); } + if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) + DI->completeClassData(RD); + // First off, check whether we've already emitted the v-table and // associated stuff. llvm::GlobalVariable *VTable = GetAddrOfVTable(RD); |