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