diff options
| author | Anna Zaks <ganna@apple.com> | 2012-08-24 00:06:12 +0000 |
|---|---|---|
| committer | Anna Zaks <ganna@apple.com> | 2012-08-24 00:06:12 +0000 |
| commit | 3d5d3d3e2cba3762cc919f661a22189797d076cc (patch) | |
| tree | 75486292995f1b1bcc2f262a7ce4d922caa63308 /clang/test/Analysis/inlining/retain-count-self-init.m | |
| parent | 907f6b8c06f0bfdb345dd2ee480a50d1e489c7d8 (diff) | |
| download | bcm5719-llvm-3d5d3d3e2cba3762cc919f661a22189797d076cc.tar.gz bcm5719-llvm-3d5d3d3e2cba3762cc919f661a22189797d076cc.zip | |
[analyzer] Make analyzer less aggressive when dealing with [self init].
With inlining, retain count checker starts tracking 'self' through the
init methods. The analyser results were too noisy if the developer
did not follow 'self = [super init]' pattern (which is common
especially in older code bases) - we reported self init anti-pattern AND
possible use-after-free. This patch teaches the retain count
checker to assume that [super init] does not fail when it's not consumed
by another expression. This silences the retain count warning that warns
about possibility of use-after-free when init fails, while preserving
all the other checking on 'self'.
llvm-svn: 162508
Diffstat (limited to 'clang/test/Analysis/inlining/retain-count-self-init.m')
| -rw-r--r-- | clang/test/Analysis/inlining/retain-count-self-init.m | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/clang/test/Analysis/inlining/retain-count-self-init.m b/clang/test/Analysis/inlining/retain-count-self-init.m new file mode 100644 index 00000000000..ee8dbe391c4 --- /dev/null +++ b/clang/test/Analysis/inlining/retain-count-self-init.m @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.SelfInit -analyzer-ipa=dynamic-bifurcate -verify %s + +typedef signed char BOOL; +typedef struct objc_class *Class; +typedef struct objc_object { + Class isa; +} *id; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@interface NSObject <NSObject> {} ++(id)alloc; ++(id)new; +- (oneway void)release; +-(id)init; +-(id)autorelease; +-(id)copy; +- (Class)class; +-(id)retain; +@end + +// We do not want to overhelm user with error messages in case they forgot to +// assign to self and check that the result of [super init] is non-nil. So +// stop tracking the receiver of init with respect to Retain Release checker. +// radar://12115830 +@interface ParentOfCell : NSObject +- (id)initWithInt: (int)inInt; +@end +@interface Cell : ParentOfCell{ + int x; +} +- (id)init; ++ (void)test; +@property int x; +@end +@implementation Cell +@synthesize x; +- (id) init { + [super init]; + self.x = 3; // no-warning + return self; // expected-warning {{Returning 'self' while it is not set to the result of '[(super or self)}} +} +- (id) initWithInt: (int)inInt { + [super initWithInt: inInt]; + self.x = inInt; // no-warning + return self; // expected-warning {{Returning 'self' while it is not set to the result of '[(super or self)}} +} +- (id) init2 { + [self init]; // The call [self init] is inlined. We will warn inside the inlined body. + self.x = 2; // no-warning + return self; +} + +- (id) initWithIntGood: (int)inInt { + if (self = [super initWithInt: inInt]) { + self.x = inInt; + } + return self; +} ++ (void) test { + Cell *sharedCell1 = [[Cell alloc] init]; + [sharedCell1 release]; + Cell *sharedCell2 = [[Cell alloc] initWithInt: 3]; + [sharedCell2 release]; + Cell *sharedCell3 = [[Cell alloc] initWithIntGood: 3]; + [sharedCell3 release]; +} + +@end + |

