Anna Zaks | bfa9ab8 | 2013-01-24 23:15:30 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-config ipa=dynamic-bifurcate -verify %s |
Anna Zaks | c739406 | 2012-08-14 00:36:20 +0000 | [diff] [blame] | 2 | |
| 3 | typedef signed char BOOL; |
| 4 | typedef struct objc_class *Class; |
| 5 | typedef struct objc_object { |
| 6 | Class isa; |
| 7 | } *id; |
| 8 | @protocol NSObject - (BOOL)isEqual:(id)object; @end |
| 9 | @interface NSObject <NSObject> {} |
| 10 | +(id)alloc; |
| 11 | +(id)new; |
| 12 | - (oneway void)release; |
| 13 | -(id)init; |
| 14 | -(id)autorelease; |
| 15 | -(id)copy; |
| 16 | - (Class)class; |
| 17 | -(id)retain; |
Anna Zaks | 554067f | 2012-08-29 23:23:43 +0000 | [diff] [blame] | 18 | - (oneway void)release; |
Anna Zaks | c739406 | 2012-08-14 00:36:20 +0000 | [diff] [blame] | 19 | @end |
| 20 | |
| 21 | @interface SelfStaysLive : NSObject |
| 22 | - (id)init; |
| 23 | @end |
| 24 | |
| 25 | @implementation SelfStaysLive |
| 26 | - (id)init { |
| 27 | return [super init]; |
| 28 | } |
| 29 | @end |
| 30 | |
| 31 | void selfStaysLive() { |
| 32 | SelfStaysLive *foo = [[SelfStaysLive alloc] init]; |
| 33 | [foo release]; |
Anna Zaks | 5a90193 | 2012-08-24 00:06:12 +0000 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | // Test that retain release checker warns on leaks and use-after-frees when |
| 37 | // self init is not enabled. |
| 38 | // radar://12115830 |
| 39 | @interface ParentOfCell : NSObject |
| 40 | - (id)initWithInt: (int)inInt; |
| 41 | @end |
| 42 | @interface Cell : ParentOfCell{ |
| 43 | int x; |
| 44 | } |
| 45 | - (id)initWithInt: (int)inInt; |
| 46 | + (void)testOverRelease; |
| 47 | + (void)testLeak; |
| 48 | @property int x; |
| 49 | @end |
| 50 | @implementation Cell |
| 51 | @synthesize x; |
| 52 | - (id) initWithInt: (int)inInt { |
| 53 | [super initWithInt: inInt]; |
| 54 | self.x = inInt; // no-warning |
| 55 | return self; // Self Init checker would produce a warning here. |
| 56 | } |
| 57 | + (void) testOverRelease { |
| 58 | Cell *sharedCell3 = [[Cell alloc] initWithInt: 3]; |
| 59 | [sharedCell3 release]; |
| 60 | [sharedCell3 release]; // expected-warning {{Reference-counted object is used after it is released}} |
| 61 | } |
| 62 | + (void) testLeak { |
| 63 | Cell *sharedCell4 = [[Cell alloc] initWithInt: 3]; // expected-warning {{leak}} |
| 64 | } |
| 65 | @end |
Anna Zaks | 554067f | 2012-08-29 23:23:43 +0000 | [diff] [blame] | 66 | |
| 67 | // We should stop tracking some objects even when we inline the call. |
| 68 | // Specialically, the objects passed into calls with delegate and callback |
| 69 | // parameters. |
| 70 | @class DelegateTest; |
| 71 | typedef void (*ReleaseCallbackTy) (DelegateTest *c); |
| 72 | |
| 73 | @interface Delegate : NSObject |
| 74 | @end |
| 75 | |
| 76 | @interface DelegateTest : NSObject { |
| 77 | Delegate *myDel; |
| 78 | } |
| 79 | // Object initialized with a delagate which could potentially release it. |
| 80 | - (id)initWithDelegate: (id) d; |
| 81 | |
| 82 | - (void) setDelegate: (id) d; |
| 83 | |
| 84 | // Releases object through callback. |
| 85 | + (void)updateObject:(DelegateTest*)obj WithCallback:(ReleaseCallbackTy)rc; |
| 86 | |
| 87 | + (void)test: (Delegate *)d; |
| 88 | |
| 89 | @property (assign) Delegate* myDel; |
| 90 | @end |
| 91 | |
| 92 | void releaseObj(DelegateTest *c); |
| 93 | |
| 94 | // Releases object through callback. |
| 95 | void updateObject(DelegateTest *c, ReleaseCallbackTy rel) { |
| 96 | rel(c); |
| 97 | } |
| 98 | |
| 99 | @implementation DelegateTest |
| 100 | @synthesize myDel; |
| 101 | |
| 102 | - (id) initWithDelegate: (id) d { |
| 103 | if ((self = [super init])) |
| 104 | myDel = d; |
| 105 | return self; |
| 106 | } |
| 107 | |
| 108 | - (void) setDelegate: (id) d { |
| 109 | myDel = d; |
| 110 | } |
| 111 | |
| 112 | + (void)updateObject:(DelegateTest*)obj WithCallback:(ReleaseCallbackTy)rc { |
| 113 | rc(obj); |
| 114 | } |
| 115 | |
| 116 | + (void) test: (Delegate *)d { |
| 117 | DelegateTest *obj1 = [[DelegateTest alloc] initWithDelegate: d]; // no-warning |
| 118 | DelegateTest *obj2 = [[DelegateTest alloc] init]; // no-warning |
| 119 | DelegateTest *obj3 = [[DelegateTest alloc] init]; // no-warning |
| 120 | updateObject(obj2, releaseObj); |
| 121 | [DelegateTest updateObject: obj3 |
| 122 | WithCallback: releaseObj]; |
| 123 | DelegateTest *obj4 = [[DelegateTest alloc] init]; // no-warning |
| 124 | [obj4 setDelegate: d]; |
| 125 | } |
| 126 | @end |
Anna Zaks | 5a90193 | 2012-08-24 00:06:12 +0000 | [diff] [blame] | 127 | |