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