1// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s 2// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s 3 4void clang_analyzer_eval(int); 5 6typedef const void * CFTypeRef; 7extern CFTypeRef CFRetain(CFTypeRef cf); 8void CFRelease(CFTypeRef cf); 9 10typedef signed char BOOL; 11typedef unsigned int NSUInteger; 12typedef struct _NSZone NSZone; 13@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 14@protocol NSObject - (BOOL)isEqual:(id)object; @end 15@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end 16@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end 17@protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end 18@interface NSObject <NSObject> {} 19+(id)alloc; 20-(id)init; 21-(id)autorelease; 22-(id)copy; 23-(id)retain; 24-(oneway void)release; 25@end 26@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> 27- (NSUInteger)length; 28-(id)initWithFormat:(NSString *)f,...; 29-(BOOL)isEqualToString:(NSString *)s; 30+ (id)string; 31@end 32@interface NSNumber : NSObject {} 33+(id)alloc; 34-(id)initWithInteger:(int)i; 35@end 36 37// rdar://6946338 38 39@interface Test1 : NSObject { 40 NSString *text; 41} 42-(id)myMethod; 43@property (nonatomic, assign) NSString *text; 44@end 45 46 47#if !__has_feature(objc_arc) 48 49@implementation Test1 50 51@synthesize text; 52 53-(id)myMethod { 54 Test1 *cell = [[[Test1 alloc] init] autorelease]; 55 56 NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // expected-warning {{Potential leak}} 57 cell.text = string1; 58 59 return cell; 60} 61 62@end 63 64 65// rdar://8824416 66 67@interface MyNumber : NSObject 68{ 69 NSNumber* _myNumber; 70} 71 72- (id)initWithNumber:(NSNumber *)number; 73 74@property (nonatomic, readonly) NSNumber* myNumber; 75@property (nonatomic, readonly) NSNumber* newMyNumber; 76 77@end 78 79@implementation MyNumber 80@synthesize myNumber=_myNumber; 81 82- (id)initWithNumber:(NSNumber *)number 83{ 84 self = [super init]; 85 86 if ( self ) 87 { 88 _myNumber = [number copy]; 89 } 90 91 return self; 92} 93 94- (NSNumber*)newMyNumber 95{ 96 if ( _myNumber ) 97 return [_myNumber retain]; 98 99 return [[NSNumber alloc] initWithInteger:1]; 100} 101 102- (id)valueForUndefinedKey:(NSString*)key 103{ 104 id value = 0; 105 106 if ([key isEqualToString:@"MyIvarNumberAsPropertyOverReleased"]) 107 value = self.myNumber; // _myNumber will be over released, since the value returned from self.myNumber is not retained. 108 else if ([key isEqualToString:@"MyIvarNumberAsPropertyOk"]) 109 value = [self.myNumber retain]; // this line fixes the over release 110 else if ([key isEqualToString:@"MyIvarNumberAsNewMyNumber"]) 111 value = self.newMyNumber; // this one is ok, since value is returned retained 112 else 113 value = [[NSNumber alloc] initWithInteger:0]; 114 115 return [value autorelease]; // expected-warning {{Object autoreleased too many times}} 116} 117 118@end 119 120NSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber) 121{ 122 NSNumber* result = aMyNumber.myNumber; 123 124 return [result autorelease]; // expected-warning {{Object autoreleased too many times}} 125} 126 127#endif 128 129 130// rdar://6611873 131 132@interface Person : NSObject { 133 NSString *_name; 134} 135@property (retain) NSString * name; 136@property (assign) id friend; 137@end 138 139@implementation Person 140@synthesize name = _name; 141@end 142 143#if !__has_feature(objc_arc) 144void rdar6611873() { 145 Person *p = [[[Person alloc] init] autorelease]; 146 147 p.name = [[NSString string] retain]; // expected-warning {{leak}} 148 p.name = [[NSString alloc] init]; // expected-warning {{leak}} 149 150 p.friend = [[Person alloc] init]; // expected-warning {{leak}} 151} 152#endif 153 154@interface SubPerson : Person 155-(NSString *)foo; 156@end 157 158@implementation SubPerson 159-(NSString *)foo { 160 return super.name; 161} 162@end 163 164 165#if !__has_feature(objc_arc) 166// <rdar://problem/9241180> Static analyzer doesn't detect uninitialized variable issues for property accesses 167@interface RDar9241180 168@property (readwrite,assign) id x; 169-(id)testAnalyzer1:(int) y; 170-(void)testAnalyzer2; 171@end 172 173@implementation RDar9241180 174@synthesize x; 175-(id)testAnalyzer1:(int)y { 176 RDar9241180 *o; 177 if (y && o.x) // expected-warning {{Property access on an uninitialized object pointer}} 178 return o; 179 return o; // expected-warning {{Undefined or garbage value returned to caller}} 180} 181-(void)testAnalyzer2 { 182 id y; 183 self.x = y; // expected-warning {{Argument for property setter is an uninitialized value}} 184} 185@end 186#endif 187 188 189//------ 190// Property accessor synthesis 191//------ 192 193extern void doSomethingWithPerson(Person *p); 194extern void doSomethingWithName(NSString *name); 195 196void testConsistencyRetain(Person *p) { 197 clang_analyzer_eval(p.name == p.name); // expected-warning{{TRUE}} 198 199 id origName = p.name; 200 clang_analyzer_eval(p.name == origName); // expected-warning{{TRUE}} 201 doSomethingWithPerson(p); 202 clang_analyzer_eval(p.name == origName); // expected-warning{{UNKNOWN}} 203} 204 205void testConsistencyAssign(Person *p) { 206 clang_analyzer_eval(p.friend == p.friend); // expected-warning{{TRUE}} 207 208 id origFriend = p.friend; 209 clang_analyzer_eval(p.friend == origFriend); // expected-warning{{TRUE}} 210 doSomethingWithPerson(p); 211 clang_analyzer_eval(p.friend == origFriend); // expected-warning{{UNKNOWN}} 212} 213 214#if !__has_feature(objc_arc) 215void testOverrelease(Person *p, int coin) { 216 switch (coin) { 217 case 0: 218 [p.name release]; // expected-warning{{not owned}} 219 break; 220 case 1: 221 [p.friend release]; // expected-warning{{not owned}} 222 break; 223 case 2: { 224 id friend = p.friend; 225 doSomethingWithPerson(p); 226 [friend release]; // expected-warning{{not owned}} 227 } 228 } 229} 230 231// <rdar://problem/16333368> 232@implementation Person (Rdar16333368) 233 234- (void)testDeliberateRelease:(Person *)other { 235 doSomethingWithName(self.name); 236 [_name release]; // no-warning 237 self->_name = 0; 238 239 doSomethingWithName(other->_name); 240 [other.name release]; // no-warning 241} 242 243- (void)deliberateReleaseFalseNegative { 244 // This is arguably a false negative because the result of p.friend shouldn't 245 // be released, even though we are manipulating the ivar in between the two 246 // actions. 247 id name = self.name; 248 _name = 0; 249 [name release]; 250} 251 252- (void)testRetainAndRelease { 253 [self.name retain]; 254 [self.name release]; 255 [self.name release]; // expected-warning{{not owned}} 256} 257 258- (void)testRetainAndReleaseIVar { 259 [self.name retain]; 260 [_name release]; 261 [_name release]; 262} 263 264@end 265#endif 266 267@interface IntWrapper 268@property int value; 269@end 270 271@implementation IntWrapper 272@synthesize value; 273@end 274 275void testConsistencyInt(IntWrapper *w) { 276 clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} 277 278 int origValue = w.value; 279 if (origValue != 42) 280 return; 281 282 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 283} 284 285void testConsistencyInt2(IntWrapper *w) { 286 if (w.value != 42) 287 return; 288 289 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 290} 291 292 293@interface IntWrapperAuto 294@property int value; 295@end 296 297@implementation IntWrapperAuto 298@end 299 300void testConsistencyIntAuto(IntWrapperAuto *w) { 301 clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} 302 303 int origValue = w.value; 304 if (origValue != 42) 305 return; 306 307 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 308} 309 310void testConsistencyIntAuto2(IntWrapperAuto *w) { 311 if (w.value != 42) 312 return; 313 314 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 315} 316 317 318typedef struct { 319 int value; 320} IntWrapperStruct; 321 322@interface StructWrapper 323@property IntWrapperStruct inner; 324@end 325 326@implementation StructWrapper 327@synthesize inner; 328@end 329 330void testConsistencyStruct(StructWrapper *w) { 331 clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}} 332 333 int origValue = w.inner.value; 334 if (origValue != 42) 335 return; 336 337 clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}} 338} 339 340 341@interface OpaqueIntWrapper 342@property int value; 343@end 344 345// For now, don't assume a property is implemented using an ivar unless we can 346// actually see that it is. 347void testOpaqueConsistency(OpaqueIntWrapper *w) { 348 clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}} 349} 350 351 352#if !__has_feature(objc_arc) 353// Test quite a few cases of retain/release issues. 354 355@interface RetainCountTesting 356@property (strong) id ownedProp; 357@property (unsafe_unretained) id unownedProp; 358@property (nonatomic, strong) id manualProp; 359@property (readonly) id readonlyProp; 360@property (nonatomic, readwrite/*, assign */) id implicitManualProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}} 361@property (nonatomic, readwrite/*, assign */) id implicitSynthProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}} 362@property CFTypeRef cfProp; 363@end 364 365@implementation RetainCountTesting { 366 id _ivarOnly; 367} 368 369- (id)manualProp { 370 return _manualProp; 371} 372 373- (void)setImplicitManualProp:(id)newValue {} 374 375- (void)testOverreleaseOwnedIvar { 376 [_ownedProp retain]; 377 [_ownedProp release]; 378 [_ownedProp release]; 379 [_ownedProp release]; // FIXME-warning{{used after it is released}} 380} 381 382- (void)testOverreleaseUnownedIvar { 383 [_unownedProp retain]; 384 [_unownedProp release]; 385 [_unownedProp release]; // FIXME-warning{{not owned at this point by the caller}} 386} 387 388- (void)testOverreleaseIvarOnly { 389 [_ivarOnly retain]; 390 [_ivarOnly release]; 391 [_ivarOnly release]; 392 [_ivarOnly release]; // FIXME-warning{{used after it is released}} 393} 394 395- (void)testOverreleaseReadonlyIvar { 396 [_readonlyProp retain]; 397 [_readonlyProp release]; 398 [_readonlyProp release]; 399 [_readonlyProp release]; // FIXME-warning{{used after it is released}} 400} 401 402- (void)testOverreleaseImplicitManualIvar { 403 [_implicitManualProp retain]; 404 [_implicitManualProp release]; 405 [_implicitManualProp release]; 406 [_implicitManualProp release]; // FIXME-warning{{used after it is released}} 407} 408 409- (void)testOverreleaseImplicitSynthIvar { 410 [_implicitSynthProp retain]; 411 [_implicitSynthProp release]; 412 [_implicitSynthProp release]; // FIXME-warning{{not owned at this point by the caller}} 413} 414 415- (void)testOverreleaseCF { 416 CFRetain(_cfProp); 417 CFRelease(_cfProp); 418 CFRelease(_cfProp); 419 CFRelease(_cfProp); // FIXME-warning{{used after it is released}} 420} 421 422- (void)testOverreleaseOwnedIvarUse { 423 [_ownedProp retain]; 424 [_ownedProp release]; 425 [_ownedProp release]; 426 [_ownedProp myMethod]; // FIXME-warning{{used after it is released}} 427} 428 429- (void)testOverreleaseIvarOnlyUse { 430 [_ivarOnly retain]; 431 [_ivarOnly release]; 432 [_ivarOnly release]; 433 [_ivarOnly myMethod]; // FIXME-warning{{used after it is released}} 434} 435 436- (void)testOverreleaseCFUse { 437 CFRetain(_cfProp); 438 CFRelease(_cfProp); 439 CFRelease(_cfProp); 440 441 extern void CFUse(CFTypeRef); 442 CFUse(_cfProp); // FIXME-warning{{used after it is released}} 443} 444 445- (void)testOverreleaseOwnedIvarAutoreleaseOkay { 446 [_ownedProp retain]; 447 [_ownedProp release]; 448 [_ownedProp autorelease]; 449} // no-warning 450 451- (void)testOverreleaseIvarOnlyAutoreleaseOkay { 452 [_ivarOnly retain]; 453 [_ivarOnly release]; 454 [_ivarOnly autorelease]; 455} // no-warning 456 457- (void)testOverreleaseOwnedIvarAutorelease { 458 [_ownedProp retain]; 459 [_ownedProp release]; 460 [_ownedProp autorelease]; 461 [_ownedProp autorelease]; 462} // FIXME-warning{{Object autoreleased too many times}} 463 464- (void)testOverreleaseIvarOnlyAutorelease { 465 [_ivarOnly retain]; 466 [_ivarOnly release]; 467 [_ivarOnly autorelease]; 468 [_ivarOnly autorelease]; 469} // FIXME-warning{{Object autoreleased too many times}} 470 471- (void)testPropertyAccessThenReleaseOwned { 472 id owned = [self.ownedProp retain]; 473 [owned release]; 474 [_ownedProp release]; 475 clang_analyzer_eval(owned == _ownedProp); // expected-warning{{TRUE}} 476} 477 478- (void)testPropertyAccessThenReleaseOwned2 { 479 id fromIvar = _ownedProp; 480 id owned = [self.ownedProp retain]; 481 [owned release]; 482 [fromIvar release]; 483 clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}} 484} 485 486- (void)testPropertyAccessThenReleaseUnowned { 487 id unowned = [self.unownedProp retain]; 488 [unowned release]; 489 [_unownedProp release]; // FIXME-warning{{not owned}} 490} 491 492- (void)testPropertyAccessThenReleaseUnowned2 { 493 id fromIvar = _unownedProp; 494 id unowned = [self.unownedProp retain]; 495 [unowned release]; 496 clang_analyzer_eval(unowned == fromIvar); // expected-warning{{TRUE}} 497 [fromIvar release]; // FIXME-warning{{not owned}} 498} 499 500- (void)testPropertyAccessThenReleaseManual { 501 id prop = [self.manualProp retain]; 502 [prop release]; 503 [_manualProp release]; // no-warning 504} 505 506- (void)testPropertyAccessThenReleaseManual2 { 507 id fromIvar = _manualProp; 508 id prop = [self.manualProp retain]; 509 [prop release]; 510 clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} 511 [fromIvar release]; // no-warning 512} 513 514- (void)testPropertyAccessThenReleaseCF { 515 CFTypeRef owned = CFRetain(self.cfProp); 516 CFRelease(owned); 517 CFRelease(_cfProp); // no-warning 518 clang_analyzer_eval(owned == _cfProp); // expected-warning{{TRUE}} 519} 520 521- (void)testPropertyAccessThenReleaseCF2 { 522 CFTypeRef fromIvar = _cfProp; 523 CFTypeRef owned = CFRetain(self.cfProp); 524 CFRelease(owned); 525 CFRelease(fromIvar); 526 clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}} 527} 528 529- (void)testPropertyAccessThenReleaseReadonly { 530 id prop = [self.readonlyProp retain]; 531 [prop release]; 532 [_readonlyProp release]; // no-warning 533} 534 535- (void)testPropertyAccessThenReleaseReadonly2 { 536 id fromIvar = _readonlyProp; 537 id prop = [self.readonlyProp retain]; 538 [prop release]; 539 clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} 540 [fromIvar release]; // no-warning 541} 542 543- (void)testPropertyAccessThenReleaseImplicitManual { 544 id prop = [self.implicitManualProp retain]; 545 [prop release]; 546 [_implicitManualProp release]; // no-warning 547} 548 549- (void)testPropertyAccessThenReleaseImplicitManual2 { 550 id fromIvar = _implicitManualProp; 551 id prop = [self.implicitManualProp retain]; 552 [prop release]; 553 clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} 554 [fromIvar release]; // no-warning 555} 556 557- (void)testPropertyAccessThenReleaseImplicitSynth { 558 id prop = [self.implicitSynthProp retain]; 559 [prop release]; 560 [_implicitSynthProp release]; // FIXME-warning{{not owned}} 561} 562 563- (void)testPropertyAccessThenReleaseImplicitSynth2 { 564 id fromIvar = _implicitSynthProp; 565 id prop = [self.implicitSynthProp retain]; 566 [prop release]; 567 clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} 568 [fromIvar release]; // FIXME-warning{{not owned}} 569} 570 571- (id)getUnownedFromProperty { 572 [_ownedProp retain]; 573 [_ownedProp autorelease]; 574 return _ownedProp; // no-warning 575} 576 577- (id)transferUnownedFromProperty { 578 [_ownedProp retain]; 579 [_ownedProp autorelease]; 580 return [_ownedProp autorelease]; // no-warning 581} 582 583- (id)transferOwnedFromProperty __attribute__((ns_returns_retained)) { 584 [_ownedProp retain]; 585 [_ownedProp autorelease]; 586 return _ownedProp; // no-warning 587} 588 589- (void)testAssignOwned:(id)newValue { 590 _ownedProp = newValue; 591 [_ownedProp release]; // FIXME: no-warning{{not owned}} 592} 593 594- (void)testAssignUnowned:(id)newValue { 595 _unownedProp = newValue; 596 [_unownedProp release]; // FIXME: no-warning{{not owned}} 597} 598 599- (void)testAssignIvarOnly:(id)newValue { 600 _ivarOnly = newValue; 601 [_ivarOnly release]; // FIXME: no-warning{{not owned}} 602} 603 604- (void)testAssignCF:(CFTypeRef)newValue { 605 _cfProp = newValue; 606 CFRelease(_cfProp); // FIXME: no-warning{{not owned}} 607} 608 609- (void)testAssignReadonly:(id)newValue { 610 _readonlyProp = newValue; 611 [_readonlyProp release]; // FIXME: no-warning{{not owned}} 612} 613 614- (void)testAssignImplicitManual:(id)newValue { 615 _implicitManualProp = newValue; 616 [_implicitManualProp release]; // FIXME: no-warning{{not owned}} 617} 618 619- (void)testAssignImplicitSynth:(id)newValue { 620 _implicitSynthProp = newValue; 621 [_implicitSynthProp release]; // FIXME: no-warning{{not owned}} 622} 623 624- (void)testAssignOwnedOkay:(id)newValue { 625 _ownedProp = [newValue retain]; 626 [_ownedProp release]; // no-warning 627} 628 629- (void)testAssignUnownedOkay:(id)newValue { 630 _unownedProp = [newValue retain]; 631 [_unownedProp release]; // no-warning 632} 633 634- (void)testAssignIvarOnlyOkay:(id)newValue { 635 _ivarOnly = [newValue retain]; 636 [_ivarOnly release]; // no-warning 637} 638 639- (void)testAssignCFOkay:(CFTypeRef)newValue { 640 _cfProp = CFRetain(newValue); 641 CFRelease(_cfProp); // no-warning 642} 643 644- (void)testAssignReadonlyOkay:(id)newValue { 645 _readonlyProp = [newValue retain]; 646 [_readonlyProp release]; // FIXME: no-warning{{not owned}} 647} 648 649- (void)testAssignImplicitManualOkay:(id)newValue { 650 _implicitManualProp = [newValue retain]; 651 [_implicitManualProp release]; // FIXME: no-warning{{not owned}} 652} 653 654- (void)testAssignImplicitSynthOkay:(id)newValue { 655 _implicitSynthProp = [newValue retain]; 656 [_implicitSynthProp release]; // FIXME: no-warning{{not owned}} 657} 658 659// rdar://problem/19862648 660- (void)establishIvarIsNilDuringLoops { 661 extern id getRandomObject(); 662 663 int i = 4; // Must be at least 4 to trigger the bug. 664 while (--i) { 665 id x = 0; 666 if (getRandomObject()) 667 x = _ivarOnly; 668 if (!x) 669 x = getRandomObject(); 670 [x myMethod]; 671 } 672} 673 674// rdar://problem/20335433 675- (void)retainIvarAndInvalidateSelf { 676 extern void invalidate(id); 677 [_unownedProp retain]; 678 invalidate(self); 679 [_unownedProp release]; // no-warning 680} 681 682@end 683#endif // non-ARC 684 685