[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / CodeGenObjC / arc.m
blob8eaca8ea1c68c9525f2770b8b6a656190ad01058
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
36 void test0(id x) {
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
46 id test1(id x) {
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]]
62   id y;
63   return y;
66 @interface Test2
67 + (void) class_method;
68 - (void) inst_method;
69 @end
70 @implementation Test2
72 // The self pointer of a class method is not retained.
73 // CHECK: define internal void @"\01+[Test2 class_method]"
74 // CHECK:      alloca
75 // CHECK-NEXT: alloca
76 // CHECK-NEXT: store
77 // CHECK-NEXT: store
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]"
83 // CHECK:      alloca
84 // CHECK-NEXT: alloca
85 // CHECK-NEXT: store
86 // CHECK-NEXT: store
87 // CHECK-NEXT: ret void
88 - (void) inst_method {}
89 @end
91 @interface Test3
92 + (id) alloc;
93 - (id) initWith: (int) x;
94 - (id) copy;
95 @end
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
104   Test3 *x;
106   // Call to +alloc.
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
111   [Test3 alloc];
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]+]]
117   [x copy];
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()
126 void test3(void) {
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];
132   // Call to +alloc.
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]]
143   // Call to -copy.
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]],
148   // Assignment to x.
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]]
153   x = [x copy];
155   // Cleanup for x.
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()
163 id test4(void) {
164   // Call to +alloc.
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];
182 @interface Test5 {
183 @public
184   id var;
186 @end
188 // CHECK-LABEL: define{{.*}} void @test5
189 void test5(Test5 *x, id y) {
190   // Prologue.
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
196   // CHECK-NEXT: store
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]]
204   x->var = 0;
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]]
214   x->var = y;
216   // Epilogue.
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()
226 void test6(void) {
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()
240 void test7(void) {
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
251   id x;
252   test7_helper(x);
255 id test8_helper(void) __attribute__((ns_returns_retained));
256 void test8(void) {
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
267 @interface Test10
268 @property (retain) Test10 *me;
269 @end
270 void test10(void) {
271   Test10 *x;
272   id y = x.me.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
311   id x = f();
314 void test12(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]])
328   x = test12_helper();
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]])
334   id y = x;
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]])
344   // CHECK: ret void
347 // Indirect consuming calls.
348 void test13(void) {
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
353   id x;
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]])
361   test13_func(x);
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]])
370   test13_block(x);
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 {
380   id z;
382 @property (assign) int x;
383 @property (retain) id y;
384 - (void) dealloc;
385 @end
386 @implementation Test16
387 @synthesize x;
388 @synthesize y;
389 - (void) dealloc {
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]]
398   // Call super.
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
403   // CHECK-NEXT: store
404   // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
405   // CHECK-NEXT: call void @objc_msgSendSuper2(
406   // CHECK-NEXT: ret void
409 // .cxx_destruct
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]]
417   // Destroy y.
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]]
422   // Destroy z.
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
429 @end
431 // This shouldn't crash.
432 @interface Test17A
433 @property (assign) int x;
434 @end
435 @interface Test17B : Test17A
436 @end
437 @implementation Test17B
438 - (int) x { return super.x + 1; }
439 @end
441 void test19(void) {
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)
446   id x[5];
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]],
469   // CHECK:      ret void
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
479   id x[n];
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]]
489   // Allocate the VLA.
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
495   // Zero-initialize.
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)
499   // Destroy.
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
523   id x[2][n][3];
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]]
533   // Allocate the VLA.
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
540   // Zero-initialize.
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)
545   // Destroy.
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]],
590 // CHECK:      ret void
592 // Check that 'init' retains self.
593 @interface Test27
594 - (id) init;
595 @end
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]]
609 @end
611 @interface Test28
612 @property (copy) id prop;
613 @end
614 @implementation Test28
615 @synthesize prop;
616 @end
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;
626 @end
627 @interface Test29 : Test29_super
628 - (id) init;
629 - (id) initWithAllocator: (id) allocator;
630 @end
631 @implementation Test29
632 static id _test29_allocator = 0;
633 - (id) init {
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]]
657 // Return statement.
658 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]
660 // Cleanup.
661 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]
662 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) [[NUW]], !clang.imprecise_release
664 // Return.
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]]
695 // Assignment.
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]])
701 // Return statement.
702 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[SELF]]
703 // CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) [[NUW]]
705 // Cleanup.
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
712 // Return.
713 // CHECK-NEXT: ret ptr [[T4]]
714   self = [super initWithAllocator: allocator];
715   return self;
717 @end
719 typedef struct Test30_helper Test30_helper;
720 @interface Test30
721 - (id) init;
722 - (Test30_helper*) initHelper;
723 @end
724 @implementation Test30 {
725 char *helper;
727 - (id) init {
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]]
732 // CHECK-NEXT: store
734 // Call.
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]])
739 // Assignment.
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]]
748 // Return.
749 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]
750 // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
752 // Cleanup.
753 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]
754 // CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])
756 // Epilogue.
757 // CHECK-NEXT: ret ptr [[T1]]
758   self->helper = [self initHelper];
759   return self;
761 - (Test30_helper*) initHelper {
762 // CHECK:    define internal ptr @"\01-[Test30 initHelper]"(
763 // CHECK:      alloca
764 // CHECK-NEXT: alloca
765 // CHECK-NEXT: store
766 // CHECK-NEXT: store
767 // CHECK-NEXT: ret ptr null
768   return 0;
771 @end
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();
782 @class Test33_a;
783 @interface Test33
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;
789 @end
790 void test33(Test33 *ptr) {
791   Test33_a *a;
792   [ptr give: &a];
793   [ptr take: &a];
794   [ptr giveStrong: &a];
795   [ptr takeStrong: &a];
796   [ptr giveOut: &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
805   // CHECK-NEXT: store
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]])
841   // 'out'
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]])
852   // CHECK-NEXT: load
853   // CHECK-NEXT: llvm.objc.release
854   // CHECK-NEXT: call void @llvm.lifetime.end
855   // CHECK-NEXT: load
856   // CHECK-NEXT: llvm.objc.release
857   // CHECK-NEXT: ret void
861 // CHECK-LABEL: define{{.*}} void @test36
862 void test36(id x) {
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]])
873   x = 0;
875   // CHECK: br label
876   // CHECK: call void @llvm.objc.release
877   // CHECK: br i1
879   // CHECK: call void @llvm.objc.release
880   // CHECK-NEXT: ret void
883 @class Test37;
884 void test37(void) {
885   extern void test37_helper(id *);
886   Test37 *var;
887   test37_helper(&var);
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(
918   // CHECK-NEXT: ret
920 @end
922 @interface Test45
923 @property (retain) id x;
924 @end
925 @implementation Test45
926 @synthesize x;
927 @end
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();
956 void test47(void) {
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
979 void test48(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
996 void test49(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
1013 id x(void);
1014 void test50(id y) {
1015   ({x();});
1016 // CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain
1017 // CHECK: call void @llvm.objc.release
1020 struct CGPoint {
1021   float x;
1022   float y;
1024 typedef struct CGPoint CGPoint;
1026 @interface Foo
1027 @property (assign) CGPoint point;
1028 @end
1030 @implementation Foo
1031 @synthesize point;
1032 @end
1034 id test52(void) {
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]]
1052 void test53(void) {
1053   id test53_helper(void);
1054   id x = ({ id y = test53_helper(); y; });
1055   (void) x;
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
1090   // CHECK: ret void
1093 // PR10228
1094 @interface Test55Base @end
1095 @interface Test55 : Test55Base @end
1096 @implementation Test55 (Category)
1097 - (void) dealloc {}
1098 @end
1099 // CHECK:   define internal void @"\01-[Test55(Category) dealloc]"(
1100 // CHECK-NOT: ret
1101 // CHECK:     call void @objc_msgSendSuper2(
1103 @protocol Test56Protocol
1104 + (id) make __attribute__((ns_returns_retained));
1105 @end
1106 @interface Test56<Test56Protocol> @end
1107 @implementation Test56
1108 // CHECK: define internal ptr @"\01+[Test56 make]"(
1109 + (id) 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();
1116 @end
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
1130 @interface Test57
1131 @property (nonatomic, strong) id strong;
1132 @property (nonatomic, weak) id weak;
1133 @property (nonatomic, unsafe_unretained) id unsafe;
1134 @end
1135 @implementation Test57
1136 @synthesize strong, weak, unsafe;
1137 @end
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]]
1160 void test59(void) {
1161   extern id test59_getlock(void);
1162   extern void test59_body(void);
1163   @synchronized (test59_getlock()) {
1164     test59_body();
1165   }
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.
1178 @interface Test61
1179 - (id) performSelector: (SEL) selector;
1180 - (void) test61_void;
1181 - (id) test61_id;
1182 @end
1183 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
1214 void test62(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
1250     // CHECK:      br label
1251     if (i != 0 && test62_make() != 0)
1252       test62_body();
1253   }
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
1260   // CHECK:      ret void
1263 @class NSString;
1265 @interface Person  {
1266   NSString *name;
1268 @property NSString *address;
1269 @end
1271 @implementation Person
1272 @synthesize address;
1273 @end
1274 // CHECK: tail call ptr @objc_getProperty
1275 // CHECK: call void @objc_setProperty
1277 // Verify that we successfully parse and preserve this attribute in
1278 // this position.
1279 @interface Test66
1280 - (void) consume: (id __attribute__((ns_consumed))) ptr;
1281 @end
1282 void test66(void) {
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:.*]]
1294 // CHECK:      [[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);
1304 void test67(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);
1316 void test68(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; }
1333 @end
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]]
1339 void test70(id i) {
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
1345   id x[3] = {
1346     [2] = i
1347   };
1350 // Be sure that we emit lifetime intrinsics only after dtors
1351 struct AggDtor {
1352   char cs[40];
1353   id x;
1356 struct AggDtor getAggDtor(void);
1358 // CHECK-LABEL: define{{.*}} void @test71
1359 void test71(void) {
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]])
1368   getAggDtor();
1369   getAggDtor();
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 }