1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,osx.cocoa.Dealloc %s -verify |
2 | |
3 | // Tests for the checker which checks missing/extra ivar 'release' calls |
4 | // in dealloc. |
5 | |
6 | @interface NSObject |
7 | - (void)release; |
8 | - (void)dealloc; |
9 | @end |
10 | |
11 | @interface MyClass : NSObject { |
12 | @private |
13 | id _X; |
14 | id _Y; |
15 | id _Z; |
16 | id _K; |
17 | id _L; |
18 | id _N; |
19 | id _M; |
20 | id _P; |
21 | id _Q; |
22 | id _R; |
23 | id _S; |
24 | id _V; |
25 | id _W; |
26 | |
27 | MyClass *_other; |
28 | |
29 | id _nonPropertyIvar; |
30 | } |
31 | @property(retain) id X; |
32 | @property(retain) id Y; |
33 | @property(assign) id Z; |
34 | @property(assign) id K; |
35 | @property(weak) id L; |
36 | @property(readonly) id N; |
37 | @property(retain) id M; |
38 | @property(weak) id P; |
39 | @property(weak) id Q; |
40 | @property(retain) id R; |
41 | @property(weak, readonly) id S; |
42 | |
43 | @property(assign, readonly) id T; // Shadowed in class extension |
44 | @property(assign) id U; |
45 | |
46 | @property(retain) id V; |
47 | @property(retain) id W; |
48 | -(id) O; |
49 | -(void) setO: (id) arg; |
50 | @end |
51 | |
52 | @interface MyClass () |
53 | // Shadows T to make it readwrite internally but readonly externally. |
54 | @property(assign, readwrite) id T; |
55 | @end |
56 | |
57 | @implementation MyClass |
58 | @synthesize X = _X; |
59 | @synthesize Y = _Y; |
60 | @synthesize Z = _Z; |
61 | @synthesize K = _K; |
62 | @synthesize L = _L; |
63 | @synthesize N = _N; |
64 | @synthesize M = _M; |
65 | @synthesize Q = _Q; |
66 | @synthesize R = _R; |
67 | @synthesize V = _V; |
68 | @synthesize W = _W; |
69 | |
70 | -(id) O{ return 0; } |
71 | -(void) setO:(id)arg { } |
72 | |
73 | |
74 | -(void) releaseInHelper { |
75 | [_R release]; // no-warning |
76 | _R = @"Hi"; |
77 | } |
78 | |
79 | - (void)dealloc |
80 | { |
81 | |
82 | [_X release]; |
83 | [_Z release]; // expected-warning{{The '_Z' ivar in 'MyClass' was synthesized for an assign, readwrite property but was released in 'dealloc'}} |
84 | [_T release]; // no-warning |
85 | |
86 | [_other->_Z release]; // no-warning |
87 | [_N release]; |
88 | |
89 | self.M = 0; // This will release '_M' |
90 | [self setV:0]; // This will release '_V' |
91 | [self setW:@"newW"]; // This will release '_W', but retain the new value |
92 | |
93 | [_S release]; // expected-warning {{The '_S' ivar in 'MyClass' was synthesized for a weak property but was released in 'dealloc'}} |
94 | |
95 | self.O = 0; // no-warning |
96 | |
97 | [_Q release]; // expected-warning {{The '_Q' ivar in 'MyClass' was synthesized for a weak property but was released in 'dealloc'}} |
98 | |
99 | self.P = 0; |
100 | |
101 | [self releaseInHelper]; |
102 | |
103 | [_nonPropertyIvar release]; // no-warning |
104 | |
105 | // Silly, but not an error. |
106 | if (!_U) |
107 | [_U release]; |
108 | |
109 | [super dealloc]; |
110 | // expected-warning@-1{{The '_Y' ivar in 'MyClass' was retained by a synthesized property but not released before '[super dealloc]'}} |
111 | // expected-warning@-2{{The '_W' ivar in 'MyClass' was retained by a synthesized property but not released before '[super dealloc]'}} |
112 | |
113 | } |
114 | |
115 | @end |
116 | |
117 | |