diff options
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/DeallocMissingRelease.m | 476 | ||||
| -rw-r--r-- | clang/test/Analysis/MissingDealloc.m | 14 | ||||
| -rw-r--r-- | clang/test/Analysis/PR2978.m | 70 | ||||
| -rw-r--r-- | clang/test/Analysis/properties.m | 13 |
4 files changed, 534 insertions, 39 deletions
diff --git a/clang/test/Analysis/DeallocMissingRelease.m b/clang/test/Analysis/DeallocMissingRelease.m index e782f9968f9..c7769db3d5f 100644 --- a/clang/test/Analysis/DeallocMissingRelease.m +++ b/clang/test/Analysis/DeallocMissingRelease.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks %s 2>&1 | FileCheck -check-prefix=CHECK %s -// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -triple x86_64-apple-darwin10 -fobjc-arc -fobjc-runtime-has-weak %s 2>&1 | FileCheck -check-prefix=CHECK-ARC -allow-empty '--implicit-check-not=error:' '--implicit-check-not=warning:' %s +// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -triple x86_64-apple-darwin10 -fobjc-arc -fobjc-runtime-has-weak -verify %s #define nil ((id)0) @@ -11,6 +11,11 @@ #define WEAK_ON_ARC __weak #endif +// No diagnostics expected under ARC. +#if !NON_ARC + // expected-no-diagnostics +#endif + typedef signed char BOOL; @protocol NSObject - (BOOL)isEqual:(id)object; @@ -18,6 +23,7 @@ typedef signed char BOOL; @end @interface NSObject <NSObject> {} ++ (instancetype)alloc; - (void)dealloc; - (id)init; - (id)retain; @@ -26,7 +32,6 @@ typedef signed char BOOL; typedef struct objc_selector *SEL; -//===------------------------------------------------------------------------=== // Do not warn about missing release in -dealloc for ivars. @interface MyIvarClass1 : NSObject { @@ -87,11 +92,9 @@ typedef struct objc_selector *SEL; } @end -//===------------------------------------------------------------------------=== // Warn about missing release in -dealloc for properties. @interface MyPropertyClass1 : NSObject -// CHECK: DeallocMissingRelease.m:[[@LINE+1]]:1: warning: The '_ivar' instance variable in 'MyPropertyClass1' was retained by a synthesized property but was not released in 'dealloc' @property (copy) NSObject *ivar; @end @@ -99,13 +102,12 @@ typedef struct objc_selector *SEL; - (void)dealloc { #if NON_ARC - [super dealloc]; + [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass1' was copied by a synthesized property but not released before '[super dealloc]'}} #endif } @end @interface MyPropertyClass2 : NSObject -// CHECK: DeallocMissingRelease.m:[[@LINE+1]]:1: warning: The '_ivar' instance variable in 'MyPropertyClass2' was retained by a synthesized property but was not released in 'dealloc' @property (retain) NSObject *ivar; @end @@ -113,7 +115,7 @@ typedef struct objc_selector *SEL; - (void)dealloc { #if NON_ARC - [super dealloc]; + [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass2' was retained by a synthesized property but not released before '[super dealloc]'}} #endif } @end @@ -125,14 +127,14 @@ typedef struct objc_selector *SEL; @end @implementation MyPropertyClass3 -// CHECK: DeallocMissingRelease.m:[[@LINE+1]]:1: warning: The '_ivar' instance variable in 'MyPropertyClass3' was retained by a synthesized property but was not released in 'dealloc' @synthesize ivar = _ivar; - (void)dealloc { #if NON_ARC - [super dealloc]; + [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClass3' was retained by a synthesized property but not released before '[super dealloc]'}} #endif } + @end @interface MyPropertyClass4 : NSObject { @@ -142,12 +144,11 @@ typedef struct objc_selector *SEL; @end @implementation MyPropertyClass4 -// CHECK: DeallocMissingRelease.m:[[@LINE+1]]:1: warning: The '_blockPropertyIvar' instance variable in 'MyPropertyClass4' was retained by a synthesized property but was not released in 'dealloc' @synthesize blockProperty = _blockPropertyIvar; - (void)dealloc { #if NON_ARC - [super dealloc]; + [super dealloc]; // expected-warning {{The '_blockPropertyIvar' ivar in 'MyPropertyClass4' was copied by a synthesized property but not released before '[super dealloc]'}} #endif } @end @@ -159,16 +160,77 @@ typedef struct objc_selector *SEL; @end @implementation MyPropertyClass5 -@synthesize ivar = _ivar; // no-warning +@synthesize ivar = _ivar; - (void)dealloc { #if NON_ARC + [super dealloc]; // no-warning because it is a weak property +#endif +} +@end + +@interface MyPropertyClassWithReturnInDealloc : NSObject { + NSObject *_ivar; +} +@property (retain) NSObject *ivar; +@end + +@implementation MyPropertyClassWithReturnInDealloc +@synthesize ivar = _ivar; +- (void)dealloc +{ + return; +#if NON_ARC + // expected-warning@-2{{The '_ivar' ivar in 'MyPropertyClassWithReturnInDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} [super dealloc]; #endif } @end -//===------------------------------------------------------------------------=== +@interface MyPropertyClassWithReleaseInOtherInstance : NSObject { + NSObject *_ivar; + MyPropertyClassWithReleaseInOtherInstance *_other; +} +@property (retain) NSObject *ivar; + +-(void)releaseIvars; +@end + +@implementation MyPropertyClassWithReleaseInOtherInstance +@synthesize ivar = _ivar; + +-(void)releaseIvars; { +#if NON_ARC + [_ivar release]; +#endif +} + +- (void)dealloc +{ + [_other releaseIvars]; +#if NON_ARC + [super dealloc]; // expected-warning {{The '_ivar' ivar in 'MyPropertyClassWithReleaseInOtherInstance' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif +} +@end + +@interface MyPropertyClassWithNeitherReturnNorSuperDealloc : NSObject { + NSObject *_ivar; +} +@property (retain) NSObject *ivar; +@end + +@implementation MyPropertyClassWithNeitherReturnNorSuperDealloc +@synthesize ivar = _ivar; +- (void)dealloc +{ +} +#if NON_ARC + // expected-warning@-2 {{method possibly missing a [super dealloc] call}} (From Sema) + // expected-warning@-3{{The '_ivar' ivar in 'MyPropertyClassWithNeitherReturnNorSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif +@end + // <rdar://problem/6380411>: 'myproperty' has kind 'assign' and thus the // assignment through the setter does not perform a release. @@ -202,40 +264,78 @@ typedef struct objc_selector *SEL; // We really should warn because there is a path through -dealloc on which // _ivar2 is not released. #if NON_ARC - [_ivar2 release]; // no-warning + [_ivar2 release]; #endif } #if NON_ARC - [super dealloc]; + [super dealloc]; // expected-warning {{The '_ivar2' ivar in 'ClassWithControlFlowInRelease' was retained by a synthesized property but not released before '[super dealloc]'}} #endif } - @end -//===------------------------------------------------------------------------=== // Don't warn when the property is nil'd out in -dealloc @interface ClassWithNildOutProperty : NSObject -@property (retain) NSObject *ivar; // no-warning +@property (retain) NSObject *ivar; +@property (assign) int *intPtrProp; @end @implementation ClassWithNildOutProperty - (void)dealloc; { self.ivar = nil; + // Make sure to handle setting a non-retainable property to 0. + self.intPtrProp = 0; #if NON_ARC - [super dealloc]; + [super dealloc]; // no-warning +#endif +} +@end + +// Do warn when the ivar but not the property is nil'd out in -dealloc + +@interface ClassWithNildOutIvar : NSObject +@property (retain) NSObject *ivar; +@end + +@implementation ClassWithNildOutIvar +- (void)dealloc; { + // Oops. Meant self.ivar = nil + _ivar = nil; + +#if NON_ARC + [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWithNildOutIvar' was retained by a synthesized property but not released before '[super dealloc]'}} #endif } +@end +// Do warn when the ivar is updated to a different value that is then +// released. + +@interface ClassWithUpdatedIvar : NSObject +@property (retain) NSObject *ivar; @end -//===------------------------------------------------------------------------=== +@implementation ClassWithUpdatedIvar +- (void)dealloc; { + _ivar = [[NSObject alloc] init]; + +#if NON_ARC + [_ivar release]; +#endif + +#if NON_ARC + [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWithUpdatedIvar' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif +} +@end + + // Don't warn when the property is nil'd out with a setter in -dealloc @interface ClassWithNildOutPropertyViaSetter : NSObject -@property (retain) NSObject *ivar; // no-warning +@property (retain) NSObject *ivar; @end @implementation ClassWithNildOutPropertyViaSetter @@ -243,10 +343,340 @@ typedef struct objc_selector *SEL; [self setIvar:nil]; #if NON_ARC + [super dealloc]; // no-warning +#endif +} +@end + + +// Don't warn about missing releases when -dealloc helpers are called. + +@interface ClassWithDeallocHelpers : NSObject +@property (retain) NSObject *ivarReleasedInMethod; +@property (retain) NSObject *propNilledOutInMethod; + +@property (retain) NSObject *ivarReleasedInFunction; +@property (retain) NSObject *propNilledOutInFunction; + +@property (retain) NSObject *ivarNeverReleased; +- (void)invalidateInMethod; +@end + +void ReleaseValueHelper(NSObject *iv) { +#if NON_ARC + [iv release]; +#endif +} + +void NilOutPropertyHelper(ClassWithDeallocHelpers *o) { + o.propNilledOutInFunction = nil; +} + +@implementation ClassWithDeallocHelpers +- (void)invalidateInMethod { +#if NON_ARC + [_ivarReleasedInMethod release]; +#endif + self.propNilledOutInMethod = nil; +} + +- (void)dealloc; { + ReleaseValueHelper(_ivarReleasedInFunction); + NilOutPropertyHelper(self); + + [self invalidateInMethod]; +#if NON_ARC + [super dealloc]; // expected-warning {{The '_ivarNeverReleased' ivar in 'ClassWithDeallocHelpers' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif +} +@end + + +// Don't warn when self in -dealloc escapes. + +@interface ClassWhereSelfEscapesViaMethodCall : NSObject +@property (retain) NSObject *ivar; // no-warning +@end + +@interface ClassWhereSelfEscapesViaMethodCall (Other) +- (void)invalidate; // In other translation unit. +@end + +@implementation ClassWhereSelfEscapesViaMethodCall +- (void)dealloc; { + [self invalidate]; +#if NON_ARC + [super dealloc]; +#endif +} // no-warning +@end + +@interface ClassWhereSelfEscapesViaPropertyAccess : NSObject +@property (retain) NSObject *ivar; +@end + +@interface ClassWhereSelfEscapesViaPropertyAccess (Other) +// The implementation of this property is unknown and therefore could +// release ivar. +@property (retain) NSObject *otherIvar; +@end + +@implementation ClassWhereSelfEscapesViaPropertyAccess +- (void)dealloc; { + self.otherIvar = nil; +#if NON_ARC [super dealloc]; #endif +} // no-warning +@end + +// Don't treat self as escaping when setter called on *synthesized* +// property. + +@interface ClassWhereSelfEscapesViaSynthesizedPropertyAccess : NSObject +@property (retain) NSObject *ivar; +@property (retain) NSObject *otherIvar; +@end + +@implementation ClassWhereSelfEscapesViaSynthesizedPropertyAccess +- (void)dealloc; { + self.otherIvar = nil; +#if NON_ARC + [super dealloc]; // expected-warning {{The '_ivar' ivar in 'ClassWhereSelfEscapesViaSynthesizedPropertyAccess' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif } +@end + +// Don't warn when value escapes. +@interface ClassWhereIvarValueEscapes : NSObject +@property (retain) NSObject *ivar; +@end + +void ReleaseMe(id arg); + +@implementation ClassWhereIvarValueEscapes +- (void)dealloc; { + + ReleaseMe(_ivar); + +#if NON_ARC + [super dealloc]; +#endif +} // no-warning +@end + +// Don't warn when value is known to be nil. + +@interface ClassWhereIvarIsNil : NSObject +@property (retain) NSObject *ivarIsNil; +@end + +@implementation ClassWhereIvarIsNil +- (void)dealloc; { + +#if NON_ARC + if (_ivarIsNil) + [_ivarIsNil release]; + + [super dealloc]; +#endif +} // no-warning +@end + + +// Don't warn for non-retainable properties. + +@interface ClassWithNonRetainableProperty : NSObject +@property (assign) int *ivar; // no-warning +@end + +@implementation ClassWithNonRetainableProperty +- (void)dealloc; { +#if NON_ARC + [super dealloc]; +#endif +} // no-warning +@end + + +@interface SuperClassOfClassWithInlinedSuperDealloc : NSObject +@property (retain) NSObject *propInSuper; +@end + +@implementation SuperClassOfClassWithInlinedSuperDealloc +- (void)dealloc { +#if NON_ARC + [super dealloc]; // expected-warning {{The '_propInSuper' ivar in 'SuperClassOfClassWithInlinedSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif +} +@end + +@interface ClassWithInlinedSuperDealloc : SuperClassOfClassWithInlinedSuperDealloc +@property (retain) NSObject *propInSub; +@end + +@implementation ClassWithInlinedSuperDealloc +- (void)dealloc { +#if NON_ARC + [super dealloc]; // expected-warning {{The '_propInSub' ivar in 'ClassWithInlinedSuperDealloc' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif +} +@end + + +@interface SuperClassOfClassWithInlinedSuperDeallocAndInvalidation : NSObject +@property (retain) NSObject *propInSuper; + +- (void)invalidate; +@end + +@implementation SuperClassOfClassWithInlinedSuperDeallocAndInvalidation + +- (void)invalidate { +#if NON_ARC + [_propInSuper release]; +#endif + _propInSuper = nil; +} + +- (void)dealloc { + [self invalidate]; +#if NON_ARC + [super dealloc]; // no-warning +#endif +} +@end + +@interface ClassWithInlinedSuperDeallocAndInvalidation : SuperClassOfClassWithInlinedSuperDeallocAndInvalidation +@property (retain) NSObject *propInSub; +@end + +@implementation ClassWithInlinedSuperDeallocAndInvalidation + +- (void)invalidate { +#if NON_ARC + [_propInSub release]; +#endif + [super invalidate]; +} + +- (void)dealloc { +#if NON_ARC + [super dealloc]; // no-warning +#endif +} +@end + + +@interface SuperClassOfClassThatEscapesBeforeInliningSuper : NSObject +@property (retain) NSObject *propInSuper; +@end + +@implementation SuperClassOfClassThatEscapesBeforeInliningSuper + +- (void)dealloc { + +#if NON_ARC + [super dealloc]; // expected-warning {{The '_propInSuper' ivar in 'SuperClassOfClassThatEscapesBeforeInliningSuper' was retained by a synthesized property but not released before '[super dealloc]'}} +#endif +} +@end + +@interface ClassThatEscapesBeforeInliningSuper : SuperClassOfClassThatEscapesBeforeInliningSuper +@property (retain) NSObject *propInSub; +@end + +@interface ClassThatEscapesBeforeInliningSuper (Other) +- (void)invalidate; // No implementation in translation unit. +@end + +@implementation ClassThatEscapesBeforeInliningSuper +- (void)dealloc { + [self invalidate]; + +#if NON_ARC + [super dealloc]; // no-warning +#endif +} +@end + + +#if NON_ARC +@interface ReleaseIvarInField : NSObject { + int _tag; + union { + NSObject *field1; + NSObject *field2; + } _someUnion; + + struct { + NSObject *field1; + } _someStruct; +} +@end + +@implementation ReleaseIvarInField +- (void)dealloc { + if (_tag) { + [_someUnion.field1 release]; + } else { + [_someUnion.field2 release]; + } + + [_someStruct.field1 release]; + [super dealloc]; +} +@end +#endif + +#if NON_ARC +@interface ReleaseIvarInArray : NSObject { + NSObject *_array[3]; +} +@end + +@implementation ReleaseIvarInArray +- (void)dealloc { + for (int i = 0; i < 3; i++) { + [_array[i] release]; + } + [super dealloc]; +} +@end +#endif + +// Don't warn about missing releases for subclasses of SenTestCase or +// for classes that are not subclasses of NSObject. + +@interface SenTestCase : NSObject {} +@end + +@interface MyClassTest : SenTestCase +@property (retain) NSObject *ivar; +@end + +@implementation MyClassTest +-(void)tearDown { +#if NON_ARC + [_ivar release]; +#endif +} + +-(void)dealloc; { +#if NON_ARC + [super dealloc]; // no-warning +#endif +} +@end + +__attribute__((objc_root_class)) +@interface NonNSObjectMissingDealloc +@property (retain) NSObject *ivar; +@end +@implementation NonNSObjectMissingDealloc +-(void)dealloc; { + +} @end -// CHECK: 4 warnings generated. diff --git a/clang/test/Analysis/MissingDealloc.m b/clang/test/Analysis/MissingDealloc.m index d6af44b895b..ae880546ff9 100644 --- a/clang/test/Analysis/MissingDealloc.m +++ b/clang/test/Analysis/MissingDealloc.m @@ -128,6 +128,9 @@ IBOutlet NSWindow *window; @interface MyClassTest : SenTestCase { NSString *resourcePath; } + +@property (retain) NSObject *ivar; + @end @interface NSBundle : NSObject {} @@ -143,4 +146,15 @@ IBOutlet NSWindow *window; // do something which uses resourcepath } @end + +//===------------------------------------------------------------------------=== +// Don't warn for clases that aren't subclasses of NSObject + +__attribute__((objc_root_class)) +@interface NonNSObjectMissingDealloc +@property (retain) NSObject *ivar; +@end +@implementation NonNSObjectMissingDealloc +@end + // CHECK: 4 warnings generated. diff --git a/clang/test/Analysis/PR2978.m b/clang/test/Analysis/PR2978.m index 2067b3e85af..bb0fc414566 100644 --- a/clang/test/Analysis/PR2978.m +++ b/clang/test/Analysis/PR2978.m @@ -5,7 +5,7 @@ @interface NSObject - (void)release; -- dealloc; +- (void)dealloc; @end @interface MyClass : NSObject { @@ -19,8 +19,14 @@ id _M; id _P; id _Q; + id _R; + id _S; id _V; id _W; + + MyClass *_other; + + id _nonPropertyIvar; } @property(retain) id X; @property(retain) id Y; @@ -29,8 +35,13 @@ @property(weak) id L; @property(readonly) id N; @property(retain) id M; -@property(weak) id P; // expected-warning {{'_P' instance variable in 'MyClass' was not retained by a synthesized property but was released in 'dealloc'}} +@property(weak) id P; @property(weak) id Q; +@property(retain) id R; +@property(weak, readonly) id S; + +@property(assign, readonly) id T; // Shadowed in class extension +@property(assign) id U; @property(retain) id V; @property(retain) id W; @@ -38,36 +49,67 @@ -(void) setO: (id) arg; @end +@interface MyClass () +// Shadows T to make it readwrite internally but readonly externally. +@property(assign, readwrite) id T; +@end + @implementation MyClass @synthesize X = _X; -@synthesize Y = _Y; // expected-warning{{The '_Y' instance variable in 'MyClass' was retained by a synthesized property but was not released in 'dealloc'}} -@synthesize Z = _Z; // expected-warning{{The '_Z' instance variable in 'MyClass' was not retained by a synthesized property but was released in 'dealloc'}} +@synthesize Y = _Y; +@synthesize Z = _Z; @synthesize K = _K; -@synthesize L = _L; // no-warning -@synthesize N = _N; // no-warning +@synthesize L = _L; +@synthesize N = _N; @synthesize M = _M; -@synthesize Q = _Q; // expected-warning {{'_Q' instance variable in 'MyClass' was not retained by a synthesized property but was released in 'dealloc'}} +@synthesize Q = _Q; +@synthesize R = _R; @synthesize V = _V; -@synthesize W = _W; // expected-warning{{The '_W' instance variable in 'MyClass' was retained by a synthesized property but was not released in 'dealloc'}} +@synthesize W = _W; -(id) O{ return 0; } -(void) setO:(id)arg { } -- (id)dealloc + +-(void) releaseInHelper { + [_R release]; // no-warning + _R = @"Hi"; +} + +- (void)dealloc { + [_X release]; - [_Z release]; + [_Z release]; // expected-warning{{The '_Z' ivar in 'MyClass' was synthesized for an assign, readwrite property but was released in 'dealloc'}} + [_T release]; // no-warning + + [_other->_Z release]; // no-warning [_N release]; - + self.M = 0; // This will release '_M' [self setV:0]; // This will release '_V' [self setW:@"newW"]; // This will release '_W', but retain the new value - self.O = 0; // no-warning - [_Q release]; + [_S release]; // expected-warning {{The '_S' ivar in 'MyClass' was synthesized for a weak property but was released in 'dealloc'}} + + self.O = 0; // no-warning + + [_Q release]; // expected-warning {{The '_Q' ivar in 'MyClass' was synthesized for a weak property but was released in 'dealloc'}} + self.P = 0; + + [self releaseInHelper]; + + [_nonPropertyIvar release]; // no-warning + + // Silly, but not an error. + if (!_U) + [_U release]; + [super dealloc]; - return 0; + // expected-warning@-1{{The '_Y' ivar in 'MyClass' was retained by a synthesized property but not released before '[super dealloc]'}} + // expected-warning@-2{{The '_W' ivar in 'MyClass' was retained by a synthesized property but not released before '[super dealloc]'}} + } @end diff --git a/clang/test/Analysis/properties.m b/clang/test/Analysis/properties.m index d92f1a1a7e8..98d6d7ce1d7 100644 --- a/clang/test/Analysis/properties.m +++ b/clang/test/Analysis/properties.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s void clang_analyzer_eval(int); @@ -22,6 +22,7 @@ typedef struct _NSZone NSZone; -(id)copy; -(id)retain; -(oneway void)release; +-(void)dealloc; @end @interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; @@ -138,6 +139,14 @@ NSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber) @implementation Person @synthesize name = _name; + +-(void)dealloc { +#if !__has_feature(objc_arc) + self.name = [[NSString alloc] init]; // expected-warning {{leak}} + + [super dealloc]; // expected-warning {{The '_name' ivar in 'Person' was retained by a synthesized property but not released before '[super dealloc]}} +#endif +} @end #if !__has_feature(objc_arc) |

