blob: 8c20c9e9ce21feaffebabccc05807864fc34399d [file] [log] [blame]
Anders Carlssonabea9512011-02-28 00:40:07 +00001// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s
Anders Carlsson8370c582009-12-11 00:32:37 +00002
John McCall7d8647f2010-09-14 07:57:04 +00003typedef typeof(sizeof(0)) size_t;
Anders Carlsson8370c582009-12-11 00:32:37 +00004
John McCall7d8647f2010-09-14 07:57:04 +00005// This just shouldn't crash.
6namespace test0 {
7 struct allocator {
8 allocator();
9 allocator(const allocator&);
10 ~allocator();
11 };
Anders Carlsson8370c582009-12-11 00:32:37 +000012
John McCall7d8647f2010-09-14 07:57:04 +000013 void f();
14 void g(bool b, bool c) {
15 if (b) {
16 if (!c)
17 throw allocator();
18
19 return;
20 }
21 f();
Anders Carlsson8370c582009-12-11 00:32:37 +000022 }
John McCall7d8647f2010-09-14 07:57:04 +000023}
24
25namespace test1 {
26 struct A { A(int); A(int, int); ~A(); void *p; };
27
28 A *a() {
29 // CHECK: define [[A:%.*]]* @_ZN5test11aEv()
30 // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8)
31 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
32 // CHECK-NEXT: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 5)
33 // CHECK: ret [[A]]* [[CAST]]
34 // CHECK: call void @_ZdlPv(i8* [[NEW]])
35 return new A(5);
36 }
37
38 A *b() {
39 // CHECK: define [[A:%.*]]* @_ZN5test11bEv()
40 // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8)
41 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
42 // CHECK-NEXT: [[FOO:%.*]] = invoke i32 @_ZN5test13fooEv()
43 // CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[FOO]])
44 // CHECK: ret [[A]]* [[CAST]]
45 // CHECK: call void @_ZdlPv(i8* [[NEW]])
46 extern int foo();
47 return new A(foo());
48 }
49
50 struct B { B(); ~B(); operator int(); int x; };
51 B makeB();
52
53 A *c() {
54 // CHECK: define [[A:%.*]]* @_ZN5test11cEv()
55 // CHECK: [[ACTIVE:%.*]] = alloca i1
John McCall7d8647f2010-09-14 07:57:04 +000056 // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8)
John McCall6f103ba2011-11-10 10:43:54 +000057 // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
John McCall7d8647f2010-09-14 07:57:04 +000058 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
59 // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]])
60 // CHECK: [[T1:%.*]] = getelementptr inbounds [[B]]* [[T0]], i32 0, i32 0
61 // CHECK-NEXT: [[T2:%.*]] = load i32* [[T1]], align 4
62 // CHECK-NEXT: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[T2]])
63 // CHECK: store i1 false, i1* [[ACTIVE]]
64 // CHECK-NEXT: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]])
65 // CHECK: ret [[A]]* [[CAST]]
66 // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]]
67 // CHECK-NEXT: br i1 [[ISACTIVE]]
68 // CHECK: call void @_ZdlPv(i8* [[NEW]])
69 return new A(B().x);
70 }
71
72 A *d() {
73 // CHECK: define [[A:%.*]]* @_ZN5test11dEv()
74 // CHECK: [[ACTIVE:%.*]] = alloca i1
John McCall7d8647f2010-09-14 07:57:04 +000075 // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8)
John McCall6f103ba2011-11-10 10:43:54 +000076 // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
John McCall7d8647f2010-09-14 07:57:04 +000077 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
78 // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]])
79 // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]])
80 // CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[T1]])
81 // CHECK: store i1 false, i1* [[ACTIVE]]
82 // CHECK-NEXT: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]])
83 // CHECK: ret [[A]]* [[CAST]]
84 // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]]
85 // CHECK-NEXT: br i1 [[ISACTIVE]]
86 // CHECK: call void @_ZdlPv(i8* [[NEW]])
87 return new A(B());
88 }
89
90 A *e() {
91 // CHECK: define [[A:%.*]]* @_ZN5test11eEv()
92 // CHECK: [[ACTIVE:%.*]] = alloca i1
John McCall7d8647f2010-09-14 07:57:04 +000093 // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8)
John McCall6f103ba2011-11-10 10:43:54 +000094 // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
John McCall7d8647f2010-09-14 07:57:04 +000095 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
96 // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]])
97 // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]])
98 // CHECK: invoke void @_ZN5test11BC1Ev([[B]]* [[T2:%.*]])
99 // CHECK: [[T3:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T2]])
100 // CHECK: invoke void @_ZN5test11AC1Eii([[A]]* [[CAST]], i32 [[T1]], i32 [[T3]])
101 // CHECK: store i1 false, i1* [[ACTIVE]]
102 // CHECK-NEXT: invoke void @_ZN5test11BD1Ev([[B]]* [[T2]])
103 // CHECK: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]])
104 // CHECK: ret [[A]]* [[CAST]]
105 // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]]
106 // CHECK-NEXT: br i1 [[ISACTIVE]]
107 // CHECK: call void @_ZdlPv(i8* [[NEW]])
108 return new A(B(), B());
109 }
110 A *f() {
111 return new A(makeB().x);
112 }
113 A *g() {
114 return new A(makeB());
115 }
116 A *h() {
117 return new A(makeB(), makeB());
118 }
119
120 A *i() {
121 // CHECK: define [[A:%.*]]* @_ZN5test11iEv()
122 // CHECK: [[X:%.*]] = alloca [[A]]*, align 8
123 // CHECK: [[ACTIVE:%.*]] = alloca i1
John McCall6f103ba2011-11-10 10:43:54 +0000124 // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8)
125 // CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
John McCall7d8647f2010-09-14 07:57:04 +0000126 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
127 // CHECK-NEXT: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret [[T0:%.*]])
128 // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]])
129 // CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[T1]])
130 // CHECK: store i1 false, i1* [[ACTIVE]]
131 // CHECK-NEXT: store [[A]]* [[CAST]], [[A]]** [[X]], align 8
132 // CHECK: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret [[T2:%.*]])
133 // CHECK: [[RET:%.*]] = load [[A]]** [[X]], align 8
134 // CHECK: invoke void @_ZN5test11BD1Ev([[B]]* [[T2]])
135 // CHECK: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]])
136 // CHECK: ret [[A]]* [[RET]]
137 // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]]
138 // CHECK-NEXT: br i1 [[ISACTIVE]]
139 // CHECK: call void @_ZdlPv(i8* [[NEW]])
140 A *x;
141 return (x = new A(makeB()), makeB(), x);
142 }
143}
144
145namespace test2 {
146 struct A {
147 A(int); A(int, int); ~A();
148 void *p;
149 void *operator new(size_t);
150 void operator delete(void*, size_t);
151 };
152
153 A *a() {
154 // CHECK: define [[A:%.*]]* @_ZN5test21aEv()
155 // CHECK: [[NEW:%.*]] = call i8* @_ZN5test21AnwEm(i64 8)
156 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
157 // CHECK-NEXT: invoke void @_ZN5test21AC1Ei([[A]]* [[CAST]], i32 5)
158 // CHECK: ret [[A]]* [[CAST]]
159 // CHECK: invoke void @_ZN5test21AdlEPvm(i8* [[NEW]], i64 8)
160 // CHECK: call void @_ZSt9terminatev()
161 return new A(5);
162 }
163}
164
165namespace test3 {
166 struct A {
John McCall3019c442010-09-17 00:50:28 +0000167 A(int); A(int, int); A(const A&); ~A();
John McCall7d8647f2010-09-14 07:57:04 +0000168 void *p;
John McCall3019c442010-09-17 00:50:28 +0000169 void *operator new(size_t, void*, double);
170 void operator delete(void*, void*, double);
John McCall7d8647f2010-09-14 07:57:04 +0000171 };
172
John McCall3019c442010-09-17 00:50:28 +0000173 void *foo();
174 double bar();
175 A makeA(), *makeAPtr();
176
John McCall7d8647f2010-09-14 07:57:04 +0000177 A *a() {
178 // CHECK: define [[A:%.*]]* @_ZN5test31aEv()
179 // CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv()
John McCall3019c442010-09-17 00:50:28 +0000180 // CHECK: [[BAR:%.*]] = call double @_ZN5test33barEv()
181 // CHECK: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[BAR]])
John McCall7d8647f2010-09-14 07:57:04 +0000182 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
183 // CHECK-NEXT: invoke void @_ZN5test31AC1Ei([[A]]* [[CAST]], i32 5)
184 // CHECK: ret [[A]]* [[CAST]]
John McCall3019c442010-09-17 00:50:28 +0000185 // CHECK: invoke void @_ZN5test31AdlEPvS1_d(i8* [[NEW]], i8* [[FOO]], double [[BAR]])
John McCall7d8647f2010-09-14 07:57:04 +0000186 // CHECK: call void @_ZSt9terminatev()
John McCall7d8647f2010-09-14 07:57:04 +0000187 return new(foo(),bar()) A(5);
188 }
John McCall3019c442010-09-17 00:50:28 +0000189
190 // rdar://problem/8439196
191 A *b(bool cond) {
192
193 // CHECK: define [[A:%.*]]* @_ZN5test31bEb(i1 zeroext
194 // CHECK: [[SAVED0:%.*]] = alloca i8*
195 // CHECK-NEXT: [[SAVED1:%.*]] = alloca i8*
196 // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1
John McCall3019c442010-09-17 00:50:28 +0000197
198 // CHECK: [[COND:%.*]] = trunc i8 {{.*}} to i1
John McCall6f103ba2011-11-10 10:43:54 +0000199 // CHECK-NEXT: store i1 false, i1* [[CLEANUPACTIVE]]
John McCall3019c442010-09-17 00:50:28 +0000200 // CHECK-NEXT: br i1 [[COND]]
201 return (cond ?
202
203 // CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv()
204 // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[CONST:.*]])
205 // CHECK-NEXT: store i8* [[NEW]], i8** [[SAVED0]]
206 // CHECK-NEXT: store i8* [[FOO]], i8** [[SAVED1]]
207 // CHECK-NEXT: store i1 true, i1* [[CLEANUPACTIVE]]
208 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
Eli Friedman22cfaf52012-02-16 22:45:48 +0000209 // CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret [[CAST]])
210 // CHECK: br label
John McCall3019c442010-09-17 00:50:28 +0000211 // -> cond.end
212 new(foo(),10.0) A(makeA()) :
213
Eli Friedman22cfaf52012-02-16 22:45:48 +0000214 // CHECK: [[MAKE:%.*]] = call [[A]]* @_ZN5test38makeAPtrEv()
John McCall3019c442010-09-17 00:50:28 +0000215 // CHECK: br label
216 // -> cond.end
217 makeAPtr());
218
219 // cond.end:
220 // CHECK: [[RESULT:%.*]] = phi [[A]]* {{.*}}[[CAST]]{{.*}}[[MAKE]]
John McCall3019c442010-09-17 00:50:28 +0000221 // CHECK: ret [[A]]* [[RESULT]]
222
223 // in the EH path:
224 // CHECK: [[ISACTIVE:%.*]] = load i1* [[CLEANUPACTIVE]]
225 // CHECK-NEXT: br i1 [[ISACTIVE]]
226 // CHECK: [[V0:%.*]] = load i8** [[SAVED0]]
227 // CHECK-NEXT: [[V1:%.*]] = load i8** [[SAVED1]]
228 // CHECK-NEXT: invoke void @_ZN5test31AdlEPvS1_d(i8* [[V0]], i8* [[V1]], double [[CONST]])
229 }
John McCall7d8647f2010-09-14 07:57:04 +0000230}
231
232namespace test4 {
233 struct A {
234 A(int); A(int, int); ~A();
235 void *p;
236 void *operator new(size_t, void*, void*);
237 void operator delete(void*, size_t, void*, void*); // not a match
238 };
239
240 A *a() {
241 // CHECK: define [[A:%.*]]* @_ZN5test41aEv()
242 // CHECK: [[FOO:%.*]] = call i8* @_ZN5test43fooEv()
243 // CHECK-NEXT: [[BAR:%.*]] = call i8* @_ZN5test43barEv()
244 // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test41AnwEmPvS1_(i64 8, i8* [[FOO]], i8* [[BAR]])
245 // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
246 // CHECK-NEXT: call void @_ZN5test41AC1Ei([[A]]* [[CAST]], i32 5)
247 // CHECK-NEXT: ret [[A]]* [[CAST]]
248 extern void *foo(), *bar();
249
250 return new(foo(),bar()) A(5);
251 }
Anders Carlsson8370c582009-12-11 00:32:37 +0000252}
John McCalle996ffd2011-02-16 08:02:54 +0000253
254// PR7908
255namespace test5 {
256 struct T { T(); ~T(); };
257
258 struct A {
259 A(const A &x, const T &t = T());
260 ~A();
261 };
262
263 void foo();
264
265 // CHECK: define void @_ZN5test54testEv()
266 // CHECK: [[EXNSLOT:%.*]] = alloca i8*
John McCall93c332a2011-05-28 21:13:02 +0000267 // CHECK-NEXT: [[SELECTORSLOT:%.*]] = alloca i32
John McCalle996ffd2011-02-16 08:02:54 +0000268 // CHECK-NEXT: [[A:%.*]] = alloca [[A_T:%.*]], align 1
269 // CHECK-NEXT: [[T:%.*]] = alloca [[T_T:%.*]], align 1
John McCalle996ffd2011-02-16 08:02:54 +0000270 // CHECK-NEXT: invoke void @_ZN5test53fooEv()
271 // CHECK: [[EXN:%.*]] = load i8** [[EXNSLOT]]
272 // CHECK-NEXT: [[ADJ:%.*]] = call i8* @__cxa_get_exception_ptr(i8* [[EXN]])
273 // CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[ADJ]] to [[A_T]]*
274 // CHECK-NEXT: invoke void @_ZN5test51TC1Ev([[T_T]]* [[T]])
275 // CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* [[SRC]], [[T_T]]* [[T]])
276 // CHECK: invoke void @_ZN5test51TD1Ev([[T_T]]* [[T]])
277 // CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind
278 // CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A_T]]* [[A]])
279 // CHECK: call void @__cxa_end_catch()
280 void test() {
281 try {
282 foo();
283 } catch (A a) {
284 }
285 }
286}
John McCall27f8d702011-02-25 04:19:13 +0000287
288// PR9303: invalid assert on this
289namespace test6 {
290 bool cond();
291 void test() {
292 try {
293 lbl:
294 if (cond()) goto lbl;
295 } catch (...) {
296 }
297 }
298}
John McCalla7f633f2011-03-07 01:52:56 +0000299
300// PR9298
301namespace test7 {
302 struct A { A(); ~A(); };
303 struct B {
304 // The throw() operator means that a bad allocation is signalled
305 // with a null return, which means that the initializer is
306 // evaluated conditionally.
307 static void *operator new(size_t size) throw();
308 B(const A&, B*);
309 ~B();
310 };
311
John McCalla7f633f2011-03-07 01:52:56 +0000312 B *test() {
John McCallc2f3e7f2011-03-07 03:12:35 +0000313 // CHECK: define [[B:%.*]]* @_ZN5test74testEv()
314 // CHECK: [[OUTER_NEW:%.*]] = alloca i1
315 // CHECK-NEXT: alloca [[A:%.*]],
316 // CHECK-NEXT: alloca i8*
317 // CHECK-NEXT: alloca i32
318 // CHECK-NEXT: [[OUTER_A:%.*]] = alloca i1
319 // CHECK-NEXT: alloca i8*
320 // CHECK-NEXT: [[INNER_NEW:%.*]] = alloca i1
321 // CHECK-NEXT: alloca [[A]]
322 // CHECK-NEXT: [[INNER_A:%.*]] = alloca i1
323
John McCallc2f3e7f2011-03-07 03:12:35 +0000324 // Allocate the outer object.
325 // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test71BnwEm(
326 // CHECK-NEXT: icmp eq i8* [[NEW]], null
327
328 // These stores, emitted before the outermost conditional branch,
329 // deactivate the temporary cleanups.
John McCall6f103ba2011-11-10 10:43:54 +0000330 // CHECK-NEXT: store i1 false, i1* [[OUTER_NEW]]
John McCallc2f3e7f2011-03-07 03:12:35 +0000331 // CHECK-NEXT: store i1 false, i1* [[OUTER_A]]
John McCall6f103ba2011-11-10 10:43:54 +0000332 // CHECK-NEXT: store i1 false, i1* [[INNER_NEW]]
John McCallc2f3e7f2011-03-07 03:12:35 +0000333 // CHECK-NEXT: store i1 false, i1* [[INNER_A]]
334 // CHECK-NEXT: br i1
335
336 // We passed the first null check; activate that cleanup and continue.
337 // CHECK: store i1 true, i1* [[OUTER_NEW]]
338 // CHECK-NEXT: bitcast
339
340 // Create the first A temporary and activate that cleanup.
341 // CHECK-NEXT: invoke void @_ZN5test71AC1Ev(
342 // CHECK: store i1 true, i1* [[OUTER_A]]
343
344 // Allocate the inner object.
345 // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test71BnwEm(
346 // CHECK-NEXT: icmp eq i8* [[NEW]], null
347 // CHECK-NEXT: br i1
348
349 // We passed the second null check; save that pointer, activate
350 // that cleanup, and continue.
351 // CHECK: store i8* [[NEW]]
352 // CHECK-NEXT: store i1 true, i1* [[INNER_NEW]]
353 // CHECK-NEXT: bitcast
354
355 // Build the second A temporary and activate that cleanup.
356 // CHECK-NEXT: invoke void @_ZN5test71AC1Ev(
357 // CHECK: store i1 true, i1* [[INNER_A]]
358
359 // Build the inner B object and deactivate the inner delete cleanup.
360 // CHECK-NEXT: invoke void @_ZN5test71BC1ERKNS_1AEPS0_(
361 // CHECK: store i1 false, i1* [[INNER_NEW]]
362 // CHECK: phi
363
364 // Build the outer B object and deactivate the outer delete cleanup.
365 // CHECK-NEXT: invoke void @_ZN5test71BC1ERKNS_1AEPS0_(
366 // CHECK: store i1 false, i1* [[OUTER_NEW]]
367 // CHECK: phi
368
369 // Destroy the inner A object.
370 // CHECK-NEXT: load i1* [[INNER_A]]
371 // CHECK-NEXT: br i1
372 // CHECK: invoke void @_ZN5test71AD1Ev(
373
374 // Destroy the outer A object.
375 // CHECK: load i1* [[OUTER_A]]
376 // CHECK-NEXT: br i1
377 // CHECK: invoke void @_ZN5test71AD1Ev(
378
John McCalla7f633f2011-03-07 01:52:56 +0000379 return new B(A(), new B(A(), 0));
380 }
381}
John McCall13668622011-08-26 00:46:38 +0000382
383// Just don't crash.
384namespace test8 {
385 struct A {
John McCall90b2bdf2011-08-26 05:38:08 +0000386 // Having both of these is required to trigger the assert we're
387 // trying to avoid.
John McCall13668622011-08-26 00:46:38 +0000388 A(const A&);
John McCall90b2bdf2011-08-26 05:38:08 +0000389 A&operator=(const A&);
390
John McCall13668622011-08-26 00:46:38 +0000391 ~A();
392 };
393
394 A makeA();
395 void test() {
396 throw makeA();
397 }
Eli Friedman576cf172011-09-06 18:53:03 +0000398 // CHECK: define void @_ZN5test84testEv
399}
400
401// Make sure we generate the correct code for the delete[] call which
402// happens if A::A() throws. (We were previously calling delete[] on
403// a pointer to the first array element, not the pointer returned by new[].)
404// PR10870
405namespace test9 {
406 struct A {
407 A();
408 ~A();
409 };
410 A* test() {
411 return new A[10];
412 }
413 // CHECK: define {{%.*}}* @_ZN5test94testEv
414 // CHECK: [[TEST9_NEW:%.*]] = call noalias i8* @_Znam
415 // CHECK: call void @_ZdaPv(i8* [[TEST9_NEW]])
John McCall13668622011-08-26 00:46:38 +0000416}
John McCallf5533012012-06-15 05:27:05 +0000417
418// In a destructor with a function-try-block, a return statement in a
419// catch handler behaves differently from running off the end of the
420// catch handler. PR13102.
421namespace test10 {
422 extern void cleanup();
423 extern bool suppress;
424
425 struct A { ~A(); };
426 A::~A() try { cleanup(); } catch (...) { return; }
427 // CHECK: define void @_ZN6test101AD1Ev(
428 // CHECK: invoke void @_ZN6test107cleanupEv()
429 // CHECK-NOT: rethrow
430 // CHECK: ret void
431
432 struct B { ~B(); };
433 B::~B() try { cleanup(); } catch (...) {}
434 // CHECK: define void @_ZN6test101BD1Ev(
435 // CHECK: invoke void @_ZN6test107cleanupEv()
436 // CHECK: call i8* @__cxa_begin_catch
437 // CHECK-NEXT: invoke void @__cxa_rethrow()
438 // CHECK: unreachable
439
440 struct C { ~C(); };
441 C::~C() try { cleanup(); } catch (...) { if (suppress) return; }
442 // CHECK: define void @_ZN6test101CD1Ev(
443 // CHECK: invoke void @_ZN6test107cleanupEv()
444 // CHECK: call i8* @__cxa_begin_catch
445 // CHECK-NEXT: load i8* @_ZN6test108suppressE, align 1
446 // CHECK-NEXT: trunc
447 // CHECK-NEXT: br i1
448 // CHECK: call void @__cxa_end_catch()
449 // CHECK-NEXT: br label
450 // CHECK: invoke void @__cxa_rethrow()
451 // CHECK: unreachable
452}