xref: /aosp_15_r20/external/clang/test/CodeGenObjC/arc-precise-lifetime.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
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