[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / test / CodeGenObjC / arc-precise-lifetime.m
blob8a44ca42c56a1e326acd6545085969f45b410af7
1 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
3 #define PRECISE_LIFETIME __attribute__((objc_precise_lifetime))
5 id test0_helper(void) __attribute__((ns_returns_retained));
6 void test0(void) {
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]]
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
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
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
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
36 extern Test1 *test1_helper(void);
38 // CHECK-LABEL: define{{.*}} void @test1a_message()
39 void 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: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
54   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
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];
70 // CHECK-LABEL: define{{.*}} void @test1a_property()
71 void 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: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
86   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
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;
102 // CHECK-LABEL: define{{.*}} void @test1b_message()
103 void 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: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
115   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
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];
131 // CHECK-LABEL: define{{.*}} void @test1b_property()
132 void 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: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
144   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
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;
160 // CHECK-LABEL: define{{.*}} void @test1c_message()
161 void 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: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
176   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
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];
191 // CHECK-LABEL: define{{.*}} void @test1c_property()
192 void 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: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
207   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
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;
222 // CHECK-LABEL: define{{.*}} void @test1d_message()
223 void 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: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
235   // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
236   // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* noundef [[EIGHT]], i8* noundef [[SEL]])
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];
250 // CHECK-LABEL: define{{.*}} void @test1d_property()
251 void 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: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
263   // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
264   // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* noundef [[EIGHT]], i8* noundef [[SEL]])
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;
278 @interface Test2 {
279 @public
280   id ivar;
282 @end
283 // CHECK-LABEL:      define{{.*}} void @test2(
284 void 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]],
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
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
306   // CHECK-NEXT: ret void
309 // CHECK-LABEL:      define{{.*}} void @test3(i8*
310 void 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]],
315   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
316   // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]]
317   // CHECK-NOT:  imprecise_release
319   // CHECK-NEXT: ret void  
322 // CHECK: attributes [[NUW]] = { nounwind }