1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -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.p0i8(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 @llvm.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 @llvm.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.p0i8(i64 8, i8* [[XPTR2]]) 26 // CHECK-NEXT: ret void 27} 28 29// rdar://problem/9821110 - precise lifetime should suppress extension 30// rdar://problem/22172983 - should work for calls via property syntax, too 31@interface Test1 32- (char*) interior __attribute__((objc_returns_inner_pointer)); 33// Should we allow this on properties? Yes! see // rdar://14990439 34@property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer)); 35@end 36extern Test1 *test1_helper(void); 37 38// CHECK-LABEL: define{{.*}} void @test1a_message() 39void test1a_message(void) { 40 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 41 // CHECK: [[C:%.*]] = alloca i8*, align 8 42 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 43 // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]]) 44 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 45 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 46 // CHECK-NEXT: store [[TEST1]]* [[T0]] 47 // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8* 48 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]]) 49 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 50 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 51 // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]]) 52 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 53 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 54 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 55 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 56 // CHECK-NEXT: store i8* [[T6]], i8** 57 // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8* 58 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]]) 59 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 60 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 61 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 62 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 63 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 64 // CHECK-NEXT: ret void 65 Test1 *ptr = test1_helper(); 66 char *c = [(ptr) interior]; 67} 68 69 70// CHECK-LABEL: define{{.*}} void @test1a_property() 71void test1a_property(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.p0i8(i64 8, i8* [[PTRPTR1]]) 76 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 77 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 78 // CHECK-NEXT: store [[TEST1]]* [[T0]] 79 // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8* 80 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]]) 81 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 82 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 83 // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]]) 84 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 85 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 86 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 87 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 88 // CHECK-NEXT: store i8* [[T6]], i8** 89 // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8* 90 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]]) 91 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 92 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 93 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 94 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 95 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 96 // CHECK-NEXT: ret void 97 Test1 *ptr = test1_helper(); 98 char *c = ptr.interior; 99} 100 101 102// CHECK-LABEL: define{{.*}} void @test1b_message() 103void test1b_message(void) { 104 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 105 // CHECK: [[C:%.*]] = alloca i8*, align 8 106 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 107 // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]]) 108 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 109 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 110 // CHECK-NEXT: store [[TEST1]]* [[T0]] 111 // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8* 112 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]]) 113 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 114 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 115 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 116 // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast 117 // CHECK-NEXT: store i8* [[T3]], i8** 118 // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8* 119 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]]) 120 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 121 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 122 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]] 123 // CHECK-NOT: clang.imprecise_release 124 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 125 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 126 // CHECK-NEXT: ret void 127 PRECISE_LIFETIME Test1 *ptr = test1_helper(); 128 char *c = [ptr interior]; 129} 130 131// CHECK-LABEL: define{{.*}} void @test1b_property() 132void test1b_property(void) { 133 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 134 // CHECK: [[C:%.*]] = alloca i8*, align 8 135 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 136 // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]]) 137 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 138 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 139 // CHECK-NEXT: store [[TEST1]]* [[T0]] 140 // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8* 141 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]]) 142 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 143 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 144 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 145 // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast 146 // CHECK-NEXT: store i8* [[T3]], i8** 147 // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8* 148 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]]) 149 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 150 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 151 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]] 152 // CHECK-NOT: clang.imprecise_release 153 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 154 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 155 // CHECK-NEXT: ret void 156 PRECISE_LIFETIME Test1 *ptr = test1_helper(); 157 char *c = ptr.interior; 158} 159 160// CHECK-LABEL: define{{.*}} void @test1c_message() 161void test1c_message(void) { 162 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 163 // CHECK: [[PC:%.*]] = alloca i8*, align 8 164 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 165 // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]]) 166 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 167 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 168 // CHECK-NEXT: store [[TEST1]]* [[T0]] 169 // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8* 170 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]]) 171 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 172 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 173 // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]]) 174 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 175 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 176 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 177 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 178 // CHECK-NEXT: store i8* [[T6]], i8** 179 // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8* 180 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]]) 181 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 182 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 183 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 184 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 185 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 186 // CHECK-NEXT: ret void 187 Test1 *ptr = test1_helper(); 188 char *pc = [ptr PropertyReturnsInnerPointer]; 189} 190 191// CHECK-LABEL: define{{.*}} void @test1c_property() 192void test1c_property(void) { 193 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 194 // CHECK: [[PC:%.*]] = alloca i8*, align 8 195 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 196 // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]]) 197 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 198 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 199 // CHECK-NEXT: store [[TEST1]]* [[T0]] 200 // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8* 201 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]]) 202 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 203 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 204 // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]]) 205 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 206 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 207 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 208 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 209 // CHECK-NEXT: store i8* [[T6]], i8** 210 // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8* 211 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]]) 212 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 213 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 214 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 215 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 216 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 217 // CHECK-NEXT: ret void 218 Test1 *ptr = test1_helper(); 219 char *pc = ptr.PropertyReturnsInnerPointer; 220} 221 222// CHECK-LABEL: define{{.*}} void @test1d_message() 223void test1d_message(void) { 224 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 225 // CHECK: [[PC:%.*]] = alloca i8*, align 8 226 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 227 // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]]) 228 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 229 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 230 // CHECK-NEXT: store [[TEST1]]* [[T0]] 231 // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8* 232 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]]) 233 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 234 // CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 235 // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 236 // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]]) 237 // CHECK-NEXT: store i8* [[CALL1]], i8** 238 // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8* 239 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]]) 240 // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]** 241 // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8* 242 // CHECK-NEXT: call void @llvm.objc.release(i8* [[TEN]]) 243 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 244 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 245 // CHECK-NEXT: ret void 246 PRECISE_LIFETIME Test1 *ptr = test1_helper(); 247 char *pc = [ptr PropertyReturnsInnerPointer]; 248} 249 250// CHECK-LABEL: define{{.*}} void @test1d_property() 251void test1d_property(void) { 252 // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8 253 // CHECK: [[PC:%.*]] = alloca i8*, align 8 254 // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 255 // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]]) 256 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] 257 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use([[TEST1]]* [[T0]]) 258 // CHECK-NEXT: store [[TEST1]]* [[T0]] 259 // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8* 260 // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]]) 261 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]** 262 // CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ 263 // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 264 // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]]) 265 // CHECK-NEXT: store i8* [[CALL1]], i8** 266 // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8* 267 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]]) 268 // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]** 269 // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8* 270 // CHECK-NEXT: call void @llvm.objc.release(i8* [[TEN]]) 271 // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8* 272 // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]]) 273 // CHECK-NEXT: ret void 274 PRECISE_LIFETIME Test1 *ptr = test1_helper(); 275 char *pc = ptr.PropertyReturnsInnerPointer; 276} 277 278@interface Test2 { 279@public 280 id ivar; 281} 282@end 283// CHECK-LABEL: define{{.*}} void @test2( 284void test2(Test2 *x) { 285 x->ivar = 0; 286 // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]* 287 // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8* 288 // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) [[NUW]] 289 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]* 290 // CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]], 291 292 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]*, [[TEST2]]** [[X]], 293 // CHECK-NEXT: [[OFFSET:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test2.ivar" 294 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 295 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, i8* [[T1]], i64 [[OFFSET]] 296 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8** 297 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]], 298 // CHECK-NEXT: store i8* null, i8** [[T3]], 299 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T4]]) [[NUW]] 300 // CHECK-NOT: imprecise 301 302 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]*, [[TEST2]]** [[X]] 303 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 304 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 305 306 // CHECK-NEXT: ret void 307} 308 309// CHECK-LABEL: define{{.*}} void @test3(i8* 310void test3(PRECISE_LIFETIME id x) { 311 // CHECK: [[X:%.*]] = alloca i8*, 312 // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}}) [[NUW]] 313 // CHECK-NEXT: store i8* [[T0]], i8** [[X]], 314 315 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] 316 // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]] 317 // CHECK-NOT: imprecise_release 318 319 // CHECK-NEXT: ret void 320} 321 322// CHECK: attributes [[NUW]] = { nounwind } 323