448 lines · plain
1// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -verify -Wno-objc-root-class %s2// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-config mode=shallow -verify -Wno-objc-root-class %s3// RUN: %clang_analyze_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -verify -Wno-objc-root-class %s4// RUN: %clang_analyze_cc1 -DOSATOMIC_USE_INLINED -triple i386-apple-darwin10 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -verify -Wno-objc-root-class %s5 6//===----------------------------------------------------------------------===//7// The following code is reduced using delta-debugging from8// Foundation.h (Mac OS X).9//10// It includes the basic definitions for the test cases below.11// Not directly including Foundation.h directly makes this test case 12// both svelte and portable to non-Mac platforms.13//===----------------------------------------------------------------------===//14 15#ifdef TEST_6416typedef long long int64_t;17_Bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );18#define COMPARE_SWAP_BARRIER OSAtomicCompareAndSwap64Barrier19typedef int64_t intptr_t;20#else21typedef int int32_t;22_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );23#define COMPARE_SWAP_BARRIER OSAtomicCompareAndSwap32Barrier24typedef int32_t intptr_t;25#endif26 27typedef const void * CFTypeRef;28typedef const struct __CFString * CFStringRef;29typedef const struct __CFAllocator * CFAllocatorRef;30extern const CFAllocatorRef kCFAllocatorDefault;31extern CFTypeRef CFRetain(CFTypeRef cf);32void CFRelease(CFTypeRef cf);33typedef const struct __CFDictionary * CFDictionaryRef;34const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key);35extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...);36typedef signed char BOOL;37typedef int NSInteger;38typedef unsigned int NSUInteger;39@class NSString, Protocol;40extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));41typedef NSInteger NSComparisonResult;42typedef struct _NSZone NSZone;43@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;44@protocol NSObject45- (BOOL)isEqual:(id)object;46- (oneway void)release;47- (id)retain;48- (id)autorelease;49@end50@protocol NSCopying51- (id)copyWithZone:(NSZone *)zone;52@end53@protocol NSMutableCopying54- (id)mutableCopyWithZone:(NSZone *)zone;55@end56@protocol NSCoding57- (void)encodeWithCoder:(NSCoder *)aCoder;58@end59@interface NSObject <NSObject> {}60- (id)init;61+ (id)alloc;62@end63extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);64typedef struct {} NSFastEnumerationState;65@protocol NSFastEnumeration66- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;67@end68@class NSString;69typedef struct _NSRange {} NSRange;70@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>71- (NSUInteger)count;72@end73@interface NSMutableArray : NSArray74- (void)addObject:(id)anObject;75- (id)initWithCapacity:(NSUInteger)numItems;76@end77typedef unsigned short unichar;78@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale;79typedef NSUInteger NSStringCompareOptions;80@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;81- (NSComparisonResult)compare:(NSString *)string;82- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;83- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange;84- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale;85- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string;86- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator;87+ (id)stringWithFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2)));88@end89@interface NSSimpleCString : NSString {} @end90@interface NSConstantString : NSSimpleCString @end91extern void *_NSConstantStringClassReference;92 93//===----------------------------------------------------------------------===//94// Test cases.95//===----------------------------------------------------------------------===//96 97NSComparisonResult f1(NSString* s) {98 NSString *aString = 0;99 return [s compare:aString]; // expected-warning {{Argument to 'NSString' method 'compare:' cannot be nil}}100}101 102NSComparisonResult f2(NSString* s) {103 NSString *aString = 0;104 return [s caseInsensitiveCompare:aString]; // expected-warning {{Argument to 'NSString' method 'caseInsensitiveCompare:' cannot be nil}}105}106 107NSComparisonResult f3(NSString* s, NSStringCompareOptions op) {108 NSString *aString = 0;109 return [s compare:aString options:op]; // expected-warning {{Argument to 'NSString' method 'compare:options:' cannot be nil}}110}111 112NSComparisonResult f4(NSString* s, NSStringCompareOptions op, NSRange R) {113 NSString *aString = 0;114 return [s compare:aString options:op range:R]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:' cannot be nil}}115}116 117NSComparisonResult f5(NSString* s, NSStringCompareOptions op, NSRange R) {118 NSString *aString = 0;119 return [s compare:aString options:op range:R locale:0]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:locale:' cannot be nil}}120}121 122NSArray *f6(NSString* s) {123 return [s componentsSeparatedByCharactersInSet:0]; // expected-warning {{Argument to 'NSString' method 'componentsSeparatedByCharactersInSet:' cannot be nil}}124}125 126NSString* f7(NSString* s1, NSString* s2, NSString* s3) {127 128 NSString* s4 = (NSString*)129 CFStringCreateWithFormat(kCFAllocatorDefault, 0, // expected-warning{{leak}}130 (CFStringRef) __builtin___CFStringMakeConstantString("%@ %@ (%@)"), 131 s1, s2, s3);132 133 CFRetain(s4);134 return s4;135}136 137NSMutableArray* f8(void) {138 139 NSString* s = [[NSString alloc] init];140 NSMutableArray* a = [[NSMutableArray alloc] initWithCapacity:2];141 [a addObject:s];142 [s release]; // no-warning143 return a;144}145 146void f9(void) {147 148 NSString* s = [[NSString alloc] init];149 NSString* q = s;150 [s release];151 [q release]; // expected-warning {{used after it is released}}152}153 154NSString* f10(void) {155 static NSString* s = 0;156 if (!s) s = [[NSString alloc] init];157 return s; // no-warning158}159 160// Essentially 's' should not be considered allocated on the false branch.161// This exercises the 'EvalAssume' logic in GRTransferFuncs (CFRefCount.cpp).162NSString* f11(CFDictionaryRef dict, const char* key) {163 NSString* s = (NSString*) CFDictionaryGetValue(dict, key);164 [s retain];165 if (s) {166 [s release];167 }168 return 0;169}170 171// Test case for passing a tracked object by-reference to a function we172// don't understand.173void unknown_function_f12(NSString** s);174void f12(void) {175 NSString *string = [[NSString alloc] init];176 unknown_function_f12(&string); // no-warning177}178 179// Test double release of CFString (PR 4014).180void f13(void) {181 CFStringRef ref = CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100);182 CFRelease(ref);183 CFRelease(ref); // expected-warning{{Reference-counted object is used after it is released}}184}185 186@interface MyString : NSString187@end188 189void f14(MyString *s) {190 [s compare:0]; // expected-warning {{Argument to 'MyString' method 'compare:' cannot be nil}}191}192 193// Test regular use of -autorelease194@interface TestAutorelease195-(NSString*) getString;196@end197@implementation TestAutorelease198-(NSString*) getString {199 NSString *str = [[NSString alloc] init];200 return [str autorelease]; // no-warning201}202- (void)m1203{204 NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}205 [s retain];206 [s autorelease];207}208- (void)m2209{210 NSString *s = [[[NSString alloc] init] autorelease]; // expected-warning{{leak}}211 [s retain];212}213- (void)m3214{215 NSString *s = [[[NSString alloc] init] autorelease];216 [s retain];217 [s autorelease];218}219- (void)m4220{221 NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}222 [s retain];223}224- (void)m5225{226 NSString *s = [[NSString alloc] init];227 [s autorelease];228}229@end230 231@interface C1 : NSObject {}232- (NSString*) getShared;233+ (C1*) sharedInstance;234@end235@implementation C1 : NSObject {}236- (NSString*) getShared {237 static NSString* s = 0;238 if (!s) s = [[NSString alloc] init]; 239 return s; // no-warning 240}241+ (C1 *)sharedInstance {242 static C1 *sharedInstance = 0;243 if (!sharedInstance) {244 sharedInstance = [[C1 alloc] init];245 }246 return sharedInstance; // no-warning247}248@end249 250@interface SharedClass : NSObject251+ (id)sharedInstance;252- (id)notShared;253@end254 255@implementation SharedClass256 257- (id)_init {258 if ((self = [super init])) {259 NSLog(@"Bar");260 }261 return self;262}263 264- (id)notShared {265 return [[SharedClass alloc] _init]; // expected-warning{{leak}}266}267 268+ (id)sharedInstance {269 static SharedClass *_sharedInstance = 0;270 if (!_sharedInstance) {271 _sharedInstance = [[SharedClass alloc] _init];272 }273 return _sharedInstance; // no-warning274}275@end276 277id testSharedClassFromFunction(void) {278 return [[SharedClass alloc] _init]; // no-warning279}280 281#if !(defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED)282// Test OSCompareAndSwap283_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );284extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);285#else286// Test that the body farm models are still used even when a body is available.287_Bool opaque_OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );288_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ) {289 return opaque_OSAtomicCompareAndSwapPtr(__oldValue, __newValue, __theValue);290}291// Test that the analyzer doesn't crash when the farm model is used. 292// The analyzer ignores the autosynthesized code.293_Bool OSAtomicCompareAndSwapEmptyFunction( void *__oldValue, void *__newValue, void * volatile *__theValue ) {294 return 0;295}296extern BOOL opaque_objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);297extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation) {298 return opaque_objc_atomicCompareAndSwapPtr(predicate, replacement, objectLocation);299}300#endif301 302void testOSCompareAndSwap(void) {303 NSString *old = 0;304 NSString *s = [[NSString alloc] init]; // no-warning305 if (!OSAtomicCompareAndSwapPtr(0, s, (void**) &old))306 [s release];307 else 308 [old release];309}310 311void testOSCompareAndSwapXXBarrier_local(void) {312 NSString *old = 0;313 NSString *s = [[NSString alloc] init]; // no-warning314 if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) &old))315 [s release];316 else 317 [old release];318}319 320void testOSCompareAndSwapXXBarrier_local_no_direct_release(void) {321 NSString *old = 0;322 NSString *s = [[NSString alloc] init]; // no-warning323 if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) &old))324 return;325 else 326 [old release];327}328 329int testOSCompareAndSwapXXBarrier_id(Class myclass, id xclass) {330 if (COMPARE_SWAP_BARRIER(0, (intptr_t) myclass, (intptr_t*) &xclass))331 return 1;332 return 0;333}334 335void test_objc_atomicCompareAndSwap_local(void) {336 NSString *old = 0;337 NSString *s = [[NSString alloc] init]; // no-warning338 if (!objc_atomicCompareAndSwapPtr(0, s, &old))339 [s release];340 else 341 [old release];342}343 344void test_objc_atomicCompareAndSwap_local_no_direct_release(void) {345 NSString *old = 0;346 NSString *s = [[NSString alloc] init]; // no-warning347 if (!objc_atomicCompareAndSwapPtr(0, s, &old))348 return;349 else 350 [old release];351}352 353void test_objc_atomicCompareAndSwap_parameter(NSString **old) {354 NSString *s = [[NSString alloc] init]; // no-warning355 if (!objc_atomicCompareAndSwapPtr(0, s, old))356 [s release];357 else 358 [*old release];359}360 361void test_objc_atomicCompareAndSwap_parameter_no_direct_release(NSString **old) {362 NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}363 if (!objc_atomicCompareAndSwapPtr(0, s, old))364 return;365 else 366 [*old release];367}368 369 370// Test stringWithFormat371void test_stringWithFormat(void) { 372 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain];373 [string release];374 [string release]; // expected-warning{{Incorrect decrement of the reference count}}375}376 377// Test isTrackedObjectType(void).378typedef NSString* WonkyTypedef;379@interface TestIsTracked380+ (WonkyTypedef)newString;381@end382 383void test_isTrackedObjectType(void) {384 NSString *str = [TestIsTracked newString]; // expected-warning{{Potential leak}}385}386 387// Test isTrackedCFObjectType().388@interface TestIsCFTracked389+ (CFStringRef) badNewCFString;390+ (CFStringRef) newCFString;391@end392 393@implementation TestIsCFTracked394+ (CFStringRef) newCFString {395 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // no-warning396}397+ (CFStringRef) badNewCFString {398 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // expected-warning{{leak}}399}400 401// Test @synchronized402void test_synchronized(id x) {403 @synchronized(x) {404 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain]; // expected-warning {{leak}}405 }406}407@end408 409void testOSCompareAndSwapXXBarrier_parameter(NSString **old) {410 NSString *s = [[NSString alloc] init]; // no-warning411 if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) old))412 [s release];413 else 414 [*old release];415}416 417void testOSCompareAndSwapXXBarrier_parameter_no_direct_release(NSString **old) {418 NSString *s = [[NSString alloc] init]; // no-warning419 if (!COMPARE_SWAP_BARRIER((intptr_t) 0, (intptr_t) s, (intptr_t*) old))420 [s release];421 else 422 return;423}424 425@interface AlwaysInlineBodyFarmBodies : NSObject {426 NSString *_value;427}428 - (NSString *)_value;429 - (void)callValue;430@end431 432@implementation AlwaysInlineBodyFarmBodies433 434- (NSString *)_value {435 if (!_value) {436 NSString *s = [[NSString alloc] init];437 if (!OSAtomicCompareAndSwapPtr(0, s, (void**)&_value)) {438 [s release];439 }440 }441 return _value;442}443 444- (void)callValue {445 [self _value];446}447@end448