diff options
Diffstat (limited to 'test/CodeGenObjC/convert-messages-to-runtime-calls.m')
-rw-r--r-- | test/CodeGenObjC/convert-messages-to-runtime-calls.m | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/test/CodeGenObjC/convert-messages-to-runtime-calls.m b/test/CodeGenObjC/convert-messages-to-runtime-calls.m index 0a018204f3..8ce024fe80 100644 --- a/test/CodeGenObjC/convert-messages-to-runtime-calls.m +++ b/test/CodeGenObjC/convert-messages-to-runtime-calls.m @@ -14,16 +14,28 @@ + (id)alloc; + (id)allocWithZone:(void*)zone; + (id)alloc2; +- (id)retain; +- (void)release; +- (id)autorelease; @end // CHECK-LABEL: define {{.*}}void @test1 void test1(id x) { // MSGS: {{call.*@objc_msgSend}} // MSGS: {{call.*@objc_msgSend}} + // MSGS: {{call.*@objc_msgSend}} + // MSGS: {{call.*@objc_msgSend}} + // MSGS: {{call.*@objc_msgSend}} // CALLS: {{call.*@objc_alloc}} // CALLS: {{call.*@objc_allocWithZone}} + // CALLS: {{call.*@objc_retain}} + // CALLS: {{call.*@objc_release}} + // CALLS: {{call.*@objc_autorelease}} [NSObject alloc]; [NSObject allocWithZone:nil]; + [x retain]; + [x release]; + [x autorelease]; } // CHECK-LABEL: define {{.*}}void @test2 @@ -42,7 +54,11 @@ void test2(void* x) { @class A; @interface B + (A*) alloc; -+ (A*)allocWithZone:(void*)zone; ++ (A*) allocWithZone:(void*)zone; +- (A*) alloc; +- (A*) allocWithZone:(void*)zone; +- (A*) retain; +- (A*) autorelease; @end // Make sure we get a bitcast on the return type as the @@ -65,9 +81,43 @@ A* test_allocWithZone_class_ptr() { return [B allocWithZone:nil]; } +// Only call objc_alloc on a Class, not an instance +// CHECK-LABEL: define {{.*}}void @test_alloc_instance +void test_alloc_instance(A *a) { + // CALLS: {{call.*@objc_alloc}} + // CALLS: {{call.*@objc_allocWithZone}} + // CALLS: {{call.*@objc_msgSend}} + // CALLS: {{call.*@objc_msgSend}} + [A alloc]; + [A allocWithZone:nil]; + [a alloc]; + [a allocWithZone:nil]; +} + +// Make sure we get a bitcast on the return type as the +// call will return i8* which we have to cast to A* +// CHECK-LABEL: define {{.*}}void @test_retain_class_ptr +A* test_retain_class_ptr(B *b) { + // CALLS: {{call.*@objc_retain}} + // CALLS-NEXT: bitcast i8* + // CALLS-NEXT: ret + return [b retain]; +} + +// Make sure we get a bitcast on the return type as the +// call will return i8* which we have to cast to A* +// CHECK-LABEL: define {{.*}}void @test_autorelease_class_ptr +A* test_autorelease_class_ptr(B *b) { + // CALLS: {{call.*@objc_autorelease}} + // CALLS-NEXT: bitcast i8* + // CALLS-NEXT: ret + return [b autorelease]; +} + @interface C + (id)allocWithZone:(int)intArg; +- (float) retain; @end // Make sure we only accept pointer types @@ -78,3 +128,37 @@ C* test_allocWithZone_int() { return [C allocWithZone:3]; } +// Make sure we use a message and not a call as the return type is +// not a pointer type. +// CHECK-LABEL: define {{.*}}void @test_cannot_message_return_float +float test_cannot_message_return_float(C *c) { + // MSGS: {{call.*@objc_msgSend}} + // CALLS: {{call.*@objc_msgSend}} + return [c retain]; +} + +@interface NSString : NSObject ++ (void)retain_self; +- (void)retain_super; +@end + +@implementation NSString + +// Make sure we can convert a message to a dynamic receiver to a call +// CHECK-LABEL: define {{.*}}void @retain_self ++ (void)retain_self { + // MSGS: {{call.*@objc_msgSend}} + // CALLS: {{call.*@objc_retain}} + [self retain]; +} + +// Make sure we never convert a message to super to a call +// CHECK-LABEL: define {{.*}}void @retain_super +- (void)retain_super { + // MSGS: {{call.*@objc_msgSend}} + // CALLS: {{call.*@objc_msgSend}} + [super retain]; +} + +@end + |