1*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-MODERN 2*67e74705SXin Li// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-FRAGILE 3*67e74705SXin Li 4*67e74705SXin Li@interface Object 5*67e74705SXin Li- (instancetype) retain; 6*67e74705SXin Li- (void) run; 7*67e74705SXin Li@end 8*67e74705SXin Li 9*67e74705SXin Li// CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00" 10*67e74705SXin Li// CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_Foo" = {{.*}} { i32 772 11*67e74705SXin Li// 772 == 0x304 12*67e74705SXin Li// ^ HasMRCWeakIvars 13*67e74705SXin Li// ^ HasCXXDestructorOnly 14*67e74705SXin Li// ^ HasCXXStructors 15*67e74705SXin Li 16*67e74705SXin Li// CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00" 17*67e74705SXin Li// CHECK-FRAGILE: @OBJC_CLASS_Foo = {{.*}} i32 134225921, 18*67e74705SXin Li// 134225921 == 0x08002001 19*67e74705SXin Li// ^ HasMRCWeakIvars 20*67e74705SXin Li// ^ HasCXXStructors 21*67e74705SXin Li// ^ Factory 22*67e74705SXin Li@interface Foo : Object { 23*67e74705SXin Li __weak id ivar; 24*67e74705SXin Li} 25*67e74705SXin Li@end 26*67e74705SXin Li 27*67e74705SXin Li@implementation Foo 28*67e74705SXin Li// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]" 29*67e74705SXin Li// CHECK: call void @objc_destroyWeak 30*67e74705SXin Li@end 31*67e74705SXin Li 32*67e74705SXin Li 33*67e74705SXin Livoid test1(__weak id x) {} 34*67e74705SXin Li// CHECK-LABEL: define void @_Z5test1P11objc_object( 35*67e74705SXin Li// CHECK: [[X:%.*]] = alloca i8*, 36*67e74705SXin Li// CHECK-NEXT: objc_initWeak 37*67e74705SXin Li// CHECK-NEXT: objc_destroyWeak 38*67e74705SXin Li// CHECK-NEXT: ret void 39*67e74705SXin Li 40*67e74705SXin Livoid test2(id y) { 41*67e74705SXin Li __weak id z = y; 42*67e74705SXin Li} 43*67e74705SXin Li// CHECK-LABEL: define void @_Z5test2P11objc_object( 44*67e74705SXin Li// CHECK: [[Y:%.*]] = alloca i8*, 45*67e74705SXin Li// CHECK-NEXT: [[Z:%.*]] = alloca i8*, 46*67e74705SXin Li// CHECK-NEXT: store 47*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] 48*67e74705SXin Li// CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]]) 49*67e74705SXin Li// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]]) 50*67e74705SXin Li// CHECK-NEXT: ret void 51*67e74705SXin Li 52*67e74705SXin Livoid test3(id y) { 53*67e74705SXin Li __weak id z; 54*67e74705SXin Li z = y; 55*67e74705SXin Li} 56*67e74705SXin Li// CHECK-LABEL: define void @_Z5test3P11objc_object( 57*67e74705SXin Li// CHECK: [[Y:%.*]] = alloca i8*, 58*67e74705SXin Li// CHECK-NEXT: [[Z:%.*]] = alloca i8*, 59*67e74705SXin Li// CHECK-NEXT: store 60*67e74705SXin Li// CHECK-NEXT: store i8* null, i8** [[Z]] 61*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] 62*67e74705SXin Li// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]]) 63*67e74705SXin Li// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]]) 64*67e74705SXin Li// CHECK-NEXT: ret void 65*67e74705SXin Li 66*67e74705SXin Livoid test4(__weak id *p) { 67*67e74705SXin Li id y = *p; 68*67e74705SXin Li} 69*67e74705SXin Li// CHECK-LABEL: define void @_Z5test4PU6__weakP11objc_object( 70*67e74705SXin Li// CHECK: [[P:%.*]] = alloca i8**, 71*67e74705SXin Li// CHECK-NEXT: [[Y:%.*]] = alloca i8*, 72*67e74705SXin Li// CHECK-NEXT: store 73*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]] 74*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]]) 75*67e74705SXin Li// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] 76*67e74705SXin Li// CHECK-NEXT: ret void 77*67e74705SXin Li 78*67e74705SXin Livoid test5(__weak id *p) { 79*67e74705SXin Li id y = [*p retain]; 80*67e74705SXin Li} 81*67e74705SXin Li// CHECK-LABEL: define void @_Z5test5PU6__weakP11objc_object 82*67e74705SXin Li// CHECK: [[P:%.*]] = alloca i8**, 83*67e74705SXin Li// CHECK-NEXT: [[Y:%.*]] = alloca i8*, 84*67e74705SXin Li// CHECK-NEXT: store 85*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]] 86*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]]) 87*67e74705SXin Li// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] 88*67e74705SXin Li// CHECK-NEXT: ret void 89*67e74705SXin Li 90*67e74705SXin Livoid test6(__weak Foo **p) { 91*67e74705SXin Li Foo *y = [*p retain]; 92*67e74705SXin Li} 93*67e74705SXin Li// CHECK-LABEL: define void @_Z5test6PU6__weakP3Foo 94*67e74705SXin Li// CHECK: [[P:%.*]] = alloca [[FOO:%.*]]**, 95*67e74705SXin Li// CHECK-NEXT: [[Y:%.*]] = alloca [[FOO]]*, 96*67e74705SXin Li// CHECK-NEXT: store 97*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]] 98*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8** 99*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]]) 100*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]* 101*67e74705SXin Li// CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]] 102*67e74705SXin Li// CHECK-NEXT: ret void 103*67e74705SXin Li 104*67e74705SXin Liextern "C" id get_object(void); 105*67e74705SXin Liextern "C" void use_block(void (^)(void)); 106*67e74705SXin Li 107*67e74705SXin Livoid test7(void) { 108*67e74705SXin Li __weak Foo *p = get_object(); 109*67e74705SXin Li use_block(^{ [p run ]; }); 110*67e74705SXin Li} 111*67e74705SXin Li// CHECK-LABEL: define void @_Z5test7v 112*67e74705SXin Li// CHECK: [[P:%.*]] = alloca [[FOO]]*, 113*67e74705SXin Li// CHECK: [[T0:%.*]] = call i8* @get_object() 114*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]* 115*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8** 116*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8* 117*67e74705SXin Li// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) 118*67e74705SXin Li// CHECK: call void @objc_copyWeak 119*67e74705SXin Li// CHECK: call void @use_block 120*67e74705SXin Li// CHECK: call void @objc_destroyWeak 121*67e74705SXin Li 122*67e74705SXin Li// CHECK-LABEL: define internal void @__copy_helper_block 123*67e74705SXin Li// CHECK: @objc_copyWeak 124*67e74705SXin Li 125*67e74705SXin Li// CHECK-LABEL: define internal void @__destroy_helper_block 126*67e74705SXin Li// CHECK: @objc_destroyWeak 127*67e74705SXin Li 128*67e74705SXin Livoid test8(void) { 129*67e74705SXin Li __block __weak Foo *p = get_object(); 130*67e74705SXin Li use_block(^{ [p run ]; }); 131*67e74705SXin Li} 132*67e74705SXin Li// CHECK-LABEL: define void @_Z5test8v 133*67e74705SXin Li// CHECK: call i8* @objc_initWeak 134*67e74705SXin Li// CHECK-NOT: call void @objc_copyWeak 135*67e74705SXin Li// CHECK: call void @use_block 136*67e74705SXin Li// CHECK: call void @objc_destroyWeak 137*67e74705SXin Li 138*67e74705SXin Li// CHECK-LABEL: define internal void @__Block_byref_object_copy 139*67e74705SXin Li// CHECK: call void @objc_moveWeak 140*67e74705SXin Li 141*67e74705SXin Li// CHECK-LABEL: define internal void @__Block_byref_object_dispose 142*67e74705SXin Li// CHECK: call void @objc_destroyWeak 143*67e74705SXin Li 144*67e74705SXin Li// CHECK-LABEL: define void @_Z14test9_baselinev() 145*67e74705SXin Li// CHECK: define internal void @__copy_helper 146*67e74705SXin Li// CHECK: define internal void @__destroy_helper 147*67e74705SXin Livoid test9_baseline(void) { 148*67e74705SXin Li Foo *p = get_object(); 149*67e74705SXin Li use_block(^{ [p run]; }); 150*67e74705SXin Li} 151*67e74705SXin Li 152*67e74705SXin Li// CHECK-LABEL: define void @_Z5test9v() 153*67e74705SXin Li// CHECK-NOT: define internal void @__copy_helper 154*67e74705SXin Li// CHECK-NOT: define internal void @__destroy_helper 155*67e74705SXin Li// CHECK: define void @_Z9test9_finv() 156*67e74705SXin Livoid test9(void) { 157*67e74705SXin Li __unsafe_unretained Foo *p = get_object(); 158*67e74705SXin Li use_block(^{ [p run]; }); 159*67e74705SXin Li} 160*67e74705SXin Livoid test9_fin() {} 161*67e74705SXin Li 162*67e74705SXin Li// CHECK-LABEL: define void @_Z6test10v() 163*67e74705SXin Li// CHECK-NOT: define internal void @__copy_helper 164*67e74705SXin Li// CHECK-NOT: define internal void @__destroy_helper 165*67e74705SXin Li// CHECK: define void @_Z10test10_finv() 166*67e74705SXin Livoid test10(void) { 167*67e74705SXin Li typedef __unsafe_unretained Foo *UnsafeFooPtr; 168*67e74705SXin Li UnsafeFooPtr p = get_object(); 169*67e74705SXin Li use_block(^{ [p run]; }); 170*67e74705SXin Li} 171*67e74705SXin Livoid test10_fin() {} 172*67e74705SXin Li 173*67e74705SXin Li// CHECK-LABEL: define weak_odr void @_Z6test11ILj0EEvv() 174*67e74705SXin Li// CHECK-NOT: define internal void @__copy_helper 175*67e74705SXin Li// CHECK-NOT: define internal void @__destroy_helper 176*67e74705SXin Li// CHECK: define void @_Z10test11_finv() 177*67e74705SXin Litemplate <unsigned i> void test11(void) { 178*67e74705SXin Li typedef __unsafe_unretained Foo *UnsafeFooPtr; 179*67e74705SXin Li UnsafeFooPtr p = get_object(); 180*67e74705SXin Li use_block(^{ [p run]; }); 181*67e74705SXin Li} 182*67e74705SXin Litemplate void test11<0>(); 183*67e74705SXin Livoid test11_fin() {} 184