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 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
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]])
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]])
47 void test_assign_assign(void) {
48 __unsafe_unretained id x, y;
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
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]])
68 void test_strong_assign_assign(void) {
70 __unsafe_unretained id y;
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
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]])
94 void test_assign_strong_assign(void) {
95 __unsafe_unretained id x;
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
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]])
120 void test_init(void) {
121 __unsafe_unretained id x = makeA();
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
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]])
137 void test_init_assignment(void) {
138 __unsafe_unretained id x;
139 __unsafe_unretained id y = x = makeA();
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
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]])
158 void test_strong_init_assignment(void) {
159 __unsafe_unretained id x;
160 __strong id y = x = makeA();
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
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]])
181 void test_init_strong_assignment(void) {
183 __unsafe_unretained id y = x = makeA();
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
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]])
206 void test_ignored(void) {
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
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]])
220 void test_cast_to_void(void) {
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
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]])
235 // This is always at the end of the module.
237 // CHECK-OPTIMIZED: !llvm.module.flags = !{!0,
238 // CHECK-OPTIMIZED: !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov{{.*}}marker for objc_retainAutoreleaseReturnValue"}