1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.SuperDealloc,debug.ExprInspection -analyzer-output=text -verify %s
3 void clang_analyzer_warnIfReached(void);
7 typedef unsigned long NSUInteger;
9 - (instancetype)retain;
10 - (oneway void)release;
13 @interface NSObject <NSObject> { }
18 typedef struct objc_selector *SEL;
20 //===------------------------------------------------------------------------===
21 // <rdar://problem/6953275>
22 // Check that 'self' is not referenced after calling '[super dealloc]'.
24 @interface SuperDeallocThenReleaseIvarClass : NSObject {
29 @implementation SuperDeallocThenReleaseIvarClass
30 - (instancetype)initWithIvar:(NSObject *)ivar {
34 _ivar = [ivar retain];
38 [super dealloc]; // expected-note {{[super dealloc] called here}}
39 [_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}}
44 @interface SuperDeallocThenAssignNilToIvarClass : NSObject {
49 @implementation SuperDeallocThenAssignNilToIvarClass
50 - (instancetype)initWithDelegate:(NSObject *)delegate {
58 [super dealloc]; // expected-note {{[super dealloc] called here}}
59 _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}}
69 @interface SuperDeallocThenAssignIvarField : NSObject {
74 @implementation SuperDeallocThenAssignIvarField
76 [super dealloc]; // expected-note {{[super dealloc] called here}}
77 _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}}
82 @interface OtherClassWithIvar {
88 @interface SuperDeallocThenAssignIvarIvar : NSObject {
89 OtherClassWithIvar *_ivar;
93 @implementation SuperDeallocThenAssignIvarIvar
95 [super dealloc]; // expected-note {{[super dealloc] called here}}
96 _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}}
101 @interface SuperDeallocThenAssignSelfIvar : NSObject {
106 @implementation SuperDeallocThenAssignSelfIvar
108 [super dealloc]; // expected-note {{[super dealloc] called here}}
109 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}}
114 @interface SuperDeallocThenReleasePropertyClass : NSObject { }
115 @property (retain) NSObject *ivar;
118 @implementation SuperDeallocThenReleasePropertyClass
119 - (instancetype)initWithProperty:(NSObject *)ivar {
127 [super dealloc]; // expected-note {{[super dealloc] called here}}
128 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}}
133 @interface SuperDeallocThenAssignNilToPropertyClass : NSObject { }
134 @property (assign) NSObject *delegate;
137 @implementation SuperDeallocThenAssignNilToPropertyClass
138 - (instancetype)initWithDelegate:(NSObject *)delegate {
142 self.delegate = delegate;
146 [super dealloc]; // expected-note {{[super dealloc] called here}}
147 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}}
152 @interface SuperDeallocThenCallInstanceMethodClass : NSObject { }
156 @implementation SuperDeallocThenCallInstanceMethodClass
157 - (void)_invalidate {
160 [super dealloc]; // expected-note {{[super dealloc] called here}}
161 [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
162 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
166 @interface SuperDeallocThenCallNonObjectiveCMethodClass : NSObject { }
169 static void _invalidate(NSObject *object) {
173 @implementation SuperDeallocThenCallNonObjectiveCMethodClass
175 [super dealloc]; // expected-note {{[super dealloc] called here}}
176 _invalidate(self); // expected-warning {{Use of 'self' after it has been deallocated}}
177 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
181 @interface SuperDeallocThenCallObjectiveClassMethodClass : NSObject { }
184 @implementation SuperDeallocThenCallObjectiveClassMethodClass
185 + (void) invalidate:(id)arg; {
189 [super dealloc]; // expected-note {{[super dealloc] called here}}
190 [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}}
195 @interface TwoSuperDeallocCallsClass : NSObject {
201 @implementation TwoSuperDeallocCallsClass
202 - (void)_invalidate {
205 if (_ivar) { // expected-note {{Assuming the condition is false}} expected-note {{Taking false branch}}
210 [super dealloc]; // expected-note {{[super dealloc] called here}}
211 [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
212 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
216 //===------------------------------------------------------------------------===
217 // Warn about calling [super dealloc] twice due to missing return statement.
219 @interface MissingReturnCausesDoubleSuperDeallocClass : NSObject {
224 @implementation MissingReturnCausesDoubleSuperDeallocClass
226 if (_ivar) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}
228 [super dealloc]; // expected-note {{[super dealloc] called here}}
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}}
236 //===------------------------------------------------------------------------===
237 // Warn about calling [super dealloc] twice in two different methods.
239 @interface SuperDeallocInOtherMethodClass : NSObject {
245 @implementation SuperDeallocInOtherMethodClass
248 [super dealloc]; // expected-note {{[super dealloc] called here}}
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}}
258 //===------------------------------------------------------------------------===
259 // Do not warn about calling [super dealloc] recursively for different objects
260 // of the same type with custom retain counting.
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.
268 @class ClassWithOwnIvarInstanceClass;
269 @interface ClassWithOwnIvarInstanceClass : NSObject {
270 ClassWithOwnIvarInstanceClass *_ivar;
271 NSUInteger _retainCount;
275 @implementation ClassWithOwnIvarInstanceClass
276 - (instancetype)retain {
280 - (oneway void)release {
287 [super dealloc]; // no warning: different instances of same class
291 //===------------------------------------------------------------------------===
292 // Do not warn about calling [super dealloc] twice if +dealloc is a class
295 @interface SuperDeallocClassMethodIgnoredClass : NSObject { }
299 @implementation SuperDeallocClassMethodIgnoredClass
303 @interface SuperDeallocClassMethodIgnoredSubClass : NSObject { }
307 @implementation SuperDeallocClassMethodIgnoredSubClass
310 [super dealloc]; // no warning: class method
314 //===------------------------------------------------------------------------===
315 // Do not warn about calling [super dealloc] twice if when the analyzer has
316 // inlined the call to its super deallocator.
318 @interface SuperClassCallingSuperDealloc : NSObject {
323 @implementation SuperClassCallingSuperDealloc
325 [_ivar release]; // no-warning
331 @interface SubclassCallingSuperDealloc : SuperClassCallingSuperDealloc
334 @implementation SubclassCallingSuperDealloc
340 //===------------------------------------------------------------------------===
341 // Treat calling [super dealloc] twice as as a sink.
343 @interface CallingSuperDeallocTwiceIsSink : NSObject
346 @implementation CallingSuperDeallocTwiceIsSink
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}}
352 clang_analyzer_warnIfReached(); // no-warning
357 //===------------------------------------------------------------------------===
358 // Test path notes with intervening method call on self.
360 @interface InterveningMethodCallOnSelf : NSObject
363 @implementation InterveningMethodCallOnSelf
364 - (void)anotherMethod {
368 [super dealloc]; // expected-note {{[super dealloc] called here}}
369 [self anotherMethod]; // expected-warning {{Use of 'self' after it has been deallocated}}
370 // expected-note@-1 {{Use of 'self' after it has been deallocated}}