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));
7 PRECISE_LIFETIME id x = test0_helper();
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
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));
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;
283 // CHECK-LABEL: define{{.*}} void @test2(
284 void test2(Test2 *x) {
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 }