Reland 192220 "Abstract out parts of thunk emission code, add support for simple thunks when using -cxx-abi microsoft" with relaxed assertions

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192285 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp
new file mode 100644
index 0000000..091ef32
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -0,0 +1,118 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 >%t 2>&1
+// RUN: FileCheck --check-prefix=MANGLING %s < %t
+// RUN: FileCheck --check-prefix=XMANGLING %s < %t
+// RUN: FileCheck --check-prefix=CODEGEN %s < %t
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
+
+void foo(void *);
+
+struct A {
+  virtual ~A();
+  virtual void public_f();
+  // Make sure we don't emit unneeded thunks:
+  // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
+ protected:
+  virtual void protected_f();
+ private:
+  virtual void private_f();
+};
+
+struct B {
+  virtual ~B();
+  virtual void public_f();
+ protected:
+  virtual void protected_f();
+ private:
+  virtual void private_f();
+};
+
+
+struct C : A, B {
+  C();
+
+  virtual ~C();
+  // MANGLING-DAG: @"\01??1C@@UAE@XZ"
+  // MANGLING-DAG: @"\01??_GC@@UAEPAXI@Z"
+  // MANGLING-DAG: @"\01??_EC@@W3AEPAXI@Z"
+  // MANGLING-X64-DAG: @"\01??1C@@UEAA@XZ"
+  // MANGLING-X64-DAG: @"\01??_GC@@UEAAPEAXI@Z"
+  // MANGLING-X64-DAG: @"\01??_EC@@W7EAAPEAXI@Z"
+
+  // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
+  virtual void public_f();
+  // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
+  // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
+  // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
+  // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
+ protected:
+  virtual void protected_f();
+  // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
+  // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
+  // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
+  // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"
+
+ private:
+  virtual void private_f();
+  // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
+  // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
+  // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
+  // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
+};
+
+C::C() {}  // Emits vftable and forces thunk generation.
+
+// CODEGEN: define weak x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete)
+// CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 -4
+// FIXME: should actually call _EC, not _GC.
+// CODEGEN:   call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z"
+// CODEGEN: ret
+
+// CODEGEN: define weak x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
+// CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 -4
+// CODEGEN:   call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
+// CODEGEN: ret
+
+void zoo(C* obj) {
+  delete obj;
+}
+
+struct D {
+  virtual B* goo();
+};
+
+struct E : D {
+  virtual C* goo();
+  // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
+  // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
+  // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
+  // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
+};
+
+E e;  // Emits vftable and forces thunk generation.
+
+// CODEGEN: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"
+// CODEGEN:   call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
+// CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 4
+// CODEGEN: ret
+
+struct F : virtual A, virtual B {
+  virtual ~F();
+};
+
+F f;  // Just make sure we don't crash, e.g. mangling the complete dtor.
+
+struct G : C { };
+
+struct H : E {
+  virtual G* goo();
+  // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
+  // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
+  // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
+  // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
+  // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
+  // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
+};
+
+H h;
+
+// FIXME: Write vtordisp adjusting thunk tests
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index 064a3ff..3805243 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -93,3 +93,11 @@
 //
 // CHECK: ret void
 }
+
+struct C : B {
+  C();
+  // has an implicit vdtor.
+};
+
+// Used to crash on an assertion.
+C::C() {}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
index a0436c8..8dad4dd 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
@@ -18,6 +18,7 @@
 // RUN: FileCheck --check-prefix=RET-THUNKS-Test3 %s < %t
 // RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t
 // RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t
+// RUN: FileCheck --check-prefix=RET-THUNKS-Test6 %s < %t
 
 // RUN: FileCheck --check-prefix=MANGLING %s < %t
 
@@ -458,4 +459,22 @@
 };
 
 Test5 t5;
+
+struct Ret3 : this_adjustment::Test1 { };
+
+struct Test6 : Test1 {
+  virtual Ret3* foo();
+  // RET-THUNKS-Test6: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test6' (4 entries).
+  // RET-THUNKS-Test6-NEXT: 0 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+  // RET-THUNKS-Test6-NEXT:     [return adjustment: 4 non-virtual]
+  // RET-THUNKS-Test6-NEXT: 1 | void return_adjustment::Ret1::z()
+  // RET-THUNKS-Test6-NEXT: 2 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+  // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+
+  // RET-THUNKS-Test6: VFTable indices for 'return_adjustment::Test6' (1 entries).
+  // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+};
+
+Test6 t6;
+
 }
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index 2487260..4a7f5da 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -154,6 +154,9 @@
   // TEST4-NOT: VFTable indices for 'Test4::X'
 
   // MANGLING-DAG: @"\01??_7X@Test4@@6B@"
+
+  // Also check the mangling of the thunk.
+  // MANGLING-DAG: define weak x86_thiscallcc void @"\01?f@C@@WPPPPPPPE@AEXXZ"
 };
 
 X x;