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