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
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
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
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
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
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
24 void test_assign(void) {
25 __unsafe_unretained id x;
28 // CHECK-LABEL: define{{.*}} void @test_assign()
29 // CHECK: [[X:%.*]] = alloca i8*
30 // CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA()
31 // CHECK-MARKED-NEXT: call void asm sideeffect
32 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
33 // NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
34 // CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
35 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
36 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
37 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
38 // CHECK-OPTIMIZED-NEXT: bitcast
39 // CHECK-OPTIMIZED-NEXT: lifetime.end
40 // CHECK-NEXT: ret void
42 // DISABLED-LABEL: define{{.*}} void @test_assign()
43 // DISABLED: [[T0:%.*]] = call [[A:.*]]* @makeA()
44 // DISABLED-MARKED-NEXT: call void asm sideeffect
45 // DISABLED-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
46 // DISABLED-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
48 // ATTACHED-CALL-LABEL: define{{.*}} void @test_assign()
49 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
50 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
52 void test_assign_assign(void) {
53 __unsafe_unretained id x, y;
56 // CHECK-LABEL: define{{.*}} void @test_assign_assign()
57 // CHECK: [[X:%.*]] = alloca i8*
58 // CHECK: [[Y:%.*]] = alloca i8*
59 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
60 // CHECK-MARKED-NEXT: call void asm sideeffect
61 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
62 // NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
63 // CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
64 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
65 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
66 // CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
67 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
68 // CHECK-OPTIMIZED-NEXT: bitcast
69 // CHECK-OPTIMIZED-NEXT: lifetime.end
70 // CHECK-OPTIMIZED-NEXT: bitcast
71 // CHECK-OPTIMIZED-NEXT: lifetime.end
72 // CHECK-NEXT: ret void
74 // ATTACHED-CALL-LABEL: define{{.*}} void @test_assign_assign()
75 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
76 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
78 void test_strong_assign_assign(void) {
80 __unsafe_unretained id y;
83 // CHECK-LABEL: define{{.*}} void @test_strong_assign_assign()
84 // CHECK: [[X:%.*]] = alloca i8*
85 // CHECK: [[Y:%.*]] = alloca i8*
86 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
87 // CHECK-MARKED-NEXT: call void asm sideeffect
88 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
89 // CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
90 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
91 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
92 // CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
93 // CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]]
94 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
95 // CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]]
96 // CHECK-OPTIMIZED-NEXT: bitcast
97 // CHECK-OPTIMIZED-NEXT: lifetime.end
98 // CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
99 // CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
100 // CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
101 // CHECK-OPTIMIZED-NEXT: bitcast
102 // CHECK-OPTIMIZED-NEXT: lifetime.end
103 // CHECK-NEXT: ret void
105 // ATTACHED-CALL-LABEL: define{{.*}} void @test_strong_assign_assign()
106 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ],
107 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
109 void test_assign_strong_assign(void) {
110 __unsafe_unretained id x;
114 // CHECK-LABEL: define{{.*}} void @test_assign_strong_assign()
115 // CHECK: [[X:%.*]] = alloca i8*
116 // CHECK: [[Y:%.*]] = alloca i8*
117 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
118 // CHECK-MARKED-NEXT: call void asm sideeffect
119 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
120 // CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
121 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
122 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
123 // CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[Y]]
124 // CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
125 // CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]]
126 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
127 // CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[Y]], i8* null)
128 // CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
129 // CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
130 // CHECK-OPTIMIZED-NEXT: bitcast
131 // CHECK-OPTIMIZED-NEXT: lifetime.end
132 // CHECK-OPTIMIZED-NEXT: bitcast
133 // CHECK-OPTIMIZED-NEXT: lifetime.end
134 // CHECK-NEXT: ret void
136 // ATTACHED-CALL-LABEL: define{{.*}} void @test_assign_strong_assign()
137 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ],
138 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
140 void test_init(void) {
141 __unsafe_unretained id x = makeA();
143 // CHECK-LABEL: define{{.*}} void @test_init()
144 // CHECK: [[X:%.*]] = alloca i8*
145 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
146 // CHECK-MARKED-NEXT: call void asm sideeffect
147 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
148 // NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
149 // CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
150 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
151 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
152 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
153 // CHECK-OPTIMIZED-NEXT: bitcast
154 // CHECK-OPTIMIZED-NEXT: lifetime.end
155 // CHECK-NEXT: ret void
157 // ATTACHED-CALL-LABEL: define{{.*}} void @test_init()
158 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
159 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
161 void test_init_assignment(void) {
162 __unsafe_unretained id x;
163 __unsafe_unretained id y = x = makeA();
165 // CHECK-LABEL: define{{.*}} void @test_init_assignment()
166 // CHECK: [[X:%.*]] = alloca i8*
167 // CHECK: [[Y:%.*]] = alloca i8*
168 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
169 // CHECK-MARKED-NEXT: call void asm sideeffect
170 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
171 // NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
172 // CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
173 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
174 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
175 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
176 // CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
177 // CHECK-OPTIMIZED-NEXT: bitcast
178 // CHECK-OPTIMIZED-NEXT: lifetime.end
179 // CHECK-OPTIMIZED-NEXT: bitcast
180 // CHECK-OPTIMIZED-NEXT: lifetime.end
181 // CHECK-NEXT: ret void
183 // ATTACHED-CALL-LABEL: define{{.*}} void @test_init_assignment()
184 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
185 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
187 void test_strong_init_assignment(void) {
188 __unsafe_unretained id x;
189 __strong id y = x = makeA();
191 // CHECK-LABEL: define{{.*}} void @test_strong_init_assignment()
192 // CHECK: [[X:%.*]] = alloca i8*
193 // CHECK: [[Y:%.*]] = alloca i8*
194 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
195 // CHECK-MARKED-NEXT: call void asm sideeffect
196 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
197 // CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
198 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
199 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
200 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
201 // CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
202 // CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[Y]], i8* null)
203 // CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
204 // CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
205 // CHECK-OPTIMIZED-NEXT: bitcast
206 // CHECK-OPTIMIZED-NEXT: lifetime.end
207 // CHECK-OPTIMIZED-NEXT: bitcast
208 // CHECK-OPTIMIZED-NEXT: lifetime.end
209 // CHECK-NEXT: ret void
211 // ATTACHED-CALL-LABEL: define{{.*}} void @test_strong_init_assignment()
212 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ],
213 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
215 void test_init_strong_assignment(void) {
217 __unsafe_unretained id y = x = makeA();
219 // CHECK-LABEL: define{{.*}} void @test_init_strong_assignment()
220 // CHECK: [[X:%.*]] = alloca i8*
221 // CHECK: [[Y:%.*]] = alloca i8*
222 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
223 // CHECK-MARKED-NEXT: call void asm sideeffect
224 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
225 // CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
226 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
227 // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
228 // CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]]
229 // CHECK-NEXT: store i8* [[T4]], i8** [[X]]
230 // CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]])
231 // CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
232 // CHECK-OPTIMIZED-NEXT: bitcast
233 // CHECK-OPTIMIZED-NEXT: lifetime.end
234 // CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
235 // CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
236 // CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
237 // CHECK-OPTIMIZED-NEXT: bitcast
238 // CHECK-OPTIMIZED-NEXT: lifetime.end
239 // CHECK-NEXT: ret void
241 // ATTACHED-CALL-LABEL: define{{.*}} void @test_init_strong_assignment()
242 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ],
243 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
245 void test_ignored(void) {
248 // CHECK-LABEL: define{{.*}} void @test_ignored()
249 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
250 // CHECK-MARKED-NEXT: call void asm sideeffect
251 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
252 // NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
253 // CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
254 // CHECK-NEXT: bitcast i8* [[T2]] to [[A]]*
255 // CHECK-NEXT: ret void
257 // ATTACHED-CALL-LABEL: define{{.*}} void @test_ignored()
258 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
259 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
261 void test_cast_to_void(void) {
264 // CHECK-LABEL: define{{.*}} void @test_cast_to_void()
265 // CHECK: [[T0:%.*]] = call [[A]]* @makeA()
266 // CHECK-MARKED-NEXT: call void asm sideeffect
267 // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
268 // NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
269 // CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
270 // CHECK-NEXT: bitcast i8* [[T2]] to [[A]]*
271 // CHECK-NEXT: ret void
273 // ATTACHED-CALL-LABEL: define{{.*}} void @test_cast_to_void()
274 // ATTACHED-CALL: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
275 // ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use([[A]]* [[T0]])
278 // This is always at the end of the module.
280 // CHECK-OPTIMIZED: !llvm.module.flags = !{!0,
281 // CHECK-OPTIMIZED: !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov{{.*}}marker for objc_retainAutoreleaseReturnValue"}