xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-structors.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -emit-llvm -fno-rtti %s -std=c++11 -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-rtti > %t
2f4a2713aSLionel Sambuc // RUN: FileCheck %s < %t
3f4a2713aSLionel Sambuc // vftables are emitted very late, so do another pass to try to keep the checks
4f4a2713aSLionel Sambuc // in source order.
5f4a2713aSLionel Sambuc // RUN: FileCheck --check-prefix DTORS %s < %t
6*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix DTORS2 %s < %t
7*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix DTORS3 %s < %t
8f4a2713aSLionel Sambuc //
9*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s
10f4a2713aSLionel Sambuc 
11f4a2713aSLionel Sambuc namespace basic {
12f4a2713aSLionel Sambuc 
13f4a2713aSLionel Sambuc class A {
14f4a2713aSLionel Sambuc  public:
A()15f4a2713aSLionel Sambuc   A() { }
16f4a2713aSLionel Sambuc   ~A();
17f4a2713aSLionel Sambuc };
18f4a2713aSLionel Sambuc 
no_constructor_destructor_infinite_recursion()19f4a2713aSLionel Sambuc void no_constructor_destructor_infinite_recursion() {
20f4a2713aSLionel Sambuc   A a;
21f4a2713aSLionel Sambuc 
22f4a2713aSLionel Sambuc // CHECK:      define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this)
23f4a2713aSLionel Sambuc // CHECK:        [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4
24f4a2713aSLionel Sambuc // CHECK-NEXT:   store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4
25f4a2713aSLionel Sambuc // CHECK-NEXT:   [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"** [[THIS_ADDR]]
26f4a2713aSLionel Sambuc // CHECK-NEXT:   ret %"class.basic::A"* [[T1]]
27f4a2713aSLionel Sambuc // CHECK-NEXT: }
28f4a2713aSLionel Sambuc }
29f4a2713aSLionel Sambuc 
~A()30f4a2713aSLionel Sambuc A::~A() {
31f4a2713aSLionel Sambuc // Make sure that the destructor doesn't call itself:
32f4a2713aSLionel Sambuc // CHECK: define {{.*}} @"\01??1A@basic@@QAE@XZ"
33f4a2713aSLionel Sambuc // CHECK-NOT: call void @"\01??1A@basic@@QAE@XZ"
34f4a2713aSLionel Sambuc // CHECK: ret
35f4a2713aSLionel Sambuc }
36f4a2713aSLionel Sambuc 
37f4a2713aSLionel Sambuc struct B {
38f4a2713aSLionel Sambuc   B();
39f4a2713aSLionel Sambuc };
40f4a2713aSLionel Sambuc 
41f4a2713aSLionel Sambuc // Tests that we can define constructors outside the class (PR12784).
B()42f4a2713aSLionel Sambuc B::B() {
43f4a2713aSLionel Sambuc   // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this)
44f4a2713aSLionel Sambuc   // CHECK: ret
45f4a2713aSLionel Sambuc }
46f4a2713aSLionel Sambuc 
47f4a2713aSLionel Sambuc struct C {
~Cbasic::C48f4a2713aSLionel Sambuc   virtual ~C() {
49*0a6a1f1dSLionel Sambuc // DTORS:      define linkonce_odr x86_thiscallcc i8* @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete)
50f4a2713aSLionel Sambuc // DTORS:        store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4
51*0a6a1f1dSLionel Sambuc // DTORS:        store i8* %{{.*}}, i8** %[[RETVAL:[0-9a-z._]+]]
52f4a2713aSLionel Sambuc // DTORS:        %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32* %[[SHOULD_DELETE_VAR]]
53f4a2713aSLionel Sambuc // DTORS:        call x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]])
54f4a2713aSLionel Sambuc // DTORS-NEXT:   %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0
55f4a2713aSLionel Sambuc // DTORS-NEXT:   br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]]
56f4a2713aSLionel Sambuc //
57f4a2713aSLionel Sambuc // DTORS:      [[CALL_DELETE_LABEL]]
58f4a2713aSLionel Sambuc // DTORS-NEXT:   %[[THIS_AS_VOID:[0-9a-z]+]] = bitcast %"struct.basic::C"* %[[THIS]] to i8*
59f4a2713aSLionel Sambuc // DTORS-NEXT:   call void @"\01??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
60f4a2713aSLionel Sambuc // DTORS-NEXT:   br label %[[CONTINUE_LABEL]]
61f4a2713aSLionel Sambuc //
62f4a2713aSLionel Sambuc // DTORS:      [[CONTINUE_LABEL]]
63*0a6a1f1dSLionel Sambuc // DTORS-NEXT:   %[[RET:.*]] = load i8** %[[RETVAL]]
64*0a6a1f1dSLionel Sambuc // DTORS-NEXT:   ret i8* %[[RET]]
65f4a2713aSLionel Sambuc 
66f4a2713aSLionel Sambuc // Check that we do the mangling correctly on x64.
67f4a2713aSLionel Sambuc // DTORS-X64:  @"\01??_GC@basic@@UEAAPEAXI@Z"
68f4a2713aSLionel Sambuc   }
69f4a2713aSLionel Sambuc   virtual void foo();
70f4a2713aSLionel Sambuc };
71f4a2713aSLionel Sambuc 
72f4a2713aSLionel Sambuc // Emits the vftable in the output.
foo()73f4a2713aSLionel Sambuc void C::foo() {}
74f4a2713aSLionel Sambuc 
check_vftable_offset()75f4a2713aSLionel Sambuc void check_vftable_offset() {
76f4a2713aSLionel Sambuc   C c;
77f4a2713aSLionel Sambuc // The vftable pointer should point at the beginning of the vftable.
78*0a6a1f1dSLionel Sambuc // CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)***
79*0a6a1f1dSLionel Sambuc // CHECK: store i32 (...)** bitcast ([2 x i8*]* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
80f4a2713aSLionel Sambuc }
81f4a2713aSLionel Sambuc 
call_complete_dtor(C * obj_ptr)82f4a2713aSLionel Sambuc void call_complete_dtor(C *obj_ptr) {
83f4a2713aSLionel Sambuc // CHECK: define void @"\01?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
84f4a2713aSLionel Sambuc   obj_ptr->~C();
85f4a2713aSLionel Sambuc // CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4
86*0a6a1f1dSLionel Sambuc // CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
87*0a6a1f1dSLionel Sambuc // CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
88*0a6a1f1dSLionel Sambuc // CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
89*0a6a1f1dSLionel Sambuc // CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
90*0a6a1f1dSLionel Sambuc // CHECK-NEXT: call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0)
91f4a2713aSLionel Sambuc // CHECK-NEXT: ret void
92f4a2713aSLionel Sambuc }
93f4a2713aSLionel Sambuc 
call_deleting_dtor(C * obj_ptr)94f4a2713aSLionel Sambuc void call_deleting_dtor(C *obj_ptr) {
95f4a2713aSLionel Sambuc // CHECK: define void @"\01?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
96f4a2713aSLionel Sambuc   delete obj_ptr;
97f4a2713aSLionel Sambuc // CHECK:      %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4
98f4a2713aSLionel Sambuc // CHECK:      br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
99f4a2713aSLionel Sambuc 
100f4a2713aSLionel Sambuc // CHECK:      [[DELETE_NOTNULL]]
101*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
102*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
103*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
104*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
105*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 1)
106*0a6a1f1dSLionel Sambuc // CHECK:      ret void
107*0a6a1f1dSLionel Sambuc }
108*0a6a1f1dSLionel Sambuc 
call_deleting_dtor_and_global_delete(C * obj_ptr)109*0a6a1f1dSLionel Sambuc void call_deleting_dtor_and_global_delete(C *obj_ptr) {
110*0a6a1f1dSLionel Sambuc // CHECK: define void @"\01?call_deleting_dtor_and_global_delete@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
111*0a6a1f1dSLionel Sambuc   ::delete obj_ptr;
112*0a6a1f1dSLionel Sambuc // CHECK:      %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4
113*0a6a1f1dSLionel Sambuc // CHECK:      br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
114*0a6a1f1dSLionel Sambuc 
115*0a6a1f1dSLionel Sambuc // CHECK:      [[DELETE_NOTNULL]]
116*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
117*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
118*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
119*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
120*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   %[[CALL:.*]] = call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0)
121*0a6a1f1dSLionel Sambuc // CHECK-NEXT:   call void @"\01??3@YAXPAX@Z"(i8* %[[CALL]])
122f4a2713aSLionel Sambuc // CHECK:      ret void
123f4a2713aSLionel Sambuc }
124f4a2713aSLionel Sambuc 
125f4a2713aSLionel Sambuc struct D {
126f4a2713aSLionel Sambuc   static int foo();
127f4a2713aSLionel Sambuc 
Dbasic::D128f4a2713aSLionel Sambuc   D() {
129f4a2713aSLionel Sambuc     static int ctor_static = foo();
130f4a2713aSLionel Sambuc     // CHECK that the static in the ctor gets mangled correctly:
131f4a2713aSLionel Sambuc     // CHECK: @"\01?ctor_static@?1???0D@basic@@QAE@XZ@4HA"
132f4a2713aSLionel Sambuc   }
~Dbasic::D133f4a2713aSLionel Sambuc   ~D() {
134f4a2713aSLionel Sambuc     static int dtor_static = foo();
135f4a2713aSLionel Sambuc     // CHECK that the static in the dtor gets mangled correctly:
136f4a2713aSLionel Sambuc     // CHECK: @"\01?dtor_static@?1???1D@basic@@QAE@XZ@4HA"
137f4a2713aSLionel Sambuc   }
138f4a2713aSLionel Sambuc };
139f4a2713aSLionel Sambuc 
use_D()140f4a2713aSLionel Sambuc void use_D() { D c; }
141f4a2713aSLionel Sambuc 
142f4a2713aSLionel Sambuc } // end namespace basic
143f4a2713aSLionel Sambuc 
144*0a6a1f1dSLionel Sambuc namespace dtor_in_second_nvbase {
145*0a6a1f1dSLionel Sambuc 
146*0a6a1f1dSLionel Sambuc struct A {
147*0a6a1f1dSLionel Sambuc   virtual void f();  // A needs vftable to be primary.
148*0a6a1f1dSLionel Sambuc };
149*0a6a1f1dSLionel Sambuc struct B {
150*0a6a1f1dSLionel Sambuc   virtual ~B();
151*0a6a1f1dSLionel Sambuc };
152*0a6a1f1dSLionel Sambuc struct C : A, B {
153*0a6a1f1dSLionel Sambuc   virtual ~C();
154*0a6a1f1dSLionel Sambuc };
155*0a6a1f1dSLionel Sambuc 
~C()156*0a6a1f1dSLionel Sambuc C::~C() {
157*0a6a1f1dSLionel Sambuc // CHECK-LABEL: define x86_thiscallcc void @"\01??1C@dtor_in_second_nvbase@@UAE@XZ"
158*0a6a1f1dSLionel Sambuc // CHECK:       (%"struct.dtor_in_second_nvbase::C"* %this)
159*0a6a1f1dSLionel Sambuc //      No this adjustment!
160*0a6a1f1dSLionel Sambuc // CHECK-NOT: getelementptr
161*0a6a1f1dSLionel Sambuc // CHECK:   load %"struct.dtor_in_second_nvbase::C"** %{{.*}}
162*0a6a1f1dSLionel Sambuc //      Now we this-adjust before calling ~B.
163*0a6a1f1dSLionel Sambuc // CHECK:   bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8*
164*0a6a1f1dSLionel Sambuc // CHECK:   getelementptr inbounds i8* %{{.*}}, i64 4
165*0a6a1f1dSLionel Sambuc // CHECK:   bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"*
166*0a6a1f1dSLionel Sambuc // CHECK:   call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ"
167*0a6a1f1dSLionel Sambuc // CHECK:       (%"struct.dtor_in_second_nvbase::B"* %{{.*}})
168*0a6a1f1dSLionel Sambuc // CHECK:   ret void
169*0a6a1f1dSLionel Sambuc }
170*0a6a1f1dSLionel Sambuc 
foo()171*0a6a1f1dSLionel Sambuc void foo() {
172*0a6a1f1dSLionel Sambuc   C c;
173*0a6a1f1dSLionel Sambuc }
174*0a6a1f1dSLionel Sambuc // DTORS2-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"
175*0a6a1f1dSLionel Sambuc // DTORS2:       (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete)
176*0a6a1f1dSLionel Sambuc //      Do an adjustment from B* to C*.
177*0a6a1f1dSLionel Sambuc // DTORS2:   getelementptr i8* %{{.*}}, i32 -4
178*0a6a1f1dSLionel Sambuc // DTORS2:   bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"*
179*0a6a1f1dSLionel Sambuc // DTORS2:   %[[CALL:.*]] = call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z"
180*0a6a1f1dSLionel Sambuc // DTORS2:   ret i8* %[[CALL]]
181*0a6a1f1dSLionel Sambuc 
182*0a6a1f1dSLionel Sambuc }
183*0a6a1f1dSLionel Sambuc 
184*0a6a1f1dSLionel Sambuc namespace test2 {
185*0a6a1f1dSLionel Sambuc // Just like dtor_in_second_nvbase, except put that in a vbase of a diamond.
186*0a6a1f1dSLionel Sambuc 
187*0a6a1f1dSLionel Sambuc // C's dtor is in the non-primary base.
188*0a6a1f1dSLionel Sambuc struct A { virtual void f(); };
189*0a6a1f1dSLionel Sambuc struct B { virtual ~B(); };
190*0a6a1f1dSLionel Sambuc struct C : A, B { virtual ~C(); int c; };
191*0a6a1f1dSLionel Sambuc 
192*0a6a1f1dSLionel Sambuc // Diamond hierarchy, with C as the shared vbase.
193*0a6a1f1dSLionel Sambuc struct D : virtual C { int d; };
194*0a6a1f1dSLionel Sambuc struct E : virtual C { int e; };
195*0a6a1f1dSLionel Sambuc struct F : D, E { ~F(); int f; };
196*0a6a1f1dSLionel Sambuc 
~F()197*0a6a1f1dSLionel Sambuc F::~F() {
198*0a6a1f1dSLionel Sambuc // CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*)
199*0a6a1f1dSLionel Sambuc //      Do an adjustment from C vbase subobject to F as though F was the
200*0a6a1f1dSLionel Sambuc //      complete type.
201*0a6a1f1dSLionel Sambuc // CHECK:   getelementptr inbounds i8* %{{.*}}, i32 -20
202*0a6a1f1dSLionel Sambuc // CHECK:   bitcast i8* %{{.*}} to %"struct.test2::F"*
203*0a6a1f1dSLionel Sambuc // CHECK:   store %"struct.test2::F"*
204*0a6a1f1dSLionel Sambuc }
205*0a6a1f1dSLionel Sambuc 
foo()206*0a6a1f1dSLionel Sambuc void foo() {
207*0a6a1f1dSLionel Sambuc   F f;
208*0a6a1f1dSLionel Sambuc }
209*0a6a1f1dSLionel Sambuc // DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@UAE@XZ"
210*0a6a1f1dSLionel Sambuc //      Do an adjustment from C* to F*.
211*0a6a1f1dSLionel Sambuc // DTORS3:   getelementptr i8* %{{.*}}, i32 20
212*0a6a1f1dSLionel Sambuc // DTORS3:   bitcast i8* %{{.*}} to %"struct.test2::F"*
213*0a6a1f1dSLionel Sambuc // DTORS3:   call x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"
214*0a6a1f1dSLionel Sambuc // DTORS3:   ret void
215*0a6a1f1dSLionel Sambuc 
216*0a6a1f1dSLionel Sambuc }
217f4a2713aSLionel Sambuc 
218f4a2713aSLionel Sambuc namespace constructors {
219f4a2713aSLionel Sambuc 
220f4a2713aSLionel Sambuc struct A {
Aconstructors::A221f4a2713aSLionel Sambuc   A() {}
222f4a2713aSLionel Sambuc };
223f4a2713aSLionel Sambuc 
224f4a2713aSLionel Sambuc struct B : A {
225f4a2713aSLionel Sambuc   B();
226f4a2713aSLionel Sambuc   ~B();
227f4a2713aSLionel Sambuc };
228f4a2713aSLionel Sambuc 
B()229f4a2713aSLionel Sambuc B::B() {
230f4a2713aSLionel Sambuc   // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)
231f4a2713aSLionel Sambuc   // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
232f4a2713aSLionel Sambuc   // CHECK: ret
233f4a2713aSLionel Sambuc }
234f4a2713aSLionel Sambuc 
235f4a2713aSLionel Sambuc struct C : virtual A {
236f4a2713aSLionel Sambuc   C();
237f4a2713aSLionel Sambuc };
238f4a2713aSLionel Sambuc 
C()239f4a2713aSLionel Sambuc C::C() {
240f4a2713aSLionel Sambuc   // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived)
241f4a2713aSLionel Sambuc   // TODO: make sure this works in the Release build too;
242f4a2713aSLionel Sambuc   // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
243f4a2713aSLionel Sambuc   // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]
244f4a2713aSLionel Sambuc   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
245f4a2713aSLionel Sambuc   // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
246f4a2713aSLionel Sambuc   //
247f4a2713aSLionel Sambuc   // CHECK: [[INIT_VBASES]]
248f4a2713aSLionel Sambuc   // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8*
249f4a2713aSLionel Sambuc   // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0
250*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
251*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
252f4a2713aSLionel Sambuc   // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*
253f4a2713aSLionel Sambuc   // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
254f4a2713aSLionel Sambuc   // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
255f4a2713aSLionel Sambuc   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
256f4a2713aSLionel Sambuc   // CHECK-NEXT: br label %[[SKIP_VBASES]]
257f4a2713aSLionel Sambuc   //
258f4a2713aSLionel Sambuc   // CHECK: [[SKIP_VBASES]]
259f4a2713aSLionel Sambuc   // Class C does not define or override methods, so shouldn't change the vfptr.
260f4a2713aSLionel Sambuc   // CHECK-NOT: @"\01??_7C@constructors@@6B@"
261f4a2713aSLionel Sambuc   // CHECK: ret
262f4a2713aSLionel Sambuc }
263f4a2713aSLionel Sambuc 
create_C()264f4a2713aSLionel Sambuc void create_C() {
265f4a2713aSLionel Sambuc   C c;
266f4a2713aSLionel Sambuc   // CHECK: define void @"\01?create_C@constructors@@YAXXZ"()
267f4a2713aSLionel Sambuc   // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1)
268f4a2713aSLionel Sambuc   // CHECK: ret
269f4a2713aSLionel Sambuc }
270f4a2713aSLionel Sambuc 
271f4a2713aSLionel Sambuc struct D : C {
272f4a2713aSLionel Sambuc   D();
273f4a2713aSLionel Sambuc };
274f4a2713aSLionel Sambuc 
D()275f4a2713aSLionel Sambuc D::D() {
276f4a2713aSLionel Sambuc   // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr
277f4a2713aSLionel Sambuc   // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
278f4a2713aSLionel Sambuc   // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]
279f4a2713aSLionel Sambuc   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
280f4a2713aSLionel Sambuc   // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
281f4a2713aSLionel Sambuc   //
282f4a2713aSLionel Sambuc   // CHECK: [[INIT_VBASES]]
283f4a2713aSLionel Sambuc   // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8*
284f4a2713aSLionel Sambuc   // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0
285*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
286*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
287f4a2713aSLionel Sambuc   // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*
288f4a2713aSLionel Sambuc   // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
289f4a2713aSLionel Sambuc   // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
290f4a2713aSLionel Sambuc   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
291f4a2713aSLionel Sambuc   // CHECK-NEXT: br label %[[SKIP_VBASES]]
292f4a2713aSLionel Sambuc   //
293f4a2713aSLionel Sambuc   // CHECK: [[SKIP_VBASES]]
294f4a2713aSLionel Sambuc   // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
295f4a2713aSLionel Sambuc   // CHECK: ret
296f4a2713aSLionel Sambuc }
297f4a2713aSLionel Sambuc 
298f4a2713aSLionel Sambuc struct E : virtual C {
299f4a2713aSLionel Sambuc   E();
300f4a2713aSLionel Sambuc };
301f4a2713aSLionel Sambuc 
E()302f4a2713aSLionel Sambuc E::E() {
303f4a2713aSLionel Sambuc   // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr
304f4a2713aSLionel Sambuc   // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
305f4a2713aSLionel Sambuc   // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]
306f4a2713aSLionel Sambuc   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
307f4a2713aSLionel Sambuc   // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
308f4a2713aSLionel Sambuc   //
309f4a2713aSLionel Sambuc   // CHECK: [[INIT_VBASES]]
310f4a2713aSLionel Sambuc   // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8*
311f4a2713aSLionel Sambuc   // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0
312*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32**
313*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32]* @"\01??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]]
314f4a2713aSLionel Sambuc   // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 4
315*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32**
316*0a6a1f1dSLionel Sambuc   // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]]
317f4a2713aSLionel Sambuc   // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*
318f4a2713aSLionel Sambuc   // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
319f4a2713aSLionel Sambuc   // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
320f4a2713aSLionel Sambuc   // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
321f4a2713aSLionel Sambuc   // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
322f4a2713aSLionel Sambuc   // CHECK-NEXT: br label %[[SKIP_VBASES]]
323f4a2713aSLionel Sambuc   //
324f4a2713aSLionel Sambuc   // CHECK: [[SKIP_VBASES]]
325f4a2713aSLionel Sambuc   // CHECK: ret
326f4a2713aSLionel Sambuc }
327f4a2713aSLionel Sambuc 
328f4a2713aSLionel Sambuc // PR16735 - even abstract classes should have a constructor emitted.
329f4a2713aSLionel Sambuc struct F {
330f4a2713aSLionel Sambuc   F();
331f4a2713aSLionel Sambuc   virtual void f() = 0;
332f4a2713aSLionel Sambuc };
333f4a2713aSLionel Sambuc 
F()334f4a2713aSLionel Sambuc F::F() {}
335f4a2713aSLionel Sambuc // CHECK: define x86_thiscallcc %"struct.constructors::F"* @"\01??0F@constructors@@QAE@XZ"
336f4a2713aSLionel Sambuc 
337f4a2713aSLionel Sambuc } // end namespace constructors
338f4a2713aSLionel Sambuc 
339f4a2713aSLionel Sambuc namespace dtors {
340f4a2713aSLionel Sambuc 
341f4a2713aSLionel Sambuc struct A {
342f4a2713aSLionel Sambuc   ~A();
343f4a2713aSLionel Sambuc };
344f4a2713aSLionel Sambuc 
call_nv_complete(A * a)345f4a2713aSLionel Sambuc void call_nv_complete(A *a) {
346f4a2713aSLionel Sambuc   a->~A();
347f4a2713aSLionel Sambuc // CHECK: define void @"\01?call_nv_complete@dtors@@YAXPAUA@1@@Z"
348f4a2713aSLionel Sambuc // CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
349f4a2713aSLionel Sambuc // CHECK: ret
350f4a2713aSLionel Sambuc }
351f4a2713aSLionel Sambuc 
352f4a2713aSLionel Sambuc // CHECK: declare x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
353f4a2713aSLionel Sambuc 
354f4a2713aSLionel Sambuc // Now try some virtual bases, where we need the complete dtor.
355f4a2713aSLionel Sambuc 
356f4a2713aSLionel Sambuc struct B : virtual A { ~B(); };
357f4a2713aSLionel Sambuc struct C : virtual A { ~C(); };
358f4a2713aSLionel Sambuc struct D : B, C { ~D(); };
359f4a2713aSLionel Sambuc 
call_vbase_complete(D * d)360f4a2713aSLionel Sambuc void call_vbase_complete(D *d) {
361f4a2713aSLionel Sambuc   d->~D();
362f4a2713aSLionel Sambuc // CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
363f4a2713aSLionel Sambuc // CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
364f4a2713aSLionel Sambuc // CHECK: ret
365f4a2713aSLionel Sambuc }
366f4a2713aSLionel Sambuc 
367f4a2713aSLionel Sambuc // The complete dtor should call the base dtors for D and the vbase A (once).
368f4a2713aSLionel Sambuc // CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"
369f4a2713aSLionel Sambuc // CHECK-NOT: call
370f4a2713aSLionel Sambuc // CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ"
371f4a2713aSLionel Sambuc // CHECK-NOT: call
372f4a2713aSLionel Sambuc // CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
373f4a2713aSLionel Sambuc // CHECK-NOT: call
374f4a2713aSLionel Sambuc // CHECK: ret
375f4a2713aSLionel Sambuc 
destroy_d_complete()376f4a2713aSLionel Sambuc void destroy_d_complete() {
377f4a2713aSLionel Sambuc   D d;
378f4a2713aSLionel Sambuc // CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ"
379f4a2713aSLionel Sambuc // CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
380f4a2713aSLionel Sambuc // CHECK: ret
381f4a2713aSLionel Sambuc }
382f4a2713aSLionel Sambuc 
383f4a2713aSLionel Sambuc // FIXME: Clang manually inlines the deletion, so we don't get a call to the
384f4a2713aSLionel Sambuc // deleting dtor (_G).  The only way to call deleting dtors currently is through
385f4a2713aSLionel Sambuc // a vftable.
call_nv_deleting_dtor(D * d)386f4a2713aSLionel Sambuc void call_nv_deleting_dtor(D *d) {
387f4a2713aSLionel Sambuc   delete d;
388f4a2713aSLionel Sambuc // CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
389f4a2713aSLionel Sambuc // CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
390f4a2713aSLionel Sambuc // CHECK: call void @"\01??3@YAXPAX@Z"
391f4a2713aSLionel Sambuc // CHECK: ret
392f4a2713aSLionel Sambuc }
393f4a2713aSLionel Sambuc 
394f4a2713aSLionel Sambuc }
395*0a6a1f1dSLionel Sambuc 
396*0a6a1f1dSLionel Sambuc namespace test1 {
397*0a6a1f1dSLionel Sambuc struct A { };
398*0a6a1f1dSLionel Sambuc struct B : virtual A {
399*0a6a1f1dSLionel Sambuc   B(int *a);
400*0a6a1f1dSLionel Sambuc   B(const char *a, ...);
401*0a6a1f1dSLionel Sambuc   __cdecl B(short *a);
402*0a6a1f1dSLionel Sambuc };
B(int * a)403*0a6a1f1dSLionel Sambuc B::B(int *a) {}
B(const char * a,...)404*0a6a1f1dSLionel Sambuc B::B(const char *a, ...) {}
B(short * a)405*0a6a1f1dSLionel Sambuc B::B(short *a) {}
406*0a6a1f1dSLionel Sambuc // CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
407*0a6a1f1dSLionel Sambuc // CHECK:               (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived)
408*0a6a1f1dSLionel Sambuc // CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ"
409*0a6a1f1dSLionel Sambuc // CHECK:               (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...)
410*0a6a1f1dSLionel Sambuc 
411*0a6a1f1dSLionel Sambuc // FIXME: This should be x86_thiscallcc.  MSVC ignores explicit CCs on structors.
412*0a6a1f1dSLionel Sambuc // CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PAF@Z"
413*0a6a1f1dSLionel Sambuc // CHECK:               (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived)
414*0a6a1f1dSLionel Sambuc 
construct_b()415*0a6a1f1dSLionel Sambuc void construct_b() {
416*0a6a1f1dSLionel Sambuc   int a;
417*0a6a1f1dSLionel Sambuc   B b1(&a);
418*0a6a1f1dSLionel Sambuc   B b2("%d %d", 1, 2);
419*0a6a1f1dSLionel Sambuc }
420*0a6a1f1dSLionel Sambuc // CHECK-LABEL: define void @"\01?construct_b@test1@@YAXXZ"()
421*0a6a1f1dSLionel Sambuc // CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
422*0a6a1f1dSLionel Sambuc // CHECK:               (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1)
423*0a6a1f1dSLionel Sambuc // CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...)* @"\01??0B@test1@@QAA@PBDZZ"
424*0a6a1f1dSLionel Sambuc // CHECK:               (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2)
425*0a6a1f1dSLionel Sambuc }
426*0a6a1f1dSLionel Sambuc 
427*0a6a1f1dSLionel Sambuc namespace implicit_copy_vtable {
428*0a6a1f1dSLionel Sambuc // This was a crash that only reproduced in ABIs without key functions.
429*0a6a1f1dSLionel Sambuc struct ImplicitCopy {
430*0a6a1f1dSLionel Sambuc   // implicit copy ctor
431*0a6a1f1dSLionel Sambuc   virtual ~ImplicitCopy();
432*0a6a1f1dSLionel Sambuc };
CreateCopy(ImplicitCopy * a)433*0a6a1f1dSLionel Sambuc void CreateCopy(ImplicitCopy *a) {
434*0a6a1f1dSLionel Sambuc   new ImplicitCopy(*a);
435*0a6a1f1dSLionel Sambuc }
436*0a6a1f1dSLionel Sambuc // CHECK: store {{.*}} @"\01??_7ImplicitCopy@implicit_copy_vtable@@6B@"
437*0a6a1f1dSLionel Sambuc 
438*0a6a1f1dSLionel Sambuc struct MoveOnly {
439*0a6a1f1dSLionel Sambuc   MoveOnly(MoveOnly &&o) = default;
440*0a6a1f1dSLionel Sambuc   virtual ~MoveOnly();
441*0a6a1f1dSLionel Sambuc };
442*0a6a1f1dSLionel Sambuc MoveOnly &&f();
g()443*0a6a1f1dSLionel Sambuc void g() { new MoveOnly(f()); }
444*0a6a1f1dSLionel Sambuc // CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@"
445*0a6a1f1dSLionel Sambuc }
446*0a6a1f1dSLionel Sambuc 
447*0a6a1f1dSLionel Sambuc // Dtor thunks for classes in anonymous namespaces should be internal, not
448*0a6a1f1dSLionel Sambuc // linkonce_odr.
449*0a6a1f1dSLionel Sambuc namespace {
450*0a6a1f1dSLionel Sambuc struct A {
~A__anon49af16620111::A451*0a6a1f1dSLionel Sambuc   virtual ~A() { }
452*0a6a1f1dSLionel Sambuc };
453*0a6a1f1dSLionel Sambuc }
getA()454*0a6a1f1dSLionel Sambuc void *getA() {
455*0a6a1f1dSLionel Sambuc   return (void*)new A();
456*0a6a1f1dSLionel Sambuc }
457*0a6a1f1dSLionel Sambuc // CHECK: define internal x86_thiscallcc i8* @"\01??_GA@?A@@UAEPAXI@Z"
458*0a6a1f1dSLionel Sambuc // CHECK:               (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
459*0a6a1f1dSLionel Sambuc // CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ"
460*0a6a1f1dSLionel Sambuc // CHECK:               (%"struct.(anonymous namespace)::A"* %this)
461