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: {{tail 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: {{tail 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