// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify %s #if __has_feature(attribute_ns_returns_retained) #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) #endif #if __has_feature(attribute_cf_returns_retained) #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) #endif #if __has_feature(attribute_ns_returns_not_retained) #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) #endif #if __has_feature(attribute_cf_returns_not_retained) #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) #endif #if __has_feature(attribute_ns_consumes_self) #define NS_CONSUMES_SELF __attribute__((ns_consumes_self)) #endif #if __has_feature(attribute_ns_consumed) #define NS_CONSUMED __attribute__((ns_consumed)) #endif #if __has_feature(attribute_cf_consumed) #define CF_CONSUMED __attribute__((cf_consumed)) #endif //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from Mac OS X headers: // // #include // #include // #include // #include // #include // #include // // It includes the basic definitions for the test cases below. //===----------------------------------------------------------------------===// typedef unsigned int __darwin_natural_t; typedef unsigned long uintptr_t; typedef unsigned int uint32_t; typedef unsigned long long uint64_t; typedef unsigned int UInt32; typedef signed long CFIndex; typedef struct { CFIndex location; CFIndex length; } CFRange; static __inline__ __attribute__((always_inline)) CFRange CFRangeMake(CFIndex loc, CFIndex len) { CFRange range; range.location = loc; range.length = len; return range; } typedef const void * CFTypeRef; typedef const struct __CFString * CFStringRef; typedef const struct __CFAllocator * CFAllocatorRef; extern const CFAllocatorRef kCFAllocatorDefault; extern CFTypeRef CFRetain(CFTypeRef cf); extern void CFRelease(CFTypeRef cf); typedef struct { } CFArrayCallBacks; extern const CFArrayCallBacks kCFTypeArrayCallBacks; typedef const struct __CFArray * CFArrayRef; typedef struct __CFArray * CFMutableArrayRef; extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks); void abort(void) __attribute__((noreturn)); CFArrayRef CFArrayCreate(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFArrayCallBacks *callBacks); extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value); typedef struct { } CFDictionaryKeyCallBacks; extern const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks; typedef struct { } CFDictionaryValueCallBacks; extern const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; typedef const struct __CFDictionary * CFDictionaryRef; typedef struct __CFDictionary * CFMutableDictionaryRef; extern CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks); typedef UInt32 CFStringEncoding; enum { kCFStringEncodingMacRoman = 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 }; extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); extern CFStringRef CFStringCreateCopy(CFAllocatorRef alloc, CFStringRef theString); typedef double CFTimeInterval; typedef CFTimeInterval CFAbsoluteTime; extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); typedef const struct __CFDate * CFDateRef; extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); typedef __darwin_natural_t natural_t; typedef natural_t mach_port_name_t; typedef mach_port_name_t mach_port_t; typedef int kern_return_t; typedef kern_return_t mach_error_t; enum { kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2, kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4, kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6, kCFNumberCharType = 7, kCFNumberShortType = 8, kCFNumberIntType = 9, kCFNumberLongType = 10, kCFNumberLongLongType = 11, kCFNumberFloatType = 12, kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14, kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16, kCFNumberMaxType = 16 }; typedef CFIndex CFNumberType; typedef const struct __CFNumber * CFNumberRef; extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); typedef const struct __CFAttributedString *CFAttributedStringRef; typedef struct __CFAttributedString *CFMutableAttributedStringRef; extern CFAttributedStringRef CFAttributedStringCreate(CFAllocatorRef alloc, CFStringRef str, CFDictionaryRef attributes) ; extern CFMutableAttributedStringRef CFAttributedStringCreateMutableCopy(CFAllocatorRef alloc, CFIndex maxLength, CFAttributedStringRef aStr) ; extern void CFAttributedStringSetAttribute(CFMutableAttributedStringRef aStr, CFRange range, CFStringRef attrName, CFTypeRef value) ; typedef signed char BOOL; typedef unsigned long NSUInteger; @class NSString, Protocol; extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); typedef struct _NSZone NSZone; @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; @protocol NSObject - (BOOL)isEqual:(id)object; - (id)retain; - (id)copy; - (oneway void)release; - (id)autorelease; @end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end @interface NSObject {} + (id)allocWithZone:(NSZone *)zone; + (id)alloc; - (void)dealloc; - (id)init; @end @interface NSObject (NSCoderMethods) - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder; @end extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); typedef struct { } NSFastEnumerationState; @protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; @end @class NSString, NSDictionary; @interface NSValue : NSObject - (void)getValue:(void *)value; @end @interface NSNumber : NSValue - (char)charValue; - (id)initWithInt:(int)value; @end @class NSString; @interface NSArray : NSObject - (NSUInteger)count; @end @interface NSArray (NSArrayCreation) + (id)array; @end @interface NSAutoreleasePool : NSObject { } - (void)drain; @end extern NSString * const NSBundleDidLoadNotification; typedef double NSTimeInterval; @interface NSDate : NSObject - (NSTimeInterval)timeIntervalSinceReferenceDate; @end typedef unsigned short unichar; @interface NSString : NSObject - (NSUInteger)length; - ( const char *)UTF8String; - (id)initWithUTF8String:(const char *)nullTerminatedCString; + (id)stringWithUTF8String:(const char *)nullTerminatedCString; @end @class NSString, NSURL, NSError; @interface NSData : NSObject - (NSUInteger)length; + (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length; + (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b; @end @class NSLocale, NSDate, NSCalendar, NSTimeZone, NSError, NSArray, NSMutableDictionary; @interface NSDictionary : NSObject - (NSUInteger)count; @end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; - (void)setObject:(id)anObject forKey:(id)aKey; @end @interface NSMutableDictionary (NSMutableDictionaryCreation) + (id)dictionaryWithCapacity:(NSUInteger)numItems; @end typedef double CGFloat; struct CGSize { }; typedef struct CGSize CGSize; struct CGRect { }; typedef struct CGRect CGRect; typedef mach_port_t io_object_t; typedef char io_name_t[128]; typedef io_object_t io_iterator_t; typedef io_object_t io_service_t; typedef struct IONotificationPort * IONotificationPortRef; typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator ); io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching ); kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing ); kern_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)); kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification ); CFMutableDictionaryRef IOServiceMatching( const char * name ); CFMutableDictionaryRef IOServiceNameMatching( const char * name ); CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName ); CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path ); CFMutableDictionaryRef IORegistryEntryIDMatching( uint64_t entryID ); typedef struct __DASession * DASessionRef; extern DASessionRef DASessionCreate( CFAllocatorRef allocator ); typedef struct __DADisk * DADiskRef; extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name ); extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media ); extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk ); extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); @interface NSTask : NSObject - (id)init; @end typedef struct CGColorSpace *CGColorSpaceRef; typedef struct CGImage *CGImageRef; typedef struct CGLayer *CGLayerRef; @interface NSResponder : NSObject { } @end @protocol NSAnimatablePropertyContainer - (id)animator; @end extern NSString *NSAnimationTriggerOrderIn ; @interface NSView : NSResponder { } @end @protocol NSValidatedUserInterfaceItem - (SEL)action; @end @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id )anItem; @end @class NSDate, NSDictionary, NSError, NSException, NSNotification; @interface NSApplication : NSResponder { } @end enum { NSTerminateCancel = 0, NSTerminateNow = 1, NSTerminateLater = 2 }; typedef NSUInteger NSApplicationTerminateReply; @protocol NSApplicationDelegate @optional - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; @end @class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView, NSTextView; @interface NSCell : NSObject { } @end @class NSTextField, NSPanel, NSArray, NSWindow, NSImage, NSButton, NSError; typedef struct { } CVTimeStamp; @interface CIImage : NSObject { } typedef int CIFormat; @end enum { kDAReturnSuccess = 0, kDAReturnError = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; typedef mach_error_t DAReturn; typedef const struct __DADissenter * DADissenterRef; extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); @interface CIContext: NSObject { } - (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r; - (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs; - (CGLayerRef)createCGLayerWithSize:(CGSize)size info:(CFDictionaryRef)d; @end extern NSString* const QCRendererEventKey; @protocol QCCompositionRenderer - (NSDictionary*) attributes; @end @interface QCRenderer : NSObject { } - (id) createSnapshotImageOfType:(NSString*)type; @end extern NSString* const QCViewDidStartRenderingNotification; @interface QCView : NSView { } - (id) createSnapshotImageOfType:(NSString*)type; @end enum { ICEXIFOrientation1 = 1, ICEXIFOrientation2 = 2, ICEXIFOrientation3 = 3, ICEXIFOrientation4 = 4, ICEXIFOrientation5 = 5, ICEXIFOrientation6 = 6, ICEXIFOrientation7 = 7, ICEXIFOrientation8 = 8, }; @class ICDevice; @protocol ICDeviceDelegate @required - (void)didRemoveDevice:(ICDevice*)device; @end extern NSString *const ICScannerStatusWarmingUp; @class ICScannerDevice; @protocol ICScannerDeviceDelegate @optional - (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner; @end typedef long unsigned int __darwin_size_t; typedef __darwin_size_t size_t; typedef unsigned long CFTypeID; struct CGPoint { CGFloat x; CGFloat y; }; typedef struct CGPoint CGPoint; typedef struct CGGradient *CGGradientRef; typedef uint32_t CGGradientDrawingOptions; extern CFTypeID CGGradientGetTypeID(void); extern CGGradientRef CGGradientCreateWithColorComponents(CGColorSpaceRef space, const CGFloat components[], const CGFloat locations[], size_t count); extern CGGradientRef CGGradientCreateWithColors(CGColorSpaceRef space, CFArrayRef colors, const CGFloat locations[]); extern CGGradientRef CGGradientRetain(CGGradientRef gradient); extern void CGGradientRelease(CGGradientRef gradient); typedef struct CGContext *CGContextRef; extern void CGContextDrawLinearGradient(CGContextRef context, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options); extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void); //===----------------------------------------------------------------------===// // Test cases. //===----------------------------------------------------------------------===// class SmartPointer { id x; public: SmartPointer(id x) : x(x) {} ~SmartPointer() { [x release]; } void adopt(id x); void noAdopt(id x); }; void test_positive() { id x = [[NSObject alloc] init]; // expected-warning {{leak}} } void test_smartpointer_1() { id x = [[NSObject alloc] init]; // no-warning SmartPointer foo(x); } void test_smartpointer_2() { id x = [[NSObject alloc] init]; // no-warning SmartPointer foo(0); foo.adopt(x); } // FIXME: Eventually we want annotations to say whether or not // a C++ method claims ownership of an Objective-C object. void test_smartpointer_3() { id x = [[NSObject alloc] init]; // no-warning SmartPointer foo(0); foo.noAdopt(x); } void test_smartpointer_4() { id x = [[NSObject alloc] init]; // no-warning SmartPointer *foo = new SmartPointer(x); delete foo; } extern CFStringRef ElectronMicroscopyEngage(void); void test_microscopy() { NSString *token = (NSString*) ElectronMicroscopyEngage(); [token release]; // expected-warning {{object that is not owned}} } extern CFStringRef Scopy(void); void test_Scopy() { NSString *token = (NSString*) Scopy(); [token release]; // expected-warning {{object that is not owned}} } //===----------------------------------------------------------------------===// // Test handling of template functions used to do magic with // tracked retained pointers. //===----------------------------------------------------------------------===// template T static_objc_cast(U* value) { // ...debugging code omitted... return static_cast(value); } int rdar10553686(void) { NSObject* bar = static_objc_cast([[NSObject alloc] init]); [bar release]; return 0; } int rdar10553686_positive(void) { NSObject* bar = static_objc_cast([[NSObject alloc] init]); [bar release]; [bar retain]; // expected-warning {{used after it is released}} return 0; } @interface NSMapTable : NSObject @end extern void *NSMapGet(NSMapTable *table, const void *key); extern void NSMapInsert(NSMapTable *table, const void *key, const void *value); extern void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value); char *strdup(const char *s); NSString * radar11152419(NSString *string1, NSString *key1, NSMapTable *map) { NSString *string = ( NSString *)NSMapGet(map, key1); if (!string) { string = [string1 copy]; NSString *key = [key1 copy]; NSMapInsert(map, (void*) key, (void*)string); // no warning NSMapInsertKnownAbsent(map, (void*)key, (void*)string); // no warning } return string; } //===----------------------------------------------------------------------===// // Don't crash on non-member functions with "callbacks" but without names. //===----------------------------------------------------------------------===// struct IntWrapper { int arg; }; int operator>> (const IntWrapper &W, int (*f)(int)) { return f(W.arg); } void testCallback() { IntWrapper val = { 42 }; extern int process(int); val >> process; } //===----------------------------------------------------------------------===// // Test handling static initializers. //===----------------------------------------------------------------------===// @interface radar13227740 : NSObject @end @implementation radar13227740 - (CFArrayRef)test { static CFArrayRef array = ::CFArrayCreate(0, 0, 0, 0); do { if (!((0 != array)/1)) { abort(); } } while (false); return array; } // Previously this reported a bogus leak. - (void)test2 { (void)[self test]; (void)[self test]; } @end //===----------------------------------------------------------------------===// // Don't crash on getting a null expression from CallEnter corresponding to a // destructor. //===----------------------------------------------------------------------===// template class Holder { public: Holder() throw(); ~Holder() throw() {} X* get() const throw(); void reset(X* p) throw(); private: X* ptr_; }; template inline Holder::Holder() throw() : ptr_(0){} template inline X* Holder::get() const throw() { return ptr_; } template inline void Holder::reset(X* p) throw() { if (ptr_ != p) { if (ptr_ != 0) { ::CFRelease( ptr_ ); } ptr_ = p; } } class radar13722286 { public: radar13722286() {} private: void PrepareBitmap(); Holder mStr; }; void radar13722286::PrepareBitmap() { if (mStr.get() != 0) { Holder str1; mStr.reset( CFStringCreateCopy( 0, str1.get() ) ); //expected-warning {{Potential leak of an object}} } } // rdar://34210609 void _() { _(); }; // no-warning // Do not assume that IOBSDNameMatching increments a reference counter, // unless return type is CFMutableDictionaryRef. void* IOBSDNameMatching(); void rdar33832412() { void* x = IOBSDNameMatching(); // no-warning } namespace member_CFRetains { class Foo { public: void CFRetain(const Foo &) {} void CFRetain(int) {} }; void bar() { Foo foo; foo.CFRetain(foo); // no-warning foo.CFRetain(0); // no-warning } } namespace cxx_method_escaping { struct S { static CFArrayRef testGetNoTracking(); CFArrayRef testGetNoTrackingMember(); }; void test_cxx_static_method_escaping() { CFArrayRef arr = S::testGetNoTracking(); CFRelease(arr); } void test_cxx_method_escaping(S *s) { CFArrayRef arr = s->testGetNoTrackingMember(); CFRelease(arr); } } namespace yet_another_unexpected_signature_crash { CFTypeRef CFSomethingSomethingRetain(); CFTypeRef CFSomethingSomethingAutorelease(); void foo() { CFSomethingSomethingRetain(); // no-crash CFSomethingSomethingAutorelease(); // no-crash } } namespace reinterpret_casts { void *foo() { void *p = const_cast( reinterpret_cast(CFArrayCreate(0, 0, 0, 0))); void *q = reinterpret_cast( reinterpret_cast(p) + 1); // FIXME: Should warn about a leak here. The function should return at +0, // but it returns at +1 instead. return q; } void *fooCreate() { void *p = const_cast( reinterpret_cast(CFArrayCreate(0, 0, 0, 0))); void *q = reinterpret_cast( reinterpret_cast(p) + 1); // The function follows the Create Rule. return q; // no-warning } void *fooBar() CF_RETURNS_RETAINED { void *p = const_cast( reinterpret_cast(CFArrayCreate(0, 0, 0, 0))); void *q = reinterpret_cast( reinterpret_cast(p) + 1); // The function follows the Create Rule. return q; // no-warning } }