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