blob: edaa4b3865150471c0eb784e6bb9366d01298a1c [file] [log] [blame]
Eli Friedmanc219a152009-05-19 11:12:40 +00001// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
Ted Kremenekc037eac2009-07-10 00:41:58 +00002// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic-old-cast -analyzer-constraints=basic -verify %s &&
Ted Kremeneke1cea752009-07-06 21:58:46 +00003// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
Ted Kremenekba024862009-07-20 21:44:10 +00004// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic-old-cast -analyzer-constraints=range -verify %s &&
5// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
6// RUN: clang-cc -triple i386-pc-linux-gnu -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 }
Mike Stump4393b3f2009-07-21 18:46:15 +0000160 return 0;
Ted Kremenek2fb78a72008-12-17 21:50:35 +0000161}
162
Ted Kremenek784606f2008-12-18 23:40:58 +0000163// Test case for passing a tracked object by-reference to a function we
Ted Kremenek09f14192009-04-21 20:01:03 +0000164// don't understand.
Ted Kremenek784606f2008-12-18 23:40:58 +0000165void unknown_function_f12(NSString** s);
166void f12() {
167 NSString *string = [[NSString alloc] init];
168 unknown_function_f12(&string); // no-warning
169}
170
Ted Kremenek09f14192009-04-21 20:01:03 +0000171// Test double release of CFString (PR 4014).
172void f13(void) {
173 CFStringRef ref = CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100);
174 CFRelease(ref);
175 CFRelease(ref); // expected-warning{{Reference-counted object is used after it is released}}
176}
Ted Kremenek784606f2008-12-18 23:40:58 +0000177
Ted Kremenek95d3b902009-05-11 15:26:06 +0000178// Test regular use of -autorelease
179@interface TestAutorelease
180-(NSString*) getString;
181@end
182@implementation TestAutorelease
183-(NSString*) getString {
184 NSString *str = [[NSString alloc] init];
185 return [str autorelease]; // no-warning
186}
Ted Kremenek2033a952009-05-13 07:12:33 +0000187- (void)m1
188{
189 NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}
190 [s retain];
191 [s autorelease];
192}
193- (void)m2
194{
195 NSString *s = [[[NSString alloc] init] autorelease]; // expected-warning{{leak}}
196 [s retain];
197}
198- (void)m3
199{
200 NSString *s = [[[NSString alloc] init] autorelease];
201 [s retain];
202 [s autorelease];
203}
204- (void)m4
205{
206 NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}
207 [s retain];
208}
209- (void)m5
210{
211 NSString *s = [[NSString alloc] init];
212 [s autorelease];
213}
Ted Kremenek95d3b902009-05-11 15:26:06 +0000214@end
215
Ted Kremenek859be3b2008-06-16 20:37:30 +0000216@interface C1 : NSObject {}
217- (NSString*) getShared;
218+ (C1*) sharedInstance;
219@end
Ted Kremenekaeca9632008-07-03 15:37:02 +0000220@implementation C1 : NSObject {}
Ted Kremenek859be3b2008-06-16 20:37:30 +0000221- (NSString*) getShared {
222 static NSString* s = 0;
223 if (!s) s = [[NSString alloc] init];
224 return s; // no-warning
225}
226+ (C1 *)sharedInstance {
227 static C1 *sharedInstance = 0;
228 if (!sharedInstance) {
229 sharedInstance = [[C1 alloc] init];
230 }
231 return sharedInstance; // no-warning
232}
233@end
234
235@interface SharedClass : NSObject
236+ (id)sharedInstance;
Ted Kremenek234a4c22009-01-07 00:39:56 +0000237- (id)notShared;
Ted Kremenek859be3b2008-06-16 20:37:30 +0000238@end
Ted Kremenek234a4c22009-01-07 00:39:56 +0000239
Ted Kremenekaeca9632008-07-03 15:37:02 +0000240@implementation SharedClass
Ted Kremenek859be3b2008-06-16 20:37:30 +0000241
242- (id)_init {
243 if ((self = [super init])) {
244 NSLog(@"Bar");
245 }
246 return self;
247}
248
Ted Kremenek234a4c22009-01-07 00:39:56 +0000249- (id)notShared {
Ted Kremenek043254a2009-02-07 22:55:48 +0000250 return [[SharedClass alloc] _init]; // expected-warning{{leak}}
Ted Kremenek234a4c22009-01-07 00:39:56 +0000251}
252
Ted Kremenek859be3b2008-06-16 20:37:30 +0000253+ (id)sharedInstance {
254 static SharedClass *_sharedInstance = 0;
255 if (!_sharedInstance) {
256 _sharedInstance = [[SharedClass alloc] _init];
257 }
258 return _sharedInstance; // no-warning
259}
260@end
Ted Kremenek234a4c22009-01-07 00:39:56 +0000261
262id testSharedClassFromFunction() {
263 return [[SharedClass alloc] _init]; // no-warning
264}
265
Ted Kremenek1670e402009-04-11 00:11:10 +0000266// Test OSCompareAndSwap
267_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );
Ted Kremenek98104722009-05-01 17:37:31 +0000268_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000269extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);
Ted Kremenek1670e402009-04-11 00:11:10 +0000270
271void testOSCompareAndSwap() {
272 NSString *old = 0;
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000273 NSString *s = [[NSString alloc] init]; // no-warning
Ted Kremenek1670e402009-04-11 00:11:10 +0000274 if (!OSAtomicCompareAndSwapPtr(0, s, (void**) &old))
275 [s release];
276 else
277 [old release];
278}
279
Ted Kremeneka3f45402009-04-29 16:03:59 +0000280void testOSCompareAndSwap32Barrier() {
281 NSString *old = 0;
282 NSString *s = [[NSString alloc] init]; // no-warning
283 if (!OSAtomicCompareAndSwap32Barrier((int32_t) 0, (int32_t) s, (int32_t*) &old))
284 [s release];
285 else
286 [old release];
287}
288
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000289void test_objc_atomicCompareAndSwap() {
290 NSString *old = 0;
291 NSString *s = [[NSString alloc] init]; // no-warning
292 if (!objc_atomicCompareAndSwapPtr(0, s, &old))
293 [s release];
294 else
295 [old release];
296}
297
Ted Kremeneke87450e2009-04-23 19:11:35 +0000298// Test stringWithFormat (<rdar://problem/6815234>)
299void test_stringWithFormat() {
300 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain];
301 [string release];
Ted Kremenekf9df1362009-04-23 21:25:57 +0000302 [string release]; // expected-warning{{Incorrect decrement of the reference count}}
Ted Kremeneke87450e2009-04-23 19:11:35 +0000303}
304
Ted Kremenek92511432009-05-03 06:08:32 +0000305// Test isTrackedObjectType().
Ted Kremenek97d095f2009-04-23 22:11:07 +0000306typedef NSString* WonkyTypedef;
307@interface TestIsTracked
308+ (WonkyTypedef)newString;
309@end
310
311void test_isTrackedObjectType(void) {
312 NSString *str = [TestIsTracked newString]; // expected-warning{{Potential leak}}
313}
Ted Kremenekb3b0b362009-05-02 01:49:13 +0000314
Ted Kremenek92511432009-05-03 06:08:32 +0000315// Test isTrackedCFObjectType().
316@interface TestIsCFTracked
317+ (CFStringRef) badNewCFString;
318+ (CFStringRef) newCFString;
319@end
320
321@implementation TestIsCFTracked
322+ (CFStringRef) newCFString {
323 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // no-warning
324}
325+ (CFStringRef) badNewCFString {
326 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // expected-warning{{leak}}
327}
328
Ted Kremenekb3b0b362009-05-02 01:49:13 +0000329// Test @synchronized
330void test_synchronized(id x) {
331 @synchronized(x) {
332 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain]; // expected-warning {{leak}}
333 }
334}
335
Ted Kremenek2033a952009-05-13 07:12:33 +0000336