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