diff options
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 56 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.h | 1 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/debug-info-class.cpp | 19 |
3 files changed, 49 insertions, 27 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 71253caabbd..31422830f19 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1453,6 +1453,9 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { if (FwdDecl.isForwardDecl()) return FwdDecl; + if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) + CollectContainingType(CXXDecl, FwdDecl); + // Push the struct on region stack. LexicalBlockStack.push_back(&*FwdDecl); RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); @@ -2207,34 +2210,37 @@ llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) { RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl); TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl; - if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) { - // A class's primary base or the class itself contains the vtable. - llvm::DICompositeType ContainingType; - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) { - // Seek non virtual primary base root. - while (1) { - const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase); - const CXXRecordDecl *PBT = BRL.getPrimaryBase(); - if (PBT && !BRL.isPrimaryBaseVirtual()) - PBase = PBT; - else - break; - } - ContainingType = llvm::DICompositeType( - getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit)); - } else if (CXXDecl->isDynamicClass()) - ContainingType = RealDecl; - - RealDecl.setContainingType(ContainingType); - if (const ClassTemplateSpecializationDecl *TSpecial = - dyn_cast<ClassTemplateSpecializationDecl>(CXXDecl)) - RealDecl.setTypeArray(llvm::DIArray(), - CollectCXXTemplateParams(TSpecial, DefUnit)); - } + if (const ClassTemplateSpecializationDecl *TSpecial = + dyn_cast<ClassTemplateSpecializationDecl>(RD)) + RealDecl.setTypeArray(llvm::DIArray(), + CollectCXXTemplateParams(TSpecial, DefUnit)); return RealDecl; } +void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD, + llvm::DICompositeType RealDecl) { + // A class's primary base or the class itself contains the vtable. + llvm::DICompositeType ContainingType; + const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); + if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) { + // Seek non virtual primary base root. + while (1) { + const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase); + const CXXRecordDecl *PBT = BRL.getPrimaryBase(); + if (PBT && !BRL.isPrimaryBaseVirtual()) + PBase = PBT; + else + break; + } + ContainingType = llvm::DICompositeType( + getOrCreateType(QualType(PBase->getTypeForDecl(), 0), + getOrCreateFile(RD->getLocation()))); + } else if (RD->isDynamicClass()) + ContainingType = RealDecl; + + RealDecl.setContainingType(ContainingType); +} + /// CreateMemberType - Create new member and increase Offset by FType's size. llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType, StringRef Name, diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 39436e18a72..54b9267f8e4 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -117,6 +117,7 @@ class CGDebugInfo { llvm::DIType CreateType(const RecordType *Ty, bool Declaration); llvm::DIType CreateTypeDefinition(const RecordType *Ty); llvm::DIType CreateLimitedType(const RecordType *Ty); + void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType CT); llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F); llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F); llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F); diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp index df2492603e3..0a337dc05d8 100644 --- a/clang/test/CodeGenCXX/debug-info-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-class.cpp @@ -12,6 +12,14 @@ class B { public: virtual ~B(); }; + +struct C { + virtual void func(); + struct inner { + int j; + }; +}; + struct A { int one; static const int HdrSize = 52; @@ -24,6 +32,7 @@ struct A { int main(int argc, char **argv) { B b; + C::inner c_i; if (argc) { A a; } @@ -44,5 +53,11 @@ int main(int argc, char **argv) { // CHECK: HdrSize // CHECK: DW_TAG_class_type ] [B] // CHECK: metadata !"_vptr$B", {{.*}}, i32 64, metadata !{{.*}}} ; [ DW_TAG_member ] -// CHECK: ![[EXCEPTLOC]] = metadata !{i32 31, -// CHECK: ![[RETLOC]] = metadata !{i32 30, +// CHECK: metadata [[C_INNER_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [inner] {{.*}} [def] +// Context chains (in Clang -flimit-debug-info and in GCC generally) contain +// definitions without members (& without a vbase 'containing type'): +// CHECK: null, i32 0, null, null} ; [ DW_TAG_structure_type ] [C] {{.*}} [def] +// CHECK: [[C_INNER_MEM]] = metadata !{metadata [[C_INNER_I:![0-9]*]]} +// CHECK: [[C_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int] +// CHECK: ![[EXCEPTLOC]] = metadata !{i32 40, +// CHECK: ![[RETLOC]] = metadata !{i32 39, |