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