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