r204567 - Simplify test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp by forcing VFTableBuilder invocation with virtual function calls or constructors codegen

Timur Iskhodzhanov timurrrr at google.com
Sun Mar 23 12:09:08 PDT 2014


Author: timurrrr
Date: Sun Mar 23 14:09:08 2014
New Revision: 204567

URL: http://llvm.org/viewvc/llvm-project?rev=204567&view=rev
Log:
Simplify test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp by forcing VFTableBuilder invocation with virtual function calls or constructors codegen

Previously the vftables were built at the end of the TU in a reverse-to-random order

Modified:
    cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp?rev=204567&r1=204566&r2=204567&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp Sun Mar 23 14:09:08 2014
@@ -1,31 +1,5 @@
 // RUN: %clang_cc1 -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -triple=i386-pc-win32 >%t
-
-// RUN: FileCheck --check-prefix=VTABLE-C %s < %t
-// RUN: FileCheck --check-prefix=VTABLE-D %s < %t
-// RUN: FileCheck --check-prefix=TEST1 %s < %t
-// RUN: FileCheck --check-prefix=TEST2 %s < %t
-// RUN: FileCheck --check-prefix=TEST3 %s < %t
-// RUN: FileCheck --check-prefix=TEST4 %s < %t
-// RUN: FileCheck --check-prefix=TEST5 %s < %t
-// RUN: FileCheck --check-prefix=TEST6 %s < %t
-// RUN: FileCheck --check-prefix=TEST7 %s < %t
-// RUN: FileCheck --check-prefix=TEST8-X %s < %t
-// RUN: FileCheck --check-prefix=TEST8-Z %s < %t
-// RUN: FileCheck --check-prefix=TEST8-T %s < %t
-// RUN: FileCheck --check-prefix=TEST9-Y %s < %t
-// RUN: FileCheck --check-prefix=TEST9-Z %s < %t
-// RUN: FileCheck --check-prefix=TEST9-W %s < %t
-// RUN: FileCheck --check-prefix=TEST9-T %s < %t
-// RUN: FileCheck --check-prefix=TEST10 %s < %t
-// RUN: FileCheck --check-prefix=VDTORS-Y %s < %t
-// RUN: FileCheck --check-prefix=VDTORS-U %s < %t
-// RUN: FileCheck --check-prefix=VDTORS-V %s < %t
-// RUN: FileCheck --check-prefix=VDTORS-P %s < %t
-// RUN: FileCheck --check-prefix=VDTORS-R %s < %t
-// RUN: FileCheck --check-prefix=RET-W %s < %t
-// RUN: FileCheck --check-prefix=RET-T %s < %t
-// RUN: FileCheck --check-prefix=RET-V %s < %t
-
+// RUN: FileCheck %s < %t
 // RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
 
 struct Empty { };
@@ -40,13 +14,13 @@ struct B {
 };
 
 struct C: virtual A {
-  // VTABLE-C: VFTable for 'A' in 'C' (2 entries)
-  // VTABLE-C-NEXT: 0 | void C::f()
-  // VTABLE-C-NEXT: 1 | void A::z()
-
-  // VTABLE-C: VFTable indices for 'C' (1 entry)
-  // VTABLE-C-NEXT: vbtable index 1, vfptr at offset 0
-  // VTABLE-C-NEXT: 0 | void C::f()
+  // CHECK-LABEL: VFTable for 'A' in 'C' (2 entries)
+  // CHECK-NEXT: 0 | void C::f()
+  // CHECK-NEXT: 1 | void A::z()
+
+  // CHECK-LABEL: VFTable indices for 'C' (1 entry)
+  // CHECK-NEXT: vbtable index 1, vfptr at offset 0
+  // CHECK-NEXT: 0 | void C::f()
 
   // MANGLING-DAG: @"\01??_7C@@6B@"
 
@@ -54,20 +28,21 @@ struct C: virtual A {
 };
 
 C c;
+void use(C *obj) { obj->f(); }
 
 struct D: virtual A {
-  // VTABLE-D: VFTable for 'D' (1 entry).
-  // VTABLE-D-NEXT: 0 | void D::h()
+  // CHECK-LABEL: VFTable for 'D' (1 entry).
+  // CHECK-NEXT: 0 | void D::h()
 
-  // VTABLE-D: VFTable for 'A' in 'D' (2 entries).
-  // VTABLE-D-NEXT: 0 | void D::f()
-  // VTABLE-D-NEXT: 1 | void A::z()
-
-  // VTABLE-D: VFTable indices for 'D' (2 entries).
-  // VTABLE-D-NEXT: via vfptr at offset 0
-  // VTABLE-D-NEXT: 0 | void D::h()
-  // VTABLE-D-NEXT: via vbtable index 1, vfptr at offset 0
-  // VTABLE-D-NEXT: 0 | void D::f()
+  // CHECK-LABEL: VFTable for 'A' in 'D' (2 entries).
+  // CHECK-NEXT: 0 | void D::f()
+  // CHECK-NEXT: 1 | void A::z()
+
+  // CHECK-LABEL: VFTable indices for 'D' (2 entries).
+  // CHECK-NEXT: via vfptr at offset 0
+  // CHECK-NEXT: 0 | void D::h()
+  // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+  // CHECK-NEXT: 0 | void D::f()
 
   // MANGLING-DAG: @"\01??_7D@@6B0@@"
   // MANGLING-DAG: @"\01??_7D@@6BA@@@"
@@ -76,8 +51,8 @@ struct D: virtual A {
   virtual void h();
 };
 
-void D::h() {}
 D d;
+void use(D *obj) { obj->h(); }
 
 namespace Test1 {
 
@@ -88,33 +63,34 @@ struct Y : X, A { };
 // MANGLING-DAG: @"\01??_7Y at Test1@@6B@"
 
 struct Z : virtual Y {
-  // TEST1: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries).
-  // TEST1-NEXT: 0 | void A::f()
-  // TEST1-NEXT: 1 | void A::z()
+  Z();
+  // CHECK-LABEL: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST1-NOT: VFTable indices for 'Test1::Z'
+  // CHECK-NOT: VFTable indices for 'Test1::Z'
 
   // MANGLING-DAG: @"\01??_7Z at Test1@@6B@"
 };
 
-Z z;
+Z::Z() {}
 }
 
 namespace Test2 {
 
 struct X: virtual A, virtual B {
-  // TEST2: VFTable for 'Test2::X' (1 entry).
-  // TEST2-NEXT: 0 | void Test2::X::h()
+  // CHECK-LABEL: VFTable for 'Test2::X' (1 entry).
+  // CHECK-NEXT: 0 | void Test2::X::h()
 
-  // TEST2: VFTable for 'A' in 'Test2::X' (2 entries).
-  // TEST2-NEXT: 0 | void A::f()
-  // TEST2-NEXT: 1 | void A::z()
+  // CHECK-LABEL: VFTable for 'A' in 'Test2::X' (2 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST2: VFTable for 'B' in 'Test2::X' (1 entry).
-  // TEST2-NEXT: 0 | void B::g()
+  // CHECK-LABEL: VFTable for 'B' in 'Test2::X' (1 entry).
+  // CHECK-NEXT: 0 | void B::g()
 
-  // TEST2: VFTable indices for 'Test2::X' (1 entry).
-  // TEST2-NEXT: 0 | void Test2::X::h()
+  // CHECK-LABEL: VFTable indices for 'Test2::X' (1 entry).
+  // CHECK-NEXT: 0 | void Test2::X::h()
 
   // MANGLING-DAG: @"\01??_7X at Test2@@6B01@@"
   // MANGLING-DAG: @"\01??_7X at Test2@@6BA@@@"
@@ -124,6 +100,7 @@ struct X: virtual A, virtual B {
 };
 
 X x;
+void use(X *obj) { obj->h(); }
 }
 
 namespace Test3 {
@@ -133,35 +110,37 @@ struct X : virtual A {
 };
 
 struct Y: virtual X {
-  // TEST3: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries).
-  // TEST3-NEXT: 0 | void A::f()
-  // TEST3-NEXT: 1 | void A::z()
+  Y();
+  // CHECK-LABEL: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST3-NOT: VFTable indices for 'Test3::Y'
+  // CHECK-NOT: VFTable indices for 'Test3::Y'
 
   // MANGLING-DAG: @"\01??_7Y at Test3@@6B@"
 };
 
-Y y;
+Y::Y() {}
 }
 
 namespace Test4 {
 
 struct X: virtual C {
+  X();
   // This one's interesting. C::f expects (A*) to be passed as 'this' and does
   // ECX-=4 to cast to (C*). In X, C and A vbases are reordered, so the thunk
   // should pass a pointer to the end of X in order
   // for ECX-=4 to point at the C part.
 
-  // TEST4: VFTable for 'A' in 'C' in 'Test4::X' (2 entries).
-  // TEST4-NEXT: 0 | void C::f()
-  // TEST4-NEXT:     [this adjustment: 8 non-virtual]
-  // TEST4-NEXT: 1 | void A::z()
+  // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test4::X' (2 entries).
+  // CHECK-NEXT: 0 | void C::f()
+  // CHECK-NEXT:     [this adjustment: 8 non-virtual]
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST4: Thunks for 'void C::f()' (1 entry).
-  // TEST4-NEXT: 0 | [this adjustment: 8 non-virtual]
+  // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual]
 
-  // TEST4-NOT: VFTable indices for 'Test4::X'
+  // CHECK-NOT: VFTable indices for 'Test4::X'
 
   // MANGLING-DAG: @"\01??_7X at Test4@@6B@"
 
@@ -169,7 +148,7 @@ struct X: virtual C {
   // MANGLING-DAG: define weak x86_thiscallcc void @"\01?f at C@@WPPPPPPPI at AEXXZ"
 };
 
-X x;
+X::X() {}
 }
 
 namespace Test5 {
@@ -181,16 +160,16 @@ struct X : A {
 };
 
 struct Y : virtual X {
-  // TEST5: VFTable for 'Test5::Y' (1 entry).
-  // TEST5-NEXT: 0 | void Test5::Y::h()
+  // CHECK-LABEL: VFTable for 'Test5::Y' (1 entry).
+  // CHECK-NEXT: 0 | void Test5::Y::h()
 
-  // TEST5: VFTable for 'A' in 'Test5::X' in 'Test5::Y' (3 entries).
-  // TEST5-NEXT: 0 | void A::f()
-  // TEST5-NEXT: 1 | void A::z()
-  // TEST5-NEXT: 2 | void Test5::X::g()
+  // CHECK-LABEL: VFTable for 'A' in 'Test5::X' in 'Test5::Y' (3 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
+  // CHECK-NEXT: 2 | void Test5::X::g()
 
-  // TEST5: VFTable indices for 'Test5::Y' (1 entry).
-  // TEST5-NEXT: 0 | void Test5::Y::h()
+  // CHECK-LABEL: VFTable indices for 'Test5::Y' (1 entry).
+  // CHECK-NEXT: 0 | void Test5::Y::h()
 
   // MANGLING-DAG: @"\01??_7Y at Test5@@6B01@@"
   // MANGLING-DAG: @"\01??_7Y at Test5@@6BX at 1@@"
@@ -199,21 +178,23 @@ struct Y : virtual X {
 };
 
 Y y;
+void use(Y *obj) { obj->h(); }
 }
 
 namespace Test6 {
 
 struct X : A, virtual Empty {
-  // TEST6: VFTable for 'A' in 'Test6::X' (2 entries).
-  // TEST6-NEXT: 0 | void A::f()
-  // TEST6-NEXT: 1 | void A::z()
+  X();
+  // CHECK-LABEL: VFTable for 'A' in 'Test6::X' (2 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST6-NOT: VFTable indices for 'Test6::X'
+  // CHECK-NOT: VFTable indices for 'Test6::X'
 
   // MANGLING-DAG: @"\01??_7X at Test6@@6B@"
 };
 
-X x;
+X::X() {}
 }
 
 namespace Test7 {
@@ -223,36 +204,37 @@ struct X : C {
 };
 
 struct Y : virtual X {
-  // TEST7: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries).
-  // TEST7-NEXT: 0 | void C::f()
-  // TEST7-NEXT:     [this adjustment: 8 non-virtual]
-  // TEST7-NEXT: 1 | void A::z()
+  Y();
+  // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries).
+  // CHECK-NEXT: 0 | void C::f()
+  // CHECK-NEXT:     [this adjustment: 8 non-virtual]
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST7: Thunks for 'void C::f()' (1 entry).
-  // TEST7-NEXT: 0 | [this adjustment: 8 non-virtual]
+  // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual]
 
-  // TEST7-NOT: VFTable indices for 'Test7::Y'
+  // CHECK-NOT: VFTable indices for 'Test7::Y'
 
   // MANGLING-DAG: @"\01??_7Y at Test7@@6B@"
 };
 
-Y y;
+Y::Y() {}
 }
 
 namespace Test8 {
 
 // This is a typical diamond inheritance with a shared 'A' vbase.
 struct X : D, C {
-  // TEST8-X: VFTable for 'D' in 'Test8::X' (1 entry).
-  // TEST8-X-NEXT: 0 | void D::h()
+  // CHECK-LABEL: VFTable for 'D' in 'Test8::X' (1 entry).
+  // CHECK-NEXT: 0 | void D::h()
 
-  // TEST8-X: VFTable for 'A' in 'D' in 'Test8::X' (2 entries).
-  // TEST8-X-NEXT: 0 | void Test8::X::f()
-  // TEST8-X-NEXT: 1 | void A::z()
-
-  // TEST8-X: VFTable indices for 'Test8::X' (1 entry).
-  // TEST8-X-NEXT: via vbtable index 1, vfptr at offset 0
-  // TEST8-X-NEXT: 0 | void Test8::X::f()
+  // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test8::X' (2 entries).
+  // CHECK-NEXT: 0 | void Test8::X::f()
+  // CHECK-NEXT: 1 | void A::z()
+
+  // CHECK-LABEL: VFTable indices for 'Test8::X' (1 entry).
+  // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+  // CHECK-NEXT: 0 | void Test8::X::f()
 
   // MANGLING-DAG: @"\01??_7X at Test8@@6BA@@@"
   // MANGLING-DAG: @"\01??_7X at Test8@@6BD@@@"
@@ -261,21 +243,23 @@ struct X : D, C {
 };
 
 X x;
+void use(X *obj) { obj->f(); }
 
 // Another diamond inheritance which led to AST crashes.
 struct Y : virtual A {};
 
 struct Z : Y, C {
-  // TEST8-Z: VFTable for 'A' in 'Test8::Y' in 'Test8::Z' (2 entries).
-  // TEST8-Z-NEXT: 0 | void Test8::Z::f()
-  // TEST8-Z-NEXT: 1 | void A::z()
-
-  // TEST8-Z: VFTable indices for 'Test8::Z' (1 entry).
-  // TEST8-Z-NEXT: via vbtable index 1, vfptr at offset 0
-  // TEST8-Z-NEXT: 0 | void Test8::Z::f()
+  // CHECK-LABEL: VFTable for 'A' in 'Test8::Y' in 'Test8::Z' (2 entries).
+  // CHECK-NEXT: 0 | void Test8::Z::f()
+  // CHECK-NEXT: 1 | void A::z()
+
+  // CHECK-LABEL: VFTable indices for 'Test8::Z' (1 entry).
+  // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+  // CHECK-NEXT: 0 | void Test8::Z::f()
   virtual void f();
 };
 Z z;
+void use(Z *obj) { obj->f(); }
 
 // Another diamond inheritance which we miscompiled (PR18967).
 struct W : virtual A {
@@ -283,20 +267,21 @@ struct W : virtual A {
 };
 
 struct T : W, C {
-  // TEST8-T: VFTable for 'Test8::W' in 'Test8::T' (1 entry)
-  // TEST8-T-NEXT: 0 | void Test8::T::bar()
+  // CHECK-LABEL: VFTable for 'Test8::W' in 'Test8::T' (1 entry)
+  // CHECK-NEXT: 0 | void Test8::T::bar()
 
-  // TEST8-T: VFTable for 'A' in 'Test8::W' in 'Test8::T' (2 entries)
-  // TEST8-T-NEXT: 0 | void C::f()
-  // TEST8-T-NEXT:     [this adjustment: -4 non-virtual]
-  // TEST8-T-NEXT: 1 | void A::z()
+  // CHECK-LABEL: VFTable for 'A' in 'Test8::W' in 'Test8::T' (2 entries)
+  // CHECK-NEXT: 0 | void C::f()
+  // CHECK-NEXT:     [this adjustment: -4 non-virtual]
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST8-T: Thunks for 'void C::f()' (1 entry).
-  // TEST8-T-NEXT: 0 | [this adjustment: -4 non-virtual]
+  // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
   virtual void bar();
   int field;
 };
 T t;
+void use(T *obj) { obj->bar(); }
 }
 
 namespace Test9 {
@@ -304,15 +289,15 @@ namespace Test9 {
 struct X : A { };
 
 struct Y : virtual X {
-  // TEST9-Y: VFTable for 'Test9::Y' (1 entry).
-  // TEST9-Y-NEXT: 0 | void Test9::Y::h()
+  // CHECK-LABEL: VFTable for 'Test9::Y' (1 entry).
+  // CHECK-NEXT: 0 | void Test9::Y::h()
 
-  // TEST9-Y: VFTable for 'A' in 'Test9::X' in 'Test9::Y' (2 entries).
-  // TEST9-Y-NEXT: 0 | void A::f()
-  // TEST9-Y-NEXT: 1 | void A::z()
+  // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' (2 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST9-Y: VFTable indices for 'Test9::Y' (1 entry).
-  // TEST9-Y-NEXT: 0 | void Test9::Y::h()
+  // CHECK-LABEL: VFTable indices for 'Test9::Y' (1 entry).
+  // CHECK-NEXT: 0 | void Test9::Y::h()
 
   // MANGLING-DAG: @"\01??_7Y at Test9@@6B01@@"
   // MANGLING-DAG: @"\01??_7Y at Test9@@6BX at 1@@"
@@ -321,19 +306,21 @@ struct Y : virtual X {
 };
 
 Y y;
+void use(Y *obj) { obj->h(); }
 
 struct Z : Y, virtual B {
-  // TEST9-Z: VFTable for 'Test9::Y' in 'Test9::Z' (1 entry).
-  // TEST9-Z-NEXT: 0 | void Test9::Y::h()
+  Z();
+  // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' (1 entry).
+  // CHECK-NEXT: 0 | void Test9::Y::h()
+
+  // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' (2 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST9-Z: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' (2 entries).
-  // TEST9-Z-NEXT: 0 | void A::f()
-  // TEST9-Z-NEXT: 1 | void A::z()
+  // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' (1 entry).
+  // CHECK-NEXT: 0 | void B::g()
 
-  // TEST9-Z: VFTable for 'B' in 'Test9::Z' (1 entry).
-  // TEST9-Z-NEXT: 0 | void B::g()
-
-  // TEST9-Z-NOT: VFTable indices for 'Test9::Z'
+  // CHECK-NOT: VFTable indices for 'Test9::Z'
 
   // MANGLING-DAG: @"\01??_7Z at Test9@@6BX at 1@@"
   // MANGLING-DAG: @"\01??_7Z at Test9@@6BY at 1@@"
@@ -341,31 +328,32 @@ struct Z : Y, virtual B {
   // MANGLING-DAG: @"\01??_7Z at Test9@@6B@"
 };
 
-Z z;
+Z::Z() {}
 
 struct W : Z, D, virtual A, virtual B {
-  // TEST9-W: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::W' (1 entry).
-  // TEST9-W-NEXT: 0 | void Test9::Y::h()
+  W();
+  // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::W' (1 entry).
+  // CHECK-NEXT: 0 | void Test9::Y::h()
 
-  // TEST9-W: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::W' (2 entries).
-  // TEST9-W-NEXT: 0 | void A::f()
-  // TEST9-W-NEXT: 1 | void A::z()
+  // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::W' (2 entries).
+  // CHECK-NEXT: 0 | void A::f()
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST9-W: VFTable for 'B' in 'Test9::Z' in 'Test9::W' (1 entry).
-  // TEST9-W-NEXT: 0 | void B::g()
+  // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::W' (1 entry).
+  // CHECK-NEXT: 0 | void B::g()
 
-  // TEST9-W: VFTable for 'D' in 'Test9::W' (1 entry).
-  // TEST9-W-NEXT: 0 | void D::h()
+  // CHECK-LABEL: VFTable for 'D' in 'Test9::W' (1 entry).
+  // CHECK-NEXT: 0 | void D::h()
 
-  // TEST9-W: VFTable for 'A' in 'D' in 'Test9::W' (2 entries).
-  // TEST9-W-NEXT: 0 | void D::f()
-  // TEST9-W-NEXT:     [this adjustment: -8 non-virtual]
-  // TEST9-W-NEXT: 1 | void A::z()
+  // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::W' (2 entries).
+  // CHECK-NEXT: 0 | void D::f()
+  // CHECK-NEXT:     [this adjustment: -8 non-virtual]
+  // CHECK-NEXT: 1 | void A::z()
 
-  // TEST9-W: Thunks for 'void D::f()' (1 entry).
-  // TEST9-W-NEXT: 0 | [this adjustment: -8 non-virtual]
+  // CHECK-LABEL: Thunks for 'void D::f()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
 
-  // TEST9-W-NOT: VFTable indices for 'Test9::W'
+  // CHECK-NOT: VFTable indices for 'Test9::W'
 
   // MANGLING-DAG: @"\01??_7W at Test9@@6BA@@@"
   // MANGLING-DAG: @"\01??_7W at Test9@@6BD@@@"
@@ -375,46 +363,46 @@ struct W : Z, D, virtual A, virtual B {
   // MANGLING-DAG: @"\01??_7W at Test9@@6BY at 1@@"
 };
 
-W w;
+W::W() {}
 
 struct T : Z, D, virtual A, virtual B {
-  // TEST9-T: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::T' (1 entry).
-  // TEST9-T-NEXT: 0 | void Test9::T::h()
+  // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::T' (1 entry).
+  // CHECK-NEXT: 0 | void Test9::T::h()
 
-  // TEST9-T: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::T' (2 entries).
-  // TEST9-T-NEXT: 0 | void Test9::T::f()
-  // TEST9-T-NEXT: 1 | void Test9::T::z()
-
-  // TEST9-T: VFTable for 'B' in 'Test9::Z' in 'Test9::T' (1 entry).
-  // TEST9-T-NEXT: 0 | void Test9::T::g()
-
-  // TEST9-T: VFTable for 'D' in 'Test9::T' (1 entry).
-  // TEST9-T-NEXT: 0 | void Test9::T::h()
-  // TEST9-T-NEXT:     [this adjustment: -8 non-virtual]
-
-  // TEST9-T: Thunks for 'void Test9::T::h()' (1 entry).
-  // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual]
-
-  // TEST9-T: VFTable for 'A' in 'D' in 'Test9::T' (2 entries).
-  // TEST9-T-NEXT: 0 | void Test9::T::f()
-  // TEST9-T-NEXT:     [this adjustment: -8 non-virtual]
-  // TEST9-T-NEXT: 1 | void Test9::T::z()
-  // TEST9-T-NEXT:     [this adjustment: -8 non-virtual]
-
-  // TEST9-T: Thunks for 'void Test9::T::f()' (1 entry).
-  // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual]
-
-  // TEST9-T: Thunks for 'void Test9::T::z()' (1 entry).
-  // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual]
-
-  // TEST9-T: VFTable indices for 'Test9::T' (4 entries).
-  // TEST9-T-NEXT: via vfptr at offset 0
-  // TEST9-T-NEXT: 0 | void Test9::T::h()
-  // TEST9-T-NEXT: via vbtable index 1, vfptr at offset 0
-  // TEST9-T-NEXT: 0 | void Test9::T::f()
-  // TEST9-T-NEXT: 1 | void Test9::T::z()
-  // TEST9-T-NEXT: via vbtable index 2, vfptr at offset 0
-  // TEST9-T-NEXT: 0 | void Test9::T::g()
+  // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::T' (2 entries).
+  // CHECK-NEXT: 0 | void Test9::T::f()
+  // CHECK-NEXT: 1 | void Test9::T::z()
+
+  // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::T' (1 entry).
+  // CHECK-NEXT: 0 | void Test9::T::g()
+
+  // CHECK-LABEL: VFTable for 'D' in 'Test9::T' (1 entry).
+  // CHECK-NEXT: 0 | void Test9::T::h()
+  // CHECK-NEXT:     [this adjustment: -8 non-virtual]
+
+  // CHECK-LABEL: Thunks for 'void Test9::T::h()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+  // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::T' (2 entries).
+  // CHECK-NEXT: 0 | void Test9::T::f()
+  // CHECK-NEXT:     [this adjustment: -8 non-virtual]
+  // CHECK-NEXT: 1 | void Test9::T::z()
+  // CHECK-NEXT:     [this adjustment: -8 non-virtual]
+
+  // CHECK-LABEL: Thunks for 'void Test9::T::f()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+  // CHECK-LABEL: Thunks for 'void Test9::T::z()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+  // CHECK-LABEL: VFTable indices for 'Test9::T' (4 entries).
+  // CHECK-NEXT: via vfptr at offset 0
+  // CHECK-NEXT: 0 | void Test9::T::h()
+  // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+  // CHECK-NEXT: 0 | void Test9::T::f()
+  // CHECK-NEXT: 1 | void Test9::T::z()
+  // CHECK-NEXT: via vbtable index 2, vfptr at offset 0
+  // CHECK-NEXT: 0 | void Test9::T::g()
 
   // MANGLING-DAG: @"\01??_7T at Test9@@6BA@@@"
   // MANGLING-DAG: @"\01??_7T at Test9@@6BD@@@"
@@ -430,22 +418,24 @@ struct T : Z, D, virtual A, virtual B {
 };
 
 T t;
+void use(T *obj) { obj->f(); }
 }
 
 namespace Test10 {
 struct X : virtual C, virtual A {
-  // TEST10: VFTable for 'A' in 'C' in 'Test10::X' (2 entries).
-  // TEST10-NEXT: 0 | void Test10::X::f()
-  // TEST10-NEXT: 1 | void A::z()
-
-  // TEST10: VFTable indices for 'Test10::X' (1 entry).
-  // TEST10-NEXT: via vbtable index 1, vfptr at offset 0
-  // TEST10-NEXT: 0 | void Test10::X::f()
+  // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test10::X' (2 entries).
+  // CHECK-NEXT: 0 | void Test10::X::f()
+  // CHECK-NEXT: 1 | void A::z()
+
+  // CHECK-LABEL: VFTable indices for 'Test10::X' (1 entry).
+  // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+  // CHECK-NEXT: 0 | void Test10::X::f()
   virtual void f();
 };
 
 void X::f() {}
 X x;
+void use(X *obj) { obj->f(); }
 }
 
 namespace Test11 {
@@ -461,8 +451,8 @@ Z z;
 
 struct W : virtual X, A {};
 
-// PR17748 FIXME this one hits UNREACHABLE:
-// W w;
+// Used to crash, PR17748.
+W w;
 }
 
 namespace vdtors {
@@ -472,15 +462,16 @@ struct X {
 };
 
 struct Y : virtual X {
-  // VDTORS-Y: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries).
-  // VDTORS-Y-NEXT: 0 | vdtors::Y::~Y() [scalar deleting]
-  // VDTORS-Y-NEXT: 1 | void vdtors::X::zzz()
+  // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries).
+  // CHECK-NEXT: 0 | vdtors::Y::~Y() [scalar deleting]
+  // CHECK-NEXT: 1 | void vdtors::X::zzz()
 
-  // VDTORS-Y-NOT: Thunks for 'vdtors::Y::~Y()'
+  // CHECK-NOT: Thunks for 'vdtors::Y::~Y()'
   virtual ~Y();
 };
 
 Y y;
+void use(Y *obj) { delete obj; }
 
 struct Z {
   virtual void z();
@@ -491,58 +482,61 @@ struct W : Z, X {
 };
 
 struct U : virtual W {
-  // VDTORS-U: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::U' (1 entry).
-  // VDTORS-U-NEXT: 0 | void vdtors::Z::z()
+  // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::U' (1 entry).
+  // CHECK-NEXT: 0 | void vdtors::Z::z()
 
-  // VDTORS-U: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries).
-  // VDTORS-U-NEXT: 0 | vdtors::U::~U() [scalar deleting]
-  // VDTORS-U-NEXT:     [this adjustment: -4 non-virtual]
-  // VDTORS-U-NEXT: 1 | void vdtors::X::zzz()
-
-  // VDTORS-U: Thunks for 'vdtors::U::~U()' (1 entry).
-  // VDTORS-U-NEXT: 0 | [this adjustment: -4 non-virtual]
-
-  // VDTORS-U: VFTable indices for 'vdtors::U' (1 entry).
-  // VDTORS-U-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
-  // VDTORS-U-NEXT: 0 | vdtors::U::~U() [scalar deleting]
+  // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries).
+  // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
+  // CHECK-NEXT:     [this adjustment: -4 non-virtual]
+  // CHECK-NEXT: 1 | void vdtors::X::zzz()
+
+  // CHECK-LABEL: Thunks for 'vdtors::U::~U()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+  // CHECK-LABEL: VFTable indices for 'vdtors::U' (1 entry).
+  // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
+  // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
   virtual ~U();
 };
 
 U u;
+void use(U *obj) { delete obj; }
 
 struct V : virtual W {
-  // VDTORS-V: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::V' (1 entry).
-  // VDTORS-V-NEXT: 0 | void vdtors::Z::z()
+  // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::V' (1 entry).
+  // CHECK-NEXT: 0 | void vdtors::Z::z()
 
-  // VDTORS-V: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries).
-  // VDTORS-V-NEXT: 0 | vdtors::V::~V() [scalar deleting]
-  // VDTORS-V-NEXT:     [this adjustment: -4 non-virtual]
-  // VDTORS-V-NEXT: 1 | void vdtors::X::zzz()
-
-  // VDTORS-V: Thunks for 'vdtors::V::~V()' (1 entry).
-  // VDTORS-V-NEXT: 0 | [this adjustment: -4 non-virtual]
-
-  // VDTORS-V: VFTable indices for 'vdtors::V' (1 entry).
-  // VDTORS-V-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
-  // VDTORS-V-NEXT: 0 | vdtors::V::~V() [scalar deleting]
+  // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries).
+  // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
+  // CHECK-NEXT:     [this adjustment: -4 non-virtual]
+  // CHECK-NEXT: 1 | void vdtors::X::zzz()
+
+  // CHECK-LABEL: Thunks for 'vdtors::V::~V()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+  // CHECK-LABEL: VFTable indices for 'vdtors::V' (1 entry).
+  // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
+  // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
 };
 
 V v;
+void use(V *obj) { delete obj; }
 
 struct T : virtual X {
   virtual ~T();
 };
 
 struct P : T, Y {
-  // VDTORS-P: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries).
-  // VDTORS-P-NEXT: 0 | vdtors::P::~P() [scalar deleting]
-  // VDTORS-P-NEXT: 1 | void vdtors::X::zzz()
+  // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries).
+  // CHECK-NEXT: 0 | vdtors::P::~P() [scalar deleting]
+  // CHECK-NEXT: 1 | void vdtors::X::zzz()
 
-  // VDTORS-P-NOT: Thunks for 'vdtors::P::~P()'
+  // CHECK-NOT: Thunks for 'vdtors::P::~P()'
   virtual ~P();
 };
 
 P p;
+void use(P *obj) { delete obj; }
 
 struct Q {
   virtual ~Q();
@@ -550,24 +544,24 @@ struct Q {
 
 // PR19172: Yet another diamond we miscompiled.
 struct R : virtual Q, X {
-  // VDTORS-R: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry).
-  // VDTORS-R-NEXT: 0 | vdtors::R::~R() [scalar deleting]
-  // VDTORS-R-NEXT:     [this adjustment: -8 non-virtual]
-
-  // VDTORS-R: Thunks for 'vdtors::R::~R()' (1 entry).
-  // VDTORS-R-NEXT: 0 | [this adjustment: -8 non-virtual]
-
-  // VDTORS-R: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries).
-  // VDTORS-R-NEXT: 0 | vdtors::R::~R() [scalar deleting]
-  // VDTORS-R-NEXT: 1 | void vdtors::X::zzz()
+  // CHECK-LABEL: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry).
+  // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+  // CHECK-NEXT:     [this adjustment: -8 non-virtual]
+
+  // CHECK-LABEL: Thunks for 'vdtors::R::~R()' (1 entry).
+  // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+  // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries).
+  // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+  // CHECK-NEXT: 1 | void vdtors::X::zzz()
 
-  // VDTORS-R: VFTable indices for 'vdtors::R' (1 entry).
-  // VDTORS-R-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+  // CHECK-LABEL: VFTable indices for 'vdtors::R' (1 entry).
+  // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
   virtual ~R();
 };
 
 R r;
-
+void use(R *obj) { delete obj; }
 }
 
 namespace return_adjustment {
@@ -585,62 +579,65 @@ struct Z {
 };
 
 struct W : Z {
-  // RET-W: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' (2 entries).
-  // RET-W-NEXT: 0 | return_adjustment::X *return_adjustment::W::foo()
-  // RET-W-NEXT:     [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
-  // RET-W-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
+  // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' (2 entries).
+  // CHECK-NEXT: 0 | return_adjustment::X *return_adjustment::W::foo()
+  // CHECK-NEXT:     [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
+  // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
 
-  // RET-W: Thunks for 'return_adjustment::X *return_adjustment::W::foo()' (1 entry).
-  // RET-W-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
+  // CHECK-LABEL: Thunks for 'return_adjustment::X *return_adjustment::W::foo()' (1 entry).
+  // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
 
-  // RET-W: VFTable indices for 'return_adjustment::W' (1 entry).
-  // RET-W-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
+  // CHECK-LABEL: VFTable indices for 'return_adjustment::W' (1 entry).
+  // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
 
   virtual X* foo();
 };
 
-W y;
+W w;
+void use(W *obj) { obj->foo(); }
 
 struct T : W {
-  // RET-T: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' in 'return_adjustment::T' (3 entries).
-  // RET-T-NEXT: 0 | return_adjustment::Y *return_adjustment::T::foo()
-  // RET-T-NEXT:     [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
-  // RET-T-NEXT: 1 | return_adjustment::Y *return_adjustment::T::foo()
-  // RET-T-NEXT:     [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
-  // RET-T-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
-
-  // RET-T: Thunks for 'return_adjustment::Y *return_adjustment::T::foo()' (2 entries).
-  // RET-T-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
-  // RET-T-NEXT: 1 | [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
+  // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' in 'return_adjustment::T' (3 entries).
+  // CHECK-NEXT: 0 | return_adjustment::Y *return_adjustment::T::foo()
+  // CHECK-NEXT:     [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
+  // CHECK-NEXT: 1 | return_adjustment::Y *return_adjustment::T::foo()
+  // CHECK-NEXT:     [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
+  // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
+
+  // CHECK-LABEL: Thunks for 'return_adjustment::Y *return_adjustment::T::foo()' (2 entries).
+  // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
+  // CHECK-NEXT: 1 | [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
 
-  // RET-T: VFTable indices for 'return_adjustment::T' (1 entry).
-  // RET-T-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
+  // CHECK-LABEL: VFTable indices for 'return_adjustment::T' (1 entry).
+  // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
 
   virtual Y* foo();
 };
 
 T t;
+void use(T *obj) { obj->foo(); }
 
 struct U : virtual A {
   virtual void g();  // adds a vfptr
 };
 
 struct V : Z {
-  // RET-V: VFTable for 'return_adjustment::Z' in 'return_adjustment::V' (2 entries).
-  // RET-V-NEXT: 0 | return_adjustment::U *return_adjustment::V::foo()
-  // RET-V-NEXT:     [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
-  // RET-V-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
+  // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::V' (2 entries).
+  // CHECK-NEXT: 0 | return_adjustment::U *return_adjustment::V::foo()
+  // CHECK-NEXT:     [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
+  // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
 
-  // RET-V: Thunks for 'return_adjustment::U *return_adjustment::V::foo()' (1 entry).
-  // RET-V-NEXT: 0 | [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
+  // CHECK-LABEL: Thunks for 'return_adjustment::U *return_adjustment::V::foo()' (1 entry).
+  // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
 
-  // RET-V: VFTable indices for 'return_adjustment::V' (1 entry).
-  // RET-V-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
+  // CHECK-LABEL: VFTable indices for 'return_adjustment::V' (1 entry).
+  // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
 
   virtual U* foo();
 };
 
 V v;
+void use(V *obj) { obj->foo(); }
 }
 
 namespace pr17748 {





More information about the cfe-commits mailing list