comparison clang/test/Analysis/DeallocUseAfterFreeErrors.m @ 150:1d019706d866

LLVM10
author anatofuz
date Thu, 13 Feb 2020 15:10:13 +0900
parents
children c4bab56944e8
comparison
equal deleted inserted replaced
147:c2174574ed3a 150:1d019706d866
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.SuperDealloc,debug.ExprInspection -analyzer-output=text -verify %s
2
3 void clang_analyzer_warnIfReached();
4
5 #define nil ((id)0)
6
7 typedef 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
18 typedef 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 {
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}}
41 }
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 {
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}}
61 }
62 @end
63
64
65 struct 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}}
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}}
79 }
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}}
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}}
98 }
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}}
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}}
111 }
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 {
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}}
130 }
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 {
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}}
149 }
150 @end
151
152 @interface SuperDeallocThenCallInstanceMethodClass : NSObject { }
153 - (void)_invalidate;
154 @end
155
156 @implementation SuperDeallocThenCallInstanceMethodClass
157 - (void)_invalidate {
158 }
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}}
163 }
164 @end
165
166 @interface SuperDeallocThenCallNonObjectiveCMethodClass : NSObject { }
167 @end
168
169 static void _invalidate(NSObject *object) {
170 (void)object;
171 }
172
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}}
178 }
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}}
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}}
192 }
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 {
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}}
213 }
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 {
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}}
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
318 @interface SuperClassCallingSuperDealloc : NSObject {
319 NSObject *_ivar;
320 }
321 @end
322
323 @implementation SuperClassCallingSuperDealloc
324 - (void)dealloc; {
325 [_ivar release]; // no-warning
326
327 [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}}
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];
372 }
373 @end