1*0a6a1f1dSLionel Sambuc// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s 2*0a6a1f1dSLionel Sambuc// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s 3*0a6a1f1dSLionel Sambuc 4*0a6a1f1dSLionel Sambucvoid clang_analyzer_eval(int); 5f4a2713aSLionel Sambuc 6f4a2713aSLionel Sambuctypedef signed char BOOL; 7f4a2713aSLionel Sambuctypedef unsigned int NSUInteger; 8f4a2713aSLionel Sambuctypedef struct _NSZone NSZone; 9f4a2713aSLionel Sambuc@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 10f4a2713aSLionel Sambuc@protocol NSObject - (BOOL)isEqual:(id)object; @end 11f4a2713aSLionel Sambuc@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end 12f4a2713aSLionel Sambuc@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end 13f4a2713aSLionel Sambuc@protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end 14f4a2713aSLionel Sambuc@interface NSObject <NSObject> {} 15f4a2713aSLionel Sambuc+(id)alloc; 16f4a2713aSLionel Sambuc-(id)init; 17f4a2713aSLionel Sambuc-(id)autorelease; 18f4a2713aSLionel Sambuc-(id)copy; 19f4a2713aSLionel Sambuc-(id)retain; 20*0a6a1f1dSLionel Sambuc-(oneway void)release; 21f4a2713aSLionel Sambuc@end 22f4a2713aSLionel Sambuc@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> 23f4a2713aSLionel Sambuc- (NSUInteger)length; 24f4a2713aSLionel Sambuc-(id)initWithFormat:(NSString *)f,...; 25f4a2713aSLionel Sambuc-(BOOL)isEqualToString:(NSString *)s; 26f4a2713aSLionel Sambuc+ (id)string; 27f4a2713aSLionel Sambuc@end 28f4a2713aSLionel Sambuc@interface NSNumber : NSObject {} 29f4a2713aSLionel Sambuc+(id)alloc; 30f4a2713aSLionel Sambuc-(id)initWithInteger:(int)i; 31f4a2713aSLionel Sambuc@end 32f4a2713aSLionel Sambuc 33f4a2713aSLionel Sambuc// rdar://6946338 34f4a2713aSLionel Sambuc 35f4a2713aSLionel Sambuc@interface Test1 : NSObject { 36f4a2713aSLionel Sambuc NSString *text; 37f4a2713aSLionel Sambuc} 38f4a2713aSLionel Sambuc-(id)myMethod; 39f4a2713aSLionel Sambuc@property (nonatomic, assign) NSString *text; 40f4a2713aSLionel Sambuc@end 41f4a2713aSLionel Sambuc 42f4a2713aSLionel Sambuc 43*0a6a1f1dSLionel Sambuc#if !__has_feature(objc_arc) 44*0a6a1f1dSLionel Sambuc 45f4a2713aSLionel Sambuc@implementation Test1 46f4a2713aSLionel Sambuc 47f4a2713aSLionel Sambuc@synthesize text; 48f4a2713aSLionel Sambuc 49f4a2713aSLionel Sambuc-(id)myMethod { 50f4a2713aSLionel Sambuc Test1 *cell = [[[Test1 alloc] init] autorelease]; 51f4a2713aSLionel Sambuc 52f4a2713aSLionel Sambuc NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // expected-warning {{Potential leak}} 53f4a2713aSLionel Sambuc cell.text = string1; 54f4a2713aSLionel Sambuc 55f4a2713aSLionel Sambuc return cell; 56f4a2713aSLionel Sambuc} 57f4a2713aSLionel Sambuc 58f4a2713aSLionel Sambuc@end 59f4a2713aSLionel Sambuc 60f4a2713aSLionel Sambuc 61f4a2713aSLionel Sambuc// rdar://8824416 62f4a2713aSLionel Sambuc 63f4a2713aSLionel Sambuc@interface MyNumber : NSObject 64f4a2713aSLionel Sambuc{ 65f4a2713aSLionel Sambuc NSNumber* _myNumber; 66f4a2713aSLionel Sambuc} 67f4a2713aSLionel Sambuc 68f4a2713aSLionel Sambuc- (id)initWithNumber:(NSNumber *)number; 69f4a2713aSLionel Sambuc 70f4a2713aSLionel Sambuc@property (nonatomic, readonly) NSNumber* myNumber; 71f4a2713aSLionel Sambuc@property (nonatomic, readonly) NSNumber* newMyNumber; 72f4a2713aSLionel Sambuc 73f4a2713aSLionel Sambuc@end 74f4a2713aSLionel Sambuc 75f4a2713aSLionel Sambuc@implementation MyNumber 76f4a2713aSLionel Sambuc@synthesize myNumber=_myNumber; 77f4a2713aSLionel Sambuc 78f4a2713aSLionel Sambuc- (id)initWithNumber:(NSNumber *)number 79f4a2713aSLionel Sambuc{ 80f4a2713aSLionel Sambuc self = [super init]; 81f4a2713aSLionel Sambuc 82f4a2713aSLionel Sambuc if ( self ) 83f4a2713aSLionel Sambuc { 84f4a2713aSLionel Sambuc _myNumber = [number copy]; 85f4a2713aSLionel Sambuc } 86f4a2713aSLionel Sambuc 87f4a2713aSLionel Sambuc return self; 88f4a2713aSLionel Sambuc} 89f4a2713aSLionel Sambuc 90f4a2713aSLionel Sambuc- (NSNumber*)newMyNumber 91f4a2713aSLionel Sambuc{ 92f4a2713aSLionel Sambuc if ( _myNumber ) 93f4a2713aSLionel Sambuc return [_myNumber retain]; 94f4a2713aSLionel Sambuc 95f4a2713aSLionel Sambuc return [[NSNumber alloc] initWithInteger:1]; 96f4a2713aSLionel Sambuc} 97f4a2713aSLionel Sambuc 98f4a2713aSLionel Sambuc- (id)valueForUndefinedKey:(NSString*)key 99f4a2713aSLionel Sambuc{ 100f4a2713aSLionel Sambuc id value = 0; 101f4a2713aSLionel Sambuc 102f4a2713aSLionel Sambuc if ([key isEqualToString:@"MyIvarNumberAsPropertyOverReleased"]) 103f4a2713aSLionel Sambuc value = self.myNumber; // _myNumber will be over released, since the value returned from self.myNumber is not retained. 104f4a2713aSLionel Sambuc else if ([key isEqualToString:@"MyIvarNumberAsPropertyOk"]) 105f4a2713aSLionel Sambuc value = [self.myNumber retain]; // this line fixes the over release 106f4a2713aSLionel Sambuc else if ([key isEqualToString:@"MyIvarNumberAsNewMyNumber"]) 107f4a2713aSLionel Sambuc value = self.newMyNumber; // this one is ok, since value is returned retained 108f4a2713aSLionel Sambuc else 109f4a2713aSLionel Sambuc value = [[NSNumber alloc] initWithInteger:0]; 110f4a2713aSLionel Sambuc 111f4a2713aSLionel Sambuc return [value autorelease]; // expected-warning {{Object autoreleased too many times}} 112f4a2713aSLionel Sambuc} 113f4a2713aSLionel Sambuc 114f4a2713aSLionel Sambuc@end 115f4a2713aSLionel Sambuc 116f4a2713aSLionel SambucNSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber) 117f4a2713aSLionel Sambuc{ 118f4a2713aSLionel Sambuc NSNumber* result = aMyNumber.myNumber; 119f4a2713aSLionel Sambuc 120f4a2713aSLionel Sambuc return [result autorelease]; // expected-warning {{Object autoreleased too many times}} 121f4a2713aSLionel Sambuc} 122f4a2713aSLionel Sambuc 123*0a6a1f1dSLionel Sambuc#endif 124*0a6a1f1dSLionel Sambuc 125f4a2713aSLionel Sambuc 126f4a2713aSLionel Sambuc// rdar://6611873 127f4a2713aSLionel Sambuc 128f4a2713aSLionel Sambuc@interface Person : NSObject { 129f4a2713aSLionel Sambuc NSString *_name; 130f4a2713aSLionel Sambuc} 131f4a2713aSLionel Sambuc@property (retain) NSString * name; 132*0a6a1f1dSLionel Sambuc@property (assign) id friend; 133f4a2713aSLionel Sambuc@end 134f4a2713aSLionel Sambuc 135f4a2713aSLionel Sambuc@implementation Person 136f4a2713aSLionel Sambuc@synthesize name = _name; 137f4a2713aSLionel Sambuc@end 138f4a2713aSLionel Sambuc 139*0a6a1f1dSLionel Sambuc#if !__has_feature(objc_arc) 140f4a2713aSLionel Sambucvoid rdar6611873() { 141f4a2713aSLionel Sambuc Person *p = [[[Person alloc] init] autorelease]; 142f4a2713aSLionel Sambuc 143f4a2713aSLionel Sambuc p.name = [[NSString string] retain]; // expected-warning {{leak}} 144f4a2713aSLionel Sambuc p.name = [[NSString alloc] init]; // expected-warning {{leak}} 145*0a6a1f1dSLionel Sambuc 146*0a6a1f1dSLionel Sambuc p.friend = [[Person alloc] init]; // expected-warning {{leak}} 147f4a2713aSLionel Sambuc} 148*0a6a1f1dSLionel Sambuc#endif 149f4a2713aSLionel Sambuc 150f4a2713aSLionel Sambuc@interface SubPerson : Person 151f4a2713aSLionel Sambuc-(NSString *)foo; 152f4a2713aSLionel Sambuc@end 153f4a2713aSLionel Sambuc 154f4a2713aSLionel Sambuc@implementation SubPerson 155f4a2713aSLionel Sambuc-(NSString *)foo { 156f4a2713aSLionel Sambuc return super.name; 157f4a2713aSLionel Sambuc} 158f4a2713aSLionel Sambuc@end 159f4a2713aSLionel Sambuc 160*0a6a1f1dSLionel Sambuc 161*0a6a1f1dSLionel Sambuc#if !__has_feature(objc_arc) 162f4a2713aSLionel Sambuc// <rdar://problem/9241180> Static analyzer doesn't detect uninitialized variable issues for property accesses 163f4a2713aSLionel Sambuc@interface RDar9241180 164f4a2713aSLionel Sambuc@property (readwrite,assign) id x; 165f4a2713aSLionel Sambuc-(id)testAnalyzer1:(int) y; 166f4a2713aSLionel Sambuc-(void)testAnalyzer2; 167f4a2713aSLionel Sambuc@end 168f4a2713aSLionel Sambuc 169f4a2713aSLionel Sambuc@implementation RDar9241180 170f4a2713aSLionel Sambuc@synthesize x; 171f4a2713aSLionel Sambuc-(id)testAnalyzer1:(int)y { 172f4a2713aSLionel Sambuc RDar9241180 *o; 173f4a2713aSLionel Sambuc if (y && o.x) // expected-warning {{Property access on an uninitialized object pointer}} 174f4a2713aSLionel Sambuc return o; 175f4a2713aSLionel Sambuc return o; // expected-warning {{Undefined or garbage value returned to caller}} 176f4a2713aSLionel Sambuc} 177f4a2713aSLionel Sambuc-(void)testAnalyzer2 { 178f4a2713aSLionel Sambuc id y; 179f4a2713aSLionel Sambuc self.x = y; // expected-warning {{Argument for property setter is an uninitialized value}} 180f4a2713aSLionel Sambuc} 181f4a2713aSLionel Sambuc@end 182*0a6a1f1dSLionel Sambuc#endif 183f4a2713aSLionel Sambuc 184f4a2713aSLionel Sambuc 185*0a6a1f1dSLionel Sambuc//------ 186*0a6a1f1dSLionel Sambuc// Property accessor synthesis 187*0a6a1f1dSLionel Sambuc//------ 188*0a6a1f1dSLionel Sambuc 189*0a6a1f1dSLionel Sambucextern void doSomethingWithPerson(Person *p); 190*0a6a1f1dSLionel Sambucextern void doSomethingWithName(NSString *name); 191*0a6a1f1dSLionel Sambuc 192*0a6a1f1dSLionel Sambucvoid testConsistencyRetain(Person *p) { 193*0a6a1f1dSLionel Sambuc clang_analyzer_eval(p.name == p.name); // expected-warning{{TRUE}} 194*0a6a1f1dSLionel Sambuc 195*0a6a1f1dSLionel Sambuc id origName = p.name; 196*0a6a1f1dSLionel Sambuc clang_analyzer_eval(p.name == origName); // expected-warning{{TRUE}} 197*0a6a1f1dSLionel Sambuc doSomethingWithPerson(p); 198*0a6a1f1dSLionel Sambuc clang_analyzer_eval(p.name == origName); // expected-warning{{UNKNOWN}} 199*0a6a1f1dSLionel Sambuc} 200*0a6a1f1dSLionel Sambuc 201*0a6a1f1dSLionel Sambucvoid testConsistencyAssign(Person *p) { 202*0a6a1f1dSLionel Sambuc clang_analyzer_eval(p.friend == p.friend); // expected-warning{{TRUE}} 203*0a6a1f1dSLionel Sambuc 204*0a6a1f1dSLionel Sambuc id origFriend = p.friend; 205*0a6a1f1dSLionel Sambuc clang_analyzer_eval(p.friend == origFriend); // expected-warning{{TRUE}} 206*0a6a1f1dSLionel Sambuc doSomethingWithPerson(p); 207*0a6a1f1dSLionel Sambuc clang_analyzer_eval(p.friend == origFriend); // expected-warning{{UNKNOWN}} 208*0a6a1f1dSLionel Sambuc} 209*0a6a1f1dSLionel Sambuc 210*0a6a1f1dSLionel Sambuc#if !__has_feature(objc_arc) 211*0a6a1f1dSLionel Sambucvoid testOverrelease(Person *p, int coin) { 212*0a6a1f1dSLionel Sambuc switch (coin) { 213*0a6a1f1dSLionel Sambuc case 0: 214*0a6a1f1dSLionel Sambuc [p.name release]; // expected-warning{{not owned}} 215*0a6a1f1dSLionel Sambuc break; 216*0a6a1f1dSLionel Sambuc case 1: 217*0a6a1f1dSLionel Sambuc [p.friend release]; // expected-warning{{not owned}} 218*0a6a1f1dSLionel Sambuc break; 219*0a6a1f1dSLionel Sambuc case 2: { 220*0a6a1f1dSLionel Sambuc id friend = p.friend; 221*0a6a1f1dSLionel Sambuc doSomethingWithPerson(p); 222*0a6a1f1dSLionel Sambuc [friend release]; // expected-warning{{not owned}} 223*0a6a1f1dSLionel Sambuc } 224*0a6a1f1dSLionel Sambuc } 225*0a6a1f1dSLionel Sambuc} 226*0a6a1f1dSLionel Sambuc 227*0a6a1f1dSLionel Sambuc// <rdar://problem/16333368> 228*0a6a1f1dSLionel Sambuc@implementation Person (Rdar16333368) 229*0a6a1f1dSLionel Sambuc 230*0a6a1f1dSLionel Sambuc- (void)testDeliberateRelease:(Person *)other { 231*0a6a1f1dSLionel Sambuc doSomethingWithName(self.name); 232*0a6a1f1dSLionel Sambuc [_name release]; // no-warning 233*0a6a1f1dSLionel Sambuc self->_name = 0; 234*0a6a1f1dSLionel Sambuc 235*0a6a1f1dSLionel Sambuc doSomethingWithName(other->_name); 236*0a6a1f1dSLionel Sambuc [other.name release]; // expected-warning{{not owned}} 237*0a6a1f1dSLionel Sambuc} 238*0a6a1f1dSLionel Sambuc 239*0a6a1f1dSLionel Sambuc- (void)deliberateReleaseFalseNegative { 240*0a6a1f1dSLionel Sambuc // This is arguably a false negative because the result of p.friend shouldn't 241*0a6a1f1dSLionel Sambuc // be released, even though we are manipulating the ivar in between the two 242*0a6a1f1dSLionel Sambuc // actions. 243*0a6a1f1dSLionel Sambuc id name = self.name; 244*0a6a1f1dSLionel Sambuc _name = 0; 245*0a6a1f1dSLionel Sambuc [name release]; 246*0a6a1f1dSLionel Sambuc} 247*0a6a1f1dSLionel Sambuc 248*0a6a1f1dSLionel Sambuc- (void)testRetainAndRelease { 249*0a6a1f1dSLionel Sambuc [self.name retain]; 250*0a6a1f1dSLionel Sambuc [self.name release]; 251*0a6a1f1dSLionel Sambuc [self.name release]; // expected-warning{{not owned}} 252*0a6a1f1dSLionel Sambuc} 253*0a6a1f1dSLionel Sambuc 254*0a6a1f1dSLionel Sambuc- (void)testRetainAndReleaseIVar { 255*0a6a1f1dSLionel Sambuc [self.name retain]; 256*0a6a1f1dSLionel Sambuc [_name release]; 257*0a6a1f1dSLionel Sambuc [_name release]; // expected-warning{{not owned}} 258*0a6a1f1dSLionel Sambuc} 259*0a6a1f1dSLionel Sambuc 260*0a6a1f1dSLionel Sambuc@end 261*0a6a1f1dSLionel Sambuc#endif 262*0a6a1f1dSLionel Sambuc 263*0a6a1f1dSLionel Sambuc@interface IntWrapper 264*0a6a1f1dSLionel Sambuc@property int value; 265*0a6a1f1dSLionel Sambuc@end 266*0a6a1f1dSLionel Sambuc 267*0a6a1f1dSLionel Sambuc@implementation IntWrapper 268*0a6a1f1dSLionel Sambuc@synthesize value; 269*0a6a1f1dSLionel Sambuc@end 270*0a6a1f1dSLionel Sambuc 271*0a6a1f1dSLionel Sambucvoid testConsistencyInt(IntWrapper *w) { 272*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} 273*0a6a1f1dSLionel Sambuc 274*0a6a1f1dSLionel Sambuc int origValue = w.value; 275*0a6a1f1dSLionel Sambuc if (origValue != 42) 276*0a6a1f1dSLionel Sambuc return; 277*0a6a1f1dSLionel Sambuc 278*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 279*0a6a1f1dSLionel Sambuc} 280*0a6a1f1dSLionel Sambuc 281*0a6a1f1dSLionel Sambucvoid testConsistencyInt2(IntWrapper *w) { 282*0a6a1f1dSLionel Sambuc if (w.value != 42) 283*0a6a1f1dSLionel Sambuc return; 284*0a6a1f1dSLionel Sambuc 285*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 286*0a6a1f1dSLionel Sambuc} 287*0a6a1f1dSLionel Sambuc 288*0a6a1f1dSLionel Sambuc 289*0a6a1f1dSLionel Sambuc@interface IntWrapperAuto 290*0a6a1f1dSLionel Sambuc@property int value; 291*0a6a1f1dSLionel Sambuc@end 292*0a6a1f1dSLionel Sambuc 293*0a6a1f1dSLionel Sambuc@implementation IntWrapperAuto 294*0a6a1f1dSLionel Sambuc@end 295*0a6a1f1dSLionel Sambuc 296*0a6a1f1dSLionel Sambucvoid testConsistencyIntAuto(IntWrapperAuto *w) { 297*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} 298*0a6a1f1dSLionel Sambuc 299*0a6a1f1dSLionel Sambuc int origValue = w.value; 300*0a6a1f1dSLionel Sambuc if (origValue != 42) 301*0a6a1f1dSLionel Sambuc return; 302*0a6a1f1dSLionel Sambuc 303*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 304*0a6a1f1dSLionel Sambuc} 305*0a6a1f1dSLionel Sambuc 306*0a6a1f1dSLionel Sambucvoid testConsistencyIntAuto2(IntWrapperAuto *w) { 307*0a6a1f1dSLionel Sambuc if (w.value != 42) 308*0a6a1f1dSLionel Sambuc return; 309*0a6a1f1dSLionel Sambuc 310*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 311*0a6a1f1dSLionel Sambuc} 312*0a6a1f1dSLionel Sambuc 313*0a6a1f1dSLionel Sambuc 314*0a6a1f1dSLionel Sambuctypedef struct { 315*0a6a1f1dSLionel Sambuc int value; 316*0a6a1f1dSLionel Sambuc} IntWrapperStruct; 317*0a6a1f1dSLionel Sambuc 318*0a6a1f1dSLionel Sambuc@interface StructWrapper 319*0a6a1f1dSLionel Sambuc@property IntWrapperStruct inner; 320*0a6a1f1dSLionel Sambuc@end 321*0a6a1f1dSLionel Sambuc 322*0a6a1f1dSLionel Sambuc@implementation StructWrapper 323*0a6a1f1dSLionel Sambuc@synthesize inner; 324*0a6a1f1dSLionel Sambuc@end 325*0a6a1f1dSLionel Sambuc 326*0a6a1f1dSLionel Sambucvoid testConsistencyStruct(StructWrapper *w) { 327*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}} 328*0a6a1f1dSLionel Sambuc 329*0a6a1f1dSLionel Sambuc int origValue = w.inner.value; 330*0a6a1f1dSLionel Sambuc if (origValue != 42) 331*0a6a1f1dSLionel Sambuc return; 332*0a6a1f1dSLionel Sambuc 333*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}} 334*0a6a1f1dSLionel Sambuc} 335*0a6a1f1dSLionel Sambuc 336*0a6a1f1dSLionel Sambuc 337*0a6a1f1dSLionel Sambuc@interface OpaqueIntWrapper 338*0a6a1f1dSLionel Sambuc@property int value; 339*0a6a1f1dSLionel Sambuc@end 340*0a6a1f1dSLionel Sambuc 341*0a6a1f1dSLionel Sambuc// For now, don't assume a property is implemented using an ivar unless we can 342*0a6a1f1dSLionel Sambuc// actually see that it is. 343*0a6a1f1dSLionel Sambucvoid testOpaqueConsistency(OpaqueIntWrapper *w) { 344*0a6a1f1dSLionel Sambuc clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}} 345*0a6a1f1dSLionel Sambuc} 346*0a6a1f1dSLionel Sambuc 347