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 ptr, 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 ptr, 45// CHECK-NEXT: [[Z:%.*]] = alloca ptr, 46// CHECK-NEXT: store 47// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]] 48// CHECK-NEXT: call ptr @llvm.objc.initWeak(ptr [[Z]], ptr [[T0]]) 49// CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[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 ptr, 58// CHECK-NEXT: [[Z:%.*]] = alloca ptr, 59// CHECK-NEXT: store 60// CHECK-NEXT: store ptr null, ptr [[Z]] 61// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]] 62// CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[Z]], ptr [[T0]]) 63// CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[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 ptr, 71// CHECK-NEXT: [[Y:%.*]] = alloca ptr, 72// CHECK-NEXT: store 73// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[P]] 74// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.loadWeak(ptr [[T0]]) 75// CHECK-NEXT: store ptr [[T1]], ptr [[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 ptr, 83// CHECK-NEXT: [[Y:%.*]] = alloca ptr, 84// CHECK-NEXT: store 85// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[P]] 86// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T0]]) 87// CHECK-NEXT: store ptr [[T1]], ptr [[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 ptr, 95// CHECK-NEXT: [[Y:%.*]] = alloca ptr, 96// CHECK-NEXT: store 97// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[P]] 98// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T0]]) 99// CHECK-NEXT: store ptr [[T2]], ptr [[Y]] 100// CHECK-NEXT: ret void 101 102extern "C" id get_object(void); 103extern "C" void use_block(void (^)(void)); 104 105void test7(void) { 106 __weak Foo *p = get_object(); 107 use_block(^{ [p run ]; }); 108} 109// CHECK-LABEL: define{{.*}} void @_Z5test7v 110// CHECK: [[P:%.*]] = alloca ptr, 111// CHECK: [[T0:%.*]] = call ptr @get_object() 112// CHECK-NEXT: call ptr @llvm.objc.initWeak(ptr [[P]], ptr [[T0]]) 113// CHECK: call void @llvm.objc.copyWeak 114// CHECK: call void @use_block 115// CHECK: call void @llvm.objc.destroyWeak 116 117// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block 118// CHECK: @llvm.objc.copyWeak 119 120// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block 121// CHECK: @llvm.objc.destroyWeak 122 123void test8(void) { 124 __block __weak Foo *p = get_object(); 125 use_block(^{ [p run ]; }); 126} 127// CHECK-LABEL: define{{.*}} void @_Z5test8v 128// CHECK: call ptr @llvm.objc.initWeak 129// CHECK-NOT: call void @llvm.objc.copyWeak 130// CHECK: call void @use_block 131// CHECK: call void @llvm.objc.destroyWeak 132 133// CHECK-LABEL: define internal void @__Block_byref_object_copy 134// CHECK: call void @llvm.objc.moveWeak 135 136// CHECK-LABEL: define internal void @__Block_byref_object_dispose 137// CHECK: call void @llvm.objc.destroyWeak 138 139// CHECK-LABEL: define{{.*}} void @_Z14test9_baselinev() 140// CHECK: define linkonce_odr hidden void @__copy_helper 141// CHECK: define linkonce_odr hidden void @__destroy_helper 142void test9_baseline(void) { 143 Foo *p = get_object(); 144 use_block(^{ [p run]; }); 145} 146 147// CHECK-LABEL: define{{.*}} void @_Z5test9v() 148// CHECK-NOT: define internal void @__copy_helper 149// CHECK-NOT: define internal void @__destroy_helper 150// CHECK: define{{.*}} void @_Z9test9_finv() 151void test9(void) { 152 __unsafe_unretained Foo *p = get_object(); 153 use_block(^{ [p run]; }); 154} 155void test9_fin() {} 156 157// CHECK-LABEL: define{{.*}} void @_Z6test10v() 158// CHECK-NOT: define internal void @__copy_helper 159// CHECK-NOT: define internal void @__destroy_helper 160// CHECK: define{{.*}} void @_Z10test10_finv() 161void test10(void) { 162 typedef __unsafe_unretained Foo *UnsafeFooPtr; 163 UnsafeFooPtr p = get_object(); 164 use_block(^{ [p run]; }); 165} 166void test10_fin() {} 167 168// CHECK-LABEL: define weak_odr void @_Z6test11ILj0EEvv() 169// CHECK-NOT: define internal void @__copy_helper 170// CHECK-NOT: define internal void @__destroy_helper 171// CHECK: define{{.*}} void @_Z10test11_finv() 172template <unsigned i> void test11(void) { 173 typedef __unsafe_unretained Foo *UnsafeFooPtr; 174 UnsafeFooPtr p = get_object(); 175 use_block(^{ [p run]; }); 176} 177template void test11<0>(); 178void test11_fin() {} 179