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