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 // Check that 'self' is not referenced after calling '[super dealloc]'.
23 @interface SuperDeallocThenReleaseIvarClass : NSObject {
28 @implementation SuperDeallocThenReleaseIvarClass
29 - (instancetype)initWithIvar:(NSObject *)ivar {
33 _ivar = [ivar retain];
37 [super dealloc]; // expected-note {{[super dealloc] called here}}
38 [_ivar release]; // expected-warning {{Use of instance variable '_ivar' after 'self' has been deallocated}}
39 // expected-note@-1 {{Use of instance variable '_ivar' after 'self' has been deallocated}}
43 @interface SuperDeallocThenAssignNilToIvarClass : NSObject {
48 @implementation SuperDeallocThenAssignNilToIvarClass
49 - (instancetype)initWithDelegate:(NSObject *)delegate {
57 [super dealloc]; // expected-note {{[super dealloc] called here}}
58 _delegate = nil; // expected-warning {{Use of instance variable '_delegate' after 'self' has been deallocated}}
59 // expected-note@-1 {{Use of instance variable '_delegate' after 'self' has been deallocated}}
68 @interface SuperDeallocThenAssignIvarField : NSObject {
73 @implementation SuperDeallocThenAssignIvarField
75 [super dealloc]; // expected-note {{[super dealloc] called here}}
76 _s.f = 7; // expected-warning {{Use of instance variable '_s' after 'self' has been deallocated}}
77 // expected-note@-1 {{Use of instance variable '_s' after 'self' has been deallocated}}
81 @interface OtherClassWithIvar {
87 @interface SuperDeallocThenAssignIvarIvar : NSObject {
88 OtherClassWithIvar *_ivar;
92 @implementation SuperDeallocThenAssignIvarIvar
94 [super dealloc]; // expected-note {{[super dealloc] called here}}
95 _ivar->_otherIvar = 7; // expected-warning {{Use of instance variable '_ivar' after 'self' has been deallocated}}
96 // expected-note@-1 {{Use of instance variable '_ivar' after 'self' has been deallocated}}
100 @interface SuperDeallocThenAssignSelfIvar : NSObject {
105 @implementation SuperDeallocThenAssignSelfIvar
107 [super dealloc]; // expected-note {{[super dealloc] called here}}
108 self->_ivar = nil; // expected-warning {{Use of instance variable '_ivar' after 'self' has been deallocated}}
109 // expected-note@-1 {{Use of instance variable '_ivar' after 'self' has been deallocated}}
113 @interface SuperDeallocThenReleasePropertyClass : NSObject { }
114 @property (retain) NSObject *ivar;
117 @implementation SuperDeallocThenReleasePropertyClass
118 - (instancetype)initWithProperty:(NSObject *)ivar {
126 [super dealloc]; // expected-note {{[super dealloc] called here}}
127 self.ivar = nil; // expected-warning {{Use of 'self' after it has been deallocated}}
128 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
132 @interface SuperDeallocThenAssignNilToPropertyClass : NSObject { }
133 @property (assign) NSObject *delegate;
136 @implementation SuperDeallocThenAssignNilToPropertyClass
137 - (instancetype)initWithDelegate:(NSObject *)delegate {
141 self.delegate = delegate;
145 [super dealloc]; // expected-note {{[super dealloc] called here}}
146 self.delegate = nil; // expected-warning {{Use of 'self' after it has been deallocated}}
147 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
151 @interface SuperDeallocThenCallInstanceMethodClass : NSObject { }
155 @implementation SuperDeallocThenCallInstanceMethodClass
156 - (void)_invalidate {
159 [super dealloc]; // expected-note {{[super dealloc] called here}}
160 [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
161 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
165 @interface SuperDeallocThenCallNonObjectiveCMethodClass : NSObject { }
168 static void _invalidate(NSObject *object) {
172 @implementation SuperDeallocThenCallNonObjectiveCMethodClass
174 [super dealloc]; // expected-note {{[super dealloc] called here}}
175 _invalidate(self); // expected-warning {{Use of 'self' after it has been deallocated}}
176 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
180 @interface SuperDeallocThenCallObjectiveClassMethodClass : NSObject { }
183 @implementation SuperDeallocThenCallObjectiveClassMethodClass
184 + (void) invalidate:(id)arg; {
188 [super dealloc]; // expected-note {{[super dealloc] called here}}
189 [SuperDeallocThenCallObjectiveClassMethodClass invalidate:self]; // expected-warning {{Use of 'self' after it has been deallocated}}
190 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
194 @interface TwoSuperDeallocCallsClass : NSObject {
200 @implementation TwoSuperDeallocCallsClass
201 - (void)_invalidate {
204 if (_ivar) { // expected-note {{Assuming the condition is false}} expected-note {{Taking false branch}}
209 [super dealloc]; // expected-note {{[super dealloc] called here}}
210 [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
211 // expected-note@-1 {{Use of 'self' after it has been deallocated}}
215 //===------------------------------------------------------------------------===
216 // Warn about calling [super dealloc] twice due to missing return statement.
218 @interface MissingReturnCausesDoubleSuperDeallocClass : NSObject {
223 @implementation MissingReturnCausesDoubleSuperDeallocClass
225 if (_ivar) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}
227 [super dealloc]; // expected-note {{[super dealloc] called here}}
230 [super dealloc]; // expected-warning{{[super dealloc] should not be called multiple times}}
231 // expected-note@-1{{[super dealloc] should not be called multiple times}}
235 //===------------------------------------------------------------------------===
236 // Warn about calling [super dealloc] twice in two different methods.
238 @interface SuperDeallocInOtherMethodClass : NSObject {
244 @implementation SuperDeallocInOtherMethodClass
247 [super dealloc]; // expected-note {{[super dealloc] called here}}
250 [self _cleanup]; // expected-note {{Calling '_cleanup'}}
251 //expected-note@-1 {{Returning from '_cleanup'}}
252 [super dealloc]; // expected-warning {{[super dealloc] should not be called multiple times}}
253 // expected-note@-1 {{[super dealloc] should not be called multiple times}}
257 //===------------------------------------------------------------------------===
258 // Do not warn about calling [super dealloc] recursively for different objects
259 // of the same type with custom retain counting.
261 // A class that contains an ivar of itself with custom retain counting (such
262 // as provided by _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN) can generate
263 // a false positive that [super dealloc] is called twice if each object instance
264 // is not tracked separately by the checker. This test case is just a simple
265 // approximation to trigger the false positive.
267 @class ClassWithOwnIvarInstanceClass;
268 @interface ClassWithOwnIvarInstanceClass : NSObject {
269 ClassWithOwnIvarInstanceClass *_ivar;
270 NSUInteger _retainCount;
274 @implementation ClassWithOwnIvarInstanceClass
275 - (instancetype)retain {
279 - (oneway void)release {
286 [super dealloc]; // no warning: different instances of same class
290 //===------------------------------------------------------------------------===
291 // Do not warn about calling [super dealloc] twice if +dealloc is a class
294 @interface SuperDeallocClassMethodIgnoredClass : NSObject { }
298 @implementation SuperDeallocClassMethodIgnoredClass
302 @interface SuperDeallocClassMethodIgnoredSubClass : NSObject { }
306 @implementation SuperDeallocClassMethodIgnoredSubClass
309 [super dealloc]; // no warning: class method
313 //===------------------------------------------------------------------------===
314 // Do not warn about calling [super dealloc] twice if when the analyzer has
315 // inlined the call to its super deallocator.
317 @interface SuperClassCallingSuperDealloc : NSObject {
322 @implementation SuperClassCallingSuperDealloc
324 [_ivar release]; // no-warning
330 @interface SubclassCallingSuperDealloc : SuperClassCallingSuperDealloc
333 @implementation SubclassCallingSuperDealloc
339 //===------------------------------------------------------------------------===
340 // Treat calling [super dealloc] twice as as a sink.
342 @interface CallingSuperDeallocTwiceIsSink : NSObject
345 @implementation CallingSuperDeallocTwiceIsSink
347 [super dealloc]; // expected-note {{[super dealloc] called here}}
348 [super dealloc]; // expected-warning {{[super dealloc] should not be called multiple times}}
349 // expected-note@-1 {{[super dealloc] should not be called multiple times}}
351 clang_analyzer_warnIfReached(); // no-warning
356 //===------------------------------------------------------------------------===
357 // Test path notes with intervening method call on self.
359 @interface InterveningMethodCallOnSelf : NSObject
362 @implementation InterveningMethodCallOnSelf
363 - (void)anotherMethod {
367 [super dealloc]; // expected-note {{[super dealloc] called here}}
368 [self anotherMethod]; // expected-warning {{Use of 'self' after it has been deallocated}}
369 // expected-note@-1 {{Use of 'self' after it has been deallocated}}