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 5id test0_helper(void) __attribute__((ns_returns_retained)); 6void test0() { 7 PRECISE_LIFETIME id x = test0_helper(); 8 x = 0; 9 // CHECK: [[X:%.*]] = alloca i8* 10 // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* 11 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]]) 12 // CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper() 13 // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] 14 15 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]] 16 // CHECK-NEXT: store i8* null, i8** [[X]] 17 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] 18 // CHECK-NOT: clang.imprecise_release 19 20 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]] 21 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] 22 // CHECK-NOT: clang.imprecise_release 23 24 // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* 25 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]]) 26 // CHECK-NEXT: ret void 27} 28 29// rdar://problem/9821110 30@interface Test1 31- (char*) interior __attribute__((objc_returns_inner_pointer)); 32// Should we allow this on properties? Yes! see // rdar://14990439 33@property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer)); 34@end 35extern Test1 *test1_helper(void); 36 37// CHECK-LABEL: define void @test1a() 38void test1a(void) { 39 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 40 // CHECK: [[C:%.*]] = alloca i8*, align 8 41 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 42 // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]]) 43 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 44 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 45 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 46 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 47 // CHECK-NEXT: store [[TEST1]]* [[T3]] 48 // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8* 49 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]]) 50 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 51 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 52 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) 53 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 54 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 55 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 56 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 57 // CHECK-NEXT: store i8* [[T6]], i8** 58 // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8* 59 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]]) 60 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 61 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 62 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 63 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 64 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]]) 65 // CHECK-NEXT: ret void 66 Test1 *ptr = test1_helper(); 67 char *c = [(ptr) interior]; 68} 69 70// CHECK-LABEL: define void @test1b() 71void test1b(void) { 72 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 73 // CHECK: [[C:%.*]] = alloca i8*, align 8 74 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 75 // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]]) 76 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 77 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 78 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 79 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 80 // CHECK-NEXT: store [[TEST1]]* [[T3]] 81 // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8* 82 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]]) 83 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 84 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 85 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 86 // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast 87 // CHECK-NEXT: store i8* [[T3]], i8** 88 // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8* 89 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]]) 90 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 91 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 92 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]] 93 // CHECK-NOT: clang.imprecise_release 94 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 95 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]]) 96 // CHECK-NEXT: ret void 97 __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper(); 98 char *c = [ptr interior]; 99} 100 101void test1c(void) { 102 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 103 // CHECK: [[PC:%.*]] = alloca i8*, align 8 104 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 105 // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]]) 106 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 107 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 108 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 109 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 110 // CHECK-NEXT: store [[TEST1]]* [[T3]] 111 // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8* 112 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]]) 113 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 114 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 115 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) 116 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 117 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 118 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 119 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 120 // CHECK-NEXT: store i8* [[T6]], i8** 121 // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8* 122 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]]) 123 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 124 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 125 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 126 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 127 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]]) 128 // CHECK-NEXT: ret void 129 Test1 *ptr = test1_helper(); 130 char *pc = ptr.PropertyReturnsInnerPointer; 131} 132 133void test1d(void) { 134 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 135 // CHECK: [[PC:%.*]] = alloca i8*, align 8 136 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 137 // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]]) 138 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 139 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 140 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 141 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 142 // CHECK-NEXT: store [[TEST1]]* [[T3]] 143 // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8* 144 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]]) 145 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 146 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 147 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease 148 // CHECK-NEXT: [[SIX:%.*]] = bitcast i8* [[T3]] to [[TEST1]]* 149 // CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 150 // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] to i8* 151 // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]]) 152 // CHECK-NEXT: store i8* [[CALL1]], i8** 153 // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8* 154 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]]) 155 // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]** 156 // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8* 157 // CHECK-NEXT: call void @objc_release(i8* [[TEN]]) 158 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 159 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]]) 160 // CHECK-NEXT: ret void 161 __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper(); 162 char *pc = ptr.PropertyReturnsInnerPointer; 163} 164 165@interface Test2 { 166@public 167 id ivar; 168} 169@end 170// CHECK-LABEL: define void @test2( 171void test2(Test2 *x) { 172 x->ivar = 0; 173 // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]* 174 // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8* 175 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]] 176 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]* 177 // CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]], 178 179 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]*, [[TEST2]]** [[X]], 180 // CHECK-NEXT: [[OFFSET:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test2.ivar" 181 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 182 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, i8* [[T1]], i64 [[OFFSET]] 183 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8** 184 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]], 185 // CHECK-NEXT: store i8* null, i8** [[T3]], 186 // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]] 187 // CHECK-NOT: imprecise 188 189 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]*, [[TEST2]]** [[X]] 190 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 191 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 192 193 // CHECK-NEXT: ret void 194} 195 196// CHECK-LABEL: define void @test3(i8* 197void test3(PRECISE_LIFETIME id x) { 198 // CHECK: [[X:%.*]] = alloca i8*, 199 // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) [[NUW]] 200 // CHECK-NEXT: store i8* [[T0]], i8** [[X]], 201 202 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] 203 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] 204 // CHECK-NOT: imprecise_release 205 206 // CHECK-NEXT: ret void 207} 208 209// CHECK: attributes [[NUW]] = { nounwind } 210