blob: d5a7870a99338aa0e6281165a65bc86a5815d9b8 [file] [log] [blame]
Ted Kremeneka3f45402009-04-29 16:03:59 +00001// RUN: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
2// RUN: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
Ted Kremenek1670e402009-04-11 00:11:10 +00003
4
Ted Kremeneka3f45402009-04-29 16:03:59 +00005// NOTWORK: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
6// NOTWORK: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
Ted Kremenek859be3b2008-06-16 20:37:30 +00007
8//===----------------------------------------------------------------------===//
9// The following code is reduced using delta-debugging from
10// Foundation.h (Mac OS X).
11//
12// It includes the basic definitions for the test cases below.
13// Not directly including Foundation.h directly makes this test case
14// both svelte and portable to non-Mac platforms.
15//===----------------------------------------------------------------------===//
16
Ted Kremeneka3f45402009-04-29 16:03:59 +000017typedef int int32_t;
Ted Kremenek859be3b2008-06-16 20:37:30 +000018typedef const void * CFTypeRef;
19typedef const struct __CFString * CFStringRef;
20typedef const struct __CFAllocator * CFAllocatorRef;
21extern const CFAllocatorRef kCFAllocatorDefault;
22extern CFTypeRef CFRetain(CFTypeRef cf);
Ted Kremenek09f14192009-04-21 20:01:03 +000023void CFRelease(CFTypeRef cf);
Ted Kremenek859be3b2008-06-16 20:37:30 +000024typedef const struct __CFDictionary * CFDictionaryRef;
Ted Kremenek2fb78a72008-12-17 21:50:35 +000025const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key);
Ted Kremenek859be3b2008-06-16 20:37:30 +000026extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...);
27typedef signed char BOOL;
28typedef int NSInteger;
29typedef unsigned int NSUInteger;
30@class NSString, Protocol;
31extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
32typedef NSInteger NSComparisonResult;
33typedef struct _NSZone NSZone;
34@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
35@protocol NSObject
36- (BOOL)isEqual:(id)object;
37- (oneway void)release;
Ted Kremenek2fb78a72008-12-17 21:50:35 +000038- (id)retain;
Ted Kremenek95d3b902009-05-11 15:26:06 +000039- (id)autorelease;
Ted Kremenek859be3b2008-06-16 20:37:30 +000040@end
41@protocol NSCopying
42- (id)copyWithZone:(NSZone *)zone;
43@end
44@protocol NSMutableCopying
45- (id)mutableCopyWithZone:(NSZone *)zone;
46@end
47@protocol NSCoding
48- (void)encodeWithCoder:(NSCoder *)aCoder;
49@end
50@interface NSObject <NSObject> {}
51- (id)init;
52+ (id)alloc;
53@end
54extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
55typedef struct {} NSFastEnumerationState;
56@protocol NSFastEnumeration
57- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
58@end
59@class NSString;
60typedef struct _NSRange {} NSRange;
61@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
62- (NSUInteger)count;
63@end
64@interface NSMutableArray : NSArray
65- (void)addObject:(id)anObject;
66- (id)initWithCapacity:(NSUInteger)numItems;
67@end
68typedef unsigned short unichar;
69@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale;
70typedef NSUInteger NSStringCompareOptions;
71@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
72- (NSComparisonResult)compare:(NSString *)string;
73- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;
74- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange;
75- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale;
76- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string;
77- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator;
Ted Kremeneke87450e2009-04-23 19:11:35 +000078+ (id)stringWithFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2)));
Ted Kremenek859be3b2008-06-16 20:37:30 +000079@end
80@interface NSSimpleCString : NSString {} @end
81@interface NSConstantString : NSSimpleCString @end
82extern void *_NSConstantStringClassReference;
83
84//===----------------------------------------------------------------------===//
85// Test cases.
86//===----------------------------------------------------------------------===//
87
88NSComparisonResult f1(NSString* s) {
89 NSString *aString = 0;
90 return [s compare:aString]; // expected-warning {{Argument to 'NSString' method 'compare:' cannot be nil.}}
91}
92
93NSComparisonResult f2(NSString* s) {
94 NSString *aString = 0;
95 return [s caseInsensitiveCompare:aString]; // expected-warning {{Argument to 'NSString' method 'caseInsensitiveCompare:' cannot be nil.}}
96}
97
98NSComparisonResult f3(NSString* s, NSStringCompareOptions op) {
99 NSString *aString = 0;
100 return [s compare:aString options:op]; // expected-warning {{Argument to 'NSString' method 'compare:options:' cannot be nil.}}
101}
102
103NSComparisonResult f4(NSString* s, NSStringCompareOptions op, NSRange R) {
104 NSString *aString = 0;
105 return [s compare:aString options:op range:R]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:' cannot be nil.}}
106}
107
108NSComparisonResult f5(NSString* s, NSStringCompareOptions op, NSRange R) {
109 NSString *aString = 0;
110 return [s compare:aString options:op range:R locale:0]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:locale:' cannot be nil.}}
111}
112
Daniel Dunbar4489fe12008-08-05 00:07:51 +0000113NSArray *f6(NSString* s) {
Ted Kremenek859be3b2008-06-16 20:37:30 +0000114 return [s componentsSeparatedByCharactersInSet:0]; // expected-warning {{Argument to 'NSString' method 'componentsSeparatedByCharactersInSet:' cannot be nil.}}
115}
116
117NSString* f7(NSString* s1, NSString* s2, NSString* s3) {
118
Daniel Dunbar4489fe12008-08-05 00:07:51 +0000119 NSString* s4 = (NSString*)
Ted Kremenekcf118d42009-02-04 23:49:09 +0000120 CFStringCreateWithFormat(kCFAllocatorDefault, 0, // expected-warning{{leak}}
Daniel Dunbar4489fe12008-08-05 00:07:51 +0000121 (CFStringRef) __builtin___CFStringMakeConstantString("%@ %@ (%@)"),
122 s1, s2, s3);
Ted Kremenek859be3b2008-06-16 20:37:30 +0000123
124 CFRetain(s4);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000125 return s4;
Ted Kremenek859be3b2008-06-16 20:37:30 +0000126}
127
128NSMutableArray* f8() {
129
130 NSString* s = [[NSString alloc] init];
131 NSMutableArray* a = [[NSMutableArray alloc] initWithCapacity:2];
132 [a addObject:s];
133 [s release]; // no-warning
134 return a;
135}
136
137void f9() {
138
139 NSString* s = [[NSString alloc] init];
140 NSString* q = s;
141 [s release];
142 [q release]; // expected-warning {{used after it is released}}
143}
144
145NSString* f10() {
Ted Kremenek859be3b2008-06-16 20:37:30 +0000146 static NSString* s = 0;
Ted Kremenek859be3b2008-06-16 20:37:30 +0000147 if (!s) s = [[NSString alloc] init];
Ted Kremenek859be3b2008-06-16 20:37:30 +0000148 return s; // no-warning
149}
150
Ted Kremenek2fb78a72008-12-17 21:50:35 +0000151// Test case for regression reported in <rdar://problem/6452745>.
152// Essentially 's' should not be considered allocated on the false branch.
153// This exercises the 'EvalAssume' logic in GRTransferFuncs (CFRefCount.cpp).
154NSString* f11(CFDictionaryRef dict, const char* key) {
155 NSString* s = (NSString*) CFDictionaryGetValue(dict, key);
156 [s retain];
157 if (s) {
158 [s release];
159 }
160}
161
Ted Kremenek784606f2008-12-18 23:40:58 +0000162// Test case for passing a tracked object by-reference to a function we
Ted Kremenek09f14192009-04-21 20:01:03 +0000163// don't understand.
Ted Kremenek784606f2008-12-18 23:40:58 +0000164void unknown_function_f12(NSString** s);
165void f12() {
166 NSString *string = [[NSString alloc] init];
167 unknown_function_f12(&string); // no-warning
168}
169
Ted Kremenek09f14192009-04-21 20:01:03 +0000170// Test double release of CFString (PR 4014).
171void f13(void) {
172 CFStringRef ref = CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100);
173 CFRelease(ref);
174 CFRelease(ref); // expected-warning{{Reference-counted object is used after it is released}}
175}
Ted Kremenek784606f2008-12-18 23:40:58 +0000176
Ted Kremenek95d3b902009-05-11 15:26:06 +0000177// Test regular use of -autorelease
178@interface TestAutorelease
179-(NSString*) getString;
180@end
181@implementation TestAutorelease
182-(NSString*) getString {
183 NSString *str = [[NSString alloc] init];
184 return [str autorelease]; // no-warning
185}
186@end
187
Ted Kremenek859be3b2008-06-16 20:37:30 +0000188@interface C1 : NSObject {}
189- (NSString*) getShared;
190+ (C1*) sharedInstance;
191@end
Ted Kremenekaeca9632008-07-03 15:37:02 +0000192@implementation C1 : NSObject {}
Ted Kremenek859be3b2008-06-16 20:37:30 +0000193- (NSString*) getShared {
194 static NSString* s = 0;
195 if (!s) s = [[NSString alloc] init];
196 return s; // no-warning
197}
198+ (C1 *)sharedInstance {
199 static C1 *sharedInstance = 0;
200 if (!sharedInstance) {
201 sharedInstance = [[C1 alloc] init];
202 }
203 return sharedInstance; // no-warning
204}
205@end
206
207@interface SharedClass : NSObject
208+ (id)sharedInstance;
Ted Kremenek234a4c22009-01-07 00:39:56 +0000209- (id)notShared;
Ted Kremenek859be3b2008-06-16 20:37:30 +0000210@end
Ted Kremenek234a4c22009-01-07 00:39:56 +0000211
Ted Kremenekaeca9632008-07-03 15:37:02 +0000212@implementation SharedClass
Ted Kremenek859be3b2008-06-16 20:37:30 +0000213
214- (id)_init {
215 if ((self = [super init])) {
216 NSLog(@"Bar");
217 }
218 return self;
219}
220
Ted Kremenek234a4c22009-01-07 00:39:56 +0000221- (id)notShared {
Ted Kremenek043254a2009-02-07 22:55:48 +0000222 return [[SharedClass alloc] _init]; // expected-warning{{leak}}
Ted Kremenek234a4c22009-01-07 00:39:56 +0000223}
224
Ted Kremenek859be3b2008-06-16 20:37:30 +0000225+ (id)sharedInstance {
226 static SharedClass *_sharedInstance = 0;
227 if (!_sharedInstance) {
228 _sharedInstance = [[SharedClass alloc] _init];
229 }
230 return _sharedInstance; // no-warning
231}
232@end
Ted Kremenek234a4c22009-01-07 00:39:56 +0000233
234id testSharedClassFromFunction() {
235 return [[SharedClass alloc] _init]; // no-warning
236}
237
Ted Kremenek1670e402009-04-11 00:11:10 +0000238// Test OSCompareAndSwap
239_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );
Ted Kremenek98104722009-05-01 17:37:31 +0000240_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000241extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);
Ted Kremenek1670e402009-04-11 00:11:10 +0000242
243void testOSCompareAndSwap() {
244 NSString *old = 0;
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000245 NSString *s = [[NSString alloc] init]; // no-warning
Ted Kremenek1670e402009-04-11 00:11:10 +0000246 if (!OSAtomicCompareAndSwapPtr(0, s, (void**) &old))
247 [s release];
248 else
249 [old release];
250}
251
Ted Kremeneka3f45402009-04-29 16:03:59 +0000252void testOSCompareAndSwap32Barrier() {
253 NSString *old = 0;
254 NSString *s = [[NSString alloc] init]; // no-warning
255 if (!OSAtomicCompareAndSwap32Barrier((int32_t) 0, (int32_t) s, (int32_t*) &old))
256 [s release];
257 else
258 [old release];
259}
260
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000261void test_objc_atomicCompareAndSwap() {
262 NSString *old = 0;
263 NSString *s = [[NSString alloc] init]; // no-warning
264 if (!objc_atomicCompareAndSwapPtr(0, s, &old))
265 [s release];
266 else
267 [old release];
268}
269
Ted Kremeneke87450e2009-04-23 19:11:35 +0000270// Test stringWithFormat (<rdar://problem/6815234>)
271void test_stringWithFormat() {
272 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain];
273 [string release];
Ted Kremenekf9df1362009-04-23 21:25:57 +0000274 [string release]; // expected-warning{{Incorrect decrement of the reference count}}
Ted Kremeneke87450e2009-04-23 19:11:35 +0000275}
276
Ted Kremenek92511432009-05-03 06:08:32 +0000277// Test isTrackedObjectType().
Ted Kremenek97d095f2009-04-23 22:11:07 +0000278typedef NSString* WonkyTypedef;
279@interface TestIsTracked
280+ (WonkyTypedef)newString;
281@end
282
283void test_isTrackedObjectType(void) {
284 NSString *str = [TestIsTracked newString]; // expected-warning{{Potential leak}}
285}
Ted Kremenekb3b0b362009-05-02 01:49:13 +0000286
Ted Kremenek92511432009-05-03 06:08:32 +0000287// Test isTrackedCFObjectType().
288@interface TestIsCFTracked
289+ (CFStringRef) badNewCFString;
290+ (CFStringRef) newCFString;
291@end
292
293@implementation TestIsCFTracked
294+ (CFStringRef) newCFString {
295 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // no-warning
296}
297+ (CFStringRef) badNewCFString {
298 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // expected-warning{{leak}}
299}
300
301
302
Ted Kremenekb3b0b362009-05-02 01:49:13 +0000303// Test @synchronized
304void test_synchronized(id x) {
305 @synchronized(x) {
306 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain]; // expected-warning {{leak}}
307 }
308}
309
Ted Kremenek92511432009-05-03 06:08:32 +0000310// Test return from method starting with 'new' or 'copy'