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
5 #include "Inputs/system-header-simulator-for-objc-dealloc.h"
7 #define NON_ARC !__has_feature(objc_arc)
12 #define WEAK_ON_ARC __weak
15 // No diagnostics expected under ARC.
17 // expected-no-diagnostics
20 // Do not warn about missing release in -dealloc for ivars.
22 @interface MyIvarClass1 : NSObject {
27 @implementation MyIvarClass1
28 - (instancetype)initWithIvar:(NSObject *)ivar
34 _ivar = [ivar retain];
46 @interface MyIvarClass2 : NSObject {
50 - (void)setIvar:(NSObject *)ivar;
53 @implementation MyIvarClass2
69 - (void)setIvar:(NSObject *)ivar
73 _ivar = [ivar retain];
80 // Warn about missing release in -dealloc for properties.
82 @interface MyPropertyClass1 : NSObject
83 @property (copy) NSObject *ivar;
86 @implementation MyPropertyClass1
90 [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass1' was copied by a synthesized property but not released before '[super dealloc]'}}
95 @interface MyPropertyClass2 : NSObject
96 @property (retain) NSObject *ivar;
99 @implementation MyPropertyClass2
103 [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass2' was retained by a synthesized property but not released before '[super dealloc]'}}
108 @interface MyPropertyClass3 : NSObject {
111 @property (retain) NSObject *ivar;
114 @implementation MyPropertyClass3
115 @synthesize ivar = _ivar;
119 [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass3' was retained by a synthesized property but not released before '[super dealloc]'}}
125 @interface MyPropertyClass4 : NSObject {
126 void (^_blockPropertyIvar)(void);
128 @property (copy) void (^blockProperty)(void);
129 @property (copy) void (^blockProperty2)(void);
130 @property (copy) void (^blockProperty3)(void);
134 @implementation MyPropertyClass4
135 @synthesize blockProperty = _blockPropertyIvar;
139 [_blockProperty2 release];
140 Block_release(_blockProperty3);
142 [super dealloc]; // expected-warning {{The '_blockPropertyIvar' ivar in 'MyPropertyClass4' was copied by a synthesized property but not released before '[super dealloc]'}}
147 @interface MyPropertyClass5 : NSObject {
148 WEAK_ON_ARC NSObject *_ivar;
150 @property (weak) NSObject *ivar;
153 @implementation MyPropertyClass5
154 @synthesize ivar = _ivar;
158 [super dealloc]; // no-warning because it is a weak property
163 @interface MyPropertyClassWithReturnInDealloc : NSObject {
166 @property (retain) NSObject *ivar;
169 @implementation MyPropertyClassWithReturnInDealloc
170 @synthesize ivar = _ivar;
175 // expected-warning@-2{{The '_ivar' ivar in 'MyPropertyClassWithReturnInDealloc' was retained by a synthesized property but not released before '[super dealloc]'}}
181 @interface MyPropertyClassWithReleaseInOtherInstance : NSObject {
183 MyPropertyClassWithReleaseInOtherInstance *_other;
185 @property (retain) NSObject *ivar;
190 @implementation MyPropertyClassWithReleaseInOtherInstance
191 @synthesize ivar = _ivar;
193 -(void)releaseIvars; {
201 [_other releaseIvars];
203 [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClassWithReleaseInOtherInstance' was retained by a synthesized property but not released before '[super dealloc]'}}
208 @interface MyPropertyClassWithNeitherReturnNorSuperDealloc : NSObject {
211 @property (retain) NSObject *ivar;
214 @implementation MyPropertyClassWithNeitherReturnNorSuperDealloc
215 @synthesize ivar = _ivar;
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]'}}
225 // <rdar://problem/6380411>: 'myproperty' has kind 'assign' and thus the
226 // assignment through the setter does not perform a release.
228 @interface MyObject : NSObject {
229 id __unsafe_unretained _myproperty;
231 @property(assign) id myproperty;
234 @implementation MyObject
235 @synthesize myproperty=_myproperty; // no-warning
237 // Don't claim that myproperty is released since it the property
238 // has the 'assign' attribute.
239 self.myproperty = 0; // no-warning
246 @interface ClassWithControlFlowInRelease : NSObject {
249 @property (retain) NSObject *ivar2;
252 @implementation ClassWithControlFlowInRelease
255 // We really should warn because there is a path through -dealloc on which
256 // _ivar2 is not released.
263 [super dealloc]; // expected-warning {{The '_ivar2' ivar in 'ClassWithControlFlowInRelease' was retained by a synthesized property but not released before '[super dealloc]'}}
268 // Don't warn when the property is nil'd out in -dealloc
270 @interface ClassWithNildOutProperty : NSObject
271 @property (retain) NSObject *ivar;
272 @property (assign) int *intPtrProp;
275 @implementation ClassWithNildOutProperty
279 // Make sure to handle setting a non-retainable property to 0.
282 [super dealloc]; // no-warning
287 // Do warn when the ivar but not the property is nil'd out in -dealloc
289 @interface ClassWithNildOutIvar : NSObject
290 @property (retain) NSObject *ivar;
293 @implementation ClassWithNildOutIvar
295 // Oops. Meant self.ivar = nil
299 [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWithNildOutIvar' was retained by a synthesized property but not released before '[super dealloc]'}}
304 // Do warn when the ivar is updated to a different value that is then
307 @interface ClassWithUpdatedIvar : NSObject
308 @property (retain) NSObject *ivar;
311 @implementation ClassWithUpdatedIvar
313 _ivar = [[NSObject alloc] init];
320 [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWithUpdatedIvar' was retained by a synthesized property but not released before '[super dealloc]'}}
326 // Don't warn when the property is nil'd out with a setter in -dealloc
328 @interface ClassWithNildOutPropertyViaSetter : NSObject
329 @property (retain) NSObject *ivar;
332 @implementation ClassWithNildOutPropertyViaSetter
337 [super dealloc]; // no-warning
343 // Don't warn about missing releases when -dealloc helpers are called.
345 @interface ClassWithDeallocHelpers : NSObject
346 @property (retain) NSObject *ivarReleasedInMethod;
347 @property (retain) NSObject *propNilledOutInMethod;
349 @property (retain) NSObject *ivarReleasedInFunction;
350 @property (retain) NSObject *propNilledOutInFunction;
352 @property (retain) NSObject *ivarNeverReleased;
353 - (void)invalidateInMethod;
356 void ReleaseValueHelper(NSObject *iv) {
362 void NilOutPropertyHelper(ClassWithDeallocHelpers *o) {
363 o.propNilledOutInFunction = nil;
366 @implementation ClassWithDeallocHelpers
367 - (void)invalidateInMethod {
369 [_ivarReleasedInMethod release];
371 self.propNilledOutInMethod = nil;
375 ReleaseValueHelper(_ivarReleasedInFunction);
376 NilOutPropertyHelper(self);
378 [self invalidateInMethod];
380 [super dealloc]; // expected-warning {{The '_ivarNeverReleased' ivar in 'ClassWithDeallocHelpers' was retained by a synthesized property but not released before '[super dealloc]'}}
386 // Don't warn when self in -dealloc escapes.
388 @interface ClassWhereSelfEscapesViaMethodCall : NSObject
389 @property (retain) NSObject *ivar; // no-warning
392 @interface ClassWhereSelfEscapesViaMethodCall (Other)
393 - (void)invalidate; // In other translation unit.
396 @implementation ClassWhereSelfEscapesViaMethodCall
405 @interface ClassWhereSelfEscapesViaPropertyAccess : NSObject
406 @property (retain) NSObject *ivar;
409 @interface ClassWhereSelfEscapesViaPropertyAccess (Other)
410 // The implementation of this property is unknown and therefore could
412 @property (retain) NSObject *otherIvar;
415 @implementation ClassWhereSelfEscapesViaPropertyAccess
417 self.otherIvar = nil;
424 // Don't treat self as escaping when setter called on *synthesized*
427 @interface ClassWhereSelfEscapesViaSynthesizedPropertyAccess : NSObject
428 @property (retain) NSObject *ivar;
429 @property (retain) NSObject *otherIvar;
432 @implementation ClassWhereSelfEscapesViaSynthesizedPropertyAccess
434 self.otherIvar = nil;
436 [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWhereSelfEscapesViaSynthesizedPropertyAccess' was retained by a synthesized property but not released before '[super dealloc]'}}
442 // Don't treat calls to system headers as escapes
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;
453 @implementation ClassWhereSelfEscapesViaCallToSystem
462 [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
463 [[NSNotificationCenter defaultCenter] removeObserver:self];
473 [[NSNotificationCenter defaultCenter] removeObserver:self];
480 [super dealloc]; // expected-warning {{The '_ivar1' ivar in 'ClassWhereSelfEscapesViaCallToSystem' was retained by a synthesized property but not released before '[super dealloc]'}}
485 // Don't warn when value escapes.
487 @interface ClassWhereIvarValueEscapes : NSObject
488 @property (retain) NSObject *ivar;
491 void ReleaseMe(id arg);
493 @implementation ClassWhereIvarValueEscapes
504 // Don't warn when value is known to be nil.
506 @interface ClassWhereIvarIsNil : NSObject
507 @property (retain) NSObject *ivarIsNil;
510 @implementation ClassWhereIvarIsNil
515 [_ivarIsNil release];
523 // Don't warn for non-retainable properties.
525 @interface ClassWithNonRetainableProperty : NSObject
526 @property (assign) int *ivar; // no-warning
529 @implementation ClassWithNonRetainableProperty
538 @interface SuperClassOfClassWithInlinedSuperDealloc : NSObject
539 @property (retain) NSObject *propInSuper;
542 @implementation SuperClassOfClassWithInlinedSuperDealloc
545 [super dealloc]; // expected-warning {{The '_propInSuper' ivar in 'SuperClassOfClassWithInlinedSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}}
550 @interface ClassWithInlinedSuperDealloc : SuperClassOfClassWithInlinedSuperDealloc
551 @property (retain) NSObject *propInSub;
554 @implementation ClassWithInlinedSuperDealloc
557 [super dealloc]; // expected-warning {{The '_propInSub' ivar in 'ClassWithInlinedSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}}
563 @interface SuperClassOfClassWithInlinedSuperDeallocAndInvalidation : NSObject
564 @property (retain) NSObject *propInSuper;
569 @implementation SuperClassOfClassWithInlinedSuperDeallocAndInvalidation
573 [_propInSuper release];
581 [super dealloc]; // no-warning
586 @interface ClassWithInlinedSuperDeallocAndInvalidation : SuperClassOfClassWithInlinedSuperDeallocAndInvalidation
587 @property (retain) NSObject *propInSub;
590 @implementation ClassWithInlinedSuperDeallocAndInvalidation
594 [_propInSub release];
601 [super dealloc]; // no-warning
607 @interface SuperClassOfClassThatEscapesBeforeInliningSuper : NSObject
608 @property (retain) NSObject *propInSuper;
611 @implementation SuperClassOfClassThatEscapesBeforeInliningSuper
616 [super dealloc]; // expected-warning {{The '_propInSuper' ivar in 'SuperClassOfClassThatEscapesBeforeInliningSuper' was retained by a synthesized property but not released before '[super dealloc]'}}
621 @interface ClassThatEscapesBeforeInliningSuper : SuperClassOfClassThatEscapesBeforeInliningSuper
622 @property (retain) NSObject *propInSub;
625 @interface ClassThatEscapesBeforeInliningSuper (Other)
626 - (void)invalidate; // No implementation in translation unit.
629 @implementation ClassThatEscapesBeforeInliningSuper
634 [super dealloc]; // no-warning
641 @interface ReleaseIvarInField : NSObject {
654 @implementation ReleaseIvarInField
657 [_someUnion.field1 release];
659 [_someUnion.field2 release];
662 [_someStruct.field1 release];
671 @interface ZeroOutStructWithSetter : NSObject
672 @property(assign) struct SomeStruct s;
675 @implementation ZeroOutStructWithSetter
677 struct SomeStruct zeroedS;
688 @interface ReleaseIvarInArray : NSObject {
693 @implementation ReleaseIvarInArray
695 for (int i = 0; i < 3; i++) {
703 // Don't warn about missing releases for subclasses of SenTestCase or
704 // for classes that are not subclasses of NSObject.
706 @interface SenTestCase : NSObject {}
709 @interface MyClassTest : SenTestCase
710 @property (retain) NSObject *ivar;
713 @implementation MyClassTest
722 [super dealloc]; // no-warning
727 @interface XCTestCase : NSObject {}
730 @interface MyClassXCTest : XCTestCase
731 @property (retain) NSObject *ivar;
734 @implementation MyClassXCTest
743 [super dealloc]; // no-warning
749 __attribute__((objc_root_class))
750 @interface NonNSObjectMissingDealloc
751 @property (retain) NSObject *ivar;
753 @implementation NonNSObjectMissingDealloc
759 // Warn about calling -dealloc rather than release by mistake.
761 @interface CallDeallocOnRetainPropIvar : NSObject {
762 NSObject *okToDeallocDirectly;
765 @property (retain) NSObject *ivar;
768 @implementation CallDeallocOnRetainPropIvar
772 // Only warn for synthesized ivars.
773 [okToDeallocDirectly dealloc]; // no-warning
774 [_ivar dealloc]; // expected-warning {{'_ivar' should be released rather than deallocated}}
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.
789 @interface ImmediateSubCIFilter : CIFilter {
791 NSObject *nonInputIvar;
792 NSObject *notPrefixedButBackingPrefixedProperty;
793 NSObject *inputPrefixedButBackingNonPrefixedProperty;
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;
804 @implementation ImmediateSubCIFilter
805 @synthesize inputIvar = inputIvar;
806 @synthesize nonInputIvar = nonInputIvar;
807 @synthesize inputExplicitlySynthesizedToNonPrefixedIvar = notPrefixedButBackingPrefixedProperty;
808 @synthesize nonPrefixedPropertyBackedByExplicitlySynthesizedPrefixedIvar = inputPrefixedButBackingNonPrefixedProperty;
812 // We don't want warnings here for:
814 // inputAutoSynthesizedIvar
815 // inputExplicitlySynthesizedToNonPrefixedIvar
816 // inputPrefixedButBackingNonPrefixedProperty
818 // expected-warning@-1 {{The 'nonInputIvar' ivar in 'ImmediateSubCIFilter' was retained by a synthesized property but not released before '[super dealloc]'}}
823 @interface SubSubCIFilter : CIFilter {
824 NSObject *inputIvarInSub;
827 @property(retain) NSObject *inputIvarInSub;
830 @implementation SubSubCIFilter
831 @synthesize inputIvarInSub = inputIvarInSub;
834 // Don't warn about inputIvarInSub.
840 @interface OverreleasingCIFilter : CIFilter {
844 @property(retain) NSObject *inputIvar;
847 @implementation OverreleasingCIFilter
848 @synthesize inputIvar = inputIvar;
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
860 @interface NotMissingDeallocCIFilter : CIFilter {
864 @property(retain) NSObject *inputIvar;
867 @implementation NotMissingDeallocCIFilter // no-warning
868 @synthesize inputIvar = inputIvar;
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;
880 @property (readonly, retain) NSObject *ivarForOutlet;
883 @implementation ClassWithRetainPropWithIBOutletIvarButNoSetter
885 @synthesize ivarForOutlet;
891 // expected-warning@-2{{The 'ivarForOutlet' ivar in 'ClassWithRetainPropWithIBOutletIvarButNoSetter' was retained by a synthesized property but not released before '[super dealloc]'}}
898 @interface ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite : NSObject {
899 IBOutlet NSObject *ivarForOutlet;
902 @property (readonly, retain) NSObject *ivarForOutlet;
906 @interface ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite ()
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;
914 @implementation ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite
916 @synthesize ivarForOutlet;
921 // expected-warning@-1{{The 'ivarForOutlet' ivar in 'ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite' was retained by a synthesized property but not released before '[super dealloc]'}}