[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / DeallocUseAfterFreeErrors.m
blobc20aebc89c5c02103d681596babf2ab28ef851e1
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 //  <rdar://problem/6953275>
22 //  Check that 'self' is not referenced after calling '[super dealloc]'.
24 @interface SuperDeallocThenReleaseIvarClass : NSObject {
25   NSObject *_ivar;
27 @end
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;
37 - (void)dealloc {
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}}
42 @end
44 @interface SuperDeallocThenAssignNilToIvarClass : NSObject {
45   NSObject *_delegate;
47 @end
49 @implementation SuperDeallocThenAssignNilToIvarClass
50 - (instancetype)initWithDelegate:(NSObject *)delegate {
51   self = [super init];
52   if (!self)
53     return nil;
54   _delegate = delegate;
55   return self;
57 - (void)dealloc {
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}}
62 @end
65 struct SomeStruct {
66   int f;
69 @interface SuperDeallocThenAssignIvarField : NSObject {
70   struct SomeStruct _s;
72 @end
74 @implementation SuperDeallocThenAssignIvarField
75 - (void)dealloc {
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}}
80 @end
82 @interface OtherClassWithIvar {
83 @public
84   int _otherIvar;
86 @end;
88 @interface SuperDeallocThenAssignIvarIvar : NSObject {
89   OtherClassWithIvar *_ivar;
91 @end
93 @implementation SuperDeallocThenAssignIvarIvar
94 - (void)dealloc {
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}}
99 @end
101 @interface SuperDeallocThenAssignSelfIvar : NSObject {
102   NSObject *_ivar;
104 @end
106 @implementation SuperDeallocThenAssignSelfIvar
107 - (void)dealloc {
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}}
112 @end
114 @interface SuperDeallocThenReleasePropertyClass : NSObject { }
115 @property (retain) NSObject *ivar;
116 @end
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;
126 - (void)dealloc {
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}}
131 @end
133 @interface SuperDeallocThenAssignNilToPropertyClass : NSObject { }
134 @property (assign) NSObject *delegate;
135 @end
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;
145 - (void)dealloc {
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}}
150 @end
152 @interface SuperDeallocThenCallInstanceMethodClass : NSObject { }
153 - (void)_invalidate;
154 @end
156 @implementation SuperDeallocThenCallInstanceMethodClass
157 - (void)_invalidate {
159 - (void)dealloc {
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}}
164 @end
166 @interface SuperDeallocThenCallNonObjectiveCMethodClass : NSObject { }
167 @end
169 static void _invalidate(NSObject *object) {
170   (void)object;
173 @implementation SuperDeallocThenCallNonObjectiveCMethodClass
174 - (void)dealloc {
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}}
179 @end
181 @interface SuperDeallocThenCallObjectiveClassMethodClass : NSObject { }
182 @end
184 @implementation SuperDeallocThenCallObjectiveClassMethodClass
185 + (void) invalidate:(id)arg; {
188 - (void)dealloc {
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}}
193 @end
195 @interface TwoSuperDeallocCallsClass : NSObject {
196   NSObject *_ivar;
198 - (void)_invalidate;
199 @end
201 @implementation TwoSuperDeallocCallsClass
202 - (void)_invalidate {
204 - (void)dealloc {
205   if (_ivar) { // expected-note {{Assuming the condition is false}} expected-note {{Taking false branch}}
206     [_ivar release];
207     [super dealloc];
208     return;
209   }
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}}
214 @end
216 //===------------------------------------------------------------------------===
217 // Warn about calling [super dealloc] twice due to missing return statement.
219 @interface MissingReturnCausesDoubleSuperDeallocClass : NSObject {
220   NSObject *_ivar;
222 @end
224 @implementation MissingReturnCausesDoubleSuperDeallocClass
225 - (void)dealloc {
226   if (_ivar) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}
227     [_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}}
234 @end
236 //===------------------------------------------------------------------------===
237 // Warn about calling [super dealloc] twice in two different methods.
239 @interface SuperDeallocInOtherMethodClass : NSObject {
240   NSObject *_ivar;
242 - (void)_cleanup;
243 @end
245 @implementation SuperDeallocInOtherMethodClass
246 - (void)_cleanup {
247   [_ivar release];
248   [super dealloc]; // expected-note {{[super dealloc] called here}}
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}}
256 @end
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;
273 @end
275 @implementation ClassWithOwnIvarInstanceClass
276 - (instancetype)retain {
277   ++_retainCount;
278   return self;
280 - (oneway void)release {
281   --_retainCount;
282   if (!_retainCount)
283     [self dealloc];
285 - (void)dealloc {
286   [_ivar release];
287   [super dealloc]; // no warning: different instances of same class
289 @end
291 //===------------------------------------------------------------------------===
292 // Do not warn about calling [super dealloc] twice if +dealloc is a class
293 // method.
295 @interface SuperDeallocClassMethodIgnoredClass : NSObject { }
296 + (void)dealloc;
297 @end
299 @implementation SuperDeallocClassMethodIgnoredClass
300 + (void)dealloc { }
301 @end
303 @interface SuperDeallocClassMethodIgnoredSubClass : NSObject { }
304 + (void)dealloc;
305 @end
307 @implementation SuperDeallocClassMethodIgnoredSubClass
308 + (void)dealloc {
309   [super dealloc];
310   [super dealloc]; // no warning: class method
312 @end
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 {
319   NSObject *_ivar;
321 @end
323 @implementation SuperClassCallingSuperDealloc
324 - (void)dealloc; {
325   [_ivar release]; // no-warning
327   [super dealloc];
329 @end
331 @interface SubclassCallingSuperDealloc : SuperClassCallingSuperDealloc
332 @end
334 @implementation SubclassCallingSuperDealloc
335 - (void)dealloc; {
336   [super dealloc];
338 @end
340 //===------------------------------------------------------------------------===
341 // Treat calling [super dealloc] twice as as a sink.
343 @interface CallingSuperDeallocTwiceIsSink : NSObject
344 @end
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}}
352   clang_analyzer_warnIfReached(); // no-warning
354 @end
357 //===------------------------------------------------------------------------===
358 // Test path notes with intervening method call on self.
360 @interface InterveningMethodCallOnSelf : NSObject
361 @end
363 @implementation InterveningMethodCallOnSelf
364 - (void)anotherMethod {
367 - (void)dealloc; {
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}}
371   [super dealloc];
373 @end