retain-release.m revision c037eac3bda3c636c961aab6377beea3242e81e4
1//>>SLICER 2// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && 3// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic-old-cast -verify %s && 4// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s 5 6//===----------------------------------------------------------------------===// 7// The following code is reduced using delta-debugging from Mac OS X headers: 8// 9// #include <Cocoa/Cocoa.h> 10// #include <CoreFoundation/CoreFoundation.h> 11// #include <DiskArbitration/DiskArbitration.h> 12// #include <QuartzCore/QuartzCore.h> 13// #include <Quartz/Quartz.h> 14// #include <IOKit/IOKitLib.h> 15// 16// It includes the basic definitions for the test cases below. 17//===----------------------------------------------------------------------===// 18 19typedef unsigned int __darwin_natural_t; 20typedef unsigned long uintptr_t; 21typedef unsigned int uint32_t; 22typedef unsigned long long uint64_t; 23typedef unsigned int UInt32; 24typedef signed long CFIndex; 25typedef const void * CFTypeRef; 26typedef const struct __CFString * CFStringRef; 27typedef const struct __CFAllocator * CFAllocatorRef; 28extern const CFAllocatorRef kCFAllocatorDefault; 29extern CFTypeRef CFRetain(CFTypeRef cf); 30extern void CFRelease(CFTypeRef cf); 31typedef struct { 32} 33CFArrayCallBacks; 34extern const CFArrayCallBacks kCFTypeArrayCallBacks; 35typedef const struct __CFArray * CFArrayRef; 36typedef struct __CFArray * CFMutableArrayRef; 37extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks); 38extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); 39extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value); 40typedef const struct __CFDictionary * CFDictionaryRef; 41typedef struct __CFDictionary * CFMutableDictionaryRef; 42typedef UInt32 CFStringEncoding; 43enum { 44kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 }; 45extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); 46typedef double CFTimeInterval; 47typedef CFTimeInterval CFAbsoluteTime; 48extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); 49typedef const struct __CFDate * CFDateRef; 50extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); 51extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); 52typedef __darwin_natural_t natural_t; 53typedef natural_t mach_port_name_t; 54typedef mach_port_name_t mach_port_t; 55typedef int kern_return_t; 56typedef kern_return_t mach_error_t; 57typedef signed char BOOL; 58typedef unsigned long NSUInteger; 59@class NSString, Protocol; 60extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); 61typedef struct _NSZone NSZone; 62@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 63@protocol NSObject - (BOOL)isEqual:(id)object; 64- (id)retain; 65- (oneway void)release; 66- (id)autorelease; 67@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; 68@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; 69@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; 70@end @interface NSObject <NSObject> { 71} 72+ (id)allocWithZone:(NSZone *)zone; 73+ (id)alloc; 74- (void)dealloc; 75@end extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); 76typedef struct { 77} 78NSFastEnumerationState; 79@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; 80@end @class NSString; 81@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; 82@end @interface NSArray (NSArrayCreation) + (id)array; 83@end @interface NSAutoreleasePool : NSObject { 84} 85- (void)drain; 86@end extern NSString * const NSBundleDidLoadNotification; 87typedef double NSTimeInterval; 88@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate; 89@end typedef unsigned short unichar; 90@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; 91- ( const char *)UTF8String; 92- (id)initWithUTF8String:(const char *)nullTerminatedCString; 93+ (id)stringWithUTF8String:(const char *)nullTerminatedCString; 94@end @class NSString, NSData; 95@interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; 96+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length; 97+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b; 98@end @class NSString; 99@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; 100@end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; 101- (void)setObject:(id)anObject forKey:(id)aKey; 102@end @interface NSMutableDictionary (NSMutableDictionaryCreation) + (id)dictionaryWithCapacity:(NSUInteger)numItems; 103@end typedef double CGFloat; 104struct CGSize { 105}; 106typedef struct CGSize CGSize; 107struct CGRect { 108}; 109typedef struct CGRect CGRect; 110@protocol NSLocking - (void)lock; 111- (id)init; 112@end @class NSURLAuthenticationChallenge; 113typedef mach_port_t io_object_t; 114typedef char io_name_t[128]; 115typedef io_object_t io_iterator_t; 116typedef io_object_t io_service_t; 117typedef struct IONotificationPort * IONotificationPortRef; 118typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator ); 119io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching ); 120kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing ); 121kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) __attribute__((deprecated)); 122kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification ); 123CFMutableDictionaryRef IOServiceMatching( const char * name ); 124CFMutableDictionaryRef IOServiceNameMatching( const char * name ); 125CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName ); 126CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path ); 127CFMutableDictionaryRef IORegistryEntryIDMatching( uint64_t entryID ); 128typedef struct __DASession * DASessionRef; 129extern DASessionRef DASessionCreate( CFAllocatorRef allocator ); 130typedef struct __DADisk * DADiskRef; 131extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name ); 132extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media ); 133extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk ); 134extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); 135typedef struct CGColorSpace *CGColorSpaceRef; 136typedef struct CGImage *CGImageRef; 137 typedef struct CGLayer *CGLayerRef; 138 @class NSArray, NSError, NSEvent, NSMenu, NSUndoManager, NSWindow; 139@interface NSResponder : NSObject <NSCoding> { 140} 141@end @protocol NSAnimatablePropertyContainer - (id)animator; 142@end extern NSString *NSAnimationTriggerOrderIn ; 143@interface NSView : NSResponder <NSAnimatablePropertyContainer> { 144struct __VFlags2 { 145} 146_vFlags2; 147} 148@end extern NSString * const NSFullScreenModeAllScreens; 149@protocol NSChangeSpelling - (void)changeSpelling:(id)sender; 150@end @protocol NSIgnoreMisspelledWords - (void)ignoreSpelling:(id)sender; 151@end @class NSColor, NSFont, NSNotification; 152@interface NSText : NSView <NSChangeSpelling, NSIgnoreMisspelledWords> { 153} 154@end @protocol NSValidatedUserInterfaceItem - (SEL)action; 155@end @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem; 156@end @class NSArray, NSError, NSImage, NSView, NSNotificationCenter, NSURL, NSScreen, NSRunningApplication; 157@interface NSApplication : NSResponder <NSUserInterfaceValidations> { 158} 159@end enum { 160NSTerminateCancel = 0, NSTerminateNow = 1, NSTerminateLater = 2 }; 161typedef NSUInteger NSApplicationTerminateReply; 162@protocol NSApplicationDelegate <NSObject> @optional - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; 163@end enum { 164} 165_CFlags; 166@interface CIImage : NSObject <NSCoding, NSCopying> { 167} 168typedef int CIFormat; 169@end enum { 170kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; 171typedef mach_error_t DAReturn; 172typedef const struct __DADissenter * DADissenterRef; 173extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); 174@interface CIContext: NSObject { 175} 176- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r; 177- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs; 178- (CGLayerRef)createCGLayerWithSize:(CGSize)size info:(CFDictionaryRef)d; 179@end @class NSURL; 180@protocol QCCompositionRenderer - (NSDictionary*) attributes; 181@end @interface QCRenderer : NSObject <QCCompositionRenderer> { 182} 183- (id) createSnapshotImageOfType:(NSString*)type; 184@end extern NSString* const QCViewDidStartRenderingNotification; 185@interface QCView : NSView <QCCompositionRenderer> { 186} 187- (id) createSnapshotImageOfType:(NSString*)type; 188@end enum { 189ICEXIFOrientation1 = 1, ICEXIFOrientation2 = 2, ICEXIFOrientation3 = 3, ICEXIFOrientation4 = 4, ICEXIFOrientation5 = 5, ICEXIFOrientation6 = 6, ICEXIFOrientation7 = 7, ICEXIFOrientation8 = 8, }; 190@class ICDevice; 191@protocol ICDeviceDelegate <NSObject> @required - (void)didRemoveDevice:(ICDevice*)device; 192@end @class ICCameraDevice; 193@class ICScannerDevice; 194@protocol ICScannerDeviceDelegate <ICDeviceDelegate> @optional - (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner; 195@end 196 197//===----------------------------------------------------------------------===// 198// Test cases. 199//===----------------------------------------------------------------------===// 200 201CFAbsoluteTime f1() { 202 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 203 CFDateRef date = CFDateCreate(0, t); 204 CFRetain(date); 205 CFRelease(date); 206 CFDateGetAbsoluteTime(date); // no-warning 207 CFRelease(date); 208 t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} 209 return t; 210} 211 212CFAbsoluteTime f2() { 213 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 214 CFDateRef date = CFDateCreate(0, t); 215 [((NSDate*) date) retain]; 216 CFRelease(date); 217 CFDateGetAbsoluteTime(date); // no-warning 218 [((NSDate*) date) release]; 219 t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} 220 return t; 221} 222 223 224NSDate* global_x; 225 226// Test to see if we supresss an error when we store the pointer 227// to a global. 228 229CFAbsoluteTime f3() { 230 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 231 CFDateRef date = CFDateCreate(0, t); 232 [((NSDate*) date) retain]; 233 CFRelease(date); 234 CFDateGetAbsoluteTime(date); // no-warning 235 global_x = (NSDate*) date; 236 [((NSDate*) date) release]; 237 t = CFDateGetAbsoluteTime(date); // no-warning 238 return t; 239} 240 241//--------------------------------------------------------------------------- 242// Test case 'f4' differs for region store and basic store. See 243// retain-release-region-store.m and retain-release-basic-store.m. 244//--------------------------------------------------------------------------- 245 246// Test a leak. 247 248CFAbsoluteTime f5(int x) { 249 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 250 CFDateRef date = CFDateCreate(0, t); // expected-warning{{leak}} 251 252 if (x) 253 CFRelease(date); 254 255 return t; 256} 257 258// Test a leak involving the return. 259 260CFDateRef f6(int x) { 261 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); // expected-warning{{leak}} 262 CFRetain(date); 263 return date; 264} 265 266// Test a leak involving an overwrite. 267 268CFDateRef f7() { 269 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); //expected-warning{{leak}} 270 CFRetain(date); 271 date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 272 return date; 273} 274 275// Generalization of Create rule. MyDateCreate returns a CFXXXTypeRef, and 276// has the word create. 277CFDateRef MyDateCreate(); 278 279CFDateRef f8() { 280 CFDateRef date = MyDateCreate(); // expected-warning{{leak}} 281 CFRetain(date); 282 return date; 283} 284 285CFDateRef f9() { 286 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 287 int *p = 0; 288 // When allocations fail, CFDateCreate can return null. 289 if (!date) *p = 1; // expected-warning{{null}} 290 return date; 291} 292 293// Handle DiskArbitration API: 294// 295// http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/DiscArbitrationFramework/ 296// 297void f10(io_service_t media, DADiskRef d, CFStringRef s) { 298 DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, 0, "hello"); // expected-warning{{leak}} 299 if (disk) NSLog(@"ok"); 300 301 disk = DADiskCreateFromIOMedia(kCFAllocatorDefault, 0, media); // expected-warning{{leak}} 302 if (disk) NSLog(@"ok"); 303 304 CFDictionaryRef dict = DADiskCopyDescription(d); // expected-warning{{leak}} 305 if (dict) NSLog(@"ok"); 306 307 disk = DADiskCopyWholeDisk(d); // expected-warning{{leak}} 308 if (disk) NSLog(@"ok"); 309 310 DADissenterRef dissenter = DADissenterCreate(kCFAllocatorDefault, // expected-warning{{leak}} 311 kDAReturnSuccess, s); 312 if (dissenter) NSLog(@"ok"); 313 314 DASessionRef session = DASessionCreate(kCFAllocatorDefault); // expected-warning{{leak}} 315 if (session) NSLog(@"ok"); 316} 317 318// Test retain/release checker with CFString and CFMutableArray. 319void f11() { 320 // Create the array. 321 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 322 323 // Create a string. 324 CFStringRef s1 = CFStringCreateWithCString(0, "hello world", 325 kCFStringEncodingUTF8); 326 327 // Add the string to the array. 328 CFArrayAppendValue(A, s1); 329 330 // Decrement the reference count. 331 CFRelease(s1); // no-warning 332 333 // Get the string. We don't own it. 334 s1 = (CFStringRef) CFArrayGetValueAtIndex(A, 0); 335 336 // Release the array. 337 CFRelease(A); // no-warning 338 339 // Release the string. This is a bug. 340 CFRelease(s1); // expected-warning{{Incorrect decrement of the reference count}} 341} 342 343// PR 3337: Handle functions declared using typedefs. 344typedef CFTypeRef CREATEFUN(); 345CREATEFUN MyCreateFun; 346 347void f12() { 348 CFTypeRef o = MyCreateFun(); // expected-warning {{leak}} 349} 350 351void f13_autorelease() { 352 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning 353 [(id) A autorelease]; // no-warning 354} 355 356void f13_autorelease_b() { 357 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 358 [(id) A autorelease]; 359 [(id) A autorelease]; // expected-warning{{Object sent -autorelease too many times}} 360} 361 362CFMutableArrayRef f13_autorelease_c() { 363 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 364 [(id) A autorelease]; 365 [(id) A autorelease]; 366 return A; // expected-warning{{Object sent -autorelease too many times}} 367} 368 369CFMutableArrayRef f13_autorelease_d() { 370 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 371 [(id) A autorelease]; 372 [(id) A autorelease]; 373 CFMutableArrayRef B = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{Object sent -autorelease too many times}} 374 CFRelease(B); // no-warning 375} 376 377 378// This case exercises the logic where the leak site is the same as the allocation site. 379void f14_leakimmediately() { 380 CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}} 381} 382 383// Test that we track an allocated object beyond the point where the *name* 384// of the variable storing the reference is no longer live. 385void f15() { 386 // Create the array. 387 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 388 CFMutableArrayRef *B = &A; 389 // At this point, the name 'A' is no longer live. 390 CFRelease(*B); // no-warning 391} 392 393 394// Test basic tracking of ivars associated with 'self'. For the retain/release 395// checker we currently do not want to flag leaks associated with stores 396// of tracked objects to ivars. 397@interface SelfIvarTest : NSObject { 398 id myObj; 399} 400- (void)test_self_tracking; 401@end 402 403@implementation SelfIvarTest 404- (void)test_self_tracking { 405 myObj = (id) CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning 406} 407@end 408 409// Test return of non-owned objects in contexts where an owned object 410// is expected. 411@interface TestReturnNotOwnedWhenExpectedOwned 412- (NSString*)newString; 413@end 414 415@implementation TestReturnNotOwnedWhenExpectedOwned 416- (NSString*)newString { 417 NSString *s = [NSString stringWithUTF8String:"hello"]; 418 return s; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} 419} 420@end 421 422// <rdar://problem/6659160> 423int isFoo(char c); 424 425static void rdar_6659160(char *inkind, char *inname) 426{ 427 // We currently expect that [NSObject alloc] cannot fail. This 428 // will be a toggled flag in the future. It can indeed return null, but 429 // Cocoa programmers generally aren't expected to reason about out-of-memory 430 // conditions. 431 NSString *kind = [[NSString alloc] initWithUTF8String:inkind]; // expected-warning{{leak}} 432 433 // We do allow stringWithUTF8String to fail. This isn't really correct, as 434 // far as returning 0. In most error conditions it will throw an exception. 435 // If allocation fails it could return 0, but again this 436 // isn't expected. 437 NSString *name = [NSString stringWithUTF8String:inname]; 438 if(!name) 439 return; 440 441 const char *kindC = 0; 442 const char *nameC = 0; 443 444 // In both cases, we cannot reach a point down below where we 445 // dereference kindC or nameC with either being null. This is because 446 // we assume that [NSObject alloc] doesn't fail and that we have the guard 447 // up above. 448 449 if(kind) 450 kindC = [kind UTF8String]; 451 if(name) 452 nameC = [name UTF8String]; 453 if(!isFoo(kindC[0])) // expected-warning{{null}} 454 return; 455 if(!isFoo(nameC[0])) // no-warning 456 return; 457 458 [kind release]; 459 [name release]; // expected-warning{{Incorrect decrement of the reference count}} 460} 461 462// PR 3677 - 'allocWithZone' should be treated as following the Cocoa naming 463// conventions with respect to 'return'ing ownership. 464@interface PR3677: NSObject @end 465@implementation PR3677 466+ (id)allocWithZone:(NSZone *)inZone { 467 return [super allocWithZone:inZone]; // no-warning 468} 469@end 470 471// PR 3820 - Reason about calls to -dealloc 472void pr3820_DeallocInsteadOfRelease(void) 473{ 474 id foo = [[NSString alloc] init]; // no-warning 475 [foo dealloc]; 476 // foo is not leaked, since it has been deallocated. 477} 478 479void pr3820_ReleaseAfterDealloc(void) 480{ 481 id foo = [[NSString alloc] init]; 482 [foo dealloc]; 483 [foo release]; // expected-warning{{used after it is release}} 484 // NSInternalInconsistencyException: message sent to deallocated object 485} 486 487void pr3820_DeallocAfterRelease(void) 488{ 489 NSLog(@"\n\n[%s]", __FUNCTION__); 490 id foo = [[NSString alloc] init]; 491 [foo release]; 492 [foo dealloc]; // expected-warning{{used after it is released}} 493 // message sent to released object 494} 495 496// From <rdar://problem/6704930>. The problem here is that 'length' binds to 497// '($0 - 1)' after '--length', but SimpleConstraintManager doesn't know how to 498// reason about '($0 - 1) > constant'. As a temporary hack, we drop the value 499// of '($0 - 1)' and conjure a new symbol. 500void rdar6704930(unsigned char *s, unsigned int length) { 501 NSString* name = 0; 502 if (s != 0) { 503 if (length > 0) { 504 while (length > 0) { 505 if (*s == ':') { 506 ++s; 507 --length; 508 name = [[NSString alloc] init]; // no-warning 509 break; 510 } 511 ++s; 512 --length; 513 } 514 if ((length == 0) && (name != 0)) { 515 [name release]; 516 name = 0; 517 } 518 if (length == 0) { // no ':' found -> use it all as name 519 name = [[NSString alloc] init]; // no-warning 520 } 521 } 522 } 523 524 if (name != 0) { 525 [name release]; 526 } 527} 528 529//===----------------------------------------------------------------------===// 530// <rdar://problem/6833332> 531// One build of the analyzer accidentally stopped tracking the allocated 532// object after the 'retain'. 533//===----------------------------------------------------------------------===// 534 535@interface rdar_6833332 : NSObject <NSApplicationDelegate> { 536 NSWindow *window; 537} 538@property (nonatomic, retain) NSWindow *window; 539@end 540 541@implementation rdar_6833332 542@synthesize window; 543- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 544 NSMutableDictionary *dict = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; // expected-warning{{leak}} 545 546 [dict setObject:@"foo" forKey:@"bar"]; 547 548 NSLog(@"%@", dict); 549} 550- (void)dealloc { 551 [window release]; 552 [super dealloc]; 553} 554@end 555 556//===----------------------------------------------------------------------===// 557// <rdar://problem/6257780> clang checker fails to catch use-after-release 558//===----------------------------------------------------------------------===// 559 560int rdar_6257780_Case1() { 561 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 562 NSArray *array = [NSArray array]; 563 [array release]; // expected-warning{{Incorrect decrement of the reference count of an object is not owned at this point by the caller}} 564 [pool drain]; 565 return 0; 566} 567 568//===----------------------------------------------------------------------===// 569// <rdar://problem/6866843> Checker should understand new/setObject:/release constructs 570//===----------------------------------------------------------------------===// 571 572void rdar_6866843() { 573 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 574 NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] init]; 575 NSArray* array = [[NSArray alloc] init]; 576 [dictionary setObject:array forKey:@"key"]; 577 [array release]; 578 // Using 'array' here should be fine 579 NSLog(@"array = %@\n", array); // no-warning 580 // Now the array is released 581 [dictionary release]; 582 [pool drain]; 583} 584 585 586//===----------------------------------------------------------------------===// 587// <rdar://problem/6877235> Classes typedef-ed to CF objects should get the same treatment as CF objects 588//===----------------------------------------------------------------------===// 589 590typedef CFTypeRef OtherRef; 591 592@interface RDar6877235 : NSObject {} 593- (CFTypeRef)_copyCFTypeRef; 594- (OtherRef)_copyOtherRef; 595@end 596 597@implementation RDar6877235 598- (CFTypeRef)_copyCFTypeRef { 599 return [[NSString alloc] init]; // no-warning 600} 601- (OtherRef)_copyOtherRef { 602 return [[NSString alloc] init]; // no-warning 603} 604@end 605 606//===----------------------------------------------------------------------===// 607//<rdar://problem/6320065> false positive - init method returns an object owned by caller 608//===----------------------------------------------------------------------===// 609 610@interface RDar6320065 : NSObject { 611 NSString *_foo; 612} 613- (id)initReturningNewClass; 614- (id)initReturningNewClassBad; 615- (id)initReturningNewClassBad2; 616@end 617 618@interface RDar6320065Subclass : RDar6320065 619@end 620 621@implementation RDar6320065 622- (id)initReturningNewClass { 623 [self release]; 624 self = [[RDar6320065Subclass alloc] init]; // no-warning 625 return self; 626} 627- (id)initReturningNewClassBad { 628 [self release]; 629 [[RDar6320065Subclass alloc] init]; // expected-warning {{leak}} 630 return self; 631} 632- (id)initReturningNewClassBad2 { 633 [self release]; 634 self = [[RDar6320065Subclass alloc] init]; 635 return [self autorelease]; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} 636} 637 638@end 639 640@implementation RDar6320065Subclass 641@end 642 643int RDar6320065_test() { 644 RDar6320065 *test = [[RDar6320065 alloc] init]; // no-warning 645 [test release]; 646 return 0; 647} 648 649//===----------------------------------------------------------------------===// 650// <rdar://problem/6859457> [NSData dataWithBytesNoCopy] does not return a retained object 651//===----------------------------------------------------------------------===// 652 653@interface RDar6859457 : NSObject {} 654- (NSString*) NoCopyString; 655- (NSString*) noCopyString; 656@end 657 658@implementation RDar6859457 659- (NSString*) NoCopyString { return [[NSString alloc] init]; } // no-warning 660- (NSString*) noCopyString { return [[NSString alloc] init]; } // no-warning 661@end 662 663void test_RDar6859457(RDar6859457 *x, void *bytes, NSUInteger dataLength) { 664 [x NoCopyString]; // expected-warning{{leak}} 665 [x noCopyString]; // expected-warning{{leak}} 666 [NSData dataWithBytesNoCopy:bytes length:dataLength]; // no-warning 667 [NSData dataWithBytesNoCopy:bytes length:dataLength freeWhenDone:1]; // no-warning 668} 669 670//===----------------------------------------------------------------------===// 671// PR 4230 - an autorelease pool is not necessarily leaked during a premature 672// return 673//===----------------------------------------------------------------------===// 674 675static void PR4230(void) 676{ 677 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // no-warning 678 NSString *object = [[[NSString alloc] init] autorelease]; // no-warning 679 return; 680} 681 682//===----------------------------------------------------------------------===// 683// Method name that has a null IdentifierInfo* for its first selector slot. 684// This test just makes sure that we handle it. 685//===----------------------------------------------------------------------===// 686 687@interface TestNullIdentifier 688@end 689 690@implementation TestNullIdentifier 691+ (id):(int)x, ... { 692 return [[NSString alloc] init]; // expected-warning{{leak}} 693} 694@end 695 696//===----------------------------------------------------------------------===// 697// <rdar://problem/6893565> don't flag leaks for return types that cannot be 698// determined to be CF types 699//===----------------------------------------------------------------------===// 700 701// We don't know if 'struct s6893565' represents a Core Foundation type, so 702// we shouldn't emit an error here. 703typedef struct s6893565* TD6893565; 704 705@interface RDar6893565 {} 706-(TD6893565)newThing; 707@end 708 709@implementation RDar6893565 710-(TD6893565)newThing { 711 return (TD6893565) [[NSString alloc] init]; // no-warning 712} 713@end 714 715//===----------------------------------------------------------------------===// 716// <rdar://problem/6902710> clang: false positives w/QC and CoreImage methods 717//===----------------------------------------------------------------------===// 718 719void rdar6902710(QCView *view, QCRenderer *renderer, CIContext *context, 720 NSString *str, CIImage *img, CGRect rect, 721 CIFormat form, CGColorSpaceRef cs) { 722 [view createSnapshotImageOfType:str]; // expected-warning{{leak}} 723 [renderer createSnapshotImageOfType:str]; // expected-warning{{leak}} 724 [context createCGImage:img fromRect:rect]; // expected-warning{{leak}} 725 [context createCGImage:img fromRect:rect format:form colorSpace:cs]; // expected-warning{{leak}} 726} 727 728//===----------------------------------------------------------------------===// 729// <rdar://problem/6945561> -[CIContext createCGLayerWithSize:info:] 730// misinterpreted by clang scan-build 731//===----------------------------------------------------------------------===// 732 733void rdar6945561(CIContext *context, CGSize size, CFDictionaryRef d) { 734 [context createCGLayerWithSize:size info:d]; // expected-warning{{leak}} 735} 736 737//===----------------------------------------------------------------------===// 738// <rdar://problem/6961230> add knowledge of IOKit functions to retain/release 739// checker 740//===----------------------------------------------------------------------===// 741 742void IOBSDNameMatching_wrapper(mach_port_t masterPort, uint32_t options, const char * bsdName) { 743 IOBSDNameMatching(masterPort, options, bsdName); // expected-warning{{leak}} 744} 745 746void IOServiceMatching_wrapper(const char * name) { 747 IOServiceMatching(name); // expected-warning{{leak}} 748} 749 750void IOServiceNameMatching_wrapper(const char * name) { 751 IOServiceNameMatching(name); // expected-warning{{leak}} 752} 753 754__attribute__((cf_returns_retained)) CFDictionaryRef CreateDict(); 755 756void IOServiceAddNotification_wrapper(mach_port_t masterPort, const io_name_t notificationType, 757 mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) { 758 759 CFDictionaryRef matching = CreateDict(); 760 CFRelease(matching); 761 IOServiceAddNotification(masterPort, notificationType, matching, // expected-warning{{used after it is released}} expected-warning{{deprecated}} 762 wakePort, reference, notification); 763} 764 765void IORegistryEntryIDMatching_wrapper(uint64_t entryID ) { 766 IORegistryEntryIDMatching(entryID); // expected-warning{{leak}} 767} 768 769void IOOpenFirmwarePathMatching_wrapper(mach_port_t masterPort, uint32_t options, 770 const char * path) { 771 IOOpenFirmwarePathMatching(masterPort, options, path); // expected-warning{{leak}} 772} 773 774void IOServiceGetMatchingService_wrapper(mach_port_t masterPort) { 775 CFDictionaryRef matching = CreateDict(); 776 IOServiceGetMatchingService(masterPort, matching); 777 CFRelease(matching); // expected-warning{{used after it is released}} 778} 779 780void IOServiceGetMatchingServices_wrapper(mach_port_t masterPort, io_iterator_t *existing) { 781 CFDictionaryRef matching = CreateDict(); 782 IOServiceGetMatchingServices(masterPort, matching, existing); 783 CFRelease(matching); // expected-warning{{used after it is released}} 784} 785 786void IOServiceAddMatchingNotification_wrapper(IONotificationPortRef notifyPort, const io_name_t notificationType, 787 IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification) { 788 789 CFDictionaryRef matching = CreateDict(); 790 IOServiceAddMatchingNotification(notifyPort, notificationType, matching, callback, refCon, notification); 791 CFRelease(matching); // expected-warning{{used after it is released}} 792} 793 794//===----------------------------------------------------------------------===// 795// Tests of ownership attributes. 796//===----------------------------------------------------------------------===// 797 798typedef NSString* MyStringTy; 799 800@interface TestOwnershipAttr : NSObject 801- (NSString*) returnsAnOwnedString __attribute__((ns_returns_retained)); // no-warning 802- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_retained)); // no-warning 803- (MyStringTy) returnsAnOwnedTypedString __attribute__((ns_returns_retained)); // no-warning 804- (int) returnsAnOwnedInt __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}} 805@end 806 807static int ownership_attribute_doesnt_go_here __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to function or method types}} 808 809void test_attr_1(TestOwnershipAttr *X) { 810 NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} 811} 812 813void test_attr_1b(TestOwnershipAttr *X) { 814 NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} 815} 816 817@interface MyClassTestCFAttr : NSObject {} 818- (NSDate*) returnsCFRetained __attribute__((cf_returns_retained)); 819- (CFDateRef) returnsCFRetainedAsCF __attribute__((cf_returns_retained)); 820- (NSDate*) alsoReturnsRetained; 821- (CFDateRef) alsoReturnsRetainedAsCF; 822- (NSDate*) returnsNSRetained __attribute__((ns_returns_retained)); 823@end 824 825__attribute__((cf_returns_retained)) 826CFDateRef returnsRetainedCFDate() { 827 return CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 828} 829 830@implementation MyClassTestCFAttr 831- (NSDate*) returnsCFRetained { 832 return (NSDate*) returnsRetainedCFDate(); // No leak. 833} 834 835- (CFDateRef) returnsCFRetainedAsCF { 836 return returnsRetainedCFDate(); // No leak. 837} 838 839 840- (NSDate*) alsoReturnsRetained { 841 return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}} 842} 843 844- (CFDateRef) alsoReturnsRetainedAsCF { 845 return returnsRetainedCFDate(); // expected-warning{{leak}} 846} 847 848 849- (NSDate*) returnsNSRetained { 850 return (NSDate*) returnsRetainedCFDate(); // no-warning 851} 852@end 853 854 855 856