Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Analysis / DeallocUseAfterFreeErrors.m
bloba7b6c8346140152a3fef8d666d2aa49b3f172fea
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.SuperDealloc,debug.ExprInspection -analyzer-output=text -verify %s
3 void clang_analyzer_warnIfReached(void);
5 #define nil ((id)0)
7 typedef unsigned long NSUInteger;
8 @protocol NSObject
9 - (instancetype)retain;
10 - (oneway void)release;
11 @end
13 @interface NSObject <NSObject> { }
14 - (void)dealloc;
15 - (instancetype)init;
16 @end
18 typedef struct objc_selector *SEL;
20 //===------------------------------------------------------------------------===
21 //  Check that 'self' is not referenced after calling '[super dealloc]'.
23 @interface SuperDeallocThenReleaseIvarClass : NSObject {
24   NSObject *_ivar;
26 @end
28 @implementation SuperDeallocThenReleaseIvarClass
29 - (instancetype)initWithIvar:(NSObject *)ivar {
30   self = [super init];
31   if (!self)
32     return nil;
33   _ivar = [ivar retain];
34   return self;
36 - (void)dealloc {
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}}
41 @end
43 @interface SuperDeallocThenAssignNilToIvarClass : NSObject {
44   NSObject *_delegate;
46 @end
48 @implementation SuperDeallocThenAssignNilToIvarClass
49 - (instancetype)initWithDelegate:(NSObject *)delegate {
50   self = [super init];
51   if (!self)
52     return nil;
53   _delegate = delegate;
54   return self;
56 - (void)dealloc {
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}}
61 @end
64 struct SomeStruct {
65   int f;
68 @interface SuperDeallocThenAssignIvarField : NSObject {
69   struct SomeStruct _s;
71 @end
73 @implementation SuperDeallocThenAssignIvarField
74 - (void)dealloc {
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}}
79 @end
81 @interface OtherClassWithIvar {
82 @public
83   int _otherIvar;
85 @end;
87 @interface SuperDeallocThenAssignIvarIvar : NSObject {
88   OtherClassWithIvar *_ivar;
90 @end
92 @implementation SuperDeallocThenAssignIvarIvar
93 - (void)dealloc {
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}}
98 @end
100 @interface SuperDeallocThenAssignSelfIvar : NSObject {
101   NSObject *_ivar;
103 @end
105 @implementation SuperDeallocThenAssignSelfIvar
106 - (void)dealloc {
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}}
111 @end
113 @interface SuperDeallocThenReleasePropertyClass : NSObject { }
114 @property (retain) NSObject *ivar;
115 @end
117 @implementation SuperDeallocThenReleasePropertyClass
118 - (instancetype)initWithProperty:(NSObject *)ivar {
119   self = [super init];
120   if (!self)
121     return nil;
122   self.ivar = ivar;
123   return self;
125 - (void)dealloc {
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}}
130 @end
132 @interface SuperDeallocThenAssignNilToPropertyClass : NSObject { }
133 @property (assign) NSObject *delegate;
134 @end
136 @implementation SuperDeallocThenAssignNilToPropertyClass
137 - (instancetype)initWithDelegate:(NSObject *)delegate {
138   self = [super init];
139   if (!self)
140     return nil;
141   self.delegate = delegate;
142   return self;
144 - (void)dealloc {
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}}
149 @end
151 @interface SuperDeallocThenCallInstanceMethodClass : NSObject { }
152 - (void)_invalidate;
153 @end
155 @implementation SuperDeallocThenCallInstanceMethodClass
156 - (void)_invalidate {
158 - (void)dealloc {
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}}
163 @end
165 @interface SuperDeallocThenCallNonObjectiveCMethodClass : NSObject { }
166 @end
168 static void _invalidate(NSObject *object) {
169   (void)object;
172 @implementation SuperDeallocThenCallNonObjectiveCMethodClass
173 - (void)dealloc {
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}}
178 @end
180 @interface SuperDeallocThenCallObjectiveClassMethodClass : NSObject { }
181 @end
183 @implementation SuperDeallocThenCallObjectiveClassMethodClass
184 + (void) invalidate:(id)arg; {
187 - (void)dealloc {
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}}
192 @end
194 @interface TwoSuperDeallocCallsClass : NSObject {
195   NSObject *_ivar;
197 - (void)_invalidate;
198 @end
200 @implementation TwoSuperDeallocCallsClass
201 - (void)_invalidate {
203 - (void)dealloc {
204   if (_ivar) { // expected-note {{Assuming the condition is false}} expected-note {{Taking false branch}}
205     [_ivar release];
206     [super dealloc];
207     return;
208   }
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}}
213 @end
215 //===------------------------------------------------------------------------===
216 // Warn about calling [super dealloc] twice due to missing return statement.
218 @interface MissingReturnCausesDoubleSuperDeallocClass : NSObject {
219   NSObject *_ivar;
221 @end
223 @implementation MissingReturnCausesDoubleSuperDeallocClass
224 - (void)dealloc {
225   if (_ivar) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}
226     [_ivar release];
227     [super dealloc]; // expected-note {{[super dealloc] called here}}
228     // return;
229   }
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}}
233 @end
235 //===------------------------------------------------------------------------===
236 // Warn about calling [super dealloc] twice in two different methods.
238 @interface SuperDeallocInOtherMethodClass : NSObject {
239   NSObject *_ivar;
241 - (void)_cleanup;
242 @end
244 @implementation SuperDeallocInOtherMethodClass
245 - (void)_cleanup {
246   [_ivar release];
247   [super dealloc]; // expected-note {{[super dealloc] called here}}
249 - (void)dealloc {
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}}
255 @end
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;
272 @end
274 @implementation ClassWithOwnIvarInstanceClass
275 - (instancetype)retain {
276   ++_retainCount;
277   return self;
279 - (oneway void)release {
280   --_retainCount;
281   if (!_retainCount)
282     [self dealloc];
284 - (void)dealloc {
285   [_ivar release];
286   [super dealloc]; // no warning: different instances of same class
288 @end
290 //===------------------------------------------------------------------------===
291 // Do not warn about calling [super dealloc] twice if +dealloc is a class
292 // method.
294 @interface SuperDeallocClassMethodIgnoredClass : NSObject { }
295 + (void)dealloc;
296 @end
298 @implementation SuperDeallocClassMethodIgnoredClass
299 + (void)dealloc { }
300 @end
302 @interface SuperDeallocClassMethodIgnoredSubClass : NSObject { }
303 + (void)dealloc;
304 @end
306 @implementation SuperDeallocClassMethodIgnoredSubClass
307 + (void)dealloc {
308   [super dealloc];
309   [super dealloc]; // no warning: class method
311 @end
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 {
318   NSObject *_ivar;
320 @end
322 @implementation SuperClassCallingSuperDealloc
323 - (void)dealloc; {
324   [_ivar release]; // no-warning
326   [super dealloc];
328 @end
330 @interface SubclassCallingSuperDealloc : SuperClassCallingSuperDealloc
331 @end
333 @implementation SubclassCallingSuperDealloc
334 - (void)dealloc; {
335   [super dealloc];
337 @end
339 //===------------------------------------------------------------------------===
340 // Treat calling [super dealloc] twice as as a sink.
342 @interface CallingSuperDeallocTwiceIsSink : NSObject
343 @end
345 @implementation CallingSuperDeallocTwiceIsSink
346 - (void)dealloc; {
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
353 @end
356 //===------------------------------------------------------------------------===
357 // Test path notes with intervening method call on self.
359 @interface InterveningMethodCallOnSelf : NSObject
360 @end
362 @implementation InterveningMethodCallOnSelf
363 - (void)anotherMethod {
366 - (void)dealloc; {
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}}
370   [super dealloc];
372 @end