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 53void 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 60void 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 72void 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 86void 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 98void 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 110void 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 124extern id get_object(void); 125extern void use_block(void (^)(void)); 126 127void 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 148void 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 167void 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() 176void test9(void) { 177 __unsafe_unretained Foo *p = get_object(); 178 use_block(^{ [p run]; }); 179} 180void 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() 186void test10(void) { 187 typedef __unsafe_unretained Foo *UnsafeFooPtr; 188 UnsafeFooPtr p = get_object(); 189 use_block(^{ [p run]; }); 190} 191void test10_fin() {} 192