summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/microsoft-abi-vbtables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/microsoft-abi-vbtables.cpp')
-rw-r--r--test/CodeGenCXX/microsoft-abi-vbtables.cpp479
1 files changed, 479 insertions, 0 deletions
diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
new file mode 100644
index 0000000..6de556b
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
@@ -0,0 +1,479 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
+
+// See microsoft-abi-structors.cpp for constructor codegen tests.
+
+namespace Test1 {
+// Classic diamond, fully virtual.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : virtual B, virtual C { int d; };
+D d; // Force vbtable emission.
+
+// Layout should be:
+// D: vbptr D
+// int d
+// A: int a
+// B: vbptr B
+// int b
+// C: vbptr C
+// int c
+
+// CHECK-DAG: @"\01??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20]
+// CHECK-DAG: @"\01??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"\01??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12]
+// CHECK-DAG: @"\01??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8B@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test2 {
+// Classic diamond, only A is virtual.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : B, C { int d; };
+D d; // Force vbtable emission.
+
+// Layout should be:
+// B: vbptr B
+// int b
+// C: vbptr C
+// int c
+// D: int d
+// A: int a
+
+// CHECK-DAG: @"\01??_8D@Test2@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"\01??_8D@Test2@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8C@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8B@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test3 {
+struct A { int a; };
+struct B { int b; };
+struct C : virtual A, virtual B { int c; };
+C c;
+
+// CHECK-DAG: @"\01??_8C@Test3@@7B@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+}
+
+namespace Test4 {
+// Test reusing a vbptr from a non-virtual base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B, virtual A { int c; };
+C c; // Force vbtable emission.
+
+// CHECK-DAG: @"\01??_8C@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test5 {
+// Test multiple base subobjects of the same type when that type has a virtual
+// base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : B, C { int d; };
+D d; // Force vbtable emission.
+
+// CHECK-DAG: @"\01??_8D@Test5@@7BB@1@@"
+// CHECK-DAG: @"\01??_8D@Test5@@7BC@1@@"
+// CHECK-DAG: @"\01??_8C@Test5@@7B@"
+// CHECK-DAG: @"\01??_8B@Test5@@7B@"
+}
+
+namespace Test6 {
+// Test that we skip unneeded base path component names.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : B, C { int d; };
+struct E : D { int e; };
+struct F : E, B, C { int f; };
+struct G : F, virtual E { int g; };
+G g;
+
+// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 52]
+// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 44]
+// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"\01??_8C@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8E@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"\01??_8E@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"\01??_8D@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"\01??_8D@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+}
+
+namespace Test7 {
+// Test a non-virtual base which reuses the vbptr of another base.
+struct A { int a; };
+struct B { int b; };
+struct C { int c; };
+struct D : virtual A { int d; };
+struct E : B, D, virtual A, virtual C { int e; };
+E o;
+
+// CHECK-DAG: @"\01??_8E@Test7@@7B@" = {{.*}} [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"\01??_8D@Test7@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test8 {
+// Test a virtual base which reuses the vbptr of another base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : virtual C { int d; };
+D o;
+
+// CHECK-DAG: @"\01??_8D@Test8@@7B01@@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+// CHECK-DAG: @"\01??_8D@Test8@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"\01??_8C@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test9 {
+// D has to add to B's vbtable because D has more morally virtual bases than B.
+// D then takes B's vbptr and the vbtable is named for D, not B.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct BB : B { int bb; }; // Indirection =/
+struct D : BB, C { int d; };
+struct E : virtual D { };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test9@@7B01@@" =
+// CHECK-DAG: @"\01??_8E@Test9@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test9@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test9@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test9@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test9@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test9@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test9@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test9@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8BB@Test9@@7B@" =
+// CHECK-DAG: @"\01??_8B@Test9@@7B@" =
+}
+
+namespace Test10 {
+struct A { int a; };
+struct B { int b; };
+struct C : virtual A { int c; };
+struct D : B, C { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test10@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test10@@7B@" =
+
+}
+
+namespace Test11 {
+// Typical diamond with an extra single inheritance indirection for B and C.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : B { int d; };
+struct E : C { int e; };
+struct F : D, E { int f; };
+F f;
+
+// CHECK-DAG: @"\01??_8F@Test11@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"\01??_8F@Test11@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"\01??_8E@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8C@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8D@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+
+}
+
+namespace Test12 {
+// Another vbptr inside a virtual base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : C, B { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test12@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test12@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test12@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test12@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test12@@7B@" =
+// CHECK-DAG: @"\01??_8B@Test12@@7B@" =
+}
+
+namespace Test13 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : virtual C { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test13@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test13@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test13@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test13@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test13@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test13@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test13@@7B@" =
+}
+
+namespace Test14 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : virtual C { int d; };
+struct E : D, virtual C, virtual B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test14@@7B@" =
+// CHECK-DAG: @"\01??_8E@Test14@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test14@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test14@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test14@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test14@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test14@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test14@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test14@@7B@" =
+}
+
+namespace Test15 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : virtual B { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test15@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test15@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test15@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test15@@7B01@@" =
+// CHECK-DAG: @"\01??_8D@Test15@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test15@@7B@" =
+}
+
+namespace Test16 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; }; // ambig
+struct D : virtual C { int d; };
+struct E : virtual D { int e; }; // ambig
+struct F : E, D, C, B { int f; }; // ambig
+F f;
+
+// CHECK-DAG: @"\01??_8F@Test16@@7BE@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7B01@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test16@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test16@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test16@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test16@@7B@" =
+}
+
+namespace Test17 {
+// This test case has an interesting alternating pattern of using "vbtable of B"
+// and "vbtable of C for C". This may be the key to the underlying algorithm.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; }; // ambig
+struct D : virtual C { int d; };
+struct E : virtual D { int e; }; // ambig
+struct F : virtual E { int f; };
+struct G : virtual F { int g; }; // ambig
+struct H : virtual G { int h; };
+struct I : virtual H { int i; }; // ambig
+struct J : virtual I { int j; };
+struct K : virtual J { int k; }; // ambig
+K k;
+
+// CHECK-DAG: @"\01??_8K@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8J@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8I@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8H@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8G@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8F@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8E@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8D@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8B@Test17@@7B@" =
+}
+
+namespace Test18 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : C, B { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test18@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test18@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test18@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test18@@7BB@1@@" =
+}
+
+namespace Test19 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : virtual C, virtual B { int d; };
+struct E : virtual D, virtual C, virtual B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test19@@7B01@@" =
+// CHECK-DAG: @"\01??_8E@Test19@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test19@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test19@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test19@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test19@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test19@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test19@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test19@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test19@@7B@" =
+}
+
+namespace Test20 {
+// E has no direct vbases, but it adds to C's vbtable anyway.
+struct A { int a; };
+struct B { int b; };
+struct C : virtual A { int c; };
+struct D : virtual B { int d; };
+struct E : C, D { int e; };
+E f;
+
+// CHECK-DAG: @"\01??_8E@Test20@@7BC@1@@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 20, i32 24]
+// CHECK-DAG: @"\01??_8E@Test20@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"\01??_8D@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8C@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test21 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : B { int d; };
+struct E : C, D { int e; };
+struct F : virtual E { int f; };
+struct G : E { int g; };
+struct H : F, G { int h; };
+H h;
+
+// CHECK-DAG: @"\01??_8H@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@F@1@@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@F@1@@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@G@1@@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@G@1@@" =
+// CHECK-DAG: @"\01??_8G@Test21@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8G@Test21@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8F@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8F@Test21@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8F@Test21@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test21@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test21@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8D@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8B@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test21@@7B@" =
+}
+
+namespace Test22 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+struct D : B, virtual C { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test22@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"\01??_8B@Test22@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test23 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+// Note the unusual order of bases. It forces C to be laid out before A.
+struct D : virtual C, B { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test23@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B@Test23@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test24 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+struct D : virtual C, B {
+ virtual void f(); // Issues a vfptr, but the vbptr is still shared with B.
+ int d;
+};
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test24@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B@Test24@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test25 {
+struct A { int a; };
+struct B : virtual A {
+ virtual void f(); // Issues a vfptr.
+ int b;
+};
+struct C { int c; };
+struct D : virtual C, B { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test25@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 -4, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B@Test25@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 8]
+}
+
+namespace Test26 {
+struct A { int a; };
+struct B { int b; };
+struct C { int c; };
+struct D : virtual A { int d; };
+struct E : virtual B {
+ virtual void foo(); // Issues a vfptr.
+ int e;
+};
+struct F: virtual C, D, E { int f; };
+F f;
+// F reuses the D's vbptr, even though D is laid out after E.
+// CHECK-DAG: @"\01??_8F@Test26@@7BD@1@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 16, i32 12, i32 20]
+// CHECK-DAG: @"\01??_8F@Test26@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 28]
+}
OpenPOWER on IntegriCloud