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