| // RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-config ipa=dynamic-bifurcate -verify %s | 
 |  | 
 | typedef signed char BOOL; | 
 | typedef struct objc_class *Class; | 
 | typedef struct objc_object { | 
 |     Class isa; | 
 | } *id; | 
 | @protocol NSObject  - (BOOL)isEqual:(id)object; @end | 
 | @interface NSObject <NSObject> {} | 
 | +(id)alloc; | 
 | +(id)new; | 
 | - (oneway void)release; | 
 | -(id)init; | 
 | -(id)autorelease; | 
 | -(id)copy; | 
 | - (Class)class; | 
 | -(id)retain; | 
 | - (oneway void)release; | 
 | @end | 
 |  | 
 | @interface SelfStaysLive : NSObject | 
 | - (id)init; | 
 | @end | 
 |  | 
 | @implementation SelfStaysLive | 
 | - (id)init { | 
 |   return [super init]; | 
 | } | 
 | @end | 
 |  | 
 | void selfStaysLive() { | 
 |     SelfStaysLive *foo = [[SelfStaysLive alloc] init];  | 
 |     [foo release]; | 
 | } | 
 |  | 
 | // Test that retain release checker warns on leaks and use-after-frees when  | 
 | // self init is not enabled.   | 
 | // radar://12115830 | 
 | @interface ParentOfCell : NSObject | 
 | - (id)initWithInt: (int)inInt; | 
 | @end | 
 | @interface Cell : ParentOfCell{ | 
 |   int x; | 
 | } | 
 | - (id)initWithInt: (int)inInt; | 
 | + (void)testOverRelease; | 
 | + (void)testLeak; | 
 | @property int x; | 
 | @end | 
 | @implementation Cell | 
 | @synthesize x; | 
 | - (id) initWithInt: (int)inInt { | 
 |   [super initWithInt: inInt]; | 
 |   self.x = inInt; // no-warning  | 
 |   return self; // Self Init checker would produce a warning here. | 
 | } | 
 | + (void) testOverRelease { | 
 |   Cell *sharedCell3 = [[Cell alloc] initWithInt: 3]; | 
 |   [sharedCell3 release]; | 
 |   [sharedCell3 release]; // expected-warning {{Reference-counted object is used after it is released}} | 
 | } | 
 | + (void) testLeak { | 
 |   Cell *sharedCell4 = [[Cell alloc] initWithInt: 3]; // expected-warning {{leak}} | 
 | } | 
 | @end | 
 |    | 
 | // We should stop tracking some objects even when we inline the call.  | 
 | // Specialically, the objects passed into calls with delegate and callback  | 
 | // parameters. | 
 | @class DelegateTest; | 
 | typedef void (*ReleaseCallbackTy) (DelegateTest *c); | 
 |  | 
 | @interface Delegate : NSObject | 
 | @end | 
 |  | 
 | @interface DelegateTest : NSObject { | 
 |   Delegate *myDel; | 
 | } | 
 | // Object initialized with a delagate which could potentially release it. | 
 | - (id)initWithDelegate: (id) d; | 
 |  | 
 | - (void) setDelegate: (id) d; | 
 |  | 
 | // Releases object through callback. | 
 | + (void)updateObject:(DelegateTest*)obj WithCallback:(ReleaseCallbackTy)rc; | 
 |  | 
 | + (void)test: (Delegate *)d; | 
 |  | 
 | @property (assign) Delegate* myDel; | 
 | @end | 
 |  | 
 | void releaseObj(DelegateTest *c); | 
 |  | 
 | // Releases object through callback. | 
 | void updateObject(DelegateTest *c, ReleaseCallbackTy rel) { | 
 |   rel(c); | 
 | } | 
 |  | 
 | @implementation DelegateTest | 
 | @synthesize myDel; | 
 |  | 
 | - (id) initWithDelegate: (id) d { | 
 |     if ((self = [super init])) | 
 |       myDel = d; | 
 |     return self; | 
 | } | 
 |  | 
 | - (void) setDelegate: (id) d { | 
 |     myDel = d; | 
 | } | 
 |  | 
 | + (void)updateObject:(DelegateTest*)obj WithCallback:(ReleaseCallbackTy)rc { | 
 |   rc(obj); | 
 | } | 
 |  | 
 | + (void) test: (Delegate *)d { | 
 |   DelegateTest *obj1 = [[DelegateTest alloc] initWithDelegate: d]; // no-warning | 
 |   DelegateTest *obj2 = [[DelegateTest alloc] init]; // no-warning | 
 |   DelegateTest *obj3 = [[DelegateTest alloc] init]; // no-warning | 
 |   updateObject(obj2, releaseObj); | 
 |   [DelegateTest updateObject: obj3 | 
 |         WithCallback: releaseObj]; | 
 |   DelegateTest *obj4 = [[DelegateTest alloc] init]; // no-warning | 
 |   [obj4 setDelegate: d]; | 
 | } | 
 | @end | 
 |  |