Mercurial > hg > CbC > CbC_llvm
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 |