xref: /llvm-project/clang/test/CodeGenObjC/arc.m (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
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
3
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
8
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)
21
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)
34
35// CHECK-LABEL: define{{.*}} void @test0
36void 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
43}
44
45// CHECK-LABEL: define{{.*}} ptr @test1(ptr
46id 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;
64}
65
66@interface Test2
67+ (void) class_method;
68- (void) inst_method;
69@end
70@implementation Test2
71
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 {}
80
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
90
91@interface Test3
92+ (id) alloc;
93- (id) initWith: (int) x;
94- (id) copy;
95@end
96
97// CHECK-LABEL: define{{.*}} void @test3_unelided()
98void test3_unelided(void) {
99  extern void test3_helper(void);
100
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;
105
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];
112
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];
118
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
123}
124
125// CHECK-LABEL: define{{.*}} void @test3()
126void test3(void) {
127  // CHECK:      [[X:%.*]] = alloca ptr
128  // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
129
130  id x = [[Test3 alloc] initWith: 5];
131
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
136
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]]
142
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]],
147
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]]
152
153  x = [x copy];
154
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
160}
161
162// CHECK-LABEL: define{{.*}} ptr @test4()
163id 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
168
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]],
172
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]])
176
177  // CHECK-NEXT: ret ptr [[RET]]
178
179  return [[Test3 alloc] initWith: 6];
180}
181
182@interface Test5 {
183@public
184  id var;
185}
186@end
187
188// CHECK-LABEL: define{{.*}} void @test5
189void 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
197
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;
205
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;
215
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
222}
223
224id test6_helper(void) __attribute__((ns_returns_retained));
225// CHECK-LABEL: define{{.*}} void @test6()
226void 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();
236}
237
238void test7_helper(id __attribute__((ns_consumed)));
239// CHECK-LABEL: define{{.*}} void @test7()
240void 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);
253}
254
255id test8_helper(void) __attribute__((ns_returns_retained));
256void 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
265}
266
267@interface Test10
268@property (retain) Test10 *me;
269@end
270void test10(void) {
271  Test10 *x;
272  id y = x.me.me;
273
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
296}
297
298void 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();
312}
313
314void test12(void) {
315  extern id test12_helper(void);
316
317  // CHECK-LABEL:      define{{.*}} void @test12()
318  // CHECK:      [[X:%.*]] = alloca ptr, align
319  // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align
320
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]])
327
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]])
333
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
338
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
345}
346
347// Indirect consuming calls.
348void 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;
354
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);
362
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);
371
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
376}
377
378@interface Test16_super @end
379@interface Test16 : Test16_super {
380  id z;
381}
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]]
397
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
407}
408
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]]
416
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]]
421
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]]
426
427  // CHECK-NEXT: ret void
428
429@end
430
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
440
441void 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];
447
448  extern id test19_helper(void);
449  x[2] = test19_helper();
450
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]]
457
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
461
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]],
468
469  // CHECK:      ret void
470}
471
472void 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
478
479  id x[n];
480
481  // Capture the VLA size.
482  // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4
483  // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
484
485  // Save the stack pointer.
486  // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0()
487  // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]]
488
489  // Allocate the VLA.
490  // CHECK-NEXT: [[VLA:%.*]] = alloca ptr, i64 [[DIM]], align 16
491
492  // Store the VLA #elements expression.
493  // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8
494
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)
498
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]]
503
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]],
510
511  // CHECK:      [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]]
512  // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]])
513  // CHECK-NEXT: ret void
514}
515
516void 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
522
523  id x[2][n][3];
524
525  // Capture the VLA size.
526  // CHECK-NEXT: [[T0:%.*]] = load i32, ptr [[N]], align 4
527  // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
528
529  // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.stacksave.p0()
530  // CHECK-NEXT: store ptr [[T0]], ptr [[SAVED_STACK]]
531
532
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
536
537  // Store the VLA #elements expression.
538  // CHECK-NEXT: store i64 [[DIM]], ptr [[VLA_EXPR]], align 8
539
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)
544
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]]
552
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]],
559
560  // CHECK:      [[T0:%.*]] = load ptr, ptr [[SAVED_STACK]]
561  // CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[T0]])
562  // CHECK-NEXT: ret void
563}
564
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
571
572// CHECK-GLOBALS: @"_OBJC_CLASS_RO_$_Test24" = internal global [[RO_T:%.*]] { i32 130,
573@interface Test24 {} @end
574@implementation Test24 @end
575
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
591
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]]
608
609@end
610
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
623
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
632static 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]]
639
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
644
645// Implicit null of 'self', i.e. direct transfer of ownership.
646// CHECK-NEXT: store ptr null, ptr [[SELF]]
647
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]])
651
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]]
656
657// Return statement.
658// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[CALL]]) [[NUW]]
659
660// Cleanup.
661// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]
662// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]]) [[NUW]], !clang.imprecise_release
663
664// Return.
665// CHECK-NEXT: ret ptr [[T1]]
666  return [self initWithAllocator: _test29_allocator];
667}
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]]
678
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
683
684// Implicit null of 'self', i.e. direct transfer of ownership.
685// CHECK-NEXT: store ptr null, ptr [[SELF]]
686
687// Actual message send.
688// CHECK:      [[CALL:%.*]] = call {{.*}} @objc_msgSendSuper2
689
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]]
694
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]])
700
701// Return statement.
702// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[SELF]]
703// CHECK-NEXT: [[T4:%.*]] = call ptr @llvm.objc.retain(ptr [[T3]]) [[NUW]]
704
705// Cleanup.
706// CHECK-NEXT: [[T5:%.*]] = load ptr, ptr [[ALLOCATOR]]
707// CHECK-NEXT: call void @llvm.objc.release(ptr [[T5]]) [[NUW]], !clang.imprecise_release
708
709// CHECK-NEXT: [[T6:%.*]] = load ptr, ptr [[SELF]]
710// CHECK-NEXT: call void @llvm.objc.release(ptr [[T6]]) [[NUW]], !clang.imprecise_release
711
712// Return.
713// CHECK-NEXT: ret ptr [[T4]]
714  self = [super initWithAllocator: allocator];
715  return self;
716}
717@end
718
719typedef struct Test30_helper Test30_helper;
720@interface Test30
721- (id) init;
722- (Test30_helper*) initHelper;
723@end
724@implementation Test30 {
725char *helper;
726}
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
733
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]])
738
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]]
747
748// Return.
749// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[SELF]]
750// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]])
751
752// Cleanup.
753// CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[SELF]]
754// CHECK-NEXT: call void @llvm.objc.release(ptr [[T2]])
755
756// Epilogue.
757// CHECK-NEXT: ret ptr [[T1]]
758  self->helper = [self initHelper];
759  return self;
760}
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;
769}
770
771@end
772
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();
780}
781
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
790void 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];
797
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]]
808
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]])
820
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]])
832
833  // CHECK-NEXT: load ptr, ptr [[PTR]]
834  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
835  // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])
836
837  // CHECK-NEXT: load ptr, ptr [[PTR]]
838  // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
839  // CHECK-NEXT: objc_msgSend{{.*}}, ptr noundef [[A]])
840
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]])
851
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
858}
859
860
861// CHECK-LABEL: define{{.*}} void @test36
862void test36(id x) {
863  // CHECK: [[X:%.*]] = alloca ptr
864
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" };
869
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;
874
875  // CHECK: br label
876  // CHECK: call void @llvm.objc.release
877  // CHECK: br i1
878
879  // CHECK: call void @llvm.objc.release
880  // CHECK-NEXT: ret void
881}
882
883@class Test37;
884void test37(void) {
885  extern void test37_helper(id *);
886  Test37 *var;
887  test37_helper(&var);
888
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]]
894
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]])
904
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
909}
910
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
919}
920@end
921
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]]
931
932void test46(__weak id *wp, __weak volatile id *wvp) {
933  extern id test46_helper(void);
934
935  // TODO: this is sub-optimal, we should retain at the actual call site.
936
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();
945
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();
954}
955
956void test47(void) {
957  extern id test47_helper(void);
958  id x = x = test47_helper();
959
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
977}
978
979void 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
994}
995
996void 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
1011}
1012
1013id x(void);
1014void test50(id y) {
1015  ({x();});
1016// CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain
1017// CHECK: call void @llvm.objc.release
1018}
1019
1020struct CGPoint {
1021  float x;
1022  float y;
1023};
1024typedef struct CGPoint CGPoint;
1025
1026@interface Foo
1027@property (assign) CGPoint point;
1028@end
1029
1030@implementation Foo
1031@synthesize point;
1032@end
1033
1034id test52(void) {
1035  id test52_helper(int) __attribute__((ns_returns_retained));
1036  return ({ int x = 5; test52_helper(x); });
1037
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]]
1050}
1051
1052void 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
1078}
1079
1080// CHECK-LABEL: define{{.*}} void @test54(i32 noundef %first, ...)
1081void 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
1091}
1092
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(
1102
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();
1115}
1116@end
1117void 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
1128}
1129
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]]
1144
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]]
1152
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]]
1159
1160void test59(void) {
1161  extern id test59_getlock(void);
1162  extern void test59_body(void);
1163  @synchronized (test59_getlock()) {
1164    test59_body();
1165  }
1166
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
1175}
1176
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
1183void test61(void) {
1184  // CHECK-LABEL:    define{{.*}} void @test61()
1185  // CHECK:      [[Y:%.*]] = alloca ptr, align 8
1186
1187  extern id test61_make(void);
1188
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)];
1196
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)];
1207
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
1212}
1213
1214void 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);
1221
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
1225
1226  // CHECK:      [[T0:%.*]] = load i32, ptr [[I]], align 4
1227  // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 20
1228  // CHECK-NEXT: br i1 [[T1]],
1229
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  }
1254
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
1259
1260  // CHECK:      ret void
1261}
1262
1263@class NSString;
1264
1265@interface Person  {
1266  NSString *name;
1267}
1268@property NSString *address;
1269@end
1270
1271@implementation Person
1272@synthesize address;
1273@end
1274// CHECK: tail call ptr @objc_getProperty
1275// CHECK: call void @objc_setProperty
1276
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
1282void test66(void) {
1283  extern Test66 *test66_receiver(void);
1284  extern id test66_arg(void);
1285  [test66_receiver() consume: test66_arg()];
1286}
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
1302
1303Class test67_helper(void);
1304void test67(void) {
1305  Class cl = test67_helper();
1306}
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
1314
1315Class test68_helper(void);
1316void test68(void) {
1317  __strong Class cl = test67_helper();
1318}
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
1329
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]]
1338
1339void 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  };
1348}
1349
1350// Be sure that we emit lifetime intrinsics only after dtors
1351struct AggDtor {
1352  char cs[40];
1353  id x;
1354};
1355
1356struct AggDtor getAggDtor(void);
1357
1358// CHECK-LABEL: define{{.*}} void @test71
1359void 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();
1370}
1371
1372// Check that no extra release calls are emitted to detruct the compond literal.
1373
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
1389
1390// CHECK-NOT: call void @llvm.objc.release
1391
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
1396
1397// CHECK-NOT: call void @llvm.objc.release
1398
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
1403
1404void test72(id a, id b) {
1405  __strong id t[] = (__strong id[]){a, b};
1406}
1407
1408// ARC-ALIEN: attributes [[NLB]] = { nonlazybind }
1409// ARC-NATIVE: attributes [[NLB]] = { nonlazybind }
1410// CHECK: attributes [[NUW]] = { nounwind }
1411