xref: /llvm-project/clang/test/CodeGenObjC/arc-unsafeclaim.m (revision 3d84f4268dd9e1257e71938485fa23d17210ba44)
1//   Make sure it works on x86-64.
2// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=NOTAIL-CALL
3
4// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -O2 -disable-llvm-passes -o - %s | FileCheck %s -check-prefix=ATTACHED-CALL
5
6//   Make sure it works on x86-32.
7// RUN: %clang_cc1 -triple i386-apple-darwin11 -fobjc-runtime=macosx-fragile-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL
8
9//   Make sure it works on ARM64.
10// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL
11
12//   Make sure it works on ARM.
13// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL
14// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL
15
16//   Make sure that it's implicitly disabled if the runtime version isn't high enough.
17// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED
18// RUN: %clang_cc1 -triple arm64-apple-ios8 -fobjc-runtime=ios-8 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED -check-prefix=DISABLED-MARKED
19
20@class A;
21
22A *makeA(void);
23
24void test_assign(void) {
25  __unsafe_unretained id x;
26  x = makeA();
27}
28// CHECK-LABEL:        define{{.*}} void @test_assign()
29// CHECK:                [[X:%.*]] = alloca ptr
30// CHECK:                [[T0:%.*]] = call ptr @makeA()
31// CHECK-MARKED-NEXT:    call void asm sideeffect
32// NOTAIL-CALL-NEXT:     [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
33// CALL-NEXT:            [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
34// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
35// CHECK-OPTIMIZED-NEXT: lifetime.end
36// CHECK-NEXT:           ret void
37
38// DISABLED-LABEL:     define{{.*}} void @test_assign()
39// DISABLED:             [[T0:%.*]] = call ptr @makeA()
40// DISABLED-MARKED-NEXT: call void asm sideeffect
41// DISABLED-NEXT:        [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])
42
43// ATTACHED-CALL-LABEL:      define{{.*}} void @test_assign()
44// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
45// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
46
47void test_assign_assign(void) {
48  __unsafe_unretained id x, y;
49  x = y = makeA();
50}
51// CHECK-LABEL:        define{{.*}} void @test_assign_assign()
52// CHECK:                [[X:%.*]] = alloca ptr
53// CHECK:                [[Y:%.*]] = alloca ptr
54// CHECK:                [[T0:%.*]] = call ptr @makeA()
55// CHECK-MARKED-NEXT:    call void asm sideeffect
56// NOTAIL-CALL-NEXT:     [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
57// CALL-NEXT:            [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
58// CHECK-NEXT:           store ptr [[T2]], ptr [[Y]]
59// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
60// CHECK-OPTIMIZED-NEXT: lifetime.end
61// CHECK-OPTIMIZED-NEXT: lifetime.end
62// CHECK-NEXT:           ret void
63
64// ATTACHED-CALL-LABEL:      define{{.*}} void @test_assign_assign()
65// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
66// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
67
68void test_strong_assign_assign(void) {
69  __strong id x;
70  __unsafe_unretained id y;
71  x = y = makeA();
72}
73// CHECK-LABEL:        define{{.*}} void @test_strong_assign_assign()
74// CHECK:                [[X:%.*]] = alloca ptr
75// CHECK:                [[Y:%.*]] = alloca ptr
76// CHECK:                [[T0:%.*]] = call ptr @makeA()
77// CHECK-MARKED-NEXT:    call void asm sideeffect
78// CHECK-NEXT:           [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])
79// CHECK-NEXT:           store ptr [[T2]], ptr [[Y]]
80// CHECK-NEXT:           [[OLD:%.*]] = load ptr, ptr [[X]]
81// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
82// CHECK-NEXT:           call void @llvm.objc.release(ptr [[OLD]]
83// CHECK-OPTIMIZED-NEXT: lifetime.end
84// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)
85// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
86// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])
87// CHECK-OPTIMIZED-NEXT: lifetime.end
88// CHECK-NEXT:           ret void
89
90// ATTACHED-CALL-LABEL:      define{{.*}} void @test_strong_assign_assign()
91// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
92// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
93
94void test_assign_strong_assign(void) {
95  __unsafe_unretained id x;
96  __strong id y;
97  x = y = makeA();
98}
99// CHECK-LABEL:        define{{.*}} void @test_assign_strong_assign()
100// CHECK:                [[X:%.*]] = alloca ptr
101// CHECK:                [[Y:%.*]] = alloca ptr
102// CHECK:                [[T0:%.*]] = call ptr @makeA()
103// CHECK-MARKED-NEXT:    call void asm sideeffect
104// CHECK-NEXT:           [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])
105// CHECK-NEXT:           [[OLD:%.*]] = load ptr, ptr [[Y]]
106// CHECK-NEXT:           store ptr [[T2]], ptr [[Y]]
107// CHECK-NEXT:           call void @llvm.objc.release(ptr [[OLD]]
108// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
109// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[Y]], ptr null)
110// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
111// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])
112// CHECK-OPTIMIZED-NEXT: lifetime.end
113// CHECK-OPTIMIZED-NEXT: lifetime.end
114// CHECK-NEXT:           ret void
115
116// ATTACHED-CALL-LABEL:      define{{.*}} void @test_assign_strong_assign()
117// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
118// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
119
120void test_init(void) {
121  __unsafe_unretained id x = makeA();
122}
123// CHECK-LABEL:        define{{.*}} void @test_init()
124// CHECK:                [[X:%.*]] = alloca ptr
125// CHECK:                [[T0:%.*]] = call ptr @makeA()
126// CHECK-MARKED-NEXT:    call void asm sideeffect
127// NOTAIL-CALL-NEXT:     [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
128// CALL-NEXT:            [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
129// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
130// CHECK-OPTIMIZED-NEXT: lifetime.end
131// CHECK-NEXT:           ret void
132
133// ATTACHED-CALL-LABEL:      define{{.*}} void @test_init()
134// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
135// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
136
137void test_init_assignment(void) {
138  __unsafe_unretained id x;
139  __unsafe_unretained id y = x = makeA();
140}
141// CHECK-LABEL:        define{{.*}} void @test_init_assignment()
142// CHECK:                [[X:%.*]] = alloca ptr
143// CHECK:                [[Y:%.*]] = alloca ptr
144// CHECK:                [[T0:%.*]] = call ptr @makeA()
145// CHECK-MARKED-NEXT:    call void asm sideeffect
146// NOTAIL-CALL-NEXT:     [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
147// CALL-NEXT:            [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
148// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
149// CHECK-NEXT:           store ptr [[T2]], ptr [[Y]]
150// CHECK-OPTIMIZED-NEXT: lifetime.end
151// CHECK-OPTIMIZED-NEXT: lifetime.end
152// CHECK-NEXT: ret void
153
154// ATTACHED-CALL-LABEL:      define{{.*}} void @test_init_assignment()
155// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
156// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
157
158void test_strong_init_assignment(void) {
159  __unsafe_unretained id x;
160  __strong id y = x = makeA();
161}
162// CHECK-LABEL:        define{{.*}} void @test_strong_init_assignment()
163// CHECK:                [[X:%.*]] = alloca ptr
164// CHECK:                [[Y:%.*]] = alloca ptr
165// CHECK:                [[T0:%.*]] = call ptr @makeA()
166// CHECK-MARKED-NEXT:    call void asm sideeffect
167// CHECK-NEXT:           [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])
168// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
169// CHECK-NEXT:           store ptr [[T2]], ptr [[Y]]
170// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[Y]], ptr null)
171// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
172// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])
173// CHECK-OPTIMIZED-NEXT: lifetime.end
174// CHECK-OPTIMIZED-NEXT: lifetime.end
175// CHECK-NEXT: ret void
176
177// ATTACHED-CALL-LABEL:      define{{.*}} void @test_strong_init_assignment()
178// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
179// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
180
181void test_init_strong_assignment(void) {
182  __strong id x;
183  __unsafe_unretained id y = x = makeA();
184}
185// CHECK-LABEL:        define{{.*}} void @test_init_strong_assignment()
186// CHECK:                [[X:%.*]] = alloca ptr
187// CHECK:                [[Y:%.*]] = alloca ptr
188// CHECK:                [[T0:%.*]] = call ptr @makeA()
189// CHECK-MARKED-NEXT:    call void asm sideeffect
190// CHECK-NEXT:           [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])
191// CHECK-NEXT:           [[OLD:%.*]] = load ptr, ptr [[X]]
192// CHECK-NEXT:           store ptr [[T2]], ptr [[X]]
193// CHECK-NEXT:           call void @llvm.objc.release(ptr [[OLD]])
194// CHECK-NEXT:           store ptr [[T2]], ptr [[Y]]
195// CHECK-OPTIMIZED-NEXT: lifetime.end
196// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)
197// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
198// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])
199// CHECK-OPTIMIZED-NEXT: lifetime.end
200// CHECK-NEXT: ret void
201
202// ATTACHED-CALL-LABEL:      define{{.*}} void @test_init_strong_assignment()
203// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
204// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
205
206void test_ignored(void) {
207  makeA();
208}
209// CHECK-LABEL:     define{{.*}} void @test_ignored()
210// CHECK:             [[T0:%.*]] = call ptr @makeA()
211// CHECK-MARKED-NEXT: call void asm sideeffect
212// NOTAIL-CALL-NEXT:  [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
213// CALL-NEXT:         [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
214// CHECK-NEXT:        ret void
215
216// ATTACHED-CALL-LABEL:      define{{.*}} void @test_ignored()
217// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
218// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
219
220void test_cast_to_void(void) {
221  (void) makeA();
222}
223// CHECK-LABEL:     define{{.*}} void @test_cast_to_void()
224// CHECK:             [[T0:%.*]] = call ptr @makeA()
225// CHECK-MARKED-NEXT: call void asm sideeffect
226// NOTAIL-CALL-NEXT:  [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
227// CALL-NEXT:         [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])
228// CHECK-NEXT:        ret void
229
230// ATTACHED-CALL-LABEL:      define{{.*}} void @test_cast_to_void()
231// ATTACHED-CALL:              [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
232// ATTACHED-CALL:              call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
233
234
235// This is always at the end of the module.
236
237// CHECK-OPTIMIZED: !llvm.module.flags = !{!0,
238// CHECK-OPTIMIZED: !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov{{.*}}marker for objc_retainAutoreleaseReturnValue"}
239