Abstract out the emission of vtables, add basic support for vtable emission when using -cxx-abi microsoft

Reviewed at http://llvm-reviews.chandlerc.com/D1532

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191523 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
new file mode 100644
index 0000000..92db9a7
--- /dev/null
+++ b/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/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
index 9059e6f..fc59e17 100644
--- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
@@ -145,3 +145,39 @@
   // 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/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index f9d65f4..2c831ca 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -71,8 +71,8 @@
 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 @@
   // 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/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index ecbb843..064a3ff 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -7,10 +7,26 @@
 };
 
 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/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
index bd0666b..a0436c8 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
+++ b/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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index 9a065d4..82e8f1c 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ b/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 @@
   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 @@
   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 @@
   // 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 @@
   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 @@
   // 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 @@
   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 @@
   // 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/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index cf9e4c0..2487260 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/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 @@
   // 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 @@
   // 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 @@
 
 // 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 @@
   // 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 @@
   // 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 @@
 
 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 @@
   // 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 @@
   // 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 @@
 
 // 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 @@
   // 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 @@
   // 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 @@
 
 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp
index a8d4520..5014eaf 100644
--- a/test/CodeGenCXX/virtual-base-destructor-call.cpp
+++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp
@@ -27,12 +27,6 @@
 //  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 @@
 //  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