1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s 2 3 #define PRECISE_LIFETIME __attribute__((objc_precise_lifetime)) 4 5 id test0_helper(void) __attribute__((ns_returns_retained)); 6 void test0() { 7 PRECISE_LIFETIME id x = test0_helper(); 8 x = 0; 9 // CHECK: [[X:%.*]] = alloca i8* 10 // CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper() 11 // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] 12 13 // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] 14 // CHECK-NEXT: store i8* null, i8** [[X]] 15 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] 16 // CHECK-NOT: clang.imprecise_release 17 18 // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] 19 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] 20 // CHECK-NOT: clang.imprecise_release 21 22 // CHECK-NEXT: ret void 23 } 24 25 // rdar://problem/9821110 26 @interface Test1 27 - (char*) interior __attribute__((objc_returns_inner_pointer)); 28 // Should we allow this on properties? Yes! see // rdar://14990439 29 @property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer)); 30 @end 31 extern Test1 *test1_helper(void); 32 33 // CHECK-LABEL: define void @test1a() 34 void test1a(void) { 35 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 36 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 37 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 38 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 39 // CHECK-NEXT: store [[TEST1]]* [[T3]] 40 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 41 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 42 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) 43 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 44 // CHECK-NEXT: [[T4:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ 45 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 46 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 47 // CHECK-NEXT: store i8* [[T6]], i8** 48 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 49 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 50 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 51 // CHECK-NEXT: ret void 52 Test1 *ptr = test1_helper(); 53 char *c = [(ptr) interior]; 54 } 55 56 // CHECK-LABEL: define void @test1b() 57 void test1b(void) { 58 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 59 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 60 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 61 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 62 // CHECK-NEXT: store [[TEST1]]* [[T3]] 63 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 64 // CHECK-NEXT: [[T1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ 65 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 66 // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast 67 // CHECK-NEXT: store i8* [[T3]], i8** 68 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 69 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 70 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]] 71 // CHECK-NOT: clang.imprecise_release 72 // CHECK-NEXT: ret void 73 __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper(); 74 char *c = [ptr interior]; 75 } 76 77 void test1c(void) { 78 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 79 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 80 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 81 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 82 // CHECK-NEXT: store [[TEST1]]* [[T3]] 83 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 84 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 85 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) 86 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 87 // CHECK-NEXT: [[T4:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ 88 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 89 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 90 // CHECK-NEXT: store i8* [[T6]], i8** 91 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 92 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 93 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 94 // CHECK-NEXT: ret void 95 Test1 *ptr = test1_helper(); 96 char *pc = ptr.PropertyReturnsInnerPointer; 97 } 98 99 void test1d(void) { 100 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 101 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 102 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 103 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 104 // CHECK-NEXT: store [[TEST1]]* [[T3]] 105 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 106 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 107 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease 108 // CHECK-NEXT: [[SIX:%.*]] = bitcast i8* [[T3]] to [[TEST1]]* 109 // CHECK-NEXT: [[SEVEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ 110 // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] to i8* 111 // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]]) 112 // CHECK-NEXT: store i8* [[CALL1]], i8** 113 // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]** 114 // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8* 115 // CHECK-NEXT: call void @objc_release(i8* [[TEN]]) 116 // CHECK-NEXT: ret void 117 __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper(); 118 char *pc = ptr.PropertyReturnsInnerPointer; 119 } 120 121 @interface Test2 { 122 @public 123 id ivar; 124 } 125 @end 126 // CHECK-LABEL: define void @test2( 127 void test2(Test2 *x) { 128 x->ivar = 0; 129 // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]* 130 // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8* 131 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]] 132 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]* 133 // CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]], 134 135 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]], 136 // CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2.ivar" 137 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 138 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 [[OFFSET]] 139 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8** 140 // CHECK-NEXT: [[T4:%.*]] = load i8** [[T3]], 141 // CHECK-NEXT: store i8* null, i8** [[T3]], 142 // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]] 143 // CHECK-NOT: imprecise 144 145 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]] 146 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 147 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 148 149 // CHECK-NEXT: ret void 150 } 151 152 // CHECK-LABEL: define void @test3(i8* 153 void test3(PRECISE_LIFETIME id x) { 154 // CHECK: [[X:%.*]] = alloca i8*, 155 // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) [[NUW]] 156 // CHECK-NEXT: store i8* [[T0]], i8** [[X]], 157 158 // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] 159 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] 160 // CHECK-NOT: imprecise_release 161 162 // CHECK-NEXT: ret void 163 } 164 165 // CHECK: attributes [[NUW]] = { nounwind } 166