1 | // RUN: %clang_analyze_cc1 -analyzer-checker=osx.cocoa.Dealloc -fblocks -triple x86_64-apple-ios4.0 -DMACOS=0 -verify %s |
2 | // RUN: %clang_analyze_cc1 -analyzer-checker=osx.cocoa.Dealloc -fblocks -triple x86_64-apple-macosx10.6.0 -DMACOS=1 -verify %s |
3 | // RUN: %clang_analyze_cc1 -analyzer-checker=osx.cocoa.Dealloc -fblocks -triple x86_64-apple-darwin10 -fobjc-arc -fobjc-runtime-has-weak -verify %s |
4 | |
5 | #include "Inputs/system-header-simulator-for-objc-dealloc.h" |
6 | |
7 | #define NON_ARC !__has_feature(objc_arc) |
8 | |
9 | #if NON_ARC |
10 | #define WEAK_ON_ARC |
11 | #else |
12 | #define WEAK_ON_ARC __weak |
13 | #endif |
14 | |
15 | // No diagnostics expected under ARC. |
16 | #if !NON_ARC |
17 | // expected-no-diagnostics |
18 | #endif |
19 | |
20 | // Do not warn about missing release in -dealloc for ivars. |
21 | |
22 | @interface MyIvarClass1 : NSObject { |
23 | NSObject *_ivar; |
24 | } |
25 | @end |
26 | |
27 | @implementation MyIvarClass1 |
28 | - (instancetype)initWithIvar:(NSObject *)ivar |
29 | { |
30 | self = [super init]; |
31 | if (!self) |
32 | return nil; |
33 | #if NON_ARC |
34 | _ivar = [ivar retain]; |
35 | #endif |
36 | return self; |
37 | } |
38 | - (void)dealloc |
39 | { |
40 | #if NON_ARC |
41 | [super dealloc]; |
42 | #endif |
43 | } |
44 | @end |
45 | |
46 | @interface MyIvarClass2 : NSObject { |
47 | NSObject *_ivar; |
48 | } |
49 | - (NSObject *)ivar; |
50 | - (void)setIvar:(NSObject *)ivar; |
51 | @end |
52 | |
53 | @implementation MyIvarClass2 |
54 | - (instancetype)init |
55 | { |
56 | self = [super init]; |
57 | return self; |
58 | } |
59 | - (void)dealloc |
60 | { |
61 | #if NON_ARC |
62 | [super dealloc]; |
63 | #endif |
64 | } |
65 | - (NSObject *)ivar |
66 | { |
67 | return _ivar; |
68 | } |
69 | - (void)setIvar:(NSObject *)ivar |
70 | { |
71 | #if NON_ARC |
72 | [_ivar release]; |
73 | _ivar = [ivar retain]; |
74 | #else |
75 | _ivar = ivar; |
76 | #endif |
77 | } |
78 | @end |
79 | |
80 | // Warn about missing release in -dealloc for properties. |
81 | |
82 | @interface MyPropertyClass1 : NSObject |
83 | @property (copy) NSObject *ivar; |
84 | @end |
85 | |
86 | @implementation MyPropertyClass1 |
87 | - (void)dealloc |
88 | { |
89 | #if NON_ARC |
90 | [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass1' was copied by a synthesized property but not released before '[super dealloc]'}} |
91 | #endif |
92 | } |
93 | @end |
94 | |
95 | @interface MyPropertyClass2 : NSObject |
96 | @property (retain) NSObject *ivar; |
97 | @end |
98 | |
99 | @implementation MyPropertyClass2 |
100 | - (void)dealloc |
101 | { |
102 | #if NON_ARC |
103 | [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass2' was retained by a synthesized property but not released before '[super dealloc]'}} |
104 | #endif |
105 | } |
106 | @end |
107 | |
108 | @interface MyPropertyClass3 : NSObject { |
109 | NSObject *_ivar; |
110 | } |
111 | @property (retain) NSObject *ivar; |
112 | @end |
113 | |
114 | @implementation MyPropertyClass3 |
115 | @synthesize ivar = _ivar; |
116 | - (void)dealloc |
117 | { |
118 | #if NON_ARC |
119 | [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass3' was retained by a synthesized property but not released before '[super dealloc]'}} |
120 | #endif |
121 | } |
122 | |
123 | @end |
124 | |
125 | @interface MyPropertyClass4 : NSObject { |
126 | void (^_blockPropertyIvar)(void); |
127 | } |
128 | @property (copy) void (^blockProperty)(void); |
129 | @property (copy) void (^blockProperty2)(void); |
130 | @property (copy) void (^blockProperty3)(void); |
131 | |
132 | @end |
133 | |
134 | @implementation MyPropertyClass4 |
135 | @synthesize blockProperty = _blockPropertyIvar; |
136 | - (void)dealloc |
137 | { |
138 | #if NON_ARC |
139 | [_blockProperty2 release]; |
140 | Block_release(_blockProperty3); |
141 | |
142 | [super dealloc]; // expected-warning {{The '_blockPropertyIvar' ivar in 'MyPropertyClass4' was copied by a synthesized property but not released before '[super dealloc]'}} |
143 | #endif |
144 | } |
145 | @end |
146 | |
147 | @interface MyPropertyClass5 : NSObject { |
148 | WEAK_ON_ARC NSObject *_ivar; |
149 | } |
150 | @property (weak) NSObject *ivar; |
151 | @end |
152 | |
153 | @implementation MyPropertyClass5 |
154 | @synthesize ivar = _ivar; |
155 | - (void)dealloc |
156 | { |
157 | #if NON_ARC |
158 | [super dealloc]; // no-warning because it is a weak property |
159 | #endif |
160 | } |
161 | @end |
162 | |
163 | @interface MyPropertyClassWithReturnInDealloc : NSObject { |
164 | NSObject *_ivar; |
165 | } |
166 | @property (retain) NSObject *ivar; |
167 | @end |
168 | |
169 | @implementation MyPropertyClassWithReturnInDealloc |
170 | @synthesize ivar = _ivar; |
171 | - (void)dealloc |
172 | { |
173 | return; |
174 | #if NON_ARC |
175 | // expected-warning@-2{{The '_ivar' ivar in 'MyPropertyClassWithReturnInDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} |
176 | [super dealloc]; |
177 | #endif |
178 | } |
179 | @end |
180 | |
181 | @interface MyPropertyClassWithReleaseInOtherInstance : NSObject { |
182 | NSObject *_ivar; |
183 | MyPropertyClassWithReleaseInOtherInstance *_other; |
184 | } |
185 | @property (retain) NSObject *ivar; |
186 | |
187 | -(void)releaseIvars; |
188 | @end |
189 | |
190 | @implementation MyPropertyClassWithReleaseInOtherInstance |
191 | @synthesize ivar = _ivar; |
192 | |
193 | -(void)releaseIvars; { |
194 | #if NON_ARC |
195 | [_ivar release]; |
196 | #endif |
197 | } |
198 | |
199 | - (void)dealloc |
200 | { |
201 | [_other releaseIvars]; |
202 | #if NON_ARC |
203 | [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClassWithReleaseInOtherInstance' was retained by a synthesized property but not released before '[super dealloc]'}} |
204 | #endif |
205 | } |
206 | @end |
207 | |
208 | @interface MyPropertyClassWithNeitherReturnNorSuperDealloc : NSObject { |
209 | NSObject *_ivar; |
210 | } |
211 | @property (retain) NSObject *ivar; |
212 | @end |
213 | |
214 | @implementation MyPropertyClassWithNeitherReturnNorSuperDealloc |
215 | @synthesize ivar = _ivar; |
216 | - (void)dealloc |
217 | { |
218 | } |
219 | #if NON_ARC |
220 | // expected-warning@-2 {{method possibly missing a [super dealloc] call}} (From Sema) |
221 | // expected-warning@-3{{The '_ivar' ivar in 'MyPropertyClassWithNeitherReturnNorSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} |
222 | #endif |
223 | @end |
224 | |
225 | // <rdar://problem/6380411>: 'myproperty' has kind 'assign' and thus the |
226 | // assignment through the setter does not perform a release. |
227 | |
228 | @interface MyObject : NSObject { |
229 | id __unsafe_unretained _myproperty; |
230 | } |
231 | @property(assign) id myproperty; |
232 | @end |
233 | |
234 | @implementation MyObject |
235 | @synthesize myproperty=_myproperty; // no-warning |
236 | - (void)dealloc { |
237 | // Don't claim that myproperty is released since it the property |
238 | // has the 'assign' attribute. |
239 | self.myproperty = 0; // no-warning |
240 | #if NON_ARC |
241 | [super dealloc]; |
242 | #endif |
243 | } |
244 | @end |
245 | |
246 | @interface ClassWithControlFlowInRelease : NSObject { |
247 | BOOL _ivar1; |
248 | } |
249 | @property (retain) NSObject *ivar2; |
250 | @end |
251 | |
252 | @implementation ClassWithControlFlowInRelease |
253 | - (void)dealloc; { |
254 | if (_ivar1) { |
255 | // We really should warn because there is a path through -dealloc on which |
256 | // _ivar2 is not released. |
257 | #if NON_ARC |
258 | [_ivar2 release]; |
259 | #endif |
260 | } |
261 | |
262 | #if NON_ARC |
263 | [super dealloc]; // expected-warning {{The '_ivar2' ivar in 'ClassWithControlFlowInRelease' was retained by a synthesized property but not released before '[super dealloc]'}} |
264 | #endif |
265 | } |
266 | @end |
267 | |
268 | // Don't warn when the property is nil'd out in -dealloc |
269 | |
270 | @interface ClassWithNildOutProperty : NSObject |
271 | @property (retain) NSObject *ivar; |
272 | @property (assign) int *intPtrProp; |
273 | @end |
274 | |
275 | @implementation ClassWithNildOutProperty |
276 | - (void)dealloc; { |
277 | self.ivar = nil; |
278 | |
279 | // Make sure to handle setting a non-retainable property to 0. |
280 | self.intPtrProp = 0; |
281 | #if NON_ARC |
282 | [super dealloc]; // no-warning |
283 | #endif |
284 | } |
285 | @end |
286 | |
287 | // Do warn when the ivar but not the property is nil'd out in -dealloc |
288 | |
289 | @interface ClassWithNildOutIvar : NSObject |
290 | @property (retain) NSObject *ivar; |
291 | @end |
292 | |
293 | @implementation ClassWithNildOutIvar |
294 | - (void)dealloc; { |
295 | // Oops. Meant self.ivar = nil |
296 | _ivar = nil; |
297 | |
298 | #if NON_ARC |
299 | [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWithNildOutIvar' was retained by a synthesized property but not released before '[super dealloc]'}} |
300 | #endif |
301 | } |
302 | @end |
303 | |
304 | // Do warn when the ivar is updated to a different value that is then |
305 | // released. |
306 | |
307 | @interface ClassWithUpdatedIvar : NSObject |
308 | @property (retain) NSObject *ivar; |
309 | @end |
310 | |
311 | @implementation ClassWithUpdatedIvar |
312 | - (void)dealloc; { |
313 | _ivar = [[NSObject alloc] init]; |
314 | |
315 | #if NON_ARC |
316 | [_ivar release]; |
317 | #endif |
318 | |
319 | #if NON_ARC |
320 | [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWithUpdatedIvar' was retained by a synthesized property but not released before '[super dealloc]'}} |
321 | #endif |
322 | } |
323 | @end |
324 | |
325 | |
326 | // Don't warn when the property is nil'd out with a setter in -dealloc |
327 | |
328 | @interface ClassWithNildOutPropertyViaSetter : NSObject |
329 | @property (retain) NSObject *ivar; |
330 | @end |
331 | |
332 | @implementation ClassWithNildOutPropertyViaSetter |
333 | - (void)dealloc; { |
334 | [self setIvar:nil]; |
335 | |
336 | #if NON_ARC |
337 | [super dealloc]; // no-warning |
338 | #endif |
339 | } |
340 | @end |
341 | |
342 | |
343 | // Don't warn about missing releases when -dealloc helpers are called. |
344 | |
345 | @interface ClassWithDeallocHelpers : NSObject |
346 | @property (retain) NSObject *ivarReleasedInMethod; |
347 | @property (retain) NSObject *propNilledOutInMethod; |
348 | |
349 | @property (retain) NSObject *ivarReleasedInFunction; |
350 | @property (retain) NSObject *propNilledOutInFunction; |
351 | |
352 | @property (retain) NSObject *ivarNeverReleased; |
353 | - (void)invalidateInMethod; |
354 | @end |
355 | |
356 | void ReleaseValueHelper(NSObject *iv) { |
357 | #if NON_ARC |
358 | [iv release]; |
359 | #endif |
360 | } |
361 | |
362 | void NilOutPropertyHelper(ClassWithDeallocHelpers *o) { |
363 | o.propNilledOutInFunction = nil; |
364 | } |
365 | |
366 | @implementation ClassWithDeallocHelpers |
367 | - (void)invalidateInMethod { |
368 | #if NON_ARC |
369 | [_ivarReleasedInMethod release]; |
370 | #endif |
371 | self.propNilledOutInMethod = nil; |
372 | } |
373 | |
374 | - (void)dealloc; { |
375 | ReleaseValueHelper(_ivarReleasedInFunction); |
376 | NilOutPropertyHelper(self); |
377 | |
378 | [self invalidateInMethod]; |
379 | #if NON_ARC |
380 | [super dealloc]; // expected-warning {{The '_ivarNeverReleased' ivar in 'ClassWithDeallocHelpers' was retained by a synthesized property but not released before '[super dealloc]'}} |
381 | #endif |
382 | } |
383 | @end |
384 | |
385 | |
386 | // Don't warn when self in -dealloc escapes. |
387 | |
388 | @interface ClassWhereSelfEscapesViaMethodCall : NSObject |
389 | @property (retain) NSObject *ivar; // no-warning |
390 | @end |
391 | |
392 | @interface ClassWhereSelfEscapesViaMethodCall (Other) |
393 | - (void)invalidate; // In other translation unit. |
394 | @end |
395 | |
396 | @implementation ClassWhereSelfEscapesViaMethodCall |
397 | - (void)dealloc; { |
398 | [self invalidate]; |
399 | #if NON_ARC |
400 | [super dealloc]; |
401 | #endif |
402 | } // no-warning |
403 | @end |
404 | |
405 | @interface ClassWhereSelfEscapesViaPropertyAccess : NSObject |
406 | @property (retain) NSObject *ivar; |
407 | @end |
408 | |
409 | @interface ClassWhereSelfEscapesViaPropertyAccess (Other) |
410 | // The implementation of this property is unknown and therefore could |
411 | // release ivar. |
412 | @property (retain) NSObject *otherIvar; |
413 | @end |
414 | |
415 | @implementation ClassWhereSelfEscapesViaPropertyAccess |
416 | - (void)dealloc; { |
417 | self.otherIvar = nil; |
418 | #if NON_ARC |
419 | [super dealloc]; |
420 | #endif |
421 | } // no-warning |
422 | @end |
423 | |
424 | // Don't treat self as escaping when setter called on *synthesized* |
425 | // property. |
426 | |
427 | @interface ClassWhereSelfEscapesViaSynthesizedPropertyAccess : NSObject |
428 | @property (retain) NSObject *ivar; |
429 | @property (retain) NSObject *otherIvar; |
430 | @end |
431 | |
432 | @implementation ClassWhereSelfEscapesViaSynthesizedPropertyAccess |
433 | - (void)dealloc; { |
434 | self.otherIvar = nil; |
435 | #if NON_ARC |
436 | [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWhereSelfEscapesViaSynthesizedPropertyAccess' was retained by a synthesized property but not released before '[super dealloc]'}} |
437 | #endif |
438 | } |
439 | @end |
440 | |
441 | |
442 | // Don't treat calls to system headers as escapes |
443 | |
444 | @interface ClassWhereSelfEscapesViaCallToSystem : NSObject |
445 | @property (retain) NSObject *ivar1; |
446 | @property (retain) NSObject *ivar2; |
447 | @property (retain) NSObject *ivar3; |
448 | @property (retain) NSObject *ivar4; |
449 | @property (retain) NSObject *ivar5; |
450 | @property (retain) NSObject *ivar6; |
451 | @end |
452 | |
453 | @implementation ClassWhereSelfEscapesViaCallToSystem |
454 | - (void)dealloc; { |
455 | #if NON_ARC |
456 | [_ivar2 release]; |
457 | if (_ivar3) { |
458 | [_ivar3 release]; |
459 | } |
460 | #endif |
461 | |
462 | [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self]; |
463 | [[NSNotificationCenter defaultCenter] removeObserver:self]; |
464 | |
465 | #if NON_ARC |
466 | [_ivar4 release]; |
467 | |
468 | if (_ivar5) { |
469 | [_ivar5 release]; |
470 | } |
471 | #endif |
472 | |
473 | [[NSNotificationCenter defaultCenter] removeObserver:self]; |
474 | |
475 | #if NON_ARC |
476 | if (_ivar6) { |
477 | [_ivar6 release]; |
478 | } |
479 | |
480 | [super dealloc]; // expected-warning {{The '_ivar1' ivar in 'ClassWhereSelfEscapesViaCallToSystem' was retained by a synthesized property but not released before '[super dealloc]'}} |
481 | #endif |
482 | } |
483 | @end |
484 | |
485 | // Don't warn when value escapes. |
486 | |
487 | @interface ClassWhereIvarValueEscapes : NSObject |
488 | @property (retain) NSObject *ivar; |
489 | @end |
490 | |
491 | void ReleaseMe(id arg); |
492 | |
493 | @implementation ClassWhereIvarValueEscapes |
494 | - (void)dealloc; { |
495 | |
496 | ReleaseMe(_ivar); |
497 | |
498 | #if NON_ARC |
499 | [super dealloc]; |
500 | #endif |
501 | } // no-warning |
502 | @end |
503 | |
504 | // Don't warn when value is known to be nil. |
505 | |
506 | @interface ClassWhereIvarIsNil : NSObject |
507 | @property (retain) NSObject *ivarIsNil; |
508 | @end |
509 | |
510 | @implementation ClassWhereIvarIsNil |
511 | - (void)dealloc; { |
512 | |
513 | #if NON_ARC |
514 | if (_ivarIsNil) |
515 | [_ivarIsNil release]; |
516 | |
517 | [super dealloc]; |
518 | #endif |
519 | } // no-warning |
520 | @end |
521 | |
522 | |
523 | // Don't warn for non-retainable properties. |
524 | |
525 | @interface ClassWithNonRetainableProperty : NSObject |
526 | @property (assign) int *ivar; // no-warning |
527 | @end |
528 | |
529 | @implementation ClassWithNonRetainableProperty |
530 | - (void)dealloc; { |
531 | #if NON_ARC |
532 | [super dealloc]; |
533 | #endif |
534 | } // no-warning |
535 | @end |
536 | |
537 | |
538 | @interface SuperClassOfClassWithInlinedSuperDealloc : NSObject |
539 | @property (retain) NSObject *propInSuper; |
540 | @end |
541 | |
542 | @implementation SuperClassOfClassWithInlinedSuperDealloc |
543 | - (void)dealloc { |
544 | #if NON_ARC |
545 | [super dealloc]; // expected-warning {{The '_propInSuper' ivar in 'SuperClassOfClassWithInlinedSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} |
546 | #endif |
547 | } |
548 | @end |
549 | |
550 | @interface ClassWithInlinedSuperDealloc : SuperClassOfClassWithInlinedSuperDealloc |
551 | @property (retain) NSObject *propInSub; |
552 | @end |
553 | |
554 | @implementation ClassWithInlinedSuperDealloc |
555 | - (void)dealloc { |
556 | #if NON_ARC |
557 | [super dealloc]; // expected-warning {{The '_propInSub' ivar in 'ClassWithInlinedSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} |
558 | #endif |
559 | } |
560 | @end |
561 | |
562 | |
563 | @interface SuperClassOfClassWithInlinedSuperDeallocAndInvalidation : NSObject |
564 | @property (retain) NSObject *propInSuper; |
565 | |
566 | - (void)invalidate; |
567 | @end |
568 | |
569 | @implementation SuperClassOfClassWithInlinedSuperDeallocAndInvalidation |
570 | |
571 | - (void)invalidate { |
572 | #if NON_ARC |
573 | [_propInSuper release]; |
574 | #endif |
575 | _propInSuper = nil; |
576 | } |
577 | |
578 | - (void)dealloc { |
579 | [self invalidate]; |
580 | #if NON_ARC |
581 | [super dealloc]; // no-warning |
582 | #endif |
583 | } |
584 | @end |
585 | |
586 | @interface ClassWithInlinedSuperDeallocAndInvalidation : SuperClassOfClassWithInlinedSuperDeallocAndInvalidation |
587 | @property (retain) NSObject *propInSub; |
588 | @end |
589 | |
590 | @implementation ClassWithInlinedSuperDeallocAndInvalidation |
591 | |
592 | - (void)invalidate { |
593 | #if NON_ARC |
594 | [_propInSub release]; |
595 | #endif |
596 | [super invalidate]; |
597 | } |
598 | |
599 | - (void)dealloc { |
600 | #if NON_ARC |
601 | [super dealloc]; // no-warning |
602 | #endif |
603 | } |
604 | @end |
605 | |
606 | |
607 | @interface SuperClassOfClassThatEscapesBeforeInliningSuper : NSObject |
608 | @property (retain) NSObject *propInSuper; |
609 | @end |
610 | |
611 | @implementation SuperClassOfClassThatEscapesBeforeInliningSuper |
612 | |
613 | - (void)dealloc { |
614 | |
615 | #if NON_ARC |
616 | [super dealloc]; // expected-warning {{The '_propInSuper' ivar in 'SuperClassOfClassThatEscapesBeforeInliningSuper' was retained by a synthesized property but not released before '[super dealloc]'}} |
617 | #endif |
618 | } |
619 | @end |
620 | |
621 | @interface ClassThatEscapesBeforeInliningSuper : SuperClassOfClassThatEscapesBeforeInliningSuper |
622 | @property (retain) NSObject *propInSub; |
623 | @end |
624 | |
625 | @interface ClassThatEscapesBeforeInliningSuper (Other) |
626 | - (void)invalidate; // No implementation in translation unit. |
627 | @end |
628 | |
629 | @implementation ClassThatEscapesBeforeInliningSuper |
630 | - (void)dealloc { |
631 | [self invalidate]; |
632 | |
633 | #if NON_ARC |
634 | [super dealloc]; // no-warning |
635 | #endif |
636 | } |
637 | @end |
638 | |
639 | |
640 | #if NON_ARC |
641 | @interface ReleaseIvarInField : NSObject { |
642 | int _tag; |
643 | union { |
644 | NSObject *field1; |
645 | NSObject *field2; |
646 | } _someUnion; |
647 | |
648 | struct { |
649 | NSObject *field1; |
650 | } _someStruct; |
651 | } |
652 | @end |
653 | |
654 | @implementation ReleaseIvarInField |
655 | - (void)dealloc { |
656 | if (_tag) { |
657 | [_someUnion.field1 release]; |
658 | } else { |
659 | [_someUnion.field2 release]; |
660 | } |
661 | |
662 | [_someStruct.field1 release]; |
663 | [super dealloc]; |
664 | } |
665 | @end |
666 | #endif |
667 | |
668 | struct SomeStruct { |
669 | int f; |
670 | }; |
671 | @interface ZeroOutStructWithSetter : NSObject |
672 | @property(assign) struct SomeStruct s; |
673 | @end |
674 | |
675 | @implementation ZeroOutStructWithSetter |
676 | - (void)dealloc { |
677 | struct SomeStruct zeroedS; |
678 | zeroedS.f = 0; |
679 | |
680 | self.s = zeroedS; |
681 | #if NON_ARC |
682 | [super dealloc]; |
683 | #endif |
684 | } |
685 | @end |
686 | |
687 | #if NON_ARC |
688 | @interface ReleaseIvarInArray : NSObject { |
689 | NSObject *_array[3]; |
690 | } |
691 | @end |
692 | |
693 | @implementation ReleaseIvarInArray |
694 | - (void)dealloc { |
695 | for (int i = 0; i < 3; i++) { |
696 | [_array[i] release]; |
697 | } |
698 | [super dealloc]; |
699 | } |
700 | @end |
701 | #endif |
702 | |
703 | // Don't warn about missing releases for subclasses of SenTestCase or |
704 | // for classes that are not subclasses of NSObject. |
705 | |
706 | @interface SenTestCase : NSObject {} |
707 | @end |
708 | |
709 | @interface MyClassTest : SenTestCase |
710 | @property (retain) NSObject *ivar; |
711 | @end |
712 | |
713 | @implementation MyClassTest |
714 | -(void)tearDown { |
715 | #if NON_ARC |
716 | [_ivar release]; |
717 | #endif |
718 | } |
719 | |
720 | -(void)dealloc; { |
721 | #if NON_ARC |
722 | [super dealloc]; // no-warning |
723 | #endif |
724 | } |
725 | @end |
726 | |
727 | @interface XCTestCase : NSObject {} |
728 | @end |
729 | |
730 | @interface MyClassXCTest : XCTestCase |
731 | @property (retain) NSObject *ivar; |
732 | @end |
733 | |
734 | @implementation MyClassXCTest |
735 | -(void)tearDown { |
736 | #if NON_ARC |
737 | [_ivar release]; |
738 | #endif |
739 | } |
740 | |
741 | -(void)dealloc; { |
742 | #if NON_ARC |
743 | [super dealloc]; // no-warning |
744 | #endif |
745 | } |
746 | @end |
747 | |
748 | |
749 | __attribute__((objc_root_class)) |
750 | @interface NonNSObjectMissingDealloc |
751 | @property (retain) NSObject *ivar; |
752 | @end |
753 | @implementation NonNSObjectMissingDealloc |
754 | -(void)dealloc; { |
755 | |
756 | } |
757 | @end |
758 | |
759 | // Warn about calling -dealloc rather than release by mistake. |
760 | |
761 | @interface CallDeallocOnRetainPropIvar : NSObject { |
762 | NSObject *okToDeallocDirectly; |
763 | } |
764 | |
765 | @property (retain) NSObject *ivar; |
766 | @end |
767 | |
768 | @implementation CallDeallocOnRetainPropIvar |
769 | - (void)dealloc |
770 | { |
771 | #if NON_ARC |
772 | // Only warn for synthesized ivars. |
773 | [okToDeallocDirectly dealloc]; // no-warning |
774 | [_ivar dealloc]; // expected-warning {{'_ivar' should be released rather than deallocated}} |
775 | |
776 | [super dealloc]; |
777 | #endif |
778 | } |
779 | @end |
780 | |
781 | // CIFilter special cases. |
782 | // By design, -[CIFilter dealloc] releases (by calling -setValue: forKey: with |
783 | // 'nil') all ivars (even in its *subclasses*) with names starting with |
784 | // 'input' or that are backed by properties with names starting with 'input'. |
785 | // The Dealloc checker needs to take particular care to not warn about missing |
786 | // releases in this case -- if the user adds a release quiet the |
787 | // warning it may result in an over release. |
788 | |
789 | @interface ImmediateSubCIFilter : CIFilter { |
790 | NSObject *inputIvar; |
791 | NSObject *nonInputIvar; |
792 | NSObject *notPrefixedButBackingPrefixedProperty; |
793 | NSObject *inputPrefixedButBackingNonPrefixedProperty; |
794 | } |
795 | |
796 | @property(retain) NSObject *inputIvar; |
797 | @property(retain) NSObject *nonInputIvar; |
798 | @property(retain) NSObject *inputAutoSynthesizedIvar; |
799 | @property(retain) NSObject *inputExplicitlySynthesizedToNonPrefixedIvar; |
800 | @property(retain) NSObject *nonPrefixedPropertyBackedByExplicitlySynthesizedPrefixedIvar; |
801 | |
802 | @end |
803 | |
804 | @implementation ImmediateSubCIFilter |
805 | @synthesize inputIvar = inputIvar; |
806 | @synthesize nonInputIvar = nonInputIvar; |
807 | @synthesize inputExplicitlySynthesizedToNonPrefixedIvar = notPrefixedButBackingPrefixedProperty; |
808 | @synthesize nonPrefixedPropertyBackedByExplicitlySynthesizedPrefixedIvar = inputPrefixedButBackingNonPrefixedProperty; |
809 | |
810 | - (void)dealloc { |
811 | #if NON_ARC |
812 | // We don't want warnings here for: |
813 | // inputIvar |
814 | // inputAutoSynthesizedIvar |
815 | // inputExplicitlySynthesizedToNonPrefixedIvar |
816 | // inputPrefixedButBackingNonPrefixedProperty |
817 | [super dealloc]; |
818 | // expected-warning@-1 {{The 'nonInputIvar' ivar in 'ImmediateSubCIFilter' was retained by a synthesized property but not released before '[super dealloc]'}} |
819 | #endif |
820 | } |
821 | @end |
822 | |
823 | @interface SubSubCIFilter : CIFilter { |
824 | NSObject *inputIvarInSub; |
825 | } |
826 | |
827 | @property(retain) NSObject *inputIvarInSub; |
828 | @end |
829 | |
830 | @implementation SubSubCIFilter |
831 | @synthesize inputIvarInSub = inputIvarInSub; |
832 | |
833 | - (void)dealloc { |
834 | // Don't warn about inputIvarInSub. |
835 | #if NON_ARC |
836 | [super dealloc]; |
837 | #endif |
838 | } |
839 | @end |
840 | @interface OverreleasingCIFilter : CIFilter { |
841 | NSObject *inputIvar; |
842 | } |
843 | |
844 | @property(retain) NSObject *inputIvar; |
845 | @end |
846 | |
847 | @implementation OverreleasingCIFilter |
848 | @synthesize inputIvar = inputIvar; |
849 | |
850 | - (void)dealloc { |
851 | #if NON_ARC |
852 | // This is an over release because CIFilter's dealloc will also release it. |
853 | [inputIvar release]; // expected-warning {{The 'inputIvar' ivar in 'OverreleasingCIFilter' will be released by '-[CIFilter dealloc]' but also released here}} |
854 | [super dealloc]; // no-warning |
855 | #endif |
856 | } |
857 | @end |
858 | |
859 | |
860 | @interface NotMissingDeallocCIFilter : CIFilter { |
861 | NSObject *inputIvar; |
862 | } |
863 | |
864 | @property(retain) NSObject *inputIvar; |
865 | @end |
866 | |
867 | @implementation NotMissingDeallocCIFilter // no-warning |
868 | @synthesize inputIvar = inputIvar; |
869 | @end |
870 | |
871 | |
872 | @interface ClassWithRetainPropWithIBOutletIvarButNoSetter : NSObject { |
873 | // On macOS, the nib-loading code will set the ivar directly without |
874 | // retaining value (unike iOS, where it is retained). This means that |
875 | // on macOS we should not warn about a missing release for a property backed |
876 | // by an IBOutlet ivar when that property does not have a setter. |
877 | IBOutlet NSObject *ivarForOutlet; |
878 | } |
879 | |
880 | @property (readonly, retain) NSObject *ivarForOutlet; |
881 | @end |
882 | |
883 | @implementation ClassWithRetainPropWithIBOutletIvarButNoSetter |
884 | |
885 | @synthesize ivarForOutlet; |
886 | - (void)dealloc { |
887 | |
888 | #if NON_ARC |
889 | [super dealloc]; |
890 | #if !MACOS |
891 | // expected-warning@-2{{The 'ivarForOutlet' ivar in 'ClassWithRetainPropWithIBOutletIvarButNoSetter' was retained by a synthesized property but not released before '[super dealloc]'}} |
892 | #endif |
893 | #endif |
894 | } |
895 | |
896 | @end |
897 | |
898 | @interface ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite : NSObject { |
899 | IBOutlet NSObject *ivarForOutlet; |
900 | } |
901 | |
902 | @property (readonly, retain) NSObject *ivarForOutlet; |
903 | |
904 | @end |
905 | |
906 | @interface ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite () |
907 | |
908 | // Since there is a shadowing readwrite property, there will be a retaining |
909 | // setter and so the ivar will be retained by nib-loading code even on |
910 | // macOS and therefore must be released. |
911 | @property (readwrite, retain) NSObject *ivarForOutlet; |
912 | @end |
913 | |
914 | @implementation ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite |
915 | |
916 | @synthesize ivarForOutlet; |
917 | - (void)dealloc { |
918 | |
919 | #if NON_ARC |
920 | [super dealloc]; |
921 | // expected-warning@-1{{The 'ivarForOutlet' ivar in 'ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite' was retained by a synthesized property but not released before '[super dealloc]'}} |
922 | #endif |
923 | } |
924 | |
925 | @end |
926 | |