blob: 276ab5209517ed52a1952d90505f4a33a5477d6b [file] [log] [blame]
Anna Zaksc7394062012-08-14 00:36:20 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-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;
Anna Zaks554067f2012-08-29 23:23:43 +000018- (oneway void)release;
Anna Zaksc7394062012-08-14 00:36:20 +000019@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() {
32 SelfStaysLive *foo = [[SelfStaysLive alloc] init];
33 [foo release];
Anna Zaks5a901932012-08-24 00:06:12 +000034}
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 Zaks554067f2012-08-29 23:23:43 +000066
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;
71typedef 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
92void releaseObj(DelegateTest *c);
93
94// Releases object through callback.
95void 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 Zaks5a901932012-08-24 00:06:12 +0000127