| // RUN: %clang_cc1 -arcmt-check -verify -triple x86_64-apple-darwin10 -fblocks -Werror %s |
| |
| #if __has_feature(objc_arc) |
| #define NS_AUTOMATED_REFCOUNT_UNAVAILABLE __attribute__((unavailable("not available in automatic reference counting mode"))) |
| #else |
| #define NS_AUTOMATED_REFCOUNT_UNAVAILABLE |
| #endif |
| |
| typedef const void * CFTypeRef; |
| CFTypeRef CFBridgingRetain(id X); |
| id CFBridgingRelease(CFTypeRef); |
| |
| typedef int BOOL; |
| typedef unsigned NSUInteger; |
| |
| @protocol NSObject |
| - (id)retain NS_AUTOMATED_REFCOUNT_UNAVAILABLE; |
| - (NSUInteger)retainCount NS_AUTOMATED_REFCOUNT_UNAVAILABLE; |
| - (oneway void)release NS_AUTOMATED_REFCOUNT_UNAVAILABLE; |
| - (id)autorelease NS_AUTOMATED_REFCOUNT_UNAVAILABLE; |
| @end |
| |
| @interface NSObject <NSObject> {} |
| - (id)init; |
| |
| + (id)new; |
| + (id)alloc; |
| - (void)dealloc; |
| |
| - (void)finalize; |
| |
| - (id)copy; |
| - (id)mutableCopy; |
| @end |
| |
| typedef const struct __CFString * CFStringRef; |
| extern const CFStringRef kUTTypePlainText; |
| extern const CFStringRef kUTTypeRTF; |
| @class NSString; |
| @class A; |
| |
| struct UnsafeS { |
| A *__unsafe_unretained unsafeObj; |
| }; |
| |
| @interface A : NSObject |
| - (id)retain __attribute__((unavailable)); // expected-note {{'retain' has been explicitly marked unavailable here}} |
| - (id)retainCount __attribute__((unavailable)); // expected-note {{'retainCount' has been explicitly marked unavailable here}} |
| - (id)autorelease __attribute__((unavailable)); // expected-note 2 {{'autorelease' has been explicitly marked unavailable here}} |
| - (id)init; |
| - (oneway void)release; |
| - (void)dealloc; |
| -(void)test; |
| -(id)delegate; |
| @end |
| |
| @implementation A |
| -(void)test { |
| [super dealloc]; |
| } |
| -(void)dealloc { |
| [super dealloc]; |
| } |
| |
| - (id)retain { return self; } // expected-error {{ARC forbids implementation}} |
| - (id)retainCount { return self; } // expected-error {{ARC forbids implementation}} |
| - (id)autorelease { return self; } // expected-error {{ARC forbids implementation}} |
| - (oneway void)release { } // expected-error {{ARC forbids implementation}} |
| |
| -(id)delegate { return self; } |
| @end |
| |
| id global_foo; |
| |
| void test1(A *a, BOOL b, struct UnsafeS *unsafeS) { |
| [[a delegate] release]; // expected-error {{it is not safe to remove 'retain' message on the result of a 'delegate' message; the object that was passed to 'setDelegate:' may not be properly retained}} \ |
| // expected-error {{ARC forbids explicit message send}} |
| [a.delegate release]; // expected-error {{it is not safe to remove 'retain' message on the result of a 'delegate' message; the object that was passed to 'setDelegate:' may not be properly retained}} \ |
| // expected-error {{ARC forbids explicit message send}} |
| [unsafeS->unsafeObj retain]; // expected-error {{it is not safe to remove 'retain' message on an __unsafe_unretained type}} \ |
| // expected-error {{ARC forbids explicit message send}} \ |
| // expected-error {{'retain' is unavailable}} |
| id foo = [unsafeS->unsafeObj retain]; // no warning. |
| [global_foo retain]; // expected-error {{it is not safe to remove 'retain' message on a global variable}} \ |
| // expected-error {{ARC forbids explicit message send}} |
| [global_foo release]; // expected-error {{it is not safe to remove 'release' message on a global variable}} \ |
| // expected-error {{ARC forbids explicit message send}} |
| [a dealloc]; |
| [a retain]; |
| [a retainCount]; // expected-error {{ARC forbids explicit message send of 'retainCount'}} \ |
| // expected-error {{'retainCount' is unavailable}} |
| [a release]; |
| [a autorelease]; // expected-error {{it is not safe to remove an unused 'autorelease' message; its receiver may be destroyed immediately}} \ |
| // expected-error {{ARC forbids explicit message send}} \ |
| // expected-error {{'autorelease' is unavailable}} |
| [a autorelease]; // expected-error {{it is not safe to remove an unused 'autorelease' message; its receiver may be destroyed immediately}} \ |
| // expected-error {{ARC forbids explicit message send}} \ |
| // expected-error {{'autorelease' is unavailable}} |
| a = 0; |
| |
| CFStringRef cfstr; |
| NSString *str = (NSString *)cfstr; // expected-error {{cast of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type 'NSString *' requires a bridged cast}} \ |
| // expected-note {{use __bridge to convert directly (no change in ownership)}} \ |
| // expected-note {{use CFBridgingRelease call to transfer ownership of a +1 'CFStringRef' (aka 'const struct __CFString *') into ARC}} \ |
| str = (NSString *)kUTTypePlainText; |
| str = b ? kUTTypeRTF : kUTTypePlainText; |
| str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText); |
| str = (NSString *)a; // no change. |
| |
| SEL s = @selector(retain); // expected-error {{ARC forbids use of 'retain' in a @selector}} |
| s = @selector(release); // expected-error {{ARC forbids use of 'release' in a @selector}} |
| s = @selector(autorelease); // expected-error {{ARC forbids use of 'autorelease' in a @selector}} |
| s = @selector(dealloc); // expected-error {{ARC forbids use of 'dealloc' in a @selector}} |
| |
| static id __autoreleasing X1; // expected-error {{global variables cannot have __autoreleasing ownership}} |
| } |
| |
| struct S { |
| A* a; // expected-error {{ARC forbids Objective-C objects in struct}} |
| }; |
| |
| @interface B |
| -(id)alloc; |
| - (id)initWithInt: (int) i; |
| @end |
| |
| void rdar8861761() { |
| B *o1 = [[B alloc] initWithInt:0]; |
| B *o2 = [B alloc]; |
| [o2 initWithInt:0]; |
| } |
| |
| @interface Test13 |
| - (id) init0; |
| - (void) noninit; |
| @end |
| @implementation Test13 |
| - (id) init0 { |
| self = 0; |
| } |
| - (void) noninit { |
| self = 0; // expected-error {{cannot assign to 'self' outside of a method in the init family}} |
| |
| for (__strong id x in collection) { // expected-error {{use of undeclared identifier 'collection'}} |
| x = 0; |
| } |
| } |
| @end |
| |
| void * cvt(id arg) |
| { |
| void* voidp_val; |
| (void)(int*)arg; // expected-error {{disallowed}} |
| (void)(id)arg; |
| (void)(__autoreleasing id*)arg; // expected-error {{disallowed}} |
| (void)(id*)arg; // expected-error {{disallowed}} |
| |
| (void)(__autoreleasing id**)voidp_val; |
| (void)(void*)voidp_val; |
| (void)(void**)arg; // expected-error {{disallowed}} |
| cvt((void*)arg); // expected-error 2 {{requires a bridged cast}} \ |
| // expected-note 2 {{use __bridge to}} expected-note {{use CFBridgingRelease call}} expected-note {{use CFBridgingRetain call}} |
| cvt(0); |
| (void)(__strong id**)(0); |
| return arg; // expected-error {{requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use CFBridgingRetain call}} |
| } |
| |
| |
| void test12(id collection) { |
| for (id x in collection) { |
| x = 0; |
| } |
| |
| for (__strong id x in collection) { |
| x = 0; |
| } |
| } |
| |
| void test6(unsigned cond) { |
| switch (cond) { |
| case 0: |
| ; |
| id x; // expected-note {{jump bypasses initialization of __strong variable}} |
| |
| case 1: // expected-error {{cannot jump}} |
| x = 0; |
| break; |
| } |
| } |
| |
| @class Test8_incomplete; |
| @interface Test8_complete @end; |
| @interface Test8_super @end; |
| @interface Test8 : Test8_super |
| - (id) init00; |
| - (id) init01; // expected-note {{declaration in interface}} |
| - (id) init02; |
| - (id) init03; // covariance |
| - (id) init04; // covariance |
| - (id) init05; |
| |
| - (void) init10; // expected-note {{declaration in interface is not in the 'init' family because its result type is not an object pointer}} |
| - (void) init11; |
| - (void) init12; |
| - (void) init13; // expected-note {{declaration in interface is not in the 'init' family because its result type is not an object pointer}} |
| - (void) init14; // expected-note {{declaration in interface is not in the 'init' family because its result type is not an object pointer}} |
| - (void) init15; |
| |
| // These should be invalid to actually call. |
| - (Test8_incomplete*) init20; |
| - (Test8_incomplete*) init21; // expected-note {{declaration in interface}} |
| - (Test8_incomplete*) init22; |
| - (Test8_incomplete*) init23; |
| - (Test8_incomplete*) init24; |
| - (Test8_incomplete*) init25; |
| |
| - (Test8_super*) init30; // id exception to covariance |
| - (Test8_super*) init31; // expected-note {{declaration in interface}} |
| - (Test8_super*) init32; |
| - (Test8_super*) init33; |
| - (Test8_super*) init34; // covariance |
| - (Test8_super*) init35; |
| |
| - (Test8*) init40; // id exception to covariance |
| - (Test8*) init41; // expected-note {{declaration in interface}} |
| - (Test8*) init42; |
| - (Test8*) init43; // this should be a warning, but that's a general language thing, not an ARC thing |
| - (Test8*) init44; |
| - (Test8*) init45; |
| |
| - (Test8_complete*) init50; // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init51; // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init52; // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init53; // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init54; // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init55; // expected-error {{init methods must return a type related to the receiver type}} |
| @end |
| @implementation Test8 |
| - (id) init00 { return 0; } |
| - (id) init10 { return 0; } // expected-error {{method implementation does not match its declaration}} |
| - (id) init20 { return 0; } |
| - (id) init30 { return 0; } |
| - (id) init40 { return 0; } |
| - (id) init50 { return 0; } |
| |
| - (void) init01 {} // expected-error {{method was declared as an 'init' method, but its implementation doesn't match because its result type is not an object pointer}} |
| - (void) init11 {} |
| - (void) init21 {} // expected-error {{method was declared as an 'init' method, but its implementation doesn't match because its result type is not an object pointer}} |
| - (void) init31 {} // expected-error {{method was declared as an 'init' method, but its implementation doesn't match because its result type is not an object pointer}} |
| - (void) init41 {} // expected-error {{method was declared as an 'init' method, but its implementation doesn't match because its result type is not an object pointer}} |
| - (void) init51 {} |
| |
| - (Test8_incomplete*) init02 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_incomplete*) init12 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_incomplete*) init22 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_incomplete*) init32 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_incomplete*) init42 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_incomplete*) init52 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| |
| - (Test8_super*) init03 { return 0; } |
| - (Test8_super*) init13 { return 0; } // expected-error {{method implementation does not match its declaration}} |
| - (Test8_super*) init23 { return 0; } |
| - (Test8_super*) init33 { return 0; } |
| - (Test8_super*) init43 { return 0; } |
| - (Test8_super*) init53 { return 0; } |
| |
| - (Test8*) init04 { return 0; } |
| - (Test8*) init14 { return 0; } // expected-error {{method implementation does not match its declaration}} |
| - (Test8*) init24 { return 0; } |
| - (Test8*) init34 { return 0; } |
| - (Test8*) init44 { return 0; } |
| - (Test8*) init54 { return 0; } |
| |
| - (Test8_complete*) init05 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init15 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init25 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init35 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init45 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test8_complete*) init55 { return 0; } // expected-error {{init methods must return a type related to the receiver type}} |
| @end |
| |
| @class Test9_incomplete; |
| @interface Test9 |
| - (Test9_incomplete*) init1; // expected-error {{init methods must return a type related to the receiver type}} |
| - (Test9_incomplete*) init2; |
| @end |
| id test9(Test9 *v) { |
| return [v init1]; |
| } |
| |
| // rdar://9491791 |
| void rdar9491791(int p) { |
| switch (p) { |
| case 3:; |
| NSObject *o = [[NSObject alloc] init]; |
| [o release]; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| #define RELEASE_MACRO(x) do { [x release]; } while(1) |
| |
| // rdar://9504750 |
| void rdar9504750(id p) { |
| RELEASE_MACRO(p); // expected-error {{ARC forbids explicit message send of 'release'}} |
| } |
| |
| // rdar://8939557 |
| @interface TestReadonlyProperty : NSObject |
| @property(assign,readonly) NSObject *value; |
| @end |
| |
| @implementation TestReadonlyProperty |
| @synthesize value; |
| - (void)viewDidLoad { |
| value = [NSObject new]; // expected-error {{assigning retained object}} |
| } |
| @end |
| |
| // rdar://9601437 |
| @interface I9601437 { |
| __unsafe_unretained id x; |
| } |
| -(void)Meth; |
| @end |
| |
| @implementation I9601437 |
| -(void)Meth { |
| self->x = [NSObject new]; // expected-error {{assigning retained object}} |
| } |
| @end |
| |
| @interface Test10 : NSObject { |
| CFStringRef cfstr; |
| } |
| @property (retain) id prop; |
| -(void)foo; |
| @end |
| |
| void test(Test10 *x) { |
| x.prop = ^{ [x foo]; }; // expected-warning {{likely to lead to a retain cycle}} \ |
| // expected-note {{retained by the captured object}} |
| } |
| |
| @implementation Test10 |
| -(void)foo { |
| ^{ |
| NSString *str = (NSString *)cfstr; // expected-error {{cast of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type 'NSString *' requires a bridged cast}} \ |
| // expected-note {{use __bridge to convert directly (no change in ownership)}} \ |
| // expected-note {{use CFBridgingRelease call to transfer ownership of a +1 'CFStringRef' (aka 'const struct __CFString *') into ARC}} |
| }; |
| } |
| @end |