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
10
11#define nil (id)0
12
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
21
22// CHECK-LABEL: define {{.*}}void @test1
23void 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: {{call.*@objc_autorelease}}
34  [NSObject alloc];
35  [NSObject allocWithZone:nil];
36  [x retain];
37  [x release];
38  [x autorelease];
39}
40
41// CHECK-LABEL: define {{.*}}void @check_invoke
42void check_invoke() {
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  }
52}
53
54// CHECK-LABEL: define {{.*}}void @test2
55void 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];
65}
66
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
76
77// Make sure we get a bitcast on the return type as the
78// call will return i8* which we have to cast to A*
79// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
80A* test_alloc_class_ptr() {
81  // CALLS: {{call.*@objc_alloc}}
82  // CALLS-NEXT: bitcast i8*
83  // CALLS-NEXT: ret
84  return [B alloc];
85}
86
87// Make sure we get a bitcast on the return type as the
88// call will return i8* which we have to cast to A*
89// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
90A* test_allocWithZone_class_ptr() {
91  // CALLS: {{call.*@objc_allocWithZone}}
92  // CALLS-NEXT: bitcast i8*
93  // CALLS-NEXT: ret
94  return [B allocWithZone:nil];
95}
96
97// Only call objc_alloc on a Class, not an instance
98// CHECK-LABEL: define {{.*}}void @test_alloc_instance
99void test_alloc_instance(A *a) {
100  // CALLS: {{call.*@objc_alloc}}
101  // CALLS: {{call.*@objc_allocWithZone}}
102  // CALLS: {{call.*@objc_msgSend}}
103  // CALLS: {{call.*@objc_msgSend}}
104  [A alloc];
105  [A allocWithZone:nil];
106  [a alloc];
107  [a allocWithZone:nil];
108}
109
110// Make sure we get a bitcast on the return type as the
111// call will return i8* which we have to cast to A*
112// CHECK-LABEL: define {{.*}}void @test_retain_class_ptr
113A* test_retain_class_ptr(B *b) {
114  // CALLS: {{call.*@objc_retain}}
115  // CALLS-NEXT: bitcast i8*
116  // CALLS-NEXT: ret
117  return [b retain];
118}
119
120// Make sure we get a bitcast on the return type as the
121// call will return i8* which we have to cast to A*
122// CHECK-LABEL: define {{.*}}void @test_autorelease_class_ptr
123A* test_autorelease_class_ptr(B *b) {
124  // CALLS: {{call.*@objc_autorelease}}
125  // CALLS-NEXT: bitcast i8*
126  // CALLS-NEXT: ret
127  return [b autorelease];
128}
129
130
131@interface C
132+ (id)allocWithZone:(int)intArg;
133- (float) retain;
134@end
135
136// Make sure we only accept pointer types
137// CHECK-LABEL: define {{.*}}void @test_allocWithZone_int
138C* test_allocWithZone_int() {
139  // MSGS: {{call.*@objc_msgSend}}
140  // CALLS: {{call.*@objc_msgSend}}
141  return [C allocWithZone:3];
142}
143
144// Make sure we use a message and not a call as the return type is
145// not a pointer type.
146// CHECK-LABEL: define {{.*}}void @test_cannot_message_return_float
147float test_cannot_message_return_float(C *c) {
148  // MSGS: {{call.*@objc_msgSend}}
149  // CALLS: {{call.*@objc_msgSend}}
150  return [c retain];
151}
152
153@interface TestSelf
154+ (instancetype)alloc;
155+ (instancetype)allocWithZone:(void*)zone;
156+ (id)classMeth;
157- (id)instanceMeth;
158@end
159
160@implementation TestSelf
161// CHECK-LABEL: define internal i8* @"\01+[TestSelf classMeth]"(
162+ (id)classMeth {
163  // MSGS: {{call.*@objc_msgSend}}
164  // MSGS: {{call.*@objc_msgSend}}
165  // CALLS: {{call.*@objc_allocWithZone\(}}
166  // CALLS: {{call.*@objc_alloc\(}}
167  [self allocWithZone:nil];
168  return [self alloc];
169}
170// CHECK-LABEL: define internal i8* @"\01-[TestSelf instanceMeth]"(
171- (id)instanceMeth {
172  // MSGS: {{call.*@objc_msgSend}}
173  // MSGS: {{call.*@objc_msgSend}}
174  // CALLS: {{call.*@objc_msgSend}}
175  // CALLS: {{call.*@objc_msgSend}}
176  [self allocWithZone:nil];
177  return [self alloc];
178}
179@end
180
181@interface NSString : NSObject
182+ (void)retain_self;
183- (void)retain_super;
184@end
185
186@implementation NSString
187
188// Make sure we can convert a message to a dynamic receiver to a call
189// CHECK-LABEL: define {{.*}}void @retain_self
190+ (void)retain_self {
191  // MSGS: {{call.*@objc_msgSend}}
192  // CALLS: {{call.*@objc_retain}}
193  [self retain];
194}
195
196// Make sure we never convert a message to super to a call
197// CHECK-LABEL: define {{.*}}void @retain_super
198- (void)retain_super {
199  // MSGS: {{call.*@objc_msgSend}}
200  // CALLS: {{call.*@objc_msgSend}}
201  [super retain];
202}
203
204@end
205
206@class Ety;
207
208// CHECK-LABEL: define {{.*}}void @testException_release
209void testException_release(NSObject *a) {
210  // MSGS: {{invoke.*@objc_msgSend}}
211  // CALLS: invoke{{.*}}void @objc_release(i8* %
212  @try {
213    [a release];
214  } @catch (Ety *e) {
215  }
216}
217
218// CHECK-LABEL: define {{.*}}void @testException_autorelease
219void testException_autorelease(NSObject *a) {
220  @try {
221    // MSGS: {{invoke.*@objc_msgSend}}
222    // CALLS: invoke{{.*}}objc_autorelease(i8* %
223    [a autorelease];
224  } @catch (Ety *e) {
225  }
226}
227
228// CHECK-LABEL: define {{.*}}void @testException_retain
229void testException_retain(NSObject *a) {
230  @try {
231    // MSGS: {{invoke.*@objc_msgSend}}
232    // CALLS: invoke{{.*}}@objc_retain(i8* %
233    [a retain];
234  } @catch (Ety *e) {
235  }
236}
237
238
239// CHECK-LABEL: define {{.*}}void @testException_alloc(
240void testException_alloc() {
241  @try {
242    // MSGS: {{invoke.*@objc_msgSend}}
243    // CALLS: invoke{{.*}}@objc_alloc(i8* %
244    [A alloc];
245  } @catch (Ety *e) {
246  }
247}
248
249// CHECK-LABEL: define {{.*}}void @testException_allocWithZone
250void testException_allocWithZone() {
251  @try {
252    // MSGS: {{invoke.*@objc_msgSend}}
253    // CALLS: invoke{{.*}}@objc_allocWithZone(i8* %
254    [A allocWithZone:nil];
255  } @catch (Ety *e) {
256  }
257}
258