1*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s
2*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s
3*67e74705SXin Li
4*67e74705SXin Li struct A {
5*67e74705SXin Li A();
6*67e74705SXin Li ~A();
7*67e74705SXin Li int a;
8*67e74705SXin Li };
9*67e74705SXin Li
10*67e74705SXin Li A getA();
11*67e74705SXin Li
12*67e74705SXin Li int TakesTwo(A a, A b);
HasEHCleanup()13*67e74705SXin Li void HasEHCleanup() {
14*67e74705SXin Li TakesTwo(getA(), getA());
15*67e74705SXin Li }
16*67e74705SXin Li
17*67e74705SXin Li // With exceptions, we need to clean up at least one of these temporaries.
18*67e74705SXin Li // WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
19*67e74705SXin Li // WIN32: %[[base:.*]] = call i8* @llvm.stacksave()
20*67e74705SXin Li // If this call throws, we have to restore the stack.
21*67e74705SXin Li // WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
22*67e74705SXin Li // If this call throws, we have to cleanup the first temporary.
23*67e74705SXin Li // WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
24*67e74705SXin Li // If this call throws, we have to cleanup the stacksave.
25*67e74705SXin Li // WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
26*67e74705SXin Li // WIN32: call void @llvm.stackrestore
27*67e74705SXin Li // WIN32: ret void
28*67e74705SXin Li //
29*67e74705SXin Li // There should be one dtor call for unwinding from the second getA.
30*67e74705SXin Li // WIN32: cleanuppad
31*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
32*67e74705SXin Li // WIN32-NOT: @"\01??1A@@QAE@XZ"
33*67e74705SXin Li // WIN32: }
34*67e74705SXin Li
35*67e74705SXin Li void TakeRef(const A &a);
HasDeactivatedCleanups()36*67e74705SXin Li int HasDeactivatedCleanups() {
37*67e74705SXin Li return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
38*67e74705SXin Li }
39*67e74705SXin Li
40*67e74705SXin Li // WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
41*67e74705SXin Li // WIN32: %[[isactive:.*]] = alloca i1
42*67e74705SXin Li // WIN32: call i8* @llvm.stacksave()
43*67e74705SXin Li // WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
44*67e74705SXin Li // WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
45*67e74705SXin Li // WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
46*67e74705SXin Li // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
47*67e74705SXin Li //
48*67e74705SXin Li // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
49*67e74705SXin Li // WIN32: store i1 true, i1* %[[isactive]]
50*67e74705SXin Li //
51*67e74705SXin Li // WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
52*67e74705SXin Li // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
53*67e74705SXin Li // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
54*67e74705SXin Li // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
55*67e74705SXin Li // WIN32: store i1 false, i1* %[[isactive]]
56*67e74705SXin Li //
57*67e74705SXin Li // WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
58*67e74705SXin Li // Destroy the two const ref temporaries.
59*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
60*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
61*67e74705SXin Li // WIN32: ret i32
62*67e74705SXin Li //
63*67e74705SXin Li // Conditionally destroy arg1.
64*67e74705SXin Li // WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]]
65*67e74705SXin Li // WIN32: br i1 %[[cond]]
66*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
67*67e74705SXin Li // WIN32: }
68*67e74705SXin Li
69*67e74705SXin Li // Test putting the cleanups inside a conditional.
70*67e74705SXin Li int CouldThrow();
HasConditionalCleanup(bool cond)71*67e74705SXin Li int HasConditionalCleanup(bool cond) {
72*67e74705SXin Li return (cond ? TakesTwo(A(), A()) : CouldThrow());
73*67e74705SXin Li }
74*67e74705SXin Li
75*67e74705SXin Li // WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
76*67e74705SXin Li // WIN32: store i1 false
77*67e74705SXin Li // WIN32: br i1
78*67e74705SXin Li // WIN32: call i8* @llvm.stacksave()
79*67e74705SXin Li // WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
80*67e74705SXin Li // WIN32: store i1 true
81*67e74705SXin Li // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
82*67e74705SXin Li // WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
83*67e74705SXin Li //
84*67e74705SXin Li // WIN32: call void @llvm.stackrestore
85*67e74705SXin Li //
86*67e74705SXin Li // WIN32: call i32 @"\01?CouldThrow@@YAHXZ"()
87*67e74705SXin Li //
88*67e74705SXin Li // Only one dtor in the invoke for arg1
89*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
90*67e74705SXin Li // WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
91*67e74705SXin Li // WIN32: }
92*67e74705SXin Li
93*67e74705SXin Li // Now test both.
HasConditionalDeactivatedCleanups(bool cond)94*67e74705SXin Li int HasConditionalDeactivatedCleanups(bool cond) {
95*67e74705SXin Li return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
96*67e74705SXin Li }
97*67e74705SXin Li
98*67e74705SXin Li // WIN32-O0-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
99*67e74705SXin Li // WIN32-O0: alloca i1
100*67e74705SXin Li // WIN32-O0: %[[arg1_cond:.*]] = alloca i1
101*67e74705SXin Li // Start all four cleanups as deactivated.
102*67e74705SXin Li // WIN32-O0: store i1 false
103*67e74705SXin Li // WIN32-O0: store i1 false
104*67e74705SXin Li // WIN32-O0: store i1 false
105*67e74705SXin Li // WIN32-O0: store i1 false
106*67e74705SXin Li // WIN32-O0: br i1
107*67e74705SXin Li // True condition.
108*67e74705SXin Li // WIN32-O0: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
109*67e74705SXin Li // WIN32-O0: store i1 true
110*67e74705SXin Li // WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
111*67e74705SXin Li // WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
112*67e74705SXin Li // WIN32-O0: store i1 true, i1* %[[arg1_cond]]
113*67e74705SXin Li // WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
114*67e74705SXin Li // WIN32-O0: store i1 true
115*67e74705SXin Li // WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
116*67e74705SXin Li // WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
117*67e74705SXin Li // WIN32-O0: store i1 true
118*67e74705SXin Li // WIN32-O0: store i1 false, i1* %[[arg1_cond]]
119*67e74705SXin Li // WIN32-O0: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
120*67e74705SXin Li // False condition.
121*67e74705SXin Li // WIN32-O0: invoke i32 @"\01?CouldThrow@@YAHXZ"()
122*67e74705SXin Li // Two normal cleanups for TakeRef args.
123*67e74705SXin Li // WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
124*67e74705SXin Li // WIN32-O0-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
125*67e74705SXin Li // WIN32-O0: ret i32
126*67e74705SXin Li //
127*67e74705SXin Li // Somewhere in the landing pad soup, we conditionally destroy arg1.
128*67e74705SXin Li // WIN32-O0: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
129*67e74705SXin Li // WIN32-O0: br i1 %[[isactive]]
130*67e74705SXin Li // WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
131*67e74705SXin Li // WIN32-O0: }
132*67e74705SXin Li
133*67e74705SXin Li // WIN32-O3-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
134*67e74705SXin Li // WIN32-O3: alloca i1
135*67e74705SXin Li // WIN32-O3: alloca i1
136*67e74705SXin Li // WIN32-O3: %[[arg1_cond:.*]] = alloca i1
137*67e74705SXin Li // Start all four cleanups as deactivated.
138*67e74705SXin Li // WIN32-O3: store i1 false
139*67e74705SXin Li // WIN32-O3: store i1 false
140*67e74705SXin Li // WIN32-O3: store i1 false
141*67e74705SXin Li // WIN32-O3: store i1 false
142*67e74705SXin Li // WIN32-O3: store i1 false
143*67e74705SXin Li // WIN32-O3: store i1 false
144*67e74705SXin Li // WIN32-O3: br i1
145*67e74705SXin Li // True condition.
146*67e74705SXin Li // WIN32-O3: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
147*67e74705SXin Li // WIN32-O3: store i1 true
148*67e74705SXin Li // WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
149*67e74705SXin Li // WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
150*67e74705SXin Li // WIN32-O3: store i1 true, i1* %[[arg1_cond]]
151*67e74705SXin Li // WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
152*67e74705SXin Li // WIN32-O3: store i1 true
153*67e74705SXin Li // WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
154*67e74705SXin Li // WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
155*67e74705SXin Li // WIN32-O3: store i1 true
156*67e74705SXin Li // WIN32-O3: store i1 false, i1* %[[arg1_cond]]
157*67e74705SXin Li // WIN32-O3: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
158*67e74705SXin Li // False condition.
159*67e74705SXin Li // WIN32-O3: invoke i32 @"\01?CouldThrow@@YAHXZ"()
160*67e74705SXin Li // Two normal cleanups for TakeRef args.
161*67e74705SXin Li // WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
162*67e74705SXin Li // WIN32-O3-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
163*67e74705SXin Li // WIN32-O3: ret i32
164*67e74705SXin Li //
165*67e74705SXin Li // Somewhere in the landing pad soup, we conditionally destroy arg1.
166*67e74705SXin Li // WIN32-O3: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
167*67e74705SXin Li // WIN32-O3: br i1 %[[isactive]]
168*67e74705SXin Li // WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
169*67e74705SXin Li // WIN32-O3: }
170*67e74705SXin Li
171*67e74705SXin Li namespace crash_on_partial_destroy {
172*67e74705SXin Li struct A {
173*67e74705SXin Li virtual ~A();
174*67e74705SXin Li };
175*67e74705SXin Li
176*67e74705SXin Li struct B : virtual A {
177*67e74705SXin Li // Has an implicit destructor.
178*67e74705SXin Li };
179*67e74705SXin Li
180*67e74705SXin Li struct C : B {
181*67e74705SXin Li C();
182*67e74705SXin Li };
183*67e74705SXin Li
184*67e74705SXin Li void foo();
185*67e74705SXin Li // We used to crash when emitting this.
C()186*67e74705SXin Li C::C() { foo(); }
187*67e74705SXin Li
188*67e74705SXin Li // Verify that we don't bother with a vbtable lookup when adjusting the this
189*67e74705SXin Li // pointer to call a base destructor from a constructor while unwinding.
190*67e74705SXin Li // WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
191*67e74705SXin Li // WIN32: cleanuppad
192*67e74705SXin Li //
193*67e74705SXin Li // We shouldn't do any vbptr loads, just constant GEPs.
194*67e74705SXin Li // WIN32-NOT: load
195*67e74705SXin Li // WIN32: getelementptr i8, i8* %{{.*}}, i32 4
196*67e74705SXin Li // WIN32-NOT: load
197*67e74705SXin Li // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
198*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"
199*67e74705SXin Li //
200*67e74705SXin Li // WIN32-NOT: load
201*67e74705SXin Li // WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
202*67e74705SXin Li // WIN32-NOT: load
203*67e74705SXin Li // WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4
204*67e74705SXin Li // WIN32-NOT: load
205*67e74705SXin Li // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
206*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
207*67e74705SXin Li // WIN32: }
208*67e74705SXin Li }
209*67e74705SXin Li
210*67e74705SXin Li namespace dont_call_terminate {
211*67e74705SXin Li struct C {
212*67e74705SXin Li ~C();
213*67e74705SXin Li };
214*67e74705SXin Li void g();
f()215*67e74705SXin Li void f() {
216*67e74705SXin Li C c;
217*67e74705SXin Li g();
218*67e74705SXin Li }
219*67e74705SXin Li
220*67e74705SXin Li // WIN32-LABEL: define void @"\01?f@dont_call_terminate@@YAXXZ"()
221*67e74705SXin Li // WIN32: invoke void @"\01?g@dont_call_terminate@@YAXXZ"()
222*67e74705SXin Li // WIN32-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
223*67e74705SXin Li //
224*67e74705SXin Li // WIN32: [[cont]]
225*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
226*67e74705SXin Li //
227*67e74705SXin Li // WIN32: [[lpad]]
228*67e74705SXin Li // WIN32-NEXT: cleanuppad
229*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
230*67e74705SXin Li }
231*67e74705SXin Li
232*67e74705SXin Li namespace noexcept_false_dtor {
233*67e74705SXin Li struct D {
234*67e74705SXin Li ~D() noexcept(false);
235*67e74705SXin Li };
f()236*67e74705SXin Li void f() {
237*67e74705SXin Li D d;
238*67e74705SXin Li CouldThrow();
239*67e74705SXin Li }
240*67e74705SXin Li }
241*67e74705SXin Li
242*67e74705SXin Li // WIN32-LABEL: define void @"\01?f@noexcept_false_dtor@@YAXXZ"()
243*67e74705SXin Li // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
244*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
245*67e74705SXin Li // WIN32: cleanuppad
246*67e74705SXin Li // WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
247*67e74705SXin Li // WIN32: cleanupret
248*67e74705SXin Li
249*67e74705SXin Li namespace lifetime_marker {
250*67e74705SXin Li struct C {
251*67e74705SXin Li ~C();
252*67e74705SXin Li };
253*67e74705SXin Li void g();
f()254*67e74705SXin Li void f() {
255*67e74705SXin Li C c;
256*67e74705SXin Li g();
257*67e74705SXin Li }
258*67e74705SXin Li
259*67e74705SXin Li // WIN32-LIFETIME-LABEL: define void @"\01?f@lifetime_marker@@YAXXZ"()
260*67e74705SXin Li // WIN32-LIFETIME: %[[c:.*]] = alloca %"struct.lifetime_marker::C"
261*67e74705SXin Li // WIN32-LIFETIME: %[[bc0:.*]] = bitcast %"struct.lifetime_marker::C"* %c to i8*
262*67e74705SXin Li // WIN32-LIFETIME: call void @llvm.lifetime.start(i64 1, i8* %[[bc0]])
263*67e74705SXin Li // WIN32-LIFETIME: invoke void @"\01?g@lifetime_marker@@YAXXZ"()
264*67e74705SXin Li // WIN32-LIFETIME-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad0:[^ ]*]]
265*67e74705SXin Li //
266*67e74705SXin Li // WIN32-LIFETIME: [[cont]]
267*67e74705SXin Li // WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
268*67e74705SXin Li // WIN32-LIFETIME: %[[bc1:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8*
269*67e74705SXin Li // WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc1]])
270*67e74705SXin Li //
271*67e74705SXin Li // WIN32-LIFETIME: [[lpad0]]
272*67e74705SXin Li // WIN32-LIFETIME-NEXT: cleanuppad
273*67e74705SXin Li // WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
274*67e74705SXin Li // WIN32-LIFETIME: cleanupret {{.*}} unwind label %[[lpad1:[^ ]*]]
275*67e74705SXin Li //
276*67e74705SXin Li // WIN32-LIFETIME: [[lpad1]]
277*67e74705SXin Li // WIN32-LIFETIME-NEXT: cleanuppad
278*67e74705SXin Li // WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8*
279*67e74705SXin Li // WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc2]])
280*67e74705SXin Li }
281