xref: /aosp_15_r20/external/clang/test/CodeGenCXX/eh.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o %t.ll
2*67e74705SXin Li // RUN: FileCheck --input-file=%t.ll %s
3*67e74705SXin Li 
4*67e74705SXin Li struct test1_D {
5*67e74705SXin Li   double d;
6*67e74705SXin Li } d1;
7*67e74705SXin Li 
test1()8*67e74705SXin Li void test1() {
9*67e74705SXin Li   throw d1;
10*67e74705SXin Li }
11*67e74705SXin Li 
12*67e74705SXin Li // CHECK-LABEL:     define void @_Z5test1v()
13*67e74705SXin Li // CHECK:       [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8)
14*67e74705SXin Li // CHECK-NEXT:  [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]]
15*67e74705SXin Li // CHECK-NEXT:  [[EXN2:%.*]] = bitcast [[DSTAR]] [[EXN]] to i8*
16*67e74705SXin Li // CHECK-NEXT:  call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[EXN2]], i8* bitcast ([[DSTAR]] @d1 to i8*), i64 8, i32 8, i1 false)
17*67e74705SXin Li // CHECK-NEXT:  call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8* }* @_ZTI7test1_D to i8*), i8* null) [[NR:#[0-9]+]]
18*67e74705SXin Li // CHECK-NEXT:  unreachable
19*67e74705SXin Li 
20*67e74705SXin Li 
21*67e74705SXin Li struct test2_D {
22*67e74705SXin Li   test2_D(const test2_D&o);
23*67e74705SXin Li   test2_D();
bartest2_D24*67e74705SXin Li   virtual void bar() { }
25*67e74705SXin Li   int i; int j;
26*67e74705SXin Li } d2;
27*67e74705SXin Li 
test2()28*67e74705SXin Li void test2() {
29*67e74705SXin Li   throw d2;
30*67e74705SXin Li }
31*67e74705SXin Li 
32*67e74705SXin Li // CHECK-LABEL:     define void @_Z5test2v()
33*67e74705SXin Li // CHECK:       [[EXNVAR:%.*]] = alloca i8*
34*67e74705SXin Li // CHECK-NEXT:  [[SELECTORVAR:%.*]] = alloca i32
35*67e74705SXin Li // CHECK-NEXT:  [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16)
36*67e74705SXin Li // CHECK-NEXT:  [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]]
37*67e74705SXin Li // CHECK-NEXT:  invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] dereferenceable({{[0-9]+}}) @d2)
38*67e74705SXin Li // CHECK-NEXT:     to label %[[CONT:.*]] unwind label %{{.*}}
39*67e74705SXin Li //      :     [[CONT]]:   (can't check this in Release-Asserts builds)
40*67e74705SXin Li // CHECK:       call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTI7test2_D to i8*), i8* null) [[NR]]
41*67e74705SXin Li // CHECK-NEXT:  unreachable
42*67e74705SXin Li 
43*67e74705SXin Li 
44*67e74705SXin Li struct test3_D {
test3_Dtest3_D45*67e74705SXin Li   test3_D() { }
46*67e74705SXin Li   test3_D(volatile test3_D&o);
47*67e74705SXin Li   virtual void bar();
48*67e74705SXin Li };
49*67e74705SXin Li 
test3()50*67e74705SXin Li void test3() {
51*67e74705SXin Li   throw (volatile test3_D *)0;
52*67e74705SXin Li }
53*67e74705SXin Li 
54*67e74705SXin Li // CHECK-LABEL:     define void @_Z5test3v()
55*67e74705SXin Li // CHECK:       [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8)
56*67e74705SXin Li // CHECK-NEXT:  [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[D:%[^*]+]]**
57*67e74705SXin Li // CHECK-NEXT:  store [[D]]* null, [[D]]** [[EXN]]
58*67e74705SXin Li // CHECK-NEXT:  call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIPV7test3_D to i8*), i8* null) [[NR]]
59*67e74705SXin Li // CHECK-NEXT:  unreachable
60*67e74705SXin Li 
61*67e74705SXin Li 
test4()62*67e74705SXin Li void test4() {
63*67e74705SXin Li   throw;
64*67e74705SXin Li }
65*67e74705SXin Li 
66*67e74705SXin Li // CHECK-LABEL:     define void @_Z5test4v()
67*67e74705SXin Li // CHECK:        call void @__cxa_rethrow() [[NR]]
68*67e74705SXin Li // CHECK-NEXT:   unreachable
69*67e74705SXin Li 
70*67e74705SXin Li 
71*67e74705SXin Li // rdar://problem/7696549
72*67e74705SXin Li namespace test5 {
73*67e74705SXin Li   struct A {
74*67e74705SXin Li     A();
75*67e74705SXin Li     A(const A&);
76*67e74705SXin Li     ~A();
77*67e74705SXin Li   };
78*67e74705SXin Li 
test()79*67e74705SXin Li   void test() {
80*67e74705SXin Li     try { throw A(); } catch (A &x) {}
81*67e74705SXin Li   }
82*67e74705SXin Li // CHECK-LABEL:      define void @_ZN5test54testEv()
83*67e74705SXin Li // CHECK:      [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 1)
84*67e74705SXin Li // CHECK:      [[EXNCAST:%.*]] = bitcast i8* [[EXNOBJ]] to [[A:%[^*]*]]*
85*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test51AC1Ev([[A]]* [[EXNCAST]])
86*67e74705SXin Li // CHECK:      invoke void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTIN5test51AE to i8*), i8* bitcast (void ([[A]]*)* @_ZN5test51AD1Ev to i8*)) [[NR]]
87*67e74705SXin Li // CHECK-NEXT:   to label {{%.*}} unwind label %[[HANDLER:[^ ]*]]
88*67e74705SXin Li //      :    [[HANDLER]]:  (can't check this in Release-Asserts builds)
89*67e74705SXin Li // CHECK:      {{%.*}} = call i32 @llvm.eh.typeid.for(i8* bitcast ({{.*}}* @_ZTIN5test51AE to i8*))
90*67e74705SXin Li }
91*67e74705SXin Li 
92*67e74705SXin Li namespace test6 {
93*67e74705SXin Li   template <class T> struct allocator {
~allocatortest6::allocator94*67e74705SXin Li     ~allocator() throw() { }
95*67e74705SXin Li   };
96*67e74705SXin Li 
foo()97*67e74705SXin Li   void foo() {
98*67e74705SXin Li     allocator<int> a;
99*67e74705SXin Li   }
100*67e74705SXin Li }
101*67e74705SXin Li 
102*67e74705SXin Li // PR7127
103*67e74705SXin Li namespace test7 {
104*67e74705SXin Li // CHECK-LABEL:      define i32 @_ZN5test73fooEv()
105*67e74705SXin Li // CHECK-SAME:  personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
foo()106*67e74705SXin Li   int foo() {
107*67e74705SXin Li // CHECK:      [[CAUGHTEXNVAR:%.*]] = alloca i8*
108*67e74705SXin Li // CHECK-NEXT: [[SELECTORVAR:%.*]] = alloca i32
109*67e74705SXin Li // CHECK-NEXT: [[INTCATCHVAR:%.*]] = alloca i32
110*67e74705SXin Li     try {
111*67e74705SXin Li       try {
112*67e74705SXin Li // CHECK-NEXT: [[EXNALLOC:%.*]] = call i8* @__cxa_allocate_exception
113*67e74705SXin Li // CHECK-NEXT: bitcast i8* [[EXNALLOC]] to i32*
114*67e74705SXin Li // CHECK-NEXT: store i32 1, i32*
115*67e74705SXin Li // CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXNALLOC]], i8* bitcast (i8** @_ZTIi to i8*), i8* null
116*67e74705SXin Li         throw 1;
117*67e74705SXin Li       }
118*67e74705SXin Li 
119*67e74705SXin Li // CHECK:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 }
120*67e74705SXin Li // CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
121*67e74705SXin Li // CHECK-NEXT:   catch i8* null
122*67e74705SXin Li // CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
123*67e74705SXin Li // CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]]
124*67e74705SXin Li // CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
125*67e74705SXin Li // CHECK-NEXT: store i32 [[SELECTOR]], i32* [[SELECTORVAR]]
126*67e74705SXin Li // CHECK-NEXT: br label
127*67e74705SXin Li // CHECK:      [[SELECTOR:%.*]] = load i32, i32* [[SELECTORVAR]]
128*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
129*67e74705SXin Li // CHECK-NEXT: icmp eq i32 [[SELECTOR]], [[T0]]
130*67e74705SXin Li // CHECK-NEXT: br i1
131*67e74705SXin Li // CHECK:      [[T0:%.*]] = load i8*, i8** [[CAUGHTEXNVAR]]
132*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = call i8* @__cxa_begin_catch(i8* [[T0]])
133*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i32*
134*67e74705SXin Li // CHECK-NEXT: [[T3:%.*]] = load i32, i32* [[T2]]
135*67e74705SXin Li // CHECK-NEXT: store i32 [[T3]], i32* {{%.*}}, align 4
136*67e74705SXin Li // CHECK-NEXT: invoke void @__cxa_rethrow
137*67e74705SXin Li       catch (int) {
138*67e74705SXin Li         throw;
139*67e74705SXin Li       }
140*67e74705SXin Li     }
141*67e74705SXin Li // CHECK:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 }
142*67e74705SXin Li // CHECK-NEXT:   catch i8* null
143*67e74705SXin Li // CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
144*67e74705SXin Li // CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]]
145*67e74705SXin Li // CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
146*67e74705SXin Li // CHECK-NEXT: store i32 [[SELECTOR]], i32* [[SELECTORVAR]]
147*67e74705SXin Li // CHECK-NEXT: call void @__cxa_end_catch()
148*67e74705SXin Li // CHECK-NEXT: br label
149*67e74705SXin Li // CHECK:      load i8*, i8** [[CAUGHTEXNVAR]]
150*67e74705SXin Li // CHECK-NEXT: call i8* @__cxa_begin_catch
151*67e74705SXin Li // CHECK-NEXT: call void @__cxa_end_catch
152*67e74705SXin Li     catch (...) {
153*67e74705SXin Li     }
154*67e74705SXin Li // CHECK:      ret i32 0
155*67e74705SXin Li     return 0;
156*67e74705SXin Li   }
157*67e74705SXin Li }
158*67e74705SXin Li 
159*67e74705SXin Li // Ordering of destructors in a catch handler.
160*67e74705SXin Li namespace test8 {
161*67e74705SXin Li   struct A { A(const A&); ~A(); };
162*67e74705SXin Li   void bar();
163*67e74705SXin Li 
164*67e74705SXin Li   // CHECK-LABEL: define void @_ZN5test83fooEv()
foo()165*67e74705SXin Li   void foo() {
166*67e74705SXin Li     try {
167*67e74705SXin Li       // CHECK:      invoke void @_ZN5test83barEv()
168*67e74705SXin Li       bar();
169*67e74705SXin Li     } catch (A a) {
170*67e74705SXin Li       // CHECK:      call i8* @__cxa_get_exception_ptr
171*67e74705SXin Li       // CHECK-NEXT: bitcast
172*67e74705SXin Li       // CHECK-NEXT: invoke void @_ZN5test81AC1ERKS0_(
173*67e74705SXin Li       // CHECK:      call i8* @__cxa_begin_catch
174*67e74705SXin Li       // CHECK-NEXT: call void @_ZN5test81AD1Ev(
175*67e74705SXin Li       // CHECK:      call void @__cxa_end_catch()
176*67e74705SXin Li       // CHECK:      ret void
177*67e74705SXin Li     }
178*67e74705SXin Li   }
179*67e74705SXin Li }
180*67e74705SXin Li 
181*67e74705SXin Li // Constructor function-try-block must rethrow on fallthrough.
182*67e74705SXin Li // rdar://problem/7696603
183*67e74705SXin Li namespace test9 {
184*67e74705SXin Li   void opaque();
185*67e74705SXin Li 
186*67e74705SXin Li   struct A { A(); };
187*67e74705SXin Li 
188*67e74705SXin Li 
189*67e74705SXin Li   // CHECK-LABEL: define void @_ZN5test91AC2Ev(%"struct.test9::A"* %this) unnamed_addr
190*67e74705SXin Li   // CHECK-SAME:  personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
A()191*67e74705SXin Li   A::A() try {
192*67e74705SXin Li   // CHECK:      invoke void @_ZN5test96opaqueEv()
193*67e74705SXin Li     opaque();
194*67e74705SXin Li   } catch (int x) {
195*67e74705SXin Li   // CHECK:      landingpad { i8*, i32 }
196*67e74705SXin Li   // CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
197*67e74705SXin Li 
198*67e74705SXin Li   // CHECK:      call i8* @__cxa_begin_catch
199*67e74705SXin Li   // CHECK:      invoke void @_ZN5test96opaqueEv()
200*67e74705SXin Li   // CHECK:      invoke void @__cxa_rethrow()
201*67e74705SXin Li 
202*67e74705SXin Li   // CHECK-LABEL:      define void @_ZN5test91AC1Ev(%"struct.test9::A"* %this) unnamed_addr
203*67e74705SXin Li   // CHECK:      call void @_ZN5test91AC2Ev
204*67e74705SXin Li   // CHECK-NEXT: ret void
205*67e74705SXin Li     opaque();
206*67e74705SXin Li   }
207*67e74705SXin Li }
208*67e74705SXin Li 
209*67e74705SXin Li // __cxa_end_catch can throw for some kinds of caught exceptions.
210*67e74705SXin Li namespace test10 {
211*67e74705SXin Li   void opaque();
212*67e74705SXin Li 
213*67e74705SXin Li   struct A { ~A(); };
214*67e74705SXin Li   struct B { int x; };
215*67e74705SXin Li 
216*67e74705SXin Li   // CHECK-LABEL: define void @_ZN6test103fooEv()
foo()217*67e74705SXin Li   void foo() {
218*67e74705SXin Li     A a; // force a cleanup context
219*67e74705SXin Li 
220*67e74705SXin Li     try {
221*67e74705SXin Li     // CHECK:      invoke void @_ZN6test106opaqueEv()
222*67e74705SXin Li       opaque();
223*67e74705SXin Li     } catch (int i) {
224*67e74705SXin Li     // CHECK:      call i8* @__cxa_begin_catch
225*67e74705SXin Li     // CHECK-NEXT: bitcast
226*67e74705SXin Li     // CHECK-NEXT: load i32, i32*
227*67e74705SXin Li     // CHECK-NEXT: store i32
228*67e74705SXin Li     // CHECK-NEXT: call void @__cxa_end_catch() [[NUW:#[0-9]+]]
229*67e74705SXin Li     } catch (B a) {
230*67e74705SXin Li     // CHECK:      call i8* @__cxa_begin_catch
231*67e74705SXin Li     // CHECK-NEXT: bitcast
232*67e74705SXin Li     // CHECK-NEXT: bitcast
233*67e74705SXin Li     // CHECK-NEXT: bitcast
234*67e74705SXin Li     // CHECK-NEXT: call void @llvm.memcpy
235*67e74705SXin Li     // CHECK-NEXT: invoke void @__cxa_end_catch()
236*67e74705SXin Li     } catch (...) {
237*67e74705SXin Li     // CHECK:      call i8* @__cxa_begin_catch
238*67e74705SXin Li     // CHECK-NEXT: invoke void @__cxa_end_catch()
239*67e74705SXin Li     }
240*67e74705SXin Li 
241*67e74705SXin Li     // CHECK: call void @_ZN6test101AD1Ev(
242*67e74705SXin Li   }
243*67e74705SXin Li }
244*67e74705SXin Li 
245*67e74705SXin Li // __cxa_begin_catch returns pointers by value, even when catching by reference
246*67e74705SXin Li // <rdar://problem/8212123>
247*67e74705SXin Li namespace test11 {
248*67e74705SXin Li   void opaque();
249*67e74705SXin Li 
250*67e74705SXin Li   // CHECK-LABEL: define void @_ZN6test113fooEv()
foo()251*67e74705SXin Li   void foo() {
252*67e74705SXin Li     try {
253*67e74705SXin Li       // CHECK:      invoke void @_ZN6test116opaqueEv()
254*67e74705SXin Li       opaque();
255*67e74705SXin Li     } catch (int**&p) {
256*67e74705SXin Li       // CHECK:      [[EXN:%.*]] = load i8*, i8**
257*67e74705SXin Li       // CHECK-NEXT: call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]]
258*67e74705SXin Li       // CHECK-NEXT: [[ADJ1:%.*]] = getelementptr i8, i8* [[EXN]], i32 32
259*67e74705SXin Li       // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to i32***
260*67e74705SXin Li       // CHECK-NEXT: store i32*** [[ADJ2]], i32**** [[P:%.*]]
261*67e74705SXin Li       // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
262*67e74705SXin Li     }
263*67e74705SXin Li   }
264*67e74705SXin Li 
265*67e74705SXin Li   struct A {};
266*67e74705SXin Li 
267*67e74705SXin Li   // CHECK-LABEL: define void @_ZN6test113barEv()
bar()268*67e74705SXin Li   void bar() {
269*67e74705SXin Li     try {
270*67e74705SXin Li       // CHECK:      [[EXNSLOT:%.*]] = alloca i8*
271*67e74705SXin Li       // CHECK-NEXT: [[SELECTORSLOT:%.*]] = alloca i32
272*67e74705SXin Li       // CHECK-NEXT: [[P:%.*]] = alloca [[A:%.*]]**,
273*67e74705SXin Li       // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]]*
274*67e74705SXin Li       // CHECK-NEXT: invoke void @_ZN6test116opaqueEv()
275*67e74705SXin Li       opaque();
276*67e74705SXin Li     } catch (A*&p) {
277*67e74705SXin Li       // CHECK:      [[EXN:%.*]] = load i8*, i8** [[EXNSLOT]]
278*67e74705SXin Li       // CHECK-NEXT: [[ADJ1:%.*]] = call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]]
279*67e74705SXin Li       // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to [[A]]*
280*67e74705SXin Li       // CHECK-NEXT: store [[A]]* [[ADJ2]], [[A]]** [[TMP]]
281*67e74705SXin Li       // CHECK-NEXT: store [[A]]** [[TMP]], [[A]]*** [[P]]
282*67e74705SXin Li       // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
283*67e74705SXin Li     }
284*67e74705SXin Li   }
285*67e74705SXin Li }
286*67e74705SXin Li 
287*67e74705SXin Li // PR7686
288*67e74705SXin Li namespace test12 {
289*67e74705SXin Li   struct A { ~A() noexcept(false); };
290*67e74705SXin Li   bool opaque(const A&);
291*67e74705SXin Li 
292*67e74705SXin Li   // CHECK-LABEL: define void @_ZN6test124testEv()
test()293*67e74705SXin Li   void test() {
294*67e74705SXin Li     // CHECK: [[X:%.*]] = alloca [[A:%.*]],
295*67e74705SXin Li     // CHECK: [[EHCLEANUPDEST:%.*]] = alloca i32
296*67e74705SXin Li     // CHECK: [[Y:%.*]] = alloca [[A]]
297*67e74705SXin Li     // CHECK: [[Z:%.*]] = alloca [[A]]
298*67e74705SXin Li     // CHECK: [[CLEANUPDEST:%.*]] = alloca i32
299*67e74705SXin Li 
300*67e74705SXin Li     A x;
301*67e74705SXin Li     // CHECK: invoke zeroext i1 @_ZN6test126opaqueERKNS_1AE(
302*67e74705SXin Li     if (opaque(x)) {
303*67e74705SXin Li       A y;
304*67e74705SXin Li       A z;
305*67e74705SXin Li 
306*67e74705SXin Li       // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Z]])
307*67e74705SXin Li       // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Y]])
308*67e74705SXin Li       // CHECK-NOT: switch
309*67e74705SXin Li       goto success;
310*67e74705SXin Li     }
311*67e74705SXin Li 
312*67e74705SXin Li   success:
313*67e74705SXin Li     bool _ = true;
314*67e74705SXin Li 
315*67e74705SXin Li     // CHECK: call void @_ZN6test121AD1Ev([[A]]* [[X]])
316*67e74705SXin Li     // CHECK-NEXT: ret void
317*67e74705SXin Li   }
318*67e74705SXin Li }
319*67e74705SXin Li 
320*67e74705SXin Li // Reduced from some TableGen code that was causing a self-host crash.
321*67e74705SXin Li namespace test13 {
322*67e74705SXin Li   struct A { ~A(); };
323*67e74705SXin Li 
test0(int x)324*67e74705SXin Li   void test0(int x) {
325*67e74705SXin Li     try {
326*67e74705SXin Li       switch (x) {
327*67e74705SXin Li       case 0:
328*67e74705SXin Li         break;
329*67e74705SXin Li       case 1:{
330*67e74705SXin Li         A a;
331*67e74705SXin Li         break;
332*67e74705SXin Li       }
333*67e74705SXin Li       default:
334*67e74705SXin Li         return;
335*67e74705SXin Li       }
336*67e74705SXin Li       return;
337*67e74705SXin Li     } catch (int x) {
338*67e74705SXin Li     }
339*67e74705SXin Li     return;
340*67e74705SXin Li   }
341*67e74705SXin Li 
test1(int x)342*67e74705SXin Li   void test1(int x) {
343*67e74705SXin Li     A y;
344*67e74705SXin Li     try {
345*67e74705SXin Li       switch (x) {
346*67e74705SXin Li       default: break;
347*67e74705SXin Li       }
348*67e74705SXin Li     } catch (int x) {}
349*67e74705SXin Li   }
350*67e74705SXin Li }
351*67e74705SXin Li 
352*67e74705SXin Li // rdar://problem/8231514
353*67e74705SXin Li namespace test14 {
354*67e74705SXin Li   struct A { ~A(); };
355*67e74705SXin Li   struct B { ~B(); };
356*67e74705SXin Li 
357*67e74705SXin Li   B b();
358*67e74705SXin Li   void opaque();
359*67e74705SXin Li 
foo()360*67e74705SXin Li   void foo() {
361*67e74705SXin Li     A a;
362*67e74705SXin Li     try {
363*67e74705SXin Li       B str = b();
364*67e74705SXin Li       opaque();
365*67e74705SXin Li     } catch (int x) {
366*67e74705SXin Li     }
367*67e74705SXin Li   }
368*67e74705SXin Li }
369*67e74705SXin Li 
370*67e74705SXin Li // rdar://problem/8231514
371*67e74705SXin Li // JumpDests shouldn't get confused by scopes that aren't normal cleanups.
372*67e74705SXin Li namespace test15 {
373*67e74705SXin Li   struct A { ~A(); };
374*67e74705SXin Li 
375*67e74705SXin Li   bool opaque(int);
376*67e74705SXin Li 
377*67e74705SXin Li   // CHECK-LABEL: define void @_ZN6test153fooEv()
foo()378*67e74705SXin Li   void foo() {
379*67e74705SXin Li     A a;
380*67e74705SXin Li 
381*67e74705SXin Li     try {
382*67e74705SXin Li       // CHECK:      [[X:%.*]] = alloca i32
383*67e74705SXin Li       // CHECK:      store i32 10, i32* [[X]]
384*67e74705SXin Li       // CHECK-NEXT: br label
385*67e74705SXin Li       //   -> while.cond
386*67e74705SXin Li       int x = 10;
387*67e74705SXin Li 
388*67e74705SXin Li       while (true) {
389*67e74705SXin Li         // CHECK:      load i32, i32* [[X]]
390*67e74705SXin Li         // CHECK-NEXT: [[COND:%.*]] = invoke zeroext i1 @_ZN6test156opaqueEi
391*67e74705SXin Li         // CHECK:      br i1 [[COND]]
392*67e74705SXin Li         if (opaque(x))
393*67e74705SXin Li         // CHECK:      br label
394*67e74705SXin Li           break;
395*67e74705SXin Li 
396*67e74705SXin Li         // CHECK:      br label
397*67e74705SXin Li       }
398*67e74705SXin Li       // CHECK:      br label
399*67e74705SXin Li     } catch (int x) { }
400*67e74705SXin Li 
401*67e74705SXin Li     // CHECK: call void @_ZN6test151AD1Ev
402*67e74705SXin Li   }
403*67e74705SXin Li }
404*67e74705SXin Li 
405*67e74705SXin Li namespace test16 {
406*67e74705SXin Li   struct A { A(); ~A() noexcept(false); };
407*67e74705SXin Li   struct B { int x; B(const A &); ~B() noexcept(false); };
408*67e74705SXin Li   void foo();
409*67e74705SXin Li   bool cond();
410*67e74705SXin Li 
411*67e74705SXin Li   // CHECK-LABEL: define void @_ZN6test163barEv()
bar()412*67e74705SXin Li   void bar() {
413*67e74705SXin Li     // CHECK:      [[EXN_SAVE:%.*]] = alloca i8*
414*67e74705SXin Li     // CHECK-NEXT: [[EXN_ACTIVE:%.*]] = alloca i1
415*67e74705SXin Li     // CHECK-NEXT: [[TEMP:%.*]] = alloca [[A:%.*]],
416*67e74705SXin Li     // CHECK-NEXT: [[EXNSLOT:%.*]] = alloca i8*
417*67e74705SXin Li     // CHECK-NEXT: [[SELECTORSLOT:%.*]] = alloca i32
418*67e74705SXin Li     // CHECK-NEXT: [[TEMP_ACTIVE:%.*]] = alloca i1
419*67e74705SXin Li 
420*67e74705SXin Li     cond() ? throw B(A()) : foo();
421*67e74705SXin Li 
422*67e74705SXin Li     // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN6test164condEv()
423*67e74705SXin Li     // CHECK-NEXT: store i1 false, i1* [[EXN_ACTIVE]]
424*67e74705SXin Li     // CHECK-NEXT: store i1 false, i1* [[TEMP_ACTIVE]]
425*67e74705SXin Li     // CHECK-NEXT: br i1 [[COND]],
426*67e74705SXin Li 
427*67e74705SXin Li     // CHECK:      [[EXN:%.*]] = call i8* @__cxa_allocate_exception(i64 4)
428*67e74705SXin Li     // CHECK-NEXT: store i8* [[EXN]], i8** [[EXN_SAVE]]
429*67e74705SXin Li     // CHECK-NEXT: store i1 true, i1* [[EXN_ACTIVE]]
430*67e74705SXin Li     // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[EXN]] to [[B:%.*]]*
431*67e74705SXin Li     // CHECK-NEXT: invoke void @_ZN6test161AC1Ev([[A]]* [[TEMP]])
432*67e74705SXin Li     // CHECK:      store i1 true, i1* [[TEMP_ACTIVE]]
433*67e74705SXin Li     // CHECK-NEXT: invoke void @_ZN6test161BC1ERKNS_1AE([[B]]* [[T0]], [[A]]* dereferenceable({{[0-9]+}}) [[TEMP]])
434*67e74705SXin Li     // CHECK:      store i1 false, i1* [[EXN_ACTIVE]]
435*67e74705SXin Li     // CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXN]],
436*67e74705SXin Li 
437*67e74705SXin Li     // CHECK:      invoke void @_ZN6test163fooEv()
438*67e74705SXin Li     // CHECK:      br label
439*67e74705SXin Li 
440*67e74705SXin Li     // CHECK:      invoke void @_ZN6test161AD1Ev([[A]]* [[TEMP]])
441*67e74705SXin Li     // CHECK:      ret void
442*67e74705SXin Li 
443*67e74705SXin Li     // CHECK:      [[T0:%.*]] = load i1, i1* [[EXN_ACTIVE]]
444*67e74705SXin Li     // CHECK-NEXT: br i1 [[T0]]
445*67e74705SXin Li     // CHECK:      [[T1:%.*]] = load i8*, i8** [[EXN_SAVE]]
446*67e74705SXin Li     // CHECK-NEXT: call void @__cxa_free_exception(i8* [[T1]])
447*67e74705SXin Li     // CHECK-NEXT: br label
448*67e74705SXin Li   }
449*67e74705SXin Li }
450*67e74705SXin Li 
451*67e74705SXin Li namespace test17 {
452*67e74705SXin Li class BaseException {
453*67e74705SXin Li private:
454*67e74705SXin Li   int a[4];
455*67e74705SXin Li public:
BaseException()456*67e74705SXin Li   BaseException() {};
457*67e74705SXin Li };
458*67e74705SXin Li 
459*67e74705SXin Li class DerivedException: public BaseException {
460*67e74705SXin Li };
461*67e74705SXin Li 
foo()462*67e74705SXin Li int foo() {
463*67e74705SXin Li   throw DerivedException();
464*67e74705SXin Li   // The alignment passed to memset is 8, not 16, on Darwin.
465*67e74705SXin Li 
466*67e74705SXin Li   // CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i64 16)
467*67e74705SXin Li   // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to %"class.test17::DerivedException"*
468*67e74705SXin Li   // CHECK-NEXT: [[T2:%.*]] = bitcast %"class.test17::DerivedException"* [[T1]] to i8*
469*67e74705SXin Li   // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T2]], i8 0, i64 16, i32 8, i1 false)
470*67e74705SXin Li }
471*67e74705SXin Li }
472*67e74705SXin Li 
473*67e74705SXin Li // CHECK: attributes [[NUW]] = { nounwind }
474*67e74705SXin Li // CHECK: attributes [[NR]] = { noreturn }
475