diff options
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 49 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.h | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 9 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/debug-info-class.cpp | 26 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/debug-info-template-member.cpp | 52 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtable-debug-info-inheritance-diamond.cpp | 87 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtable-debug-info-inheritance-multiple.cpp | 72 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp | 152 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp | 55 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtable-debug-info-inheritance-virtual.cpp | 87 | ||||
-rw-r--r-- | clang/test/Modules/ExtDebugInfo.cpp | 10 |
12 files changed, 564 insertions, 47 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index d5662b1..9a6f3b1 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2635,6 +2635,55 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + if (!CGM.getTarget().getCXXABI().isItaniumFamily()) + return; + + ASTContext &Context = CGM.getContext(); + StringRef SymbolName = "_vtable$"; + SourceLocation Loc; + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + // We deal with two different contexts: + // - The type for the variable, which is part of the class that has the + // vtable, is placed in the context of the DICompositeType metadata. + // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope. + + // The created non-member should be mark as 'artificial'. It will be + // placed inside the scope of the C++ class/structure. + llvm::DIScope *DContext = getContextDescriptor(RD, TheCU); + auto *Ctxt = cast<llvm::DICompositeType>(DContext); + llvm::DIFile *Unit = getOrCreateFile(Loc); + llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit); + llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD) | + llvm::DINode::FlagArtificial; + auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5 + ? llvm::dwarf::DW_TAG_variable + : llvm::dwarf::DW_TAG_member; + llvm::DIDerivedType *DT = DBuilder.createStaticMemberType( + Ctxt, SymbolName, Unit, /*LineNumber=*/0, VTy, Flags, + /*Val=*/nullptr, Tag); + + // Use the same vtable pointer to global alignment for the symbol. + unsigned PAlign = CGM.getVtableGlobalVarAlignment(); + + // The global variable is in the CU scope, and links back to the type it's + // "within" via the declaration field. + llvm::DIGlobalVariableExpression *GVE = + DBuilder.createGlobalVariableExpression( + TheCU, SymbolName, VTable->getName(), Unit, /*LineNo=*/0, + getOrCreateType(VoidPtr, Unit), VTable->hasLocalLinkage(), + /*isDefined=*/true, nullptr, DT, /*TemplateParameters=*/nullptr, + PAlign); + VTable->addDebugInfo(GVE); +} + StringRef CGDebugInfo::getDynamicInitializerName(const VarDecl *VD, DynamicInitKind StubKind, llvm::Function *InitFn) { diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index ec27fb0..8558817 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -669,6 +669,9 @@ public: void addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup, uint64_t Atom); + /// Emit symbol for debugger that holds the pointer to the vtable. + void emitVTableSymbol(llvm::GlobalVariable *VTable, const CXXRecordDecl *RD); + private: /// Amend \p I's DebugLoc with \p Group (its source atom group) and \p /// Rank (lower nonzero rank is higher precedence). Does nothing if \p I diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 1db5c3b..1b67d43 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1810,6 +1810,15 @@ public: return !getLangOpts().CPlusPlus; } + // Helper to get the alignment for a variable. + unsigned getVtableGlobalVarAlignment(const VarDecl *D = nullptr) { + LangAS AS = GetGlobalVarAddressSpace(D); + unsigned PAlign = getItaniumVTableContext().isRelativeLayout() + ? 32 + : getTarget().getPointerAlign(AS); + return PAlign; + } + private: bool shouldDropDLLAttribute(const Decl *D, const llvm::GlobalValue *GV) const; diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index e811474..f7e9c84 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2061,6 +2061,10 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, if (!VTable->isDSOLocal()) CGVT.GenerateRelativeVTableAlias(VTable, VTable->getName()); } + + // Emit symbol for debugger only if requested debug info. + if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) + DI->emitVTableSymbol(VTable, RD); } bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField( @@ -2166,10 +2170,7 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, // Use pointer to global alignment for the vtable. Otherwise we would align // them based on the size of the initializer which doesn't make sense as only // single values are read. - LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr); - unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout() - ? 32 - : CGM.getTarget().getPointerAlign(AS); + unsigned PAlign = CGM.getVtableGlobalVarAlignment(); VTable = CGM.CreateOrReplaceCXXRuntimeVariable( Name, VTableType, llvm::GlobalValue::ExternalLinkage, diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp index 8d610ca..0bc4fdaa 100644 --- a/clang/test/CodeGenCXX/debug-info-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-class.cpp @@ -122,14 +122,6 @@ int main(int argc, char **argv) { // CHECK-SAME: ){{$}} // CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar" -// CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz" -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} -// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", -// CHECK-SAME: DIFlagArtificial // CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK-NOT: DIFlagFwdDecl @@ -145,6 +137,20 @@ int main(int argc, char **argv) { // CHECK-SAME: DIFlagStaticMember // CHECK: [[C_DTOR]] = !DISubprogram(name: "~C" +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "K" +// CHECK-SAME: identifier: "_ZTS1K" +// CHECK-SAME: ){{$}} + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B" +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", +// CHECK-SAME: DIFlagArtificial + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar" +// CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz" + // CHECK: [[D:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "D" // CHECK-SAME: size: // CHECK-SAME: DIFlagFwdDecl @@ -156,10 +162,6 @@ int main(int argc, char **argv) { // CHECK-NOT: identifier: // CHECK-SAME: ){{$}} -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "K" -// CHECK-SAME: identifier: "_ZTS1K" -// CHECK-SAME: ){{$}} - // CHECK: [[L:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "L" // CHECK-SAME: ){{$}} // CHECK: [[L_FUNC_DECL:![0-9]*]] = !DISubprogram(name: "func",{{.*}} scope: [[L]] diff --git a/clang/test/CodeGenCXX/debug-info-template-member.cpp b/clang/test/CodeGenCXX/debug-info-template-member.cpp index 66d9ba5..bb947c2 100644 --- a/clang/test/CodeGenCXX/debug-info-template-member.cpp +++ b/clang/test/CodeGenCXX/debug-info-template-member.cpp @@ -22,29 +22,6 @@ inline int add3(int x) { // CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]], expr: !DIExpression()) // CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x", // CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]] -// -// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( -// CHECK-SAME: name: "var" -// CHECK-SAME: templateParams: {{![0-9]+}} -// CHECK: !DITemplateTypeParameter(name: "T", type: [[TY:![0-9]+]]) -// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( -// CHECK-SAME: name: "var" -// CHECK-SAME: templateParams: {{![0-9]+}} -// CHECK: !DITemplateTypeParameter(name: "T", type: {{![0-9]+}}) -// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( -// CHECK-SAME: name: "varray" -// CHECK-SAME: templateParams: {{![0-9]+}} -// CHECK: !DITemplateValueParameter(name: "N", type: [[TY]], value: i32 1) - -// CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" -// CHECK-SAME: elements: [[FOO_MEM:![0-9]*]] -// CHECK-SAME: identifier: "_ZTS3foo" -// CHECK: [[FOO_MEM]] = !{[[FOO_FUNC:![0-9]*]]} -// CHECK: [[FOO_FUNC]] = !DISubprogram(name: "func", linkageName: "_ZN3foo4funcEN5outerIS_E5innerE", -// CHECK-SAME: type: [[FOO_FUNC_TYPE:![0-9]*]] -// CHECK: [[FOO_FUNC_TYPE]] = !DISubroutineType(types: [[FOO_FUNC_PARAMS:![0-9]*]]) -// CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, ![[OUTER_FOO_INNER_ID]]} // CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass" // CHECK-SAME: elements: [[C_MEM:![0-9]*]] @@ -55,9 +32,6 @@ inline int add3(int x) { // CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 9, -// CHECK: !DISubprogram(name: "add<2>" -// CHECK-SAME: scope: [[C]] -// // CHECK: [[VIRT_TEMP:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "virt<elem>" // CHECK-SAME: elements: [[VIRT_MEM:![0-9]*]] // CHECK-SAME: vtableHolder: [[VIRT_TEMP]] @@ -74,6 +48,32 @@ inline int add3(int x) { // CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]} // CHECK: [[VIRT_T]] = !DITemplateTypeParameter(name: "T", type: [[ELEM]]) +// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( +// CHECK-SAME: name: "var" +// CHECK-SAME: templateParams: {{![0-9]+}} +// CHECK: !DITemplateTypeParameter(name: "T", type: [[TY:![0-9]+]]) +// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( +// CHECK-SAME: name: "var" +// CHECK-SAME: templateParams: {{![0-9]+}} +// CHECK: !DITemplateTypeParameter(name: "T", type: {{![0-9]+}}) +// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( +// CHECK-SAME: name: "varray" +// CHECK-SAME: templateParams: {{![0-9]+}} +// CHECK: !DITemplateValueParameter(name: "N", type: [[TY]], value: i32 1) + +// CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECK-SAME: elements: [[FOO_MEM:![0-9]*]] +// CHECK-SAME: identifier: "_ZTS3foo" +// CHECK: [[FOO_MEM]] = !{[[FOO_FUNC:![0-9]*]]} +// CHECK: [[FOO_FUNC]] = !DISubprogram(name: "func", linkageName: "_ZN3foo4funcEN5outerIS_E5innerE", +// CHECK-SAME: type: [[FOO_FUNC_TYPE:![0-9]*]] +// CHECK: [[FOO_FUNC_TYPE]] = !DISubroutineType(types: [[FOO_FUNC_PARAMS:![0-9]*]]) +// CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, ![[OUTER_FOO_INNER_ID]]} + +// CHECK: !DISubprogram(name: "add<2>" +// CHECK-SAME: scope: [[C]] + template<typename T> struct outer { struct inner { diff --git a/clang/test/CodeGenCXX/vtable-debug-info-inheritance-diamond.cpp b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-diamond.cpp new file mode 100644 index 0000000..5ed1353 --- /dev/null +++ b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-diamond.cpp @@ -0,0 +1,87 @@ +// REQUIRES: target={{x86_64.*-linux.*}} + +// Diamond inheritance case: +// For CBase, CLeft, CRight and CDerived we check: +// - Generation of their vtables (including attributes). +// - Generation of their '_vtable$' data members: +// * Correct scope and attributes + +namespace NSP { + struct CBase { + int B = 0; + virtual char fooBase() { return 'B'; } + }; +} + +namespace NSP_1 { + struct CLeft : NSP::CBase { + int M1 = 1; + char fooBase() override { return 'O'; }; + virtual int fooLeft() { return 1; } + }; +} + +namespace NSP_2 { + struct CRight : NSP::CBase { + int M2 = 2; + char fooBase() override { return 'T'; }; + virtual int fooRight() { return 2; } + }; +} + +struct CDerived : NSP_1::CLeft, NSP_2::CRight { + int D = 3; + char fooBase() override { return 'D'; }; + int fooDerived() { return 3; }; +}; + +int main() { + NSP::CBase Base; + NSP_1::CLeft Left; + NSP_2::CRight Right; + CDerived Derived; + + return 0; +} + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -S -g %s -o - | FileCheck %s + +// CHECK: $_ZTVN3NSP5CBaseE = comdat any +// CHECK: $_ZTVN5NSP_15CLeftE = comdat any +// CHECK: $_ZTVN5NSP_26CRightE = comdat any +// CHECK: $_ZTV8CDerived = comdat any + +// CHECK: @_ZTVN3NSP5CBaseE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[BASE_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTVN5NSP_15CLeftE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[LEFT_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTVN5NSP_26CRightE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[RIGHT_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTV8CDerived = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[DERIVED_VTABLE_VAR:![0-9]*]] + +// CHECK: [[BASE_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[BASE_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN3NSP5CBaseE" + +// CHECK: [[LEFT_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[LEFT_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[LEFT_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN5NSP_15CLeftE" + +// CHECK: [[TYPE:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[LEFT:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[LEFT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CLeft" + +// CHECK: [[BASE:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CBase" + +// CHECK: [[RIGHT_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[RIGHT_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[RIGHT_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN5NSP_26CRightE" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[RIGHT:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[RIGHT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CRight" + +// CHECK: [[DERIVED_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[DERIVED_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[DERIVED_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV8CDerived" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[DERIVED:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[DERIVED]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CDerived" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[BASE]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) diff --git a/clang/test/CodeGenCXX/vtable-debug-info-inheritance-multiple.cpp b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-multiple.cpp new file mode 100644 index 0000000..23973a3 --- /dev/null +++ b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-multiple.cpp @@ -0,0 +1,72 @@ +// REQUIRES: target={{x86_64.*-linux.*}} + +// Multiple inheritance case: +// For CBaseOne, CBaseTwo and CDerived we check: +// - Generation of their vtables (including attributes). +// - Generation of their '_vtable$' data members: +// * Correct scope and attributes + +namespace NSP_1 { + struct CBaseOne { + int B1 = 1; + virtual int one() { return 1; } + virtual int two() { return 2; } + virtual int three() { return 3; } + }; +} + +namespace NSP_2 { + struct CBaseTwo { + int B2 = 1; + virtual int four() { return 4; } + virtual int five() { return 5; } + virtual int six() { return 6; } + }; +} + +struct CDerived : NSP_1::CBaseOne, NSP_2::CBaseTwo { + int D = 1; + int two() override { return 22; }; + int six() override { return 66; } +}; + +int main() { + NSP_1::CBaseOne BaseOne; + NSP_2::CBaseTwo BaseTwo; + CDerived Derived; + + return 0; +} + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -S -g %s -o - | FileCheck %s + +// CHECK: $_ZTVN5NSP_18CBaseOneE = comdat any +// CHECK: $_ZTVN5NSP_28CBaseTwoE = comdat any +// CHECK: $_ZTV8CDerived = comdat any + +// CHECK: @_ZTVN5NSP_18CBaseOneE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[BASE_ONE_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTVN5NSP_28CBaseTwoE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[BASE_TWO_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTV8CDerived = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[DERIVED_VTABLE_VAR:![0-9]*]] + +// CHECK: [[BASE_ONE_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_ONE_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[BASE_ONE_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN5NSP_18CBaseOneE" + +// CHECK: [[BASE_TWO_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_TWO_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[BASE_TWO_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN5NSP_28CBaseTwoE" + +// CHECK: [[TYPE:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[BASE_TWO:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// check: [[BASE_TWO]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CBaseTwo" + +// CHECK: [[DERIVED_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[DERIVED_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK: [[DERIVED_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV8CDerived" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[DERIVED:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[DERIVED]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CDerived" + +// CHECK: [[BASE_ONE:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CBaseOne" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[BASE_ONE]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) diff --git a/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp new file mode 100644 index 0000000..d64e711 --- /dev/null +++ b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp @@ -0,0 +1,152 @@ +// REQUIRES: target={{x86_64.*-linux.*}} + +// Simple inheritance case: +// For CBase and CDerived we check: +// - Generation of their vtables (including attributes). +// - Generation of their '_vtable$' data members: +// * Correct scope and attributes + +#ifdef BASE_CODE +#define BASE_DEF +#endif + +#ifdef DERIVED_CODE +#define BASE_DEF +#define DERIVED_DEF +#endif + +#ifdef MAIN_CODE +#define BASE_DEF +#define DERIVED_DEF +#endif + +#ifdef BASE_DEF +namespace NSP { + struct CBase { + unsigned B = 1; + virtual void zero(); + virtual int one(); + virtual int two(); + virtual int three(); + }; +} +extern void fooBase(); +#endif + +#ifdef BASE_CODE +void NSP::CBase::zero() {} +int NSP::CBase::one() { return 1; } +int NSP::CBase::two() { return 2; }; +int NSP::CBase::three() { return 3; } + +#ifdef SYMBOL_AT_FILE_SCOPE +static NSP::CBase Base; +#else +void fooBase() { + NSP::CBase Base; +} +#endif +#endif + +#ifdef DERIVED_DEF +struct CDerived : NSP::CBase { + unsigned D = 2; + void zero() override; + int two() override; + int three() override; +}; +extern void fooDerived(); +#endif + +#ifdef DERIVED_CODE +void CDerived::zero() {} +int CDerived::two() { return 22; }; +int CDerived::three() { return 33; } + +#ifdef SYMBOL_AT_FILE_SCOPE +static CDerived Derived; +#else +void fooDerived() { + CDerived Derived; +} +#endif +#endif + +#ifdef MAIN_CODE +int main() { +#ifdef SYMBOL_AT_FILE_SCOPE + NSP::CBase Base; + CDerived Derived; +#else + fooBase(); + fooDerived(); +#endif + + return 0; +} +#endif + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g %s -o %t.simple-base.bc -DBASE_CODE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g %s -o %t.simple-derived.bc -DDERIVED_CODE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g %s -o %t.simple-main.bc -DMAIN_CODE +// RUN: llvm-link %t.simple-base.bc %t.simple-derived.bc %t.simple-main.bc -S -o %t.simple-combined.ll +// RUN: FileCheck --input-file=%t.simple-combined.ll -check-prefix=CHECK-ONE %s + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g -flto %s -o %t.simple-base.bc -DBASE_CODE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g -flto %s -o %t.simple-derived.bc -DDERIVED_CODE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g -flto %s -o %t.simple-main.bc -DMAIN_CODE +// RUN: llvm-link %t.simple-base.bc %t.simple-derived.bc %t.simple-main.bc -S -o %t.simple-combined.ll +// RUN: FileCheck --input-file=%t.simple-combined.ll -check-prefix=CHECK-ONE %s + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g %s -o %t.simple-base.bc -DBASE_CODE -DSYMBOL_AT_FILE_SCOPE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g %s -o %t.simple-derived.bc -DDERIVED_CODE -DSYMBOL_AT_FILE_SCOPE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g %s -o %t.simple-main.bc -DMAIN_CODE -DSYMBOL_AT_FILE_SCOPE +// RUN: llvm-link %t.simple-base.bc %t.simple-derived.bc %t.simple-main.bc -S -o %t.simple-combined.ll +// RUN: FileCheck --input-file=%t.simple-combined.ll -check-prefix=CHECK-TWO %s + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g -flto %s -o %t.simple-base.bc -DBASE_CODE -DSYMBOL_AT_FILE_SCOPE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g -flto %s -o %t.simple-derived.bc -DDERIVED_CODE -DSYMBOL_AT_FILE_SCOPE +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -c -g -flto %s -o %t.simple-main.bc -DMAIN_CODE -DSYMBOL_AT_FILE_SCOPE +// RUN: llvm-link %t.simple-base.bc %t.simple-derived.bc %t.simple-main.bc -S -o %t.simple-combined.ll +// RUN: FileCheck --input-file=%t.simple-combined.ll -check-prefix=CHECK-TWO %s + +// CHECK-ONE: ${{_ZN3NSP5CBaseC2Ev|_ZN8CDerivedC2Ev}} = comdat any +// CHECK-ONE: ${{_ZN3NSP5CBaseC2Ev|_ZN8CDerivedC2Ev}} = comdat any + +// CHECK-ONE: @_ZTV8CDerived = {{dso_local|hidden}} unnamed_addr constant {{.*}}, align 8, !dbg [[DERIVED_VTABLE_VAR:![0-9]*]] +// CHECK-ONE: @_ZTVN3NSP5CBaseE = {{dso_local|hidden}} unnamed_addr constant {{.*}}, align 8, !dbg [[BASE_VTABLE_VAR:![0-9]*]] + +// CHECK-ONE: [[DERIVED_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[DERIVED_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-ONE-NEXT: [[DERIVED_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV8CDerived" + +// CHECK-ONE: [[TYPE:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) + +// CHECK-ONE: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[DERIVED:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) +// CHECK-ONE: [[DERIVED]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CDerived" + +// CHECK-ONE: [[BASE_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-ONE-NEXT: [[BASE_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN3NSP5CBaseE" + +// CHECK-ONE: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[BASE:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) +// CHECK-ONE: [[BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CBase" + +// CHECK-TWO: ${{_ZN3NSP5CBaseC2Ev|_ZN8CDerivedC2Ev}} = comdat any +// CHECK-TWO: ${{_ZN3NSP5CBaseC2Ev|_ZN8CDerivedC2Ev}} = comdat any + +// CHECK-TWO: @_ZTVN3NSP5CBaseE = {{dso_local|hidden}} unnamed_addr constant {{.*}}, align 8, !dbg [[BASE_VTABLE_VAR:![0-9]*]] +// CHECK-TWO: @_ZTV8CDerived = {{dso_local|hidden}} unnamed_addr constant {{.*}}, align 8, !dbg [[DERIVED_VTABLE_VAR:![0-9]*]] + +// CHECK-TWO: [[BASE_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-TWO-NEXT: [[BASE_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN3NSP5CBaseE" + +// CHECK-TWO: [[TYPE:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) + +// CHECK-TWO: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[BASE:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) +// CHECK-TWO: [[BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CBase" + +// CHECK-TWO: [[DERIVED_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[DERIVED_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-TWO-NEXT: [[DERIVED_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV8CDerived" + +// CHECK-TWO: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[DERIVED:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK-TWO: [[DERIVED]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CDerived" diff --git a/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp new file mode 100644 index 0000000..249586f --- /dev/null +++ b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp @@ -0,0 +1,55 @@ +// REQUIRES: target={{x86_64.*-linux.*}} + +// Simple inheritance case: +// For CBase and CDerived we check: +// - Generation of their vtables (including attributes). +// - Generation of their '_vtable$' data members: +// * Correct scope and attributes + +namespace NSP { + struct CBase { + unsigned B = 1; + virtual void zero() {} + virtual int one() { return 1; } + virtual int two() { return 2; } + virtual int three() { return 3; } + }; +} + +struct CDerived : NSP::CBase { + unsigned D = 2; + void zero() override {} + int two() override { return 22; }; + int three() override { return 33; } +}; + +int main() { + NSP::CBase Base; + CDerived Derived; + + return 0; +} + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -S -g %s -o - | FileCheck %s + +// CHECK: $_ZTVN3NSP5CBaseE = comdat any +// CHECK: $_ZTV8CDerived = comdat any + +// CHECK: @_ZTVN3NSP5CBaseE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[BASE_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTV8CDerived = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[DERIVED_VTABLE_VAR:![0-9]*]] + +// CHECK: [[BASE_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[BASE_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN3NSP5CBaseE" + +// CHECK: [[DERIVED_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[DERIVED_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[DERIVED_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV8CDerived" + +// CHECK: [[TYPE:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[DERIVED:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[DERIVED]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CDerived" + +// CHECK: [[BASE:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CBase" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[BASE]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) diff --git a/clang/test/CodeGenCXX/vtable-debug-info-inheritance-virtual.cpp b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-virtual.cpp new file mode 100644 index 0000000..b01f156 --- /dev/null +++ b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-virtual.cpp @@ -0,0 +1,87 @@ +// REQUIRES: target={{x86_64.*-linux.*}} + +// Virtual inheritance case: +// For CBase, CLeft, CRight and CDerived we check: +// - Generation of their vtables (including attributes). +// - Generation of their '_vtable$' data members: +// * Correct scope and attributes + +namespace NSP { + struct CBase { + int B = 0; + virtual char fooBase() { return 'B'; } + }; +} + +namespace NSP_1 { + struct CLeft : virtual NSP::CBase { + int M1 = 1; + char fooBase() override { return 'O'; }; + virtual int fooLeft() { return 1; } + }; +} + +namespace NSP_2 { + struct CRight : virtual NSP::CBase { + int M2 = 2; + char fooBase() override { return 'T'; }; + virtual int fooRight() { return 2; } + }; +} + +struct CDerived : NSP_1::CLeft, NSP_2::CRight { + int D = 3; + char fooBase() override { return 'D'; }; + int fooDerived() { return 3; }; +}; + +int main() { + NSP::CBase Base; + NSP_1::CLeft Left; + NSP_2::CRight Right; + CDerived Derived; + + return 0; +} + +// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -S -g %s -o - | FileCheck %s + +// CHECK: $_ZTVN3NSP5CBaseE = comdat any +// CHECK: $_ZTVN5NSP_15CLeftE = comdat any +// CHECK: $_ZTVN5NSP_26CRightE = comdat any +// CHECK: $_ZTV8CDerived = comdat any + +// CHECK: @_ZTVN3NSP5CBaseE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[BASE_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTVN5NSP_15CLeftE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[LEFT_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTVN5NSP_26CRightE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[RIGHT_VTABLE_VAR:![0-9]*]] +// CHECK: @_ZTV8CDerived = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[DERIVED_VTABLE_VAR:![0-9]*]] + +// CHECK: [[BASE_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[BASE_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN3NSP5CBaseE" + +// CHECK: [[LEFT_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[LEFT_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[LEFT_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN5NSP_15CLeftE" + +// CHECK: [[TYPE:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[LEFT:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[LEFT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CLeft" + +// CHECK: [[BASE:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CBase" + +// CHECK: [[RIGHT_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[RIGHT_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[RIGHT_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN5NSP_26CRightE" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[RIGHT:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[RIGHT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CRight" + +// CHECK: [[DERIVED_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[DERIVED_VTABLE:![0-9]*]], expr: !DIExpression()) +// CHECK-NEXT: [[DERIVED_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTV8CDerived" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[DERIVED:![0-9]*]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) + +// CHECK: [[DERIVED]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "CDerived" + +// CHECK: !DIDerivedType(tag: DW_TAG_variable, name: "_vtable$", scope: [[BASE]], file: {{.*}}, baseType: [[TYPE]], flags: DIFlagPrivate | DIFlagArtificial | DIFlagStaticMember) diff --git a/clang/test/Modules/ExtDebugInfo.cpp b/clang/test/Modules/ExtDebugInfo.cpp index 7691653..184973b 100644 --- a/clang/test/Modules/ExtDebugInfo.cpp +++ b/clang/test/Modules/ExtDebugInfo.cpp @@ -207,6 +207,11 @@ void foo() { // CHECK: ![[GLOBAL_ANON]] = !DICompositeType(tag: DW_TAG_structure_type, // CHECK-SAME: name: "InAnonymousNamespace", {{.*}}DIFlagFwdDecl) +// There is a full definition of the type available in the module. +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Virtual", +// CHECK-SAME: DIFlagFwdDecl +// CHECK-SAME: identifier: "_ZTS7Virtual") + // CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !{{[0-9]+}}, entity: ![[STRUCT]], file: ![[CPP]], line: 50) // CHECK: !DICompileUnit( @@ -217,8 +222,3 @@ void foo() { // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A", // CHECK-SAME: DIFlagFwdDecl - -// There is a full definition of the type available in the module. -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Virtual", -// CHECK-SAME: DIFlagFwdDecl -// CHECK-SAME: identifier: "_ZTS7Virtual") |