1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
2 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s
4 // Check both native/non-native arc platforms. Here we check that they treat
5 // nonlazybind differently.
6 // RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s
7 // RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s
9 // ARC-ALIEN: declare extern_weak void @llvm.objc.storeStrong(ptr, ptr)
10 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.retain(ptr returned)
11 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.autoreleaseReturnValue(ptr returned)
12 // ARC-ALIEN: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]]
13 // ARC-ALIEN: declare extern_weak void @llvm.objc.release(ptr)
14 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
15 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.initWeak(ptr, ptr)
16 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.storeWeak(ptr, ptr)
17 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.loadWeakRetained(ptr)
18 // ARC-ALIEN: declare extern_weak void @llvm.objc.destroyWeak(ptr)
19 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.autorelease(ptr returned)
20 // ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutorelease(ptr returned)
22 // ARC-NATIVE: declare void @llvm.objc.storeStrong(ptr, ptr)
23 // ARC-NATIVE: declare ptr @llvm.objc.retain(ptr returned)
24 // ARC-NATIVE: declare ptr @llvm.objc.autoreleaseReturnValue(ptr returned)
25 // ARC-NATIVE: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]]
26 // ARC-NATIVE: declare void @llvm.objc.release(ptr)
27 // ARC-NATIVE: declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
28 // ARC-NATIVE: declare ptr @llvm.objc.initWeak(ptr, ptr)
29 // ARC-NATIVE: declare ptr @llvm.objc.storeWeak(ptr, ptr)
30 // ARC-NATIVE: declare ptr @llvm.objc.loadWeakRetained(ptr)
31 // ARC-NATIVE: declare void @llvm.objc.destroyWeak(ptr)
32 // ARC-NATIVE: declare ptr @llvm.objc.autorelease(ptr returned)
33 // ARC-NATIVE: declare ptr @llvm.objc.retainAutorelease(ptr returned)
35 // CHECK-LABEL: define{{.*}} void @test0
37 // CHECK: [[X:%.*]] = alloca ptr
38 // CHECK-NEXT: [[PARM:%.*]] = call ptr @llvm.objc.retain(ptr {{.*}})
39 // CHECK-NEXT: store ptr [[PARM]], ptr [[X]]
40 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]]
41 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]])
42 // CHECK-NEXT: ret void
45 // CHECK-LABEL: define{{.*}} ptr @test1(ptr
47 // CHECK: [[X:%.*]] = alloca ptr
48 // CHECK-NEXT: [[Y:%.*]] = alloca ptr
49 // CHECK-NEXT: [[PARM:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}})
50 // CHECK-NEXT: store ptr [[PARM]], ptr [[X]]
51 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]])
52 // CHECK-NEXT: store ptr null, ptr [[Y]]
53 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
54 // CHECK-NEXT: [[RET:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
55 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
56 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
57 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[Y]])
58 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]
59 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
60 // CHECK-NEXT: [[T1:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[RET]])
61 // CHECK-NEXT: ret ptr [[T1]]
67 + (void) class_method;
72 // The self pointer of a class method is not retained.
73 // CHECK: define internal void @"\01+[Test2 class_method]"
78 // CHECK-NEXT: ret void
79 + (void) class_method {}
81 // The self pointer of an instance method is not retained.
82 // CHECK: define internal void @"\01-[Test2 inst_method]"
87 // CHECK-NEXT: ret void
88 - (void) inst_method {}
93 - (id) initWith: (int) x;
97 // CHECK-LABEL: define{{.*}} void @test3_unelided()
98 void test3_unelided(void) {
99 extern void test3_helper(void);
101 // CHECK: [[X:%.*]] = alloca ptr
102 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
103 // CHECK-NEXT: store ptr null, ptr [[X]], align
107 // CHECK-NEXT: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_
108 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
109 // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend
110 // CHECK-NEXT: call void @llvm.objc.release(ptr
113 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
114 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
115 // CHECK-NEXT: [[COPY:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]],
116 // CHECK-NEXT: call void @llvm.objc.release(ptr [[COPY]]) [[NUW:#[0-9]+]]
119 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
120 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]
121 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
122 // CHECK-NEXT: ret void
125 // CHECK-LABEL: define{{.*}} void @test3()
127 // CHECK: [[X:%.*]] = alloca ptr
128 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
130 id x = [[Test3 alloc] initWith: 5];
133 // CHECK-NEXT: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_
134 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
135 // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend
137 // Call to -initWith: with elided retain of consumed argument.
138 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
139 // CHECK-NEXT: [[INIT:%.*]] = call ptr @objc_msgSend(ptr
140 // Assignment for initialization, retention elided.
141 // CHECK-NEXT: store ptr [[INIT]], ptr [[X]]
144 // CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[X]]
145 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
146 // CHECK-NEXT: [[COPY:%.*]] = call ptr @objc_msgSend(ptr noundef [[V]],
149 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]]
150 // CHECK-NEXT: store ptr [[COPY]], ptr [[X]]
151 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]
156 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[X]]
157 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]
158 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
159 // CHECK-NEXT: ret void
162 // CHECK-LABEL: define{{.*}} ptr @test4()
165 // CHECK: load {{.*}}, ptr @"OBJC_CLASSLIST_REFERENCES_
166 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
167 // CHECK-NEXT: [[ALLOC:%.*]] = call ptr @objc_msgSend
169 // Call to -initWith: with elided retain of consumed argument.
170 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
171 // CHECK-NEXT: [[INIT:%.*]] = call ptr @objc_msgSend(ptr noundef [[ALLOC]],
173 // Initialization of return value, occurring within full-expression.
174 // Retain/release elided.
175 // CHECK-NEXT: [[RET:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[INIT]])
177 // CHECK-NEXT: ret ptr [[RET]]
179 return [[Test3 alloc] initWith: 6];
188 // CHECK-LABEL: define{{.*}} void @test5
189 void test5(Test5 *x, id y) {
191 // CHECK: [[X:%.*]] = alloca ptr,
192 // CHECK-NEXT: [[Y:%.*]] = alloca ptr
193 // CHECK-NEXT: call ptr @llvm.objc.retain
194 // CHECK-NEXT: store ptr {{%.*}}, ptr [[X]]
195 // CHECK-NEXT: call ptr @llvm.objc.retain
198 // CHECK-NEXT: load ptr, ptr [[X]]
199 // CHECK-NEXT: load i64, ptr @"OBJC_IVAR_$_Test5.var"
200 // CHECK-NEXT: [[VAR:%.*]] = getelementptr
201 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[VAR]]
202 // CHECK-NEXT: store ptr null, ptr [[VAR]]
203 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]
206 // CHECK-NEXT: [[YVAL:%.*]] = load ptr, ptr [[Y]]
207 // CHECK-NEXT: load ptr, ptr [[X]]
208 // CHECK-NEXT: load i64, ptr @"OBJC_IVAR_$_Test5.var"
209 // CHECK-NEXT: [[VAR:%.*]] = getelementptr
210 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr [[YVAL]]) [[NUW]]
211 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[VAR]]
212 // CHECK-NEXT: store ptr [[T0]], ptr [[VAR]]
213 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]
217 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[Y]]
218 // CHECK-NEXT: call void @llvm.objc.release(ptr [[TMP]]) [[NUW]]
219 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
220 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]
221 // CHECK-NEXT: ret void
224 id test6_helper(void) __attribute__((ns_returns_retained));
225 // CHECK-LABEL: define{{.*}} void @test6()
227 // CHECK: [[X:%.*]] = alloca ptr
228 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
229 // CHECK-NEXT: [[CALL:%.*]] = call ptr @test6_helper()
230 // CHECK-NEXT: store ptr [[CALL]], ptr [[X]]
231 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]
232 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW]], !clang.imprecise_release
233 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
234 // CHECK-NEXT: ret void
235 id x = test6_helper();
238 void test7_helper(id __attribute__((ns_consumed)));
239 // CHECK-LABEL: define{{.*}} void @test7()
241 // CHECK: [[X:%.*]] = alloca ptr
242 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
243 // CHECK-NEXT: store ptr null, ptr [[X]]
244 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
245 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) [[NUW]]
246 // CHECK-NEXT: call void @test7_helper(ptr noundef [[T1]])
247 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]
248 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW]], !clang.imprecise_release
249 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
250 // CHECK-NEXT: ret void
255 id test8_helper(void) __attribute__((ns_returns_retained));
257 __unsafe_unretained id x = test8_helper();
258 // CHECK: [[X:%.*]] = alloca ptr
259 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
260 // CHECK-NEXT: [[T0:%.*]] = call ptr @test8_helper()
261 // CHECK-NEXT: store ptr [[T0]], ptr [[X]]
262 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release
263 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
264 // CHECK-NEXT: ret void
268 @property (retain) Test10 *me;
274 // CHECK-LABEL: define{{.*}} void @test10()
275 // CHECK: [[X:%.*]] = alloca ptr, align
276 // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align
277 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
278 // CHECK-NEXT: store ptr null, ptr [[X]]
279 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]])
280 // CHECK-NEXT: load ptr, ptr [[X]], align
281 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}
282 // CHECK-NEXT: [[V:%.*]] = call ptr @objc_msgSend{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
283 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[V]])
284 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}
285 // CHECK-NEXT: [[T3:%.*]] = call ptr @objc_msgSend{{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
286 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T3]])
287 // CHECK-NEXT: store ptr [[T3]], ptr [[Y]]
288 // CHECK-NEXT: call void @llvm.objc.release(ptr [[V]])
289 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
290 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
291 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[Y]])
292 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
293 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
294 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
295 // CHECK-NEXT: ret void
298 void test11(id (*f)(void) __attribute__((ns_returns_retained))) {
299 // CHECK-LABEL: define{{.*}} void @test11(
300 // CHECK: [[F:%.*]] = alloca ptr, align
301 // CHECK-NEXT: [[X:%.*]] = alloca ptr, align
302 // CHECK-NEXT: store ptr {{%.*}}, ptr [[F]], align
303 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
304 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[F]], align
305 // CHECK-NEXT: [[T1:%.*]] = call ptr [[T0]]()
306 // CHECK-NEXT: store ptr [[T1]], ptr [[X]], align
307 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]]
308 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]]) [[NUW]], !clang.imprecise_release
309 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
310 // CHECK-NEXT: ret void
315 extern id test12_helper(void);
317 // CHECK-LABEL: define{{.*}} void @test12()
318 // CHECK: [[X:%.*]] = alloca ptr, align
319 // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align
321 __weak id x = test12_helper();
322 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
323 // CHECK-NEXT: [[T1:%.*]] = call ptr @test12_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
324 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
325 // CHECK-NEXT: call ptr @llvm.objc.initWeak(ptr [[X]], ptr [[T1]])
326 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
329 // CHECK-NEXT: [[T1:%.*]] = call ptr @test12_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
330 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
331 // CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T1]])
332 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
335 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]])
336 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[X]])
337 // CHECK-NEXT: store ptr [[T2]], ptr [[Y]], align
339 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[Y]]
340 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) [[NUW]], !clang.imprecise_release
341 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[Y]])
342 // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]])
343 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
347 // Indirect consuming calls.
349 // CHECK-LABEL: define{{.*}} void @test13()
350 // CHECK: [[X:%.*]] = alloca ptr, align
351 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
352 // CHECK-NEXT: store ptr null, ptr [[X]], align
355 typedef void fnty(id __attribute__((ns_consumed)));
356 extern fnty *test13_func;
357 // CHECK-NEXT: [[FN:%.*]] = load ptr, ptr @test13_func, align
358 // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align
359 // CHECK-NEXT: [[X_TMP:%.*]] = call ptr @llvm.objc.retain(ptr [[X_VAL]]) [[NUW]]
360 // CHECK-NEXT: call void [[FN]](ptr noundef [[X_TMP]])
363 extern fnty ^test13_block;
364 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr @test13_block, align
365 // CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds nuw [[BLOCKTY:%.*]], ptr [[TMP]], i32 0, i32 3
366 // CHECK-NEXT: [[X_VAL:%.*]] = load ptr, ptr [[X]], align
367 // CHECK-NEXT: [[X_TMP:%.*]] = call ptr @llvm.objc.retain(ptr [[X_VAL]]) [[NUW]]
368 // CHECK-NEXT: [[BLOCK_FN_TMP:%.*]] = load ptr, ptr [[BLOCK_FN_PTR]]
369 // CHECK-NEXT: call void [[BLOCK_FN_TMP]](ptr noundef [[TMP]], ptr noundef [[X_TMP]])
372 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
373 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]
374 // CHECK-NEXT: void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
375 // CHECK-NEXT: ret void
378 @interface Test16_super @end
379 @interface Test16 : Test16_super {
382 @property (assign) int x;
383 @property (retain) id y;
386 @implementation Test16
390 // CHECK: define internal void @"\01-[Test16 dealloc]"(
391 // CHECK: [[SELF:%.*]] = alloca ptr, align
392 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align
393 // CHECK-NEXT: alloca
394 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align
395 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]
396 // CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[SELF]]
399 // CHECK-NEXT: [[T0:%.*]] = getelementptr
400 // CHECK-NEXT: store ptr [[BASE]], ptr [[T0]]
401 // CHECK-NEXT: load ptr, ptr @"OBJC_CLASSLIST_SUP_REFS_$_
402 // CHECK-NEXT: getelementptr
404 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
405 // CHECK-NEXT: call void @objc_msgSendSuper2(
406 // CHECK-NEXT: ret void
410 // CHECK: define internal void @"\01-[Test16 .cxx_destruct]"(
411 // CHECK: [[SELF:%.*]] = alloca ptr, align
412 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align
413 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]], align
414 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]
415 // CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[SELF]]
418 // CHECK-NEXT: [[Y_OFF:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test16.y"
419 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[Y_OFF]]
420 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) [[NUW]]
423 // CHECK-NEXT: [[Z_OFF:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test16.z"
424 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[Z_OFF]]
425 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) [[NUW]]
427 // CHECK-NEXT: ret void
431 // This shouldn't crash.
433 @property (assign) int x;
435 @interface Test17B : Test17A
437 @implementation Test17B
438 - (int) x { return super.x + 1; }
442 // CHECK-LABEL: define{{.*}} void @test19()
443 // CHECK: [[X:%.*]] = alloca [5 x ptr], align 16
444 // CHECK: call void @llvm.lifetime.start
445 // CHECK: call void @llvm.memset.p0.i64(ptr align 16 [[X]], i8 0, i64 40, i1 false)
448 extern id test19_helper(void);
449 x[2] = test19_helper();
451 // CHECK-NEXT: [[T1:%.*]] = call ptr @test19_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
452 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
453 // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [5 x ptr], ptr [[X]], i64 0, i64 2
454 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SLOT]]
455 // CHECK-NEXT: store ptr [[T1]], ptr [[SLOT]]
456 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]
458 // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x ptr], ptr [[X]], i32 0, i32 0
459 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 5
460 // CHECK-NEXT: br label
462 // CHECK: [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
463 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1
464 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]
465 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release
466 // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]
467 // CHECK-NEXT: br i1 [[EQ]],
472 void test20(unsigned n) {
473 // CHECK-LABEL: define{{.*}} void @test20
474 // CHECK: [[N:%.*]] = alloca i32, align 4
475 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr
476 // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8
477 // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4
481 // Capture the VLA size.
482 // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4
483 // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
485 // Save the stack pointer.
486 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0()
487 // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]]
490 // CHECK-NEXT: [[VLA:%.*]] = alloca ptr, i64 [[DIM]], align 16
492 // Store the VLA #elements expression.
493 // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8
496 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8
497 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[VLA]], i8 0, i64 [[T1]], i1 false)
500 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[VLA]], i64 [[DIM]]
501 // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq ptr [[VLA]], [[END]]
502 // CHECK-NEXT: br i1 [[EMPTY]]
504 // CHECK: [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
505 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1
506 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]
507 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release
508 // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[VLA]]
509 // CHECK-NEXT: br i1 [[EQ]],
511 // CHECK: [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]]
512 // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]])
513 // CHECK-NEXT: ret void
516 void test21(unsigned n) {
517 // CHECK-LABEL: define{{.*}} void @test21
518 // CHECK: [[N:%.*]] = alloca i32, align 4
519 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr
520 // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8
521 // CHECK-NEXT: store i32 {{%.*}}, ptr [[N]], align 4
525 // Capture the VLA size.
526 // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4
527 // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
529 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0()
530 // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]]
534 // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
535 // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x ptr], i64 [[T0]], align 16
537 // Store the VLA #elements expression.
538 // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8
541 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]]
542 // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24
543 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[VLA]], i8 0, i64 [[T2]], i1 false)
546 // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
547 // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [3 x ptr], ptr [[VLA]], i32 0, i32 0
548 // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3
549 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 [[T1]]
550 // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]
551 // CHECK-NEXT: br i1 [[EMPTY]]
553 // CHECK: [[AFTER:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
554 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds ptr, ptr [[AFTER]], i64 -1
555 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[CUR]]
556 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release
557 // CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]
558 // CHECK-NEXT: br i1 [[EQ]],
560 // CHECK: [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]]
561 // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]])
562 // CHECK-NEXT: ret void
565 // Note that we no longer emit .release_ivars flags.
566 // Note that we set the flag saying that we need destruction *and*
567 // the flag saying that we don't also need construction.
568 // CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 390,
569 @interface Test23 { id x; } @end
570 @implementation Test23 @end
572 // CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test24" = internal global [[RO_T:%.*]] { i32 130,
573 @interface Test24 {} @end
574 @implementation Test24 @end
576 @interface Test26 { id x[4]; } @end
577 @implementation Test26 @end
578 // CHECK: define internal void @"\01-[Test26 .cxx_destruct]"(
579 // CHECK: [[SELF:%.*]] = load ptr, ptr
580 // CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test26.x"
581 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 [[OFFSET]]
582 // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x ptr], ptr [[T1]], i32 0, i32 0
583 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds ptr, ptr [[BEGIN]], i64 4
584 // CHECK-NEXT: br label
585 // CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
586 // CHECK-NEXT: [[CUR]] = getelementptr inbounds ptr, ptr [[PAST]], i64 -1
587 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[CUR]], ptr null)
588 // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]
589 // CHECK-NEXT: br i1 [[ISDONE]],
592 // Check that 'init' retains self.
596 @implementation Test27
597 - (id) init { return self; }
598 // CHECK: define internal ptr @"\01-[Test27 init]"
599 // CHECK: [[SELF:%.*]] = alloca ptr,
600 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr,
601 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]
602 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]
603 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]
604 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
605 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]
606 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
607 // CHECK-NEXT: ret ptr [[T2]]
612 @property (copy) id prop;
614 @implementation Test28
617 // CHECK: define internal void @"\01-[Test28 .cxx_destruct]"
618 // CHECK: [[SELF:%.*]] = load ptr, ptr
619 // CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test28.prop"
620 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i64 [[OFFSET]]
621 // CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null)
622 // CHECK-NEXT: ret void
624 @interface Test29_super
625 - (id) initWithAllocator: (id) allocator;
627 @interface Test29 : Test29_super
629 - (id) initWithAllocator: (id) allocator;
631 @implementation Test29
632 static id _test29_allocator = 0;
634 // CHECK: define internal ptr @"\01-[Test29 init]"(ptr noundef {{%.*}},
635 // CHECK: [[SELF:%.*]] = alloca ptr, align 8
636 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8
637 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]
638 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]
640 // Evaluate arguments. Note that the send argument is evaluated
641 // before the zeroing of self.
642 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]], align 8
643 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr @_test29_allocator, align 8
645 // Implicit null of 'self', i.e. direct transfer of ownership.
646 // CHECK-NEXT: store ptr null, ptr [[SELF]]
648 // Actual message send.
649 // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
650 // CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]], ptr noundef [[T1]])
652 // Implicit write of result back into 'self'. This is not supposed to
653 // be detectable because we're supposed to ban accesses to the old
654 // self value past the delegate init call.
655 // CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]]
658 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]
661 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]
662 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) [[NUW]], !clang.imprecise_release
665 // CHECK-NEXT: ret ptr [[T1]]
666 return [self initWithAllocator: _test29_allocator];
668 - (id) initWithAllocator: (id) allocator {
669 // CHECK: define internal ptr @"\01-[Test29 initWithAllocator:]"(
670 // CHECK: [[SELF:%.*]] = alloca ptr, align 8
671 // CHECK-NEXT: [[CMD:%.*]] = alloca ptr, align 8
672 // CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca ptr, align 8
673 // CHECK-NEXT: alloca
674 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]
675 // CHECK-NEXT: store ptr {{%.*}}, ptr [[CMD]]
676 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}})
677 // CHECK-NEXT: store ptr [[T0]], ptr [[ALLOCATOR]]
679 // Evaluate arguments. Note that the send argument is evaluated
680 // before the zeroing of self.
681 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]
682 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[ALLOCATOR]], align 8
684 // Implicit null of 'self', i.e. direct transfer of ownership.
685 // CHECK-NEXT: store ptr null, ptr [[SELF]]
687 // Actual message send.
688 // CHECK: [[CALL:%.*]] = call {{.*}} @objc_msgSendSuper2
690 // Implicit write of result back into 'self'. This is not supposed to
691 // be detectable because we're supposed to ban accesses to the old
692 // self value past the delegate init call.
693 // CHECK-NEXT: store ptr [[CALL]], ptr [[SELF]]
696 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]
697 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[SELF]], align
698 // CHECK-NEXT: store ptr [[T2]], ptr [[SELF]], align
699 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])
702 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[SELF]]
703 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) [[NUW]]
706 // CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[ALLOCATOR]]
707 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]]) [[NUW]], !clang.imprecise_release
709 // CHECK-NEXT: [[T6:%.*]] = load ptr, ptr [[SELF]]
710 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T6]]) [[NUW]], !clang.imprecise_release
713 // CHECK-NEXT: ret ptr [[T4]]
714 self = [super initWithAllocator: allocator];
719 typedef struct Test30_helper Test30_helper;
722 - (Test30_helper*) initHelper;
724 @implementation Test30 {
728 // CHECK: define internal ptr @"\01-[Test30 init]"(ptr noundef {{%.*}},
729 // CHECK: [[RET:%.*]] = alloca ptr
730 // CHECK-NEXT: alloca ptr
731 // CHECK-NEXT: store ptr {{%.*}}, ptr [[SELF]]
735 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]
736 // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
737 // CHECK-NEXT: [[CALL:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]])
740 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[SELF]]
741 // CHECK-NEXT: [[IVAR:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test30.helper"
742 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 [[IVAR]]
743 // CHECK-NEXT#: [[T5:%.*]] = load ptr, ptr [[T3]]
744 // CHECK-NEXT#: [[T6:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]])
745 // CHECK-NEXT#: call void @llvm.objc.release(ptr [[T5]])
746 // CHECK-NEXT: store ptr [[CALL]], ptr [[T3]]
749 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]
750 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
753 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]
754 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])
757 // CHECK-NEXT: ret ptr [[T1]]
758 self->helper = [self initHelper];
761 - (Test30_helper*) initHelper {
762 // CHECK: define internal ptr @"\01-[Test30 initHelper]"(
764 // CHECK-NEXT: alloca
767 // CHECK-NEXT: ret ptr null
773 __attribute__((ns_returns_retained)) id test32(void) {
774 // CHECK-LABEL: define{{.*}} ptr @test32()
775 // CHECK: [[T0:%.*]] = call ptr @test32_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
776 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
777 // CHECK-NEXT: ret ptr [[T0]]
778 extern id test32_helper(void);
779 return test32_helper();
784 - (void) give: (Test33_a **) x;
785 - (void) take: (Test33_a **) x;
786 - (void) giveStrong: (out __strong Test33_a **) x;
787 - (void) takeStrong: (inout __strong Test33_a **) x;
788 - (void) giveOut: (out Test33_a **) x;
790 void test33(Test33 *ptr) {
794 [ptr giveStrong: &a];
795 [ptr takeStrong: &a];
798 // CHECK: define{{.*}} void @test33(ptr
799 // CHECK: [[PTR:%.*]] = alloca ptr
800 // CHECK-NEXT: [[A:%.*]] = alloca ptr
801 // CHECK-NEXT: [[TEMP0:%.*]] = alloca ptr
802 // CHECK-NEXT: [[TEMP1:%.*]] = alloca ptr
803 // CHECK-NEXT: [[TEMP2:%.*]] = alloca ptr
804 // CHECK-NEXT: llvm.objc.retain
806 // CHECK-NEXT: call void @llvm.lifetime.start
807 // CHECK-NEXT: store ptr null, ptr [[A]]
809 // CHECK-NEXT: load ptr, ptr [[PTR]]
810 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]]
811 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP0]]
812 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
813 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP0]])
814 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP0]]
815 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
816 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]
817 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]
818 // CHECK-NEXT: store ptr [[T2]], ptr [[A]]
819 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])
821 // CHECK-NEXT: load ptr, ptr [[PTR]]
822 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[A]]
823 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP1]]
824 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
825 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP1]])
826 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP1]]
827 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
828 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]
829 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]
830 // CHECK-NEXT: store ptr [[T2]], ptr [[A]]
831 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])
833 // CHECK-NEXT: load ptr, ptr [[PTR]]
834 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
835 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])
837 // CHECK-NEXT: load ptr, ptr [[PTR]]
838 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
839 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])
842 // CHECK-NEXT: load ptr, ptr [[PTR]]
843 // CHECK-NEXT: store ptr null, ptr [[TEMP2]]
844 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
845 // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[TEMP2]])
846 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP2]]
847 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
848 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[A]]
849 // CHECK-NEXT: store ptr [[T2]], ptr [[A]]
850 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])
853 // CHECK-NEXT: llvm.objc.release
854 // CHECK-NEXT: call void @llvm.lifetime.end
856 // CHECK-NEXT: llvm.objc.release
857 // CHECK-NEXT: ret void
861 // CHECK-LABEL: define{{.*}} void @test36
863 // CHECK: [[X:%.*]] = alloca ptr
865 // CHECK: call ptr @llvm.objc.retain
866 // CHECK: call ptr @llvm.objc.retain
867 // CHECK: call ptr @llvm.objc.retain
868 id array[3] = { @"A", x, @"y" };
870 // CHECK: [[T0:%.*]] = load ptr, ptr [[X]]
871 // CHECK-NEXT: store ptr null, ptr [[X]]
872 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
876 // CHECK: call void @llvm.objc.release
879 // CHECK: call void @llvm.objc.release
880 // CHECK-NEXT: ret void
885 extern void test37_helper(id *);
889 // CHECK-LABEL: define{{.*}} void @test37()
890 // CHECK: [[VAR:%.*]] = alloca ptr,
891 // CHECK-NEXT: [[TEMP:%.*]] = alloca ptr
892 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[VAR]])
893 // CHECK-NEXT: store ptr null, ptr [[VAR]]
895 // CHECK-NEXT: [[W0:%.*]] = load ptr, ptr [[VAR]]
896 // CHECK-NEXT: store ptr [[W0]], ptr [[TEMP]]
897 // CHECK-NEXT: call void @test37_helper(ptr noundef [[TEMP]])
898 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[TEMP]]
899 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
900 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(ptr [[W0]]) [[NUW]]
901 // CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[VAR]]
902 // CHECK-NEXT: store ptr [[T3]], ptr [[VAR]]
903 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]])
905 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[VAR]]
906 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
907 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[VAR]])
908 // CHECK-NEXT: ret void
911 @interface Test43 @end
912 @implementation Test43
913 - (id) test __attribute__((ns_returns_retained)) {
914 extern id test43_produce(void);
915 return test43_produce();
916 // CHECK: call ptr @test43_produce(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
917 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(
923 @property (retain) id x;
925 @implementation Test45
928 // CHECK: define internal ptr @"\01-[Test45 x]"(
929 // CHECK: [[CALL:%.*]] = tail call ptr @objc_getProperty(
930 // CHECK-NEXT: ret ptr [[CALL]]
932 void test46(__weak id *wp, __weak volatile id *wvp) {
933 extern id test46_helper(void);
935 // TODO: this is sub-optimal, we should retain at the actual call site.
937 // CHECK: [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
938 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
939 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8
940 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])
941 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]])
942 // CHECK-NEXT: store ptr [[T4]], ptr
943 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
944 id x = *wp = test46_helper();
946 // CHECK: [[T1:%.*]] = call ptr @test46_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
947 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
948 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr {{%.*}}, align 8
949 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[T2]], ptr [[T1]])
950 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]])
951 // CHECK-NEXT: store ptr [[T4]], ptr
952 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
953 id y = *wvp = test46_helper();
957 extern id test47_helper(void);
958 id x = x = test47_helper();
960 // CHECK-LABEL: define{{.*}} void @test47()
961 // CHECK: [[X:%.*]] = alloca ptr
962 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
963 // CHECK-NEXT: store ptr null, ptr [[X]]
964 // CHECK-NEXT: [[T0:%.*]] = call ptr @test47_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
965 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
966 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]
967 // CHECK-NEXT: store ptr [[T0]], ptr [[X]]
968 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
969 // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
970 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]]
971 // CHECK-NEXT: store ptr [[T2]], ptr [[X]]
972 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]])
973 // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[X]]
974 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]])
975 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
976 // CHECK-NEXT: ret void
980 extern id test48_helper(void);
981 __weak id x = x = test48_helper();
982 // CHECK-LABEL: define{{.*}} void @test48()
983 // CHECK: [[X:%.*]] = alloca ptr
984 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
985 // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.initWeak(ptr [[X]], ptr null)
986 // CHECK-NEXT: [[T2:%.*]] = call ptr @test48_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
987 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T2]])
988 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T2]])
989 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.storeWeak(ptr [[X]], ptr [[T3]])
990 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])
991 // CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[X]])
992 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
993 // CHECK-NEXT: ret void
997 extern id test49_helper(void);
998 __autoreleasing id x = x = test49_helper();
999 // CHECK-LABEL: define{{.*}} void @test49()
1000 // CHECK: [[X:%.*]] = alloca ptr
1001 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
1002 // CHECK-NEXT: store ptr null, ptr [[X]]
1003 // CHECK-NEXT: [[T0:%.*]] = call ptr @test49_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1004 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
1005 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[T0]])
1006 // CHECK-NEXT: store ptr [[T1]], ptr [[X]]
1007 // CHECK-NEXT: [[T3:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T1]])
1008 // CHECK-NEXT: store ptr [[T3]], ptr [[X]]
1009 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
1010 // CHECK-NEXT: ret void
1016 // CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain
1017 // CHECK: call void @llvm.objc.release
1024 typedef struct CGPoint CGPoint;
1027 @property (assign) CGPoint point;
1035 id test52_helper(int) __attribute__((ns_returns_retained));
1036 return ({ int x = 5; test52_helper(x); });
1038 // CHECK-LABEL: define{{.*}} ptr @test52()
1039 // CHECK: [[X:%.*]] = alloca i32
1040 // CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr
1041 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[X]])
1042 // CHECK-NEXT: store i32 5, ptr [[X]],
1043 // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[X]],
1044 // CHECK-NEXT: [[T1:%.*]] = call ptr @test52_helper(i32 noundef [[T0]])
1045 // CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]]
1046 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[X]])
1047 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[TMPALLOCA]]
1048 // CHECK-NEXT: [[T3:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T2]])
1049 // CHECK-NEXT: ret ptr [[T3]]
1053 id test53_helper(void);
1054 id x = ({ id y = test53_helper(); y; });
1056 // CHECK-LABEL: define{{.*}} void @test53()
1057 // CHECK: [[X:%.*]] = alloca ptr,
1058 // CHECK-NEXT: [[Y:%.*]] = alloca ptr,
1059 // CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca ptr,
1060 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
1061 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]])
1062 // CHECK-NEXT: [[T1:%.*]] = call ptr @test53_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1063 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
1064 // CHECK-NEXT: store ptr [[T1]], ptr [[Y]],
1065 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]],
1066 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
1067 // CHECK-NEXT: store ptr [[T1]], ptr [[TMPALLOCA]]
1068 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[Y]]
1069 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])
1070 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[Y]])
1071 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[TMPALLOCA]]
1072 // CHECK-NEXT: store ptr [[T3]], ptr [[X]],
1073 // CHECK-NEXT: load ptr, ptr [[X]],
1074 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
1075 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
1076 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
1077 // CHECK-NEXT: ret void
1080 // CHECK-LABEL: define{{.*}} void @test54(i32 noundef %first, ...)
1081 void test54(int first, ...) {
1082 __builtin_va_list arglist;
1083 // CHECK: call void @llvm.va_start
1084 __builtin_va_start(arglist, first);
1085 // CHECK: call ptr @llvm.objc.retain
1086 id obj = __builtin_va_arg(arglist, id);
1087 // CHECK: call void @llvm.va_end
1088 __builtin_va_end(arglist);
1089 // CHECK: call void @llvm.objc.release
1094 @interface Test55Base @end
1095 @interface Test55 : Test55Base @end
1096 @implementation Test55 (Category)
1099 // CHECK: define internal void @"\01-[Test55(Category) dealloc]"(
1101 // CHECK: call void @objc_msgSendSuper2(
1103 @protocol Test56Protocol
1104 + (id) make __attribute__((ns_returns_retained));
1106 @interface Test56<Test56Protocol> @end
1107 @implementation Test56
1108 // CHECK: define internal ptr @"\01+[Test56 make]"(
1110 extern id test56_helper(void);
1111 // CHECK: [[T1:%.*]] = call ptr @test56_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1112 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
1113 // CHECK-NEXT: ret ptr [[T1]]
1114 return test56_helper();
1117 void test56_test(void) {
1118 id x = [Test56 make];
1119 // CHECK-LABEL: define{{.*}} void @test56_test()
1120 // CHECK: [[X:%.*]] = alloca ptr, align 8
1121 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
1122 // CHECK: [[T0:%.*]] = call ptr @objc_msgSend(
1123 // CHECK-NEXT: store ptr [[T0]], ptr [[X]]
1124 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
1125 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
1126 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[X]])
1127 // CHECK-NEXT: ret void
1131 @property (nonatomic, strong) id strong;
1132 @property (nonatomic, weak) id weak;
1133 @property (nonatomic, unsafe_unretained) id unsafe;
1135 @implementation Test57
1136 @synthesize strong, weak, unsafe;
1138 // CHECK: define internal ptr @"\01-[Test57 strong]"(
1139 // CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}
1140 // CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.strong"
1141 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]]
1142 // CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]
1143 // CHECK-NEXT: ret ptr [[T5]]
1145 // CHECK: define internal ptr @"\01-[Test57 weak]"(
1146 // CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}
1147 // CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.weak"
1148 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]]
1149 // CHECK-NEXT: [[T5:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T3]])
1150 // CHECK-NEXT: [[T6:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[T5]])
1151 // CHECK-NEXT: ret ptr [[T6]]
1153 // CHECK: define internal ptr @"\01-[Test57 unsafe]"(
1154 // CHECK: [[T0:%.*]] = load ptr, ptr {{%.*}}
1155 // CHECK-NEXT: [[T1:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test57.unsafe"
1156 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[T1]]
1157 // CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[T3]]
1158 // CHECK-NEXT: ret ptr [[T5]]
1161 extern id test59_getlock(void);
1162 extern void test59_body(void);
1163 @synchronized (test59_getlock()) {
1167 // CHECK-LABEL: define{{.*}} void @test59()
1168 // CHECK: [[T1:%.*]] = call ptr @test59_getlock(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1169 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
1170 // CHECK-NEXT: call i32 @objc_sync_enter(ptr [[T1]])
1171 // CHECK-NEXT: call void @test59_body()
1172 // CHECK-NEXT: call i32 @objc_sync_exit(ptr [[T1]])
1173 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
1174 // CHECK-NEXT: ret void
1177 // Verify that we don't try to reclaim the result of performSelector.
1179 - (id) performSelector: (SEL) selector;
1180 - (void) test61_void;
1184 // CHECK-LABEL: define{{.*}} void @test61()
1185 // CHECK: [[Y:%.*]] = alloca ptr, align 8
1187 extern id test61_make(void);
1189 // CHECK-NEXT: [[T0:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1190 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
1191 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
1192 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
1193 // CHECK-NEXT: [[T4:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]])
1194 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
1195 [test61_make() performSelector: @selector(test61_void)];
1197 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[Y]])
1198 // CHECK-NEXT: [[T1:%.*]] = call ptr @test61_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1199 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
1200 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
1201 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
1202 // CHECK-NEXT: [[T5:%.*]] = call ptr @objc_msgSend(ptr noundef [[T1]], ptr noundef [[T3]], ptr noundef [[T2]]){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1203 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T5]])
1204 // CHECK-NEXT: store ptr [[T5]], ptr [[Y]]
1205 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]])
1206 id y = [test61_make() performSelector: @selector(test61_id)];
1208 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
1209 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
1210 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[Y]])
1211 // CHECK-NEXT: ret void
1215 // CHECK-LABEL: define{{.*}} void @test62()
1216 // CHECK: [[I:%.*]] = alloca i32, align 4
1217 // CHECK-NEXT: [[CLEANUP_VALUE:%.*]] = alloca ptr
1218 // CHECK-NEXT: [[CLEANUP_REQUIRED:%.*]] = alloca i1
1219 extern id test62_make(void);
1220 extern void test62_body(void);
1222 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[I]])
1223 // CHECK-NEXT: store i32 0, ptr [[I]], align 4
1224 // CHECK-NEXT: br label
1226 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 4
1227 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 20
1228 // CHECK-NEXT: br i1 [[T1]],
1230 for (unsigned i = 0; i != 20; ++i) {
1231 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 4
1232 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0
1233 // CHECK-NEXT: store i1 false, ptr [[CLEANUP_REQUIRED]]
1234 // CHECK-NEXT: br i1 [[T1]],
1235 // CHECK: [[T1:%.*]] = call ptr @test62_make(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1236 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
1237 // CHECK-NEXT: store ptr [[T1]], ptr [[CLEANUP_VALUE]]
1238 // CHECK-NEXT: store i1 true, ptr [[CLEANUP_REQUIRED]]
1239 // CHECK-NEXT: [[T2:%.*]] = icmp ne ptr [[T1]], null
1240 // CHECK-NEXT: br label
1241 // CHECK: [[COND:%.*]] = phi i1 [ false, {{%.*}} ], [ [[T2]], {{%.*}} ]
1242 // CHECK-NEXT: [[T0:%.*]] = load i1, ptr [[CLEANUP_REQUIRED]]
1243 // CHECK-NEXT: br i1 [[T0]],
1244 // CHECK: [[T0:%.*]] = load ptr, ptr [[CLEANUP_VALUE]]
1245 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
1246 // CHECK-NEXT: br label
1247 // CHECK: br i1 [[COND]]
1248 // CHECK: call void @test62_body()
1249 // CHECK-NEXT: br label
1251 if (i != 0 && test62_make() != 0)
1255 // CHECK: [[T0:%.*]] = load i32, ptr [[I]], align 4
1256 // CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 1
1257 // CHECK-NEXT: store i32 [[T1]], ptr [[I]]
1258 // CHECK-NEXT: br label
1268 @property NSString *address;
1271 @implementation Person
1272 @synthesize address;
1274 // CHECK: tail call ptr @objc_getProperty
1275 // CHECK: call void @objc_setProperty
1277 // Verify that we successfully parse and preserve this attribute in
1280 - (void) consume: (id __attribute__((ns_consumed))) ptr;
1283 extern Test66 *test66_receiver(void);
1284 extern id test66_arg(void);
1285 [test66_receiver() consume: test66_arg()];
1287 // CHECK-LABEL: define{{.*}} void @test66()
1288 // CHECK: [[T3:%.*]] = call ptr @test66_receiver(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1289 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T3]])
1290 // CHECK-NEXT: [[T4:%.*]] = call ptr @test66_arg(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1291 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T4]])
1292 // CHECK-NEXT: [[SIX:%.*]] = icmp eq ptr [[T3]], null
1293 // CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label %[[CALL:.*]]
1295 // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES
1296 // CHECK-NEXT: call void @objc_msgSend(ptr noundef [[T3]], ptr noundef [[SEL]], ptr noundef [[T4]])
1297 // CHECK-NEXT: br label [[CONT:%.*]]
1298 // CHECK: call void @llvm.objc.release(ptr [[T4]]) [[NUW]]
1299 // CHECK-NEXT: br label [[CONT:%.*]]
1300 // CHECK: call void @llvm.objc.release(ptr [[T3]])
1301 // CHECK-NEXT: ret void
1303 Class test67_helper(void);
1305 Class cl = test67_helper();
1307 // CHECK-LABEL: define{{.*}} void @test67()
1308 // CHECK: [[CL:%.*]] = alloca ptr, align 8
1309 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[CL]])
1310 // CHECK-NEXT: [[T0:%.*]] = call ptr @test67_helper()
1311 // CHECK-NEXT: store ptr [[T0]], ptr [[CL]], align 8
1312 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[CL]])
1313 // CHECK-NEXT: ret void
1315 Class test68_helper(void);
1317 __strong Class cl = test67_helper();
1319 // CHECK-LABEL: define{{.*}} void @test68()
1320 // CHECK: [[CL:%.*]] = alloca ptr, align 8
1321 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[CL]])
1322 // CHECK-NEXT: [[T1:%.*]] = call ptr @test67_helper(){{.*}} [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
1323 // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T1]])
1324 // CHECK-NEXT: store ptr [[T1]], ptr [[CL]], align 8
1325 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[CL]]
1326 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])
1327 // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[CL]])
1328 // CHECK-NEXT: ret void
1330 @interface Test69 @end
1331 @implementation Test69
1332 - (id) foo { return self; }
1334 // CHECK: define internal ptr @"\01-[Test69 foo]"(
1335 // CHECK: [[SELF:%.*]] = alloca ptr, align 8
1336 // CHECK: [[T0:%.*]] = load ptr, ptr [[SELF]], align 8
1337 // CHECK-NEXT: ret ptr [[T0]]
1340 // CHECK-LABEL: define{{.*}} void @test70
1341 // CHECK: store ptr null, ptr
1342 // CHECK: store ptr null, ptr
1343 // CHECK: [[ID:%.*]] = call ptr @llvm.objc.retain(ptr
1344 // CHECK: store ptr [[ID]], ptr
1350 // Be sure that we emit lifetime intrinsics only after dtors
1356 struct AggDtor getAggDtor(void);
1358 // CHECK-LABEL: define{{.*}} void @test71
1360 // CHECK: call void @llvm.lifetime.start.p0({{[^,]+}}, ptr %[[T:.*]])
1361 // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T]])
1362 // CHECK: call void @__destructor_8_s40(ptr %[[T]])
1363 // CHECK: call void @llvm.lifetime.end.p0({{[^,]+}}, ptr %[[T]])
1364 // CHECK: call void @llvm.lifetime.start.p0({{[^,]+}}, ptr %[[T2:.*]])
1365 // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T2]])
1366 // CHECK: call void @__destructor_8_s40(ptr %[[T2]])
1367 // CHECK: call void @llvm.lifetime.end.p0({{[^,]+}}, ptr %[[T2]])
1372 // Check that no extra release calls are emitted to detruct the compond literal.
1374 // CHECK: define{{.*}} void @test72(ptr noundef %[[A:.*]], ptr noundef %[[B:.*]])
1375 // CHECK: %[[A_ADDR:.*]] = alloca ptr, align 8
1376 // CHECK: %[[B_ADDR:.*]] = alloca ptr, align 8
1377 // CHECK: %[[T:.*]] = alloca [2 x ptr], align 16
1378 // CHECK: %[[V0:.*]] = call ptr @llvm.objc.retain(ptr %[[A]])
1379 // CHECK: %[[V1:.*]] = call ptr @llvm.objc.retain(ptr %[[B]]) #2
1380 // CHECK: %[[V3:.*]] = load ptr, ptr %[[A_ADDR]], align 8, !tbaa !7
1381 // CHECK: %[[V4:.*]] = call ptr @llvm.objc.retain(ptr %[[V3]]) #2
1382 // CHECK: store ptr %[[V4]], ptr %[[T]], align 8, !tbaa !7
1383 // CHECK: %[[ARRAYINIT_ELEMENT:.*]] = getelementptr inbounds ptr, ptr %[[T]], i64 1
1384 // CHECK: %[[V5:.*]] = load ptr, ptr %[[B_ADDR]], align 8, !tbaa !7
1385 // CHECK: %[[V6:.*]] = call ptr @llvm.objc.retain(ptr %[[V5]]) #2
1386 // CHECK: store ptr %[[V6]], ptr %[[ARRAYINIT_ELEMENT]], align 8, !tbaa !7
1387 // CHECK: %[[ARRAY_BEGIN:.*]] = getelementptr inbounds [2 x ptr], ptr %[[T]], i32 0, i32 0
1388 // CHECK: %[[V7:.*]] = getelementptr inbounds ptr, ptr %[[ARRAY_BEGIN]], i64 2
1390 // CHECK-NOT: call void @llvm.objc.release
1392 // CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi ptr [ %[[V7]], %{{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], %{{.*}} ]
1393 // CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds ptr, ptr %[[ARRAYDESTROY_ELEMENTPAST]], i64 -1
1394 // CHECK: %[[V8:.*]] = load ptr, ptr %[[ARRAYDESTROY_ELEMENT]], align 8
1395 // CHECK: call void @llvm.objc.release(ptr %[[V8]]) #2, !clang.imprecise_release
1397 // CHECK-NOT: call void @llvm.objc.release
1399 // CHECK: %[[V10:.*]] = load ptr, ptr %[[B_ADDR]], align 8
1400 // CHECK: call void @llvm.objc.release(ptr %[[V10]]) #2, !clang.imprecise_release
1401 // CHECK: %[[V11:.*]] = load ptr, ptr %[[A_ADDR]], align 8
1402 // CHECK: call void @llvm.objc.release(ptr %[[V11]]) #2, !clang.imprecise_release
1404 void test72(id a, id b) {
1405 __strong id t[] = (__strong id[]){a, b};
1408 // ARC-ALIEN: attributes [[NLB]] = { nonlazybind }
1409 // ARC-NATIVE: attributes [[NLB]] = { nonlazybind }
1410 // CHECK: attributes [[NUW]] = { nounwind }