Emit virtual/deleting destructors properly with -cxx-abi microsoft, PR15058

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175045 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index 12622f1..16763d5 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -1,4 +1,8 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t 2>&1
+// RUN: FileCheck %s < %t
+// Using a different check prefix as the inline destructors might be placed
+// anywhere in the output.
+// RUN: FileCheck --check-prefix=DTORS %s < %t
 
 class A {
  public:
@@ -23,13 +27,60 @@
 }
 
 struct B {
-  virtual ~B();
+  virtual ~B() {
+// Complete destructor first:
+// DTORS: define {{.*}} x86_thiscallcc void @"\01??1B@@UAE@XZ"(%struct.B* %this)
+//
+// Then, the scalar deleting destructor (used in the vtable):
+// DTORS:      define {{.*}} x86_thiscallcc void @"\01??_GB@@UAEPAXI@Z"(%struct.B* %this, i1 zeroext %should_call_delete)
+// DTORS:        %0 = icmp eq i8 %should_call_delete{{.*}}, 0
+// DTORS-NEXT:   br i1 %0, label %dtor.continue, label %dtor.call_delete
+// DTORS:      dtor.call_delete:
+// DTORS-NEXT:   %1 = bitcast %struct.B* %this1 to i8*
+// DTORS-NEXT:   call void @"\01??3@YAXPAX@Z"(i8* %1) nounwind
+// DTORS-NEXT:   br label %dtor.continue
+// DTORS:      dtor.continue:
+// DTORS-NEXT:   ret void
+  }
   virtual void foo();
 };
 
+// Emits the vftable in the output.
+void B::foo() {}
+
 void check_vftable_offset() {
   B b;
 // The vftable pointer should point at the beginning of the vftable.
 // CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %struct.B* {{.*}} to i8***
 // CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7B@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]
 }
+
+// FIXME: Enable the following block and add expectations when calls
+// to virtual complete dtor are supported.
+#if 0
+void call_complete_dtor(B *obj_ptr) {
+  obj_ptr->~B();
+}
+#endif
+
+void call_deleting_dtor(B *obj_ptr) {
+// FIXME: Add CHECKs when calls to virtual deleting dtor are generated properly.
+  delete obj_ptr;
+}
+
+struct C {
+  static int foo();
+
+  C() {
+    static int ctor_static = foo();
+    // CHECK that the static in the ctor gets mangled correctly:
+    // CHECK: @"\01?ctor_static@?1???0C@@QAE@XZ@4HA"
+  }
+  ~C() {
+    static int dtor_static = foo();
+    // CHECK that the static in the dtor gets mangled correctly:
+    // CHECK: @"\01?dtor_static@?1???1C@@QAE@XZ@4HA"
+  }
+};
+
+void use_C() { C c; }
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index 176ecf1..5d430db 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -37,10 +37,10 @@
 
 struct C {
   // CHECK-C: Vtable for 'C' (2 entries)
-  // CHECK-C-NEXT: 0 | C::~C()
+  // 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()
+  // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
   // CHECK-C-NEXT: 1 | void C::f()
   // Never used, so doesn't emit a vtable.
   virtual ~C();
@@ -52,7 +52,7 @@
 struct D {
   // CHECK-D: Vtable for 'D' (2 entries)
   // CHECK-D-NEXT: 0 | void D::f()
-  // CHECK-D-NEXT: 1 | D::~D()
+  // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
   // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]
   virtual void f();
 
@@ -65,10 +65,10 @@
   // 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()
+  // 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()
+  // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
   // CHECK-E-NEXT: 4 | void E::i()
 
   // Never used, so doesn't emit a vtable.
@@ -83,10 +83,10 @@
   // 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()
+  // 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()
+  // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
   // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]
   virtual void i();
   virtual ~F();
@@ -98,12 +98,12 @@
   // 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()
+  // 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()
+  // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
   // CHECK-G-NEXT: 5 | void G::j()
   // Never used, so doesn't emit a vtable.
   virtual void f();  // overrides A::f()