blob: 2e1bdc41bb6e9c40a0b656300dbc6183561596ae [file] [log] [blame]
Dominic Chen184c6242017-03-03 18:02:02 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.SuperDealloc,debug.ExprInspection -analyzer-output=text -verify %s
Devin Coughlineb6673c2016-02-22 17:56:24 +00002
3void clang_analyzer_warnIfReached();
4
5#define nil ((id)0)
6
7typedef unsigned long NSUInteger;
8@protocol NSObject
9- (instancetype)retain;
10- (oneway void)release;
11@end
12
13@interface NSObject <NSObject> { }
14- (void)dealloc;
15- (instancetype)init;
16@end
17
18typedef struct objc_selector *SEL;
19
20//===------------------------------------------------------------------------===
21// <rdar://problem/6953275>
22// Check that 'self' is not referenced after calling '[super dealloc]'.
23
24@interface SuperDeallocThenReleaseIvarClass : NSObject {
25 NSObject *_ivar;
26}
27@end
28
29@implementation SuperDeallocThenReleaseIvarClass
30- (instancetype)initWithIvar:(NSObject *)ivar {
31 self = [super init];
32 if (!self)
33 return nil;
34 _ivar = [ivar retain];
35 return self;
36}
37- (void)dealloc {
Devin Coughlin591991c2016-02-25 23:36:52 +000038 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlindce8d8b2016-03-02 21:22:48 +000039 [_ivar release]; // expected-warning {{Use of instance variable '_ivar' after 'self' has been deallocated}}
40 // expected-note@-1 {{Use of instance variable '_ivar' after 'self' has been deallocated}}
Devin Coughlineb6673c2016-02-22 17:56:24 +000041}
42@end
43
44@interface SuperDeallocThenAssignNilToIvarClass : NSObject {
45 NSObject *_delegate;
46}
47@end
48
49@implementation SuperDeallocThenAssignNilToIvarClass
50- (instancetype)initWithDelegate:(NSObject *)delegate {
51 self = [super init];
52 if (!self)
53 return nil;
54 _delegate = delegate;
55 return self;
56}
57- (void)dealloc {
Devin Coughlin591991c2016-02-25 23:36:52 +000058 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlindce8d8b2016-03-02 21:22:48 +000059 _delegate = nil; // expected-warning {{Use of instance variable '_delegate' after 'self' has been deallocated}}
60 // expected-note@-1 {{Use of instance variable '_delegate' after 'self' has been deallocated}}
Devin Coughlin591991c2016-02-25 23:36:52 +000061}
62@end
63
64
65struct SomeStruct {
66 int f;
67};
68
69@interface SuperDeallocThenAssignIvarField : NSObject {
70 struct SomeStruct _s;
71}
72@end
73
74@implementation SuperDeallocThenAssignIvarField
75- (void)dealloc {
76 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlindce8d8b2016-03-02 21:22:48 +000077 _s.f = 7; // expected-warning {{Use of instance variable '_s' after 'self' has been deallocated}}
78 // expected-note@-1 {{Use of instance variable '_s' after 'self' has been deallocated}}
Devin Coughlin591991c2016-02-25 23:36:52 +000079}
80@end
81
82@interface OtherClassWithIvar {
83@public
84 int _otherIvar;
85}
86@end;
87
88@interface SuperDeallocThenAssignIvarIvar : NSObject {
89 OtherClassWithIvar *_ivar;
90}
91@end
92
93@implementation SuperDeallocThenAssignIvarIvar
94- (void)dealloc {
95 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlindce8d8b2016-03-02 21:22:48 +000096 _ivar->_otherIvar = 7; // expected-warning {{Use of instance variable '_ivar' after 'self' has been deallocated}}
97 // expected-note@-1 {{Use of instance variable '_ivar' after 'self' has been deallocated}}
Devin Coughlin896dffe2016-02-26 00:47:42 +000098}
99@end
100
101@interface SuperDeallocThenAssignSelfIvar : NSObject {
102 NSObject *_ivar;
103}
104@end
105
106@implementation SuperDeallocThenAssignSelfIvar
107- (void)dealloc {
108 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlindce8d8b2016-03-02 21:22:48 +0000109 self->_ivar = nil; // expected-warning {{Use of instance variable '_ivar' after 'self' has been deallocated}}
110 // expected-note@-1 {{Use of instance variable '_ivar' after 'self' has been deallocated}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000111}
112@end
113
114@interface SuperDeallocThenReleasePropertyClass : NSObject { }
115@property (retain) NSObject *ivar;
116@end
117
118@implementation SuperDeallocThenReleasePropertyClass
119- (instancetype)initWithProperty:(NSObject *)ivar {
120 self = [super init];
121 if (!self)
122 return nil;
123 self.ivar = ivar;
124 return self;
125}
126- (void)dealloc {
Devin Coughlin591991c2016-02-25 23:36:52 +0000127 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlin05c03842016-11-01 22:16:39 +0000128 self.ivar = nil; // expected-warning {{Use of 'self' after it has been deallocated}}
129 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000130}
131@end
132
133@interface SuperDeallocThenAssignNilToPropertyClass : NSObject { }
134@property (assign) NSObject *delegate;
135@end
136
137@implementation SuperDeallocThenAssignNilToPropertyClass
138- (instancetype)initWithDelegate:(NSObject *)delegate {
139 self = [super init];
140 if (!self)
141 return nil;
142 self.delegate = delegate;
143 return self;
144}
145- (void)dealloc {
Devin Coughlin591991c2016-02-25 23:36:52 +0000146 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlin05c03842016-11-01 22:16:39 +0000147 self.delegate = nil; // expected-warning {{Use of 'self' after it has been deallocated}}
148 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000149}
150@end
151
152@interface SuperDeallocThenCallInstanceMethodClass : NSObject { }
153- (void)_invalidate;
154@end
155
156@implementation SuperDeallocThenCallInstanceMethodClass
157- (void)_invalidate {
158}
159- (void)dealloc {
Devin Coughlin591991c2016-02-25 23:36:52 +0000160 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlin05c03842016-11-01 22:16:39 +0000161 [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
162 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000163}
164@end
165
166@interface SuperDeallocThenCallNonObjectiveCMethodClass : NSObject { }
167@end
168
169static void _invalidate(NSObject *object) {
170 (void)object;
171}
172
173@implementation SuperDeallocThenCallNonObjectiveCMethodClass
174- (void)dealloc {
Devin Coughlin591991c2016-02-25 23:36:52 +0000175 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlin05c03842016-11-01 22:16:39 +0000176 _invalidate(self); // expected-warning {{Use of 'self' after it has been deallocated}}
177 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
Devin Coughlin591991c2016-02-25 23:36:52 +0000178}
179@end
180
181@interface SuperDeallocThenCallObjectiveClassMethodClass : NSObject { }
182@end
183
184@implementation SuperDeallocThenCallObjectiveClassMethodClass
185+ (void) invalidate:(id)arg; {
186}
187
188- (void)dealloc {
189 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlin05c03842016-11-01 22:16:39 +0000190 [SuperDeallocThenCallObjectiveClassMethodClass invalidate:self]; // expected-warning {{Use of 'self' after it has been deallocated}}
191 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000192}
193@end
194
195@interface TwoSuperDeallocCallsClass : NSObject {
196 NSObject *_ivar;
197}
198- (void)_invalidate;
199@end
200
201@implementation TwoSuperDeallocCallsClass
202- (void)_invalidate {
203}
204- (void)dealloc {
Artem Dergachev0c334062016-10-05 08:19:49 +0000205 if (_ivar) { // expected-note {{Assuming the condition is false}} expected-note {{Taking false branch}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000206 [_ivar release];
207 [super dealloc];
208 return;
209 }
Devin Coughlin591991c2016-02-25 23:36:52 +0000210 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlin05c03842016-11-01 22:16:39 +0000211 [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
212 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000213}
214@end
215
216//===------------------------------------------------------------------------===
217// Warn about calling [super dealloc] twice due to missing return statement.
218
219@interface MissingReturnCausesDoubleSuperDeallocClass : NSObject {
220 NSObject *_ivar;
221}
222@end
223
224@implementation MissingReturnCausesDoubleSuperDeallocClass
225- (void)dealloc {
Artem Dergachev0c334062016-10-05 08:19:49 +0000226 if (_ivar) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000227 [_ivar release];
228 [super dealloc]; // expected-note {{[super dealloc] called here}}
229 // return;
230 }
231 [super dealloc]; // expected-warning{{[super dealloc] should not be called multiple times}}
232 // expected-note@-1{{[super dealloc] should not be called multiple times}}
233}
234@end
235
236//===------------------------------------------------------------------------===
237// Warn about calling [super dealloc] twice in two different methods.
238
239@interface SuperDeallocInOtherMethodClass : NSObject {
240 NSObject *_ivar;
241}
242- (void)_cleanup;
243@end
244
245@implementation SuperDeallocInOtherMethodClass
246- (void)_cleanup {
247 [_ivar release];
248 [super dealloc]; // expected-note {{[super dealloc] called here}}
249}
250- (void)dealloc {
251 [self _cleanup]; // expected-note {{Calling '_cleanup'}}
252 //expected-note@-1 {{Returning from '_cleanup'}}
253 [super dealloc]; // expected-warning {{[super dealloc] should not be called multiple times}}
254 // expected-note@-1 {{[super dealloc] should not be called multiple times}}
255}
256@end
257
258//===------------------------------------------------------------------------===
259// Do not warn about calling [super dealloc] recursively for different objects
260// of the same type with custom retain counting.
261//
262// A class that contains an ivar of itself with custom retain counting (such
263// as provided by _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN) can generate
264// a false positive that [super dealloc] is called twice if each object instance
265// is not tracked separately by the checker. This test case is just a simple
266// approximation to trigger the false positive.
267
268@class ClassWithOwnIvarInstanceClass;
269@interface ClassWithOwnIvarInstanceClass : NSObject {
270 ClassWithOwnIvarInstanceClass *_ivar;
271 NSUInteger _retainCount;
272}
273@end
274
275@implementation ClassWithOwnIvarInstanceClass
276- (instancetype)retain {
277 ++_retainCount;
278 return self;
279}
280- (oneway void)release {
281 --_retainCount;
282 if (!_retainCount)
283 [self dealloc];
284}
285- (void)dealloc {
286 [_ivar release];
287 [super dealloc]; // no warning: different instances of same class
288}
289@end
290
291//===------------------------------------------------------------------------===
292// Do not warn about calling [super dealloc] twice if +dealloc is a class
293// method.
294
295@interface SuperDeallocClassMethodIgnoredClass : NSObject { }
296+ (void)dealloc;
297@end
298
299@implementation SuperDeallocClassMethodIgnoredClass
300+ (void)dealloc { }
301@end
302
303@interface SuperDeallocClassMethodIgnoredSubClass : NSObject { }
304+ (void)dealloc;
305@end
306
307@implementation SuperDeallocClassMethodIgnoredSubClass
308+ (void)dealloc {
309 [super dealloc];
310 [super dealloc]; // no warning: class method
311}
312@end
313
314//===------------------------------------------------------------------------===
315// Do not warn about calling [super dealloc] twice if when the analyzer has
316// inlined the call to its super deallocator.
317
Devin Coughlin591991c2016-02-25 23:36:52 +0000318@interface SuperClassCallingSuperDealloc : NSObject {
319 NSObject *_ivar;
320}
Devin Coughlineb6673c2016-02-22 17:56:24 +0000321@end
322
323@implementation SuperClassCallingSuperDealloc
324- (void)dealloc; {
Devin Coughlin591991c2016-02-25 23:36:52 +0000325 [_ivar release]; // no-warning
326
Devin Coughlineb6673c2016-02-22 17:56:24 +0000327 [super dealloc];
328}
329@end
330
331@interface SubclassCallingSuperDealloc : SuperClassCallingSuperDealloc
332@end
333
334@implementation SubclassCallingSuperDealloc
335- (void)dealloc; {
336 [super dealloc];
337}
338@end
339
340//===------------------------------------------------------------------------===
341// Treat calling [super dealloc] twice as as a sink.
342
343@interface CallingSuperDeallocTwiceIsSink : NSObject
344@end
345
346@implementation CallingSuperDeallocTwiceIsSink
347- (void)dealloc; {
348 [super dealloc]; // expected-note {{[super dealloc] called here}}
349 [super dealloc]; // expected-warning {{[super dealloc] should not be called multiple times}}
350 // expected-note@-1 {{[super dealloc] should not be called multiple times}}
351
352 clang_analyzer_warnIfReached(); // no-warning
353}
354@end
355
356
357//===------------------------------------------------------------------------===
358// Test path notes with intervening method call on self.
359
360@interface InterveningMethodCallOnSelf : NSObject
361@end
362
363@implementation InterveningMethodCallOnSelf
364- (void)anotherMethod {
365}
366
367- (void)dealloc; {
368 [super dealloc]; // expected-note {{[super dealloc] called here}}
Devin Coughlin05c03842016-11-01 22:16:39 +0000369 [self anotherMethod]; // expected-warning {{Use of 'self' after it has been deallocated}}
370 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
Devin Coughlin591991c2016-02-25 23:36:52 +0000371 [super dealloc];
Devin Coughlineb6673c2016-02-22 17:56:24 +0000372}
373@end