Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGenObjC / convert-messages-to-runtime-calls.m
blob9a5ecbc03d8ae6eecf130cb88e567131fb7c8086
1 // RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
2 // RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
3 // RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
4 // RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
5 // RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
6 // RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
7 // Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime.
8 // RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
9 // RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
11 #define nil (id)0
13 @interface NSObject
14 + (id)alloc;
15 + (id)allocWithZone:(void*)zone;
16 + (id)alloc2;
17 - (id)retain;
18 - (void)release;
19 - (id)autorelease;
20 @end
22 // CHECK-LABEL: define {{.*}}void @test1
23 void test1(id x) {
24   // MSGS: {{call.*@objc_msgSend}}
25   // MSGS: {{call.*@objc_msgSend}}
26   // MSGS: {{call.*@objc_msgSend}}
27   // MSGS: {{call.*@objc_msgSend}}
28   // MSGS: {{call.*@objc_msgSend}}
29   // CALLS: {{call.*@objc_alloc}}
30   // CALLS: {{call.*@objc_allocWithZone}}
31   // CALLS: {{call.*@objc_retain}}
32   // CALLS: {{call.*@objc_release}}
33   // CALLS: {{tail call.*@objc_autorelease}}
34   [NSObject alloc];
35   [NSObject allocWithZone:nil];
36   [x retain];
37   [x release];
38   [x autorelease];
41 // CHECK-LABEL: define {{.*}}void @check_invoke
42 void check_invoke(void) {
43   // MSGS: {{invoke.*@objc_msgSend}}
44   // MSGS: {{invoke.*@objc_msgSend}}
45   // CALLS: {{invoke.*@objc_alloc}}
46   // CALLS: {{invoke.*@objc_allocWithZone}}
47   @try {
48     [NSObject alloc];
49     [NSObject allocWithZone:nil];
50   } @catch (...) {
51   }
54 // CHECK-LABEL: define {{.*}}void @test2
55 void test2(void* x) {
56   // MSGS: {{call.*@objc_msgSend}}
57   // MSGS: {{call.*@objc_msgSend}}
58   // MSGS: {{call.*@objc_msgSend}}
59   // CALLS: {{call.*@objc_msgSend}}
60   // CALLS: {{call.*@objc_msgSend}}
61   // CALLS: {{call.*@objc_msgSend}}
62   [NSObject alloc2];
63   [NSObject allocWithZone:(void*)-1];
64   [NSObject allocWithZone:x];
67 @class A;
68 @interface B
69 + (A*) alloc;
70 + (A*) allocWithZone:(void*)zone;
71 - (A*) alloc;
72 - (A*) allocWithZone:(void*)zone;
73 - (A*) retain;
74 - (A*) autorelease;
75 @end
77 // CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
78 A* test_alloc_class_ptr(void) {
79   // CALLS: {{call.*@objc_alloc}}
80   // CALLS-NEXT: ret
81   return [B alloc];
84 // CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
85 A* test_allocWithZone_class_ptr(void) {
86   // CALLS: {{call.*@objc_allocWithZone}}
87   // CALLS-NEXT: ret
88   return [B allocWithZone:nil];
91 // Only call objc_alloc on a Class, not an instance
92 // CHECK-LABEL: define {{.*}}void @test_alloc_instance
93 void test_alloc_instance(A *a) {
94   // CALLS: {{call.*@objc_alloc}}
95   // CALLS: {{call.*@objc_allocWithZone}}
96   // CALLS: {{call.*@objc_msgSend}}
97   // CALLS: {{call.*@objc_msgSend}}
98   [A alloc];
99   [A allocWithZone:nil];
100   [a alloc];
101   [a allocWithZone:nil];
104 // Make sure we get a bitcast on the return type as the
105 // call will return ptr which we have to cast to A*
106 // CHECK-LABEL: define {{.*}}void @test_retain_class_ptr
107 A* test_retain_class_ptr(B *b) {
108   // CALLS: {{call.*@objc_retain}}
109   // CALLS-NEXT: ret
110   return [b retain];
113 // Make sure we get a bitcast on the return type as the
114 // call will return ptr which we have to cast to A*
115 // CHECK-LABEL: define {{.*}}void @test_autorelease_class_ptr
116 A* test_autorelease_class_ptr(B *b) {
117   // CALLS: {{tail call.*@objc_autorelease}}
118   // CALLS-NEXT: ret
119   return [b autorelease];
123 @interface C
124 + (id)allocWithZone:(int)intArg;
125 - (float) retain;
126 @end
128 // Make sure we only accept pointer types
129 // CHECK-LABEL: define {{.*}}void @test_allocWithZone_int
130 C* test_allocWithZone_int(void) {
131   // MSGS: {{call.*@objc_msgSend}}
132   // CALLS: {{call.*@objc_msgSend}}
133   return [C allocWithZone:3];
136 // Make sure we use a message and not a call as the return type is
137 // not a pointer type.
138 // CHECK-LABEL: define {{.*}}void @test_cannot_message_return_float
139 float test_cannot_message_return_float(C *c) {
140   // MSGS: {{call.*@objc_msgSend}}
141   // CALLS: {{call.*@objc_msgSend}}
142   return [c retain];
145 @interface TestSelf
146 + (instancetype)alloc;
147 + (instancetype)allocWithZone:(void*)zone;
148 + (id)classMeth;
149 - (id)instanceMeth;
150 @end
152 @implementation TestSelf
153 // CHECK-LABEL: define internal ptr @"\01+[TestSelf classMeth]"(
154 + (id)classMeth {
155   // MSGS: {{call.*@objc_msgSend}}
156   // MSGS: {{call.*@objc_msgSend}}
157   // CALLS: {{call.*@objc_allocWithZone\(}}
158   // CALLS: {{call.*@objc_alloc\(}}
159   [self allocWithZone:nil];
160   return [self alloc];
162 // CHECK-LABEL: define internal ptr @"\01-[TestSelf instanceMeth]"(
163 - (id)instanceMeth {
164   // MSGS: {{call.*@objc_msgSend}}
165   // MSGS: {{call.*@objc_msgSend}}
166   // CALLS: {{call.*@objc_msgSend}}
167   // CALLS: {{call.*@objc_msgSend}}
168   [self allocWithZone:nil];
169   return [self alloc];
171 @end
173 @interface NSString : NSObject
174 + (void)retain_self;
175 - (void)retain_super;
176 @end
178 @implementation NSString
180 // Make sure we can convert a message to a dynamic receiver to a call
181 // CHECK-LABEL: define {{.*}}void @retain_self
182 + (void)retain_self {
183   // MSGS: {{call.*@objc_msgSend}}
184   // CALLS: {{call.*@objc_retain}}
185   [self retain];
188 // Make sure we never convert a message to super to a call
189 // CHECK-LABEL: define {{.*}}void @retain_super
190 - (void)retain_super {
191   // MSGS: {{call.*@objc_msgSend}}
192   // CALLS: {{call.*@objc_msgSend}}
193   [super retain];
196 @end
198 @class Ety;
200 // CHECK-LABEL: define {{.*}}void @testException_release
201 void testException_release(NSObject *a) {
202   // MSGS: {{invoke.*@objc_msgSend}}
203   // CALLS: invoke{{.*}}void @objc_release(ptr %
204   @try {
205     [a release];
206   } @catch (Ety *e) {
207   }
210 // CHECK-LABEL: define {{.*}}void @testException_autorelease
211 void testException_autorelease(NSObject *a) {
212   @try {
213     // MSGS: {{invoke.*@objc_msgSend}}
214     // CALLS: invoke{{.*}}objc_autorelease(ptr %
215     [a autorelease];
216   } @catch (Ety *e) {
217   }
220 // CHECK-LABEL: define {{.*}}void @testException_retain
221 void testException_retain(NSObject *a) {
222   @try {
223     // MSGS: {{invoke.*@objc_msgSend}}
224     // CALLS: invoke{{.*}}@objc_retain(ptr %
225     [a retain];
226   } @catch (Ety *e) {
227   }
231 // CHECK-LABEL: define {{.*}}void @testException_alloc(
232 void testException_alloc(void) {
233   @try {
234     // MSGS: {{invoke.*@objc_msgSend}}
235     // CALLS: invoke{{.*}}@objc_alloc(ptr %
236     [A alloc];
237   } @catch (Ety *e) {
238   }
241 // CHECK-LABEL: define {{.*}}void @testException_allocWithZone
242 void testException_allocWithZone(void) {
243   @try {
244     // MSGS: {{invoke.*@objc_msgSend}}
245     // CALLS: invoke{{.*}}@objc_allocWithZone(ptr %
246     [A allocWithZone:nil];
247   } @catch (Ety *e) {
248   }