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: @"_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 @llvm.objc.destroyWeak 30@end 31 32 33void test1(__weak id x) {} 34// CHECK-LABEL: define void @_Z5test1P11objc_object( 35// CHECK: [[X:%.*]] = alloca i8*, 36// CHECK-NEXT: llvm.objc.initWeak 37// CHECK-NEXT: llvm.objc.destroyWeak 38// CHECK-NEXT: ret void 39 40void 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* @llvm.objc.initWeak(i8** [[Z]], i8* [[T0]]) 49// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]]) 50// CHECK-NEXT: ret void 51 52void 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* @llvm.objc.storeWeak(i8** [[Z]], i8* [[T0]]) 63// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]]) 64// CHECK-NEXT: ret void 65 66void 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* @llvm.objc.loadWeak(i8** [[T0]]) 75// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] 76// CHECK-NEXT: ret void 77 78void 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* @llvm.objc.loadWeakRetained(i8** [[T0]]) 87// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] 88// CHECK-NEXT: ret void 89 90void 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* @llvm.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 104extern "C" id get_object(void); 105extern "C" void use_block(void (^)(void)); 106 107void 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* @llvm.objc.initWeak(i8** [[T2]], i8* [[T3]]) 118// CHECK: call void @llvm.objc.copyWeak 119// CHECK: call void @use_block 120// CHECK: call void @llvm.objc.destroyWeak 121 122// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block 123// CHECK: @llvm.objc.copyWeak 124 125// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block 126// CHECK: @llvm.objc.destroyWeak 127 128void 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* @llvm.objc.initWeak 134// CHECK-NOT: call void @llvm.objc.copyWeak 135// CHECK: call void @use_block 136// CHECK: call void @llvm.objc.destroyWeak 137 138// CHECK-LABEL: define internal void @__Block_byref_object_copy 139// CHECK: call void @llvm.objc.moveWeak 140 141// CHECK-LABEL: define internal void @__Block_byref_object_dispose 142// CHECK: call void @llvm.objc.destroyWeak 143 144// CHECK-LABEL: define void @_Z14test9_baselinev() 145// CHECK: define linkonce_odr hidden void @__copy_helper 146// CHECK: define linkonce_odr hidden void @__destroy_helper 147void 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() 156void test9(void) { 157 __unsafe_unretained Foo *p = get_object(); 158 use_block(^{ [p run]; }); 159} 160void 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() 166void test10(void) { 167 typedef __unsafe_unretained Foo *UnsafeFooPtr; 168 UnsafeFooPtr p = get_object(); 169 use_block(^{ [p run]; }); 170} 171void 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() 177template <unsigned i> void test11(void) { 178 typedef __unsafe_unretained Foo *UnsafeFooPtr; 179 UnsafeFooPtr p = get_object(); 180 use_block(^{ [p run]; }); 181} 182template void test11<0>(); 183void test11_fin() {} 184