diff options
Diffstat (limited to 'clang/test')
8 files changed, 195 insertions, 76 deletions
diff --git a/clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp new file mode 100644 index 00000000000..92db9a789b3 --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s + +struct A { + constexpr A(int x) : x(x) {} + virtual void f(); + int x; +}; + +A a(42); +// CHECK: @"\01?a@@3UA@@A" = global { [1 x i8*]*, i32 } { [1 x i8*]* @"\01??_7A@@6B@", i32 42 }, align 4 + +struct B { + constexpr B(int y) : y(y) {} + virtual void g(); + int y; +}; + +struct C : A, B { + constexpr C() : A(777), B(13) {} +}; + +C c; +// CHECK: @"\01?c@@3UC@@A" = global { [1 x i8*]*, i32, [1 x i8*]*, i32 } { [1 x i8*]* @"\01??_7C@@6BA@@@", i32 777, [1 x i8*]* @"\01??_7C@@6BB@@@", i32 13 } diff --git a/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp index 9059e6f028b..fc59e1751fd 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp @@ -145,3 +145,39 @@ void call_grandchild_right(GrandchildOverride *obj) { // Just make sure we don't crash. obj->right(); } + +void emit_ctors() { + Left l; + // CHECK: define {{.*}} @"\01??0Left@@QAE@XZ" + // CHECK-NOT: getelementptr + // CHECK: store [1 x i8*]* @"\01??_7Left@@6B@" + // CHECK: ret + + Right r; + // CHECK: define {{.*}} @"\01??0Right@@QAE@XZ" + // CHECK-NOT: getelementptr + // CHECK: store [1 x i8*]* @"\01??_7Right@@6B@" + // CHECK: ret + + ChildOverride co; + // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ" + // CHECK: %[[THIS:.*]] = load %struct.ChildOverride** + // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %this1 to [1 x i8*]** + // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8* + // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4 + // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]** + // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: ret + + GrandchildOverride gc; + // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ" + // CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride** + // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %this1 to [1 x i8*]** + // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8* + // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4 + // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]** + // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: ret +} diff --git a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp index f9d65f44f27..2c831ca2d46 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -71,8 +71,8 @@ void C::foo() {} void check_vftable_offset() { C c; // The vftable pointer should point at the beginning of the vftable. -// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i8*** -// CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7C@basic@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]] +// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to [2 x i8*]** +// CHECK: store [2 x i8*]* @"\01??_7C@basic@@6B@", [2 x i8*]** [[THIS_PTR]] } void call_complete_dtor(C *obj_ptr) { @@ -161,7 +161,8 @@ C::C() { // CHECK-NEXT: br label %[[SKIP_VBASES]] // // CHECK: [[SKIP_VBASES]] - // CHECK: @"\01??_7C@constructors@@6B@" + // Class C does not define or override methods, so shouldn't change the vfptr. + // CHECK-NOT: @"\01??_7C@constructors@@6B@" // CHECK: ret } diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index ecbb8433797..064a3ffda91 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -7,10 +7,26 @@ struct VBase { }; struct B : virtual VBase { + B(); virtual void foo(); virtual void bar(); }; +B::B() { + // CHECK: @"\01??0B@@QAE@XZ" + // CHECK: %[[THIS:.*]] = load %struct.B** + // CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] + // CHECK: %[[SKIP_VBASES]] + // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* + // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0 + // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* + // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}} + // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [2 x i8*]** + // CHECK: store [2 x i8*]* @"\01??_7B@@6B@", [2 x i8*]** %[[VFPTR]] + // FIXME: Should initialize the vtorDisp here. + // CHECK: ret +} + void B::foo() { // CHECK: define x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8* // diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp index bd0666b7d6b..a0436c8e810 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp @@ -19,6 +19,8 @@ // RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t // RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t +// RUN: FileCheck --check-prefix=MANGLING %s < %t + struct Empty { // Doesn't have a vftable! }; @@ -51,6 +53,9 @@ struct Test1: A, B { // NO-THUNKS-Test1: VFTable indices for 'no_thunks::Test1' (1 entries) // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f() + // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BA@@@" + // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BB@@@" + // Overrides only the left child's method (A::f), needs no thunks. virtual void f(); }; @@ -102,6 +107,8 @@ struct Test4 : Empty, A { // NO-THUNKS-Test4: VFTable indices for 'no_thunks::Test4' (1 entries). // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f() + // MANGLING-DAG: @"\01??_7Test4@no_thunks@@6B@" + virtual void f(); }; @@ -127,6 +134,11 @@ struct Test5: Test1, Test2 { // NO-THUNKS-Test5: VFTable indices for 'no_thunks::Test5' (1 entries). // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z() + // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test1@1@@" + // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test2@1@@" + // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test1@1@@" + // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test2@1@@" + virtual void z(); }; @@ -143,6 +155,9 @@ struct Test6: Test1 { // NO-THUNKS-Test6: VFTable indices for 'no_thunks::Test6' (1 entries). // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f() + // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BA@@@" + // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BB@@@" + // Overrides both no_thunks::Test1::f and A::f. virtual void f(); }; @@ -203,6 +218,9 @@ struct Test9: A, D { // NO-THUNKS-Test9: VFTable indices for 'no_thunks::Test9' (1 entries). // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h() + // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BA@@@" + // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BD@1@@" + virtual void h(); }; @@ -228,6 +246,9 @@ struct Test1: A, D { // PURE-VIRTUAL-Test1-NEXT: via vfptr at offset 4 // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g() + // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BA@@@" + // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BD@1@@" + // Overrides only the right child's method (pure_virtual::D::g), needs this adjustment but // not thunks. virtual void g(); @@ -254,6 +275,9 @@ struct Test1 : B, C { // THIS-THUNKS-Test1: VFTable indices for 'this_adjustment::Test1' (1 entries). // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g() + // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BB@@@" + // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BC@@@" + virtual void g(); }; @@ -278,6 +302,10 @@ struct Test2 : A, B, C { // THIS-THUNKS-Test2-NEXT: via vfptr at offset 4 // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g() + // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BA@@@" + // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BB@@@" + // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BC@@@" + virtual void g(); }; @@ -337,6 +365,8 @@ struct Test1 : Ret1 { // RET-THUNKS-Test1: VFTable indices for 'return_adjustment::Test1' (1 entries). // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test1::foo() + // MANGLING-DAG: @"\01??_7Test1@return_adjustment@@6B@" + virtual this_adjustment::Test1* foo(); }; diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp index 9a065d4c02f..82e8f1c516c 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o - > %t 2>&1 -// RUN: FileCheck --check-prefix=EMITS-VTABLE %s < %t -// RUN: FileCheck --check-prefix=NO-VTABLE %s < %t +// RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t +// RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t // RUN: FileCheck --check-prefix=CHECK-A %s < %t // RUN: FileCheck --check-prefix=CHECK-B %s < %t // RUN: FileCheck --check-prefix=CHECK-C %s < %t @@ -10,19 +10,12 @@ // RUN: FileCheck --check-prefix=CHECK-G %s < %t // RUN: FileCheck --check-prefix=CHECK-I %s < %t -// FIXME: Currently, we only test VFTableContext in the AST, but still use -// VTableContext for CodeGen. We should remove the "Vtable" checks below when we -// completely switch from VTableContext to VFTableContext. -// Currently, the order of Vtable vs VFTable output depends on whether the -// v*table info was required by a constructor or a method definition. - struct A { // CHECK-A: VFTable for 'A' (3 entries) // CHECK-A-NEXT: 0 | void A::f() // CHECK-A-NEXT: 1 | void A::g() // CHECK-A-NEXT: 2 | void A::h() - - // CHECK-A: Vtable for 'A' (3 entries) + // CHECK-A: VFTable indices for 'A' (3 entries) // CHECK-A-NEXT: 0 | void A::f() // CHECK-A-NEXT: 1 | void A::g() // CHECK-A-NEXT: 2 | void A::h() @@ -33,20 +26,17 @@ struct A { int ia; }; A a; -// EMITS-VTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] struct B : A { - // CHECK-B: Vtable for 'B' (5 entries) + // CHECK-B: VFTable for 'A' in 'B' (5 entries) // CHECK-B-NEXT: 0 | void B::f() // CHECK-B-NEXT: 1 | void A::g() // CHECK-B-NEXT: 2 | void A::h() // CHECK-B-NEXT: 3 | void B::i() // CHECK-B-NEXT: 4 | void B::j() - - // CHECK-B: VFTable for 'A' in 'B' (5 entries) + // CHECK-B: VFTable indices for 'B' (3 entries) // CHECK-B-NEXT: 0 | void B::f() - // CHECK-B-NEXT: 1 | void A::g() - // CHECK-B-NEXT: 2 | void A::h() // CHECK-B-NEXT: 3 | void B::i() // CHECK-B-NEXT: 4 | void B::j() @@ -55,7 +45,7 @@ struct B : A { virtual void j(); }; B b; -// EMITS-VTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] struct C { // CHECK-C: VFTable for 'C' (2 entries) @@ -65,25 +55,17 @@ struct C { // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] // CHECK-C-NEXT: 1 | void C::f() - // CHECK-C: Vtable for 'C' (2 entries) - // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] - // CHECK-C-NEXT: 1 | void C::f() - // CHECK-C: VTable indices for 'C' (2 entries). - // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] - // CHECK-C-NEXT: 1 | void C::f() - virtual ~C(); virtual void f(); }; void C::f() {} -// NO-VTABLE-NOT: @"\01??_7C@@6B@" +// NO-VFTABLE-NOT: @"\01??_7C@@6B@" struct D { - // CHECK-D: Vtable for 'D' (2 entries) + // CHECK-D: VFTable for 'D' (2 entries) // CHECK-D-NEXT: 0 | void D::f() // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] - - // CHECK-D: VFTable for 'D' (2 entries) + // CHECK-D: VFTable indices for 'D' (2 entries) // CHECK-D-NEXT: 0 | void D::f() // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] @@ -91,7 +73,7 @@ struct D { virtual ~D(); }; D d; -// EMITS-VTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] struct E : A { // CHECK-E: VFTable for 'A' in 'E' (5 entries) @@ -104,35 +86,15 @@ struct E : A { // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] // CHECK-E-NEXT: 4 | void E::i() - // CHECK-E: Vtable for 'E' (5 entries) - // CHECK-E-NEXT: 0 | void A::f() - // CHECK-E-NEXT: 1 | void A::g() - // CHECK-E-NEXT: 2 | void A::h() - // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] - // CHECK-E-NEXT: 4 | void E::i() - // CHECK-E: VTable indices for 'E' (2 entries). - // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] - // CHECK-E-NEXT: 4 | void E::i() - // ~E would be the key method, but it isn't used, and MS ABI has no key // methods. virtual ~E(); virtual void i(); }; void E::i() {} -// NO-VTABLE-NOT: @"\01??_7E@@6B@" +// NO-VFTABLE-NOT: @"\01??_7E@@6B@" struct F : A { - // CHECK-F: Vtable for 'F' (5 entries) - // CHECK-F-NEXT: 0 | void A::f() - // CHECK-F-NEXT: 1 | void A::g() - // CHECK-F-NEXT: 2 | void A::h() - // CHECK-F-NEXT: 3 | void F::i() - // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] - // CHECK-F: VTable indices for 'F' (2 entries). - // CHECK-F-NEXT: 3 | void F::i() - // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] - // CHECK-F: VFTable for 'A' in 'F' (5 entries) // CHECK-F-NEXT: 0 | void A::f() // CHECK-F-NEXT: 1 | void A::g() @@ -147,7 +109,7 @@ struct F : A { virtual ~F(); }; F f; -// EMITS-VTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] struct G : E { // CHECK-G: VFTable for 'A' in 'E' in 'G' (6 entries) @@ -162,31 +124,19 @@ struct G : E { // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] // CHECK-G-NEXT: 5 | void G::j() - // CHECK-G: Vtable for 'G' (6 entries) - // CHECK-G-NEXT: 0 | void G::f() - // CHECK-G-NEXT: 1 | void A::g() - // CHECK-G-NEXT: 2 | void A::h() - // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] - // CHECK-G-NEXT: 4 | void E::i() - // CHECK-G-NEXT: 5 | void G::j() - // CHECK-G: VTable indices for 'G' (3 entries). - // CHECK-G-NEXT: 0 | void G::f() - // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] - // CHECK-G-NEXT: 5 | void G::j() - virtual void f(); // overrides A::f() virtual ~G(); virtual void j(); }; void G::j() {} -// NO-VTABLE-NOT: @"\01??_7G@@6B@" +// NO-VFTABLE-NOT: @"\01??_7G@@6B@" // Test that the usual Itanium-style key method does not emit a vtable. struct H { virtual void f(); }; void H::f() {} -// NO-VTABLE-NOT: @"\01??_7H@@6B@" +// NO-VFTABLE-NOT: @"\01??_7H@@6B@" struct Empty { }; diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index cf9e4c012c5..24872609d52 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -18,6 +18,8 @@ // RUN: FileCheck --check-prefix=RET-W %s < %t // RUN: FileCheck --check-prefix=RET-T %s < %t +// RUN: FileCheck --check-prefix=MANGLING %s < %t + struct Empty { }; struct A { @@ -38,6 +40,8 @@ struct C: virtual A { // VTABLE-C-NEXT: vbtable index 1, vfptr at offset 0 // VTABLE-C-NEXT: 0 | void C::f() + // MANGLING-DAG: @"\01??_7C@@6B@" + ~C(); // Currently required to have correct record layout, see PR16406 virtual void f(); }; @@ -58,6 +62,9 @@ struct D: virtual A { // VTABLE-D-NEXT: via vbtable index 1, vfptr at offset 0 // VTABLE-D-NEXT: 0 | void D::f() + // MANGLING-DAG: @"\01??_7D@@6B0@@" + // MANGLING-DAG: @"\01??_7D@@6BA@@@" + virtual void f(); virtual void h(); }; @@ -71,6 +78,7 @@ struct X { int x; }; // X and A get reordered in the layout since X doesn't have a vfptr while A has. struct Y : X, A { }; +// MANGLING-DAG: @"\01??_7Y@Test1@@6B@" struct Z : virtual Y { // TEST1: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries). @@ -78,6 +86,8 @@ struct Z : virtual Y { // TEST1-NEXT: 1 | void A::z() // TEST1-NOT: VFTable indices for 'Test1::Z' + + // MANGLING-DAG: @"\01??_7Z@Test1@@6B@" }; Z z; @@ -99,6 +109,10 @@ struct X: virtual A, virtual B { // TEST2: VFTable indices for 'Test2::X' (1 entries). // TEST2-NEXT: 0 | void Test2::X::h() + // MANGLING-DAG: @"\01??_7X@Test2@@6B01@@" + // MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@" + // MANGLING-DAG: @"\01??_7X@Test2@@6BB@@@" + virtual void h(); }; @@ -107,7 +121,9 @@ X x; namespace Test3 { -struct X : virtual A { }; +struct X : virtual A { + // MANGLING-DAG: @"\01??_7X@Test3@@6B@" +}; struct Y: virtual X { // TEST3: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries). @@ -115,6 +131,8 @@ struct Y: virtual X { // TEST3-NEXT: 1 | void A::z() // TEST3-NOT: VFTable indices for 'Test3::Y' + + // MANGLING-DAG: @"\01??_7Y@Test3@@6B@" }; Y y; @@ -134,6 +152,8 @@ struct X: virtual C { // TEST4-NEXT: 1 | void A::z() // TEST4-NOT: VFTable indices for 'Test4::X' + + // MANGLING-DAG: @"\01??_7X@Test4@@6B@" }; X x; @@ -143,6 +163,7 @@ namespace Test5 { // New methods are added to the base's vftable. struct X : A { + // MANGLING-DAG: @"\01??_7X@Test5@@6B@" virtual void g(); }; @@ -158,6 +179,9 @@ struct Y : virtual X { // TEST5: VFTable indices for 'Test5::Y' (1 entries). // TEST5-NEXT: 0 | void Test5::Y::h() + // MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@" + // MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@" + virtual void h(); }; @@ -172,6 +196,8 @@ struct X : A, virtual Empty { // TEST6-NEXT: 1 | void A::z() // TEST6-NOT: VFTable indices for 'Test6::X' + + // MANGLING-DAG: @"\01??_7X@Test6@@6B@" }; X x; @@ -179,7 +205,9 @@ X x; namespace Test7 { -struct X : C { }; +struct X : C { + // MANGLING-DAG: @"\01??_7X@Test7@@6B@" +}; struct Y : virtual X { // TEST7: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries). @@ -191,6 +219,8 @@ struct Y : virtual X { // TEST7-NEXT: 0 | this adjustment: 12 non-virtual // TEST7-NOT: VFTable indices for 'Test7::Y' + + // MANGLING-DAG: @"\01??_7Y@Test7@@6B@" }; Y y; @@ -210,6 +240,9 @@ struct X : D, C { // TEST8: VFTable indices for 'Test8::X' (1 entries). // TEST8-NEXT: via vbtable index 1, vfptr at offset 0 + // MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@" + // MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@" + virtual void f(); }; @@ -231,6 +264,9 @@ struct Y : virtual X { // TEST9-Y: VFTable indices for 'Test9::Y' (1 entries). // TEST9-Y-NEXT: 0 | void Test9::Y::h() + // MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@" + // MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@" + virtual void h(); }; @@ -248,6 +284,13 @@ struct Z : Y, virtual B { // TEST9-Z-NEXT: 0 | void B::g() // TEST9-Z-NOT: VFTable indices for 'Test9::Z' + + // MANGLING-DAG: @"\01??_7Z@Test9@@6BX@1@@" + // MANGLING-DAG: @"\01??_7Z@Test9@@6BY@1@@" + + // FIXME this one is wrong: + // INCORRECT MANGLING-DAG: @"\01??_7Z@Test9@@6BB@@@" + // MANGLING-DAG-SHOULD-BE: @"\01??_7Z@Test9@@6B@" }; Z z; @@ -275,6 +318,16 @@ struct W : Z, D, virtual A, virtual B { // TEST9-W-NEXT: 0 | this adjustment: -8 non-virtual // TEST9-W-NOT: VFTable indices for 'Test9::W' + + // MANGLING-DAG: @"\01??_7W@Test9@@6BA@@@" + // MANGLING-DAG: @"\01??_7W@Test9@@6BD@@@" + // MANGLING-DAG: @"\01??_7W@Test9@@6BX@1@@" + + // FIXME: these two are wrong: + // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BB@@@" + // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6B@" + // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@Z@1@@" + // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6BY@1@@" }; W w; @@ -320,6 +373,16 @@ struct T : Z, D, virtual A, virtual B { // TEST9-T-NEXT: via vbtable index 2, vfptr at offset 0 // TEST9-T-NEXT: 0 | void Test9::T::g() + // MANGLING-DAG: @"\01??_7T@Test9@@6BA@@@" + // MANGLING-DAG: @"\01??_7T@Test9@@6BD@@@" + // MANGLING-DAG: @"\01??_7T@Test9@@6BX@1@@" + + // FIXME: these two are wrong: + // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BB@@@" + // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6B@" + // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@Z@1@@" + // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6BY@1@@" + virtual void f(); virtual void g(); virtual void h(); diff --git a/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp b/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp index a8d4520b5eb..5014eaf2643 100644 --- a/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -27,12 +27,6 @@ int main() { // CHECK: call {{.*}} @_ZN13basic_istreamIcED2Ev // CHECK: } -// basic_iostream's deleting dtor calls its complete dtor, then -// operator delete(). -// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this) unnamed_addr -// CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev -// CHECK: call {{.*}} @_ZdlPv - // basic_istream's complete dtor calls the base dtor, // then its virtual base's base dtor. // CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* {{.*}}%this) unnamed_addr @@ -45,6 +39,12 @@ int main() { // CHECK: call {{.*}} @_ZN13basic_istreamIcED1Ev // CHECK: call {{.*}} @_ZdlPv +// basic_iostream's deleting dtor calls its complete dtor, then +// operator delete(). +// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this) unnamed_addr +// CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev +// CHECK: call {{.*}} @_ZdlPv + // basic_istream's base dtor is a no-op. // CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* {{.*}}%this, i8** %vtt) unnamed_addr // CHECK-NOT: call |

