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