1*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime-has-weak -o - -fobjc-arc-exceptions %s | FileCheck %s 2*67e74705SXin Li 3*67e74705SXin Li@class Ety; 4*67e74705SXin Li 5*67e74705SXin Li// These first four tests are all PR11732 / rdar://problem/10667070. 6*67e74705SXin Li 7*67e74705SXin Livoid test0_helper(void); 8*67e74705SXin Livoid test0(void) { 9*67e74705SXin Li @try { 10*67e74705SXin Li test0_helper(); 11*67e74705SXin Li } @catch (Ety *e) { 12*67e74705SXin Li } 13*67e74705SXin Li} 14*67e74705SXin Li// CHECK-LABEL: define void @_Z5test0v() 15*67e74705SXin Li// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 16*67e74705SXin Li// CHECK-NEXT: invoke void @_Z12test0_helperv() 17*67e74705SXin Li// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch( 18*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* 19*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8* 20*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW:#[0-9]+]] 21*67e74705SXin Li// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* 22*67e74705SXin Li// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] 23*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** 24*67e74705SXin Li// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]] 25*67e74705SXin Li// CHECK-NEXT: call void @objc_end_catch() [[NUW]] 26*67e74705SXin Li 27*67e74705SXin Livoid test1_helper(void); 28*67e74705SXin Livoid test1(void) { 29*67e74705SXin Li @try { 30*67e74705SXin Li test1_helper(); 31*67e74705SXin Li } @catch (__weak Ety *e) { 32*67e74705SXin Li } 33*67e74705SXin Li} 34*67e74705SXin Li// CHECK-LABEL: define void @_Z5test1v() 35*67e74705SXin Li// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 36*67e74705SXin Li// CHECK-NEXT: invoke void @_Z12test1_helperv() 37*67e74705SXin Li// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch( 38*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* 39*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8** 40*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8* 41*67e74705SXin Li// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]] 42*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** 43*67e74705SXin Li// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]] 44*67e74705SXin Li// CHECK-NEXT: call void @objc_end_catch() [[NUW]] 45*67e74705SXin Li 46*67e74705SXin Livoid test2_helper(void); 47*67e74705SXin Livoid test2(void) { 48*67e74705SXin Li try { 49*67e74705SXin Li test2_helper(); 50*67e74705SXin Li } catch (Ety *e) { 51*67e74705SXin Li } 52*67e74705SXin Li} 53*67e74705SXin Li// CHECK-LABEL: define void @_Z5test2v() 54*67e74705SXin Li// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 55*67e74705SXin Li// CHECK-NEXT: invoke void @_Z12test2_helperv() 56*67e74705SXin Li// CHECK: [[T0:%.*]] = call i8* @__cxa_begin_catch( 57*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* 58*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8* 59*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW]] 60*67e74705SXin Li// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* 61*67e74705SXin Li// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] 62*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** 63*67e74705SXin Li// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]] 64*67e74705SXin Li// CHECK-NEXT: call void @__cxa_end_catch() [[NUW]] 65*67e74705SXin Li 66*67e74705SXin Livoid test3_helper(void); 67*67e74705SXin Livoid test3(void) { 68*67e74705SXin Li try { 69*67e74705SXin Li test3_helper(); 70*67e74705SXin Li } catch (Ety * __weak e) { 71*67e74705SXin Li } 72*67e74705SXin Li} 73*67e74705SXin Li// CHECK-LABEL: define void @_Z5test3v() 74*67e74705SXin Li// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 75*67e74705SXin Li// CHECK-NEXT: invoke void @_Z12test3_helperv() 76*67e74705SXin Li// CHECK: [[T0:%.*]] = call i8* @__cxa_begin_catch( 77*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* 78*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8** 79*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8* 80*67e74705SXin Li// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]] 81*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** 82*67e74705SXin Li// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]] 83*67e74705SXin Li// CHECK-NEXT: call void @__cxa_end_catch() [[NUW]] 84*67e74705SXin Li 85*67e74705SXin Linamespace test4 { 86*67e74705SXin Li struct A { 87*67e74705SXin Li id single; 88*67e74705SXin Li id array[2][3]; 89*67e74705SXin Li 90*67e74705SXin Li A(); 91*67e74705SXin Li }; 92*67e74705SXin Li 93*67e74705SXin Li A::A() { 94*67e74705SXin Li throw 0; 95*67e74705SXin Li } 96*67e74705SXin Li // CHECK-LABEL: define void @_ZN5test41AC2Ev( 97*67e74705SXin Li // CHECK: [[THIS:%.*]] = load [[A:%.*]]*, [[A:%.*]]** {{%.*}} 98*67e74705SXin Li // Construct single. 99*67e74705SXin Li // CHECK-NEXT: [[SINGLE:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0 100*67e74705SXin Li // CHECK-NEXT: store i8* null, i8** [[SINGLE]], align 8 101*67e74705SXin Li // Construct array. 102*67e74705SXin Li // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 1 103*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = bitcast [2 x [3 x i8*]]* [[ARRAY]] to i8* 104*67e74705SXin Li // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 8, i1 false) 105*67e74705SXin Li // throw 0; 106*67e74705SXin Li // CHECK: invoke void @__cxa_throw( 107*67e74705SXin Li // Landing pad from throw site: 108*67e74705SXin Li // CHECK: landingpad 109*67e74705SXin Li // - First, destroy all of array. 110*67e74705SXin Li // CHECK: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x i8*]], [2 x [3 x i8*]]* [[ARRAY]], i32 0, i32 0, i32 0 111*67e74705SXin Li // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds i8*, i8** [[ARRAYBEGIN]], i64 6 112*67e74705SXin Li // CHECK-NEXT: br label 113*67e74705SXin Li // CHECK: [[AFTER:%.*]] = phi i8** [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] 114*67e74705SXin Li // CHECK-NEXT: [[ELT]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1 115*67e74705SXin Li // CHECK-NEXT: call void @objc_storeStrong(i8** [[ELT]], i8* null) [[NUW]] 116*67e74705SXin Li // CHECK-NEXT: [[DONE:%.*]] = icmp eq i8** [[ELT]], [[ARRAYBEGIN]] 117*67e74705SXin Li // CHECK-NEXT: br i1 [[DONE]], 118*67e74705SXin Li // - Next, destroy single. 119*67e74705SXin Li // CHECK: call void @objc_storeStrong(i8** [[SINGLE]], i8* null) [[NUW]] 120*67e74705SXin Li // CHECK: br label 121*67e74705SXin Li // CHECK: resume 122*67e74705SXin Li} 123*67e74705SXin Li 124*67e74705SXin Li// rdar://21397946 125*67e74705SXin Li__attribute__((ns_returns_retained)) id test5_helper(unsigned); 126*67e74705SXin Livoid test5(void) { 127*67e74705SXin Li id array[][2] = { 128*67e74705SXin Li test5_helper(0), 129*67e74705SXin Li test5_helper(1), 130*67e74705SXin Li test5_helper(2), 131*67e74705SXin Li test5_helper(3) 132*67e74705SXin Li }; 133*67e74705SXin Li} 134*67e74705SXin Li// CHECK-LABEL: define void @_Z5test5v() 135*67e74705SXin Li// CHECK: [[ARRAY:%.*]] = alloca [2 x [2 x i8*]], align 136*67e74705SXin Li// CHECK: [[A0:%.*]] = getelementptr inbounds [2 x [2 x i8*]], [2 x [2 x i8*]]* [[ARRAY]], i64 0, i64 0 137*67e74705SXin Li// CHECK-NEXT: store [2 x i8*]* [[A0]], 138*67e74705SXin Li// CHECK-NEXT: [[A00:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A0]], i64 0, i64 0 139*67e74705SXin Li// CHECK-NEXT: store i8** [[A00]], 140*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 0) 141*67e74705SXin Li// CHECK: store i8* [[T0]], i8** [[A00]], align 142*67e74705SXin Li// CHECK-NEXT: [[A01:%.*]] = getelementptr inbounds i8*, i8** [[A00]], i64 1 143*67e74705SXin Li// CHECK-NEXT: store i8** [[A01]], 144*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 1) 145*67e74705SXin Li// CHECK: store i8* [[T0]], i8** [[A01]], align 146*67e74705SXin Li// CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A0]], i64 1 147*67e74705SXin Li// CHECK-NEXT: store [2 x i8*]* [[A1]], 148*67e74705SXin Li// CHECK-NEXT: [[A10:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A1]], i64 0, i64 0 149*67e74705SXin Li// CHECK-NEXT: store i8** [[A10]], 150*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 2) 151*67e74705SXin Li// CHECK: store i8* [[T0]], i8** [[A10]], align 152*67e74705SXin Li// CHECK-NEXT: [[A11:%.*]] = getelementptr inbounds i8*, i8** [[A10]], i64 1 153*67e74705SXin Li// CHECK-NEXT: store i8** [[A11]], 154*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 3) 155*67e74705SXin Li// CHECK: store i8* [[T0]], i8** [[A11]], align 156*67e74705SXin Li 157*67e74705SXin Li// CHECK: attributes [[NUW]] = { nounwind } 158