blob: e6c6ab546132bb08bfafe615ae16cfc4adf34b65 [file] [log] [blame]
John McCalld1e40d52011-10-02 01:16:38 +00001// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc %s
John McCallf85e1932011-06-15 23:02:42 +00002
3typedef signed char BOOL;
4typedef struct _NSZone NSZone;
5@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
Ted Kremenek1a45a5f2012-03-06 20:06:12 +00006typedef unsigned long NSUInteger;
John McCallf85e1932011-06-15 23:02:42 +00007
8@protocol NSObject
9- (BOOL)isEqual:(id)object;
10@end
11@protocol NSCopying
12- (id)copyWithZone:(NSZone *)zone;
13@end
Ted Kremenek1a45a5f2012-03-06 20:06:12 +000014@protocol NSCoding;
15@protocol NSMutableCopying;
16@protocol NSFastEnumeration
John McCallf85e1932011-06-15 23:02:42 +000017- (void)encodeWithCoder:(NSCoder *)aCoder;
18@end
Ted Kremenek1a45a5f2012-03-06 20:06:12 +000019@protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone;
20@end
21@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;
22@end
John McCallf85e1932011-06-15 23:02:42 +000023@interface NSObject <NSObject> {}
24+ (id)alloc;
Ted Kremenek1a45a5f2012-03-06 20:06:12 +000025- (id)init;
26- (NSString *)description;
John McCallf85e1932011-06-15 23:02:42 +000027@end
Ted Kremenek1a45a5f2012-03-06 20:06:12 +000028@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
29- (NSUInteger)count;
30- (id)initWithObjects:(const id [])objects count:(NSUInteger)cnt;
31+ (id)arrayWithObject:(id)anObject;
32+ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
33+ (id)arrayWithObjects:(id)firstObj, ... __attribute__((sentinel(0,1)));
34- (id)initWithObjects:(id)firstObj, ... __attribute__((sentinel(0,1)));
35- (id)initWithArray:(NSArray *)array;
36@end
37
John McCallf85e1932011-06-15 23:02:42 +000038typedef const struct __CFAllocator * CFAllocatorRef;
39extern const CFAllocatorRef kCFAllocatorDefault;
40typedef double CFTimeInterval;
41typedef CFTimeInterval CFAbsoluteTime;
42extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void);
43typedef const struct __CFDate * CFDateRef;
44extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
45
46typedef const void* objc_objectptr_t;
47__attribute__((ns_returns_retained)) id objc_retainedObject(objc_objectptr_t __attribute__((cf_consumed)) pointer);
48__attribute__((ns_returns_not_retained)) id objc_unretainedObject(objc_objectptr_t pointer);
49
50// Test the analyzer is working at all.
51void test_working() {
52 int *p = 0;
53 *p = 0xDEADBEEF; // expected-warning {{null}}
54}
55
56// Test that in ARC mode that blocks are correctly automatically copied
57// and not flagged as warnings by the analyzer.
58typedef void (^Block)(void);
59void testblock_bar(int x);
60
61Block testblock_foo(int x) {
62 Block b = ^{ testblock_bar(x); };
63 return b; // no-warning
64}
65
66Block testblock_baz(int x) {
67 return ^{ testblock_bar(x); }; // no-warning
68}
69
70Block global_block;
71
72void testblock_qux(int x) {
73 global_block = ^{ testblock_bar(x); }; // no-warning
74}
75
76// Test that Objective-C pointers are null initialized.
77void test_nil_initialized() {
78 id x;
79 if (x == 0)
80 return;
81 int *p = 0;
82 *p = 0xDEADBEEF; // no-warning
83}
84
85// Test that we don't flag leaks of Objective-C objects.
86void test_alloc() {
87 [NSObject alloc]; // no-warning
88}
89
90// Test that CF allocations are still caught as leaks.
91void test_cf_leak() {
92 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
93 CFDateRef date = CFDateCreate(0, t); // expected-warning {{Potential leak}}
94 (void) date;
95}
96
97// Test that 'init' methods do not try to claim ownerhip of an *unowned* allocated object
98// in ARC mode.
99@interface RDar9424890_A : NSObject
100- (id)initWithCleaner:(int)pop mop:(NSString *)mop ;
101- (RDar9424890_A *)rdar9424890:(NSString *)identifier;
102@end
103@interface RDar9424890_B : NSObject
104@end
105@implementation RDar9424890_B
106- (RDar9424890_A *)obj:(RDar9424890_A *)obj {
107 static NSString *WhizFiz = @"WhizFiz";
108 RDar9424890_A *cell = [obj rdar9424890:WhizFiz];
109 if (cell == ((void*)0)) {
110 cell = [[RDar9424890_A alloc] initWithCleaner:0 mop:WhizFiz]; // no-warning
111 }
112 return cell;
113}
114@end
115
116// Test that dead store checking works in the prescence of "cleanups" in the AST.
117void rdar9424882() {
118 id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}}
119}
120
121// Test
122typedef const void *CFTypeRef;
123typedef const struct __CFString *CFStringRef;
124
125@interface NSString
126- (id) self;
127@end
128
129CFTypeRef CFCreateSomething();
130CFStringRef CFCreateString();
131CFTypeRef CFGetSomething();
132CFStringRef CFGetString();
133
134id CreateSomething();
135NSString *CreateNSString();
136
137void from_cf() {
138 id obj1 = (__bridge_transfer id)CFCreateSomething(); // expected-warning{{never read}}
139 id obj2 = (__bridge_transfer NSString*)CFCreateString();
140 [obj2 self]; // Add a use, to show we can use the object after it has been transfered.
141 id obj3 = (__bridge id)CFGetSomething();
142 [obj3 self]; // Add a use, to show we can use the object after it has been bridged.
143 id obj4 = (__bridge NSString*)CFGetString(); // expected-warning{{never read}}
144 id obj5 = (__bridge id)CFCreateSomething(); // expected-warning{{never read}} expected-warning{{leak}}
145 id obj6 = (__bridge NSString*)CFCreateString(); // expected-warning{{never read}} expected-warning{{leak}}
146}
147
148void to_cf(id obj) {
149 CFTypeRef cf1 = (__bridge_retained CFTypeRef)CreateSomething(); // expected-warning{{never read}}
150 CFStringRef cf2 = (__bridge_retained CFStringRef)CreateNSString(); // expected-warning{{never read}}
151 CFTypeRef cf3 = (__bridge CFTypeRef)CreateSomething(); // expected-warning{{never read}}
152 CFStringRef cf4 = (__bridge CFStringRef)CreateNSString(); // expected-warning{{never read}}
153}
154
155void test_objc_retainedObject() {
156 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
157 CFDateRef date = CFDateCreate(0, t);
158 id x = objc_retainedObject(date);
159 (void) x;
160}
161
162void test_objc_unretainedObject() {
163 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
164 CFDateRef date = CFDateCreate(0, t); // expected-warning {{Potential leak}}
165 id x = objc_unretainedObject(date);
166 (void) x;
167}
168
Ted Kremenek05a46522011-08-27 21:15:48 +0000169// Previously this resulted in a "return of stack address" warning.
170id test_return() {
171 id x = (__bridge_transfer id) CFCreateString();
172 return x; // no-warning
173}
174
Ted Kremenek1a45a5f2012-03-06 20:06:12 +0000175void test_objc_arrays() {
176 { // CASE ONE -- OBJECT IN ARRAY CREATED DIRECTLY
177 NSObject *o = [[NSObject alloc] init];
178 NSArray *a = [[NSArray alloc] initWithObjects:o, (void*)0];
179 [a description];
180 [o description];
181 }
182
183 { // CASE TWO -- OBJECT IN ARRAY CREATED BY DUPING AUTORELEASED ARRAY
184 NSObject *o = [[NSObject alloc] init];
185 NSArray *a1 = [NSArray arrayWithObjects:o, (void*)0];
186 NSArray *a2 = [[NSArray alloc] initWithArray:a1];
187 [a2 description];
188 [o description];
189 }
190
191 { // CASE THREE -- OBJECT IN RETAINED @[]
192 NSObject *o = [[NSObject alloc] init];
193 NSArray *a3 = @[o];
194 [a3 description];
195 [o description];
196 }
197 {
198 // CASE 4, verify analyzer still working.
199 CFCreateString(); // expected-warning {{leak}}
200 }
201}
202
Ted Kremenek06911d42012-03-22 06:29:41 +0000203// <rdar://problem/11059275> - dispatch_set_context and ARC.
204__attribute__((cf_returns_retained)) CFTypeRef CFBridgingRetain(id X);
205typedef void* dispatch_object_t;
206void dispatch_set_context(dispatch_object_t object, const void *context);
207
208void rdar11059275(dispatch_object_t object) {
209 NSObject *o = [[NSObject alloc] init];
210 dispatch_set_context(object, CFBridgingRetain(o)); // no-warning
211}
212void rdar11059275_positive() {
213 NSObject *o = [[NSObject alloc] init]; // expected-warning {{leak}}
214 CFBridgingRetain(o);
215}
216void rdar11059275_negative() {
217 NSObject *o = [[NSObject alloc] init]; // no-warning
218 (void) o;
219}
Ted Kremenek1a45a5f2012-03-06 20:06:12 +0000220