1// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc -analyzer-output=plist-multi-file -analyzer-config deadcode.DeadStores:ShowFixIts=true -o %t.plist %s
2// RUN: %normalize_plist <%t.plist | diff -ub %S/Inputs/expected-plists/objc-arc.m.plist -
3
4typedef signed char BOOL;
5typedef struct _NSZone NSZone;
6@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
7typedef unsigned long NSUInteger;
8
9@protocol NSObject
10- (BOOL)isEqual:(id)object;
11@end
12@protocol NSCopying
13- (id)copyWithZone:(NSZone *)zone;
14@end
15@protocol NSCoding;
16@protocol NSMutableCopying;
17@protocol NSFastEnumeration
18- (void)encodeWithCoder:(NSCoder *)aCoder;
19@end
20@protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone;
21@end
22@protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder;
23@end
24@interface NSObject <NSObject> {}
25+ (id)alloc;
26- (id)init;
27- (NSString *)description;
28@end
29@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
30- (NSUInteger)count;
31- (id)initWithObjects:(const id [])objects count:(NSUInteger)cnt;
32+ (id)arrayWithObject:(id)anObject;
33+ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
34+ (id)arrayWithObjects:(id)firstObj, ... __attribute__((sentinel(0,1)));
35- (id)initWithObjects:(id)firstObj, ... __attribute__((sentinel(0,1)));
36- (id)initWithArray:(NSArray *)array;
37@end
38
39typedef const struct __CFAllocator * CFAllocatorRef;
40extern const CFAllocatorRef kCFAllocatorDefault;
41typedef double CFTimeInterval;
42typedef CFTimeInterval CFAbsoluteTime;
43extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void);
44typedef const struct __CFDate * CFDateRef;
45extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
46
47typedef const void* objc_objectptr_t;
48__attribute__((ns_returns_retained)) id objc_retainedObject(objc_objectptr_t __attribute__((cf_consumed)) pointer);
49__attribute__((ns_returns_not_retained)) id objc_unretainedObject(objc_objectptr_t pointer);
50
51// Test the analyzer is working at all.
52void test_working() {
53  int *p = 0;
54  *p = 0xDEADBEEF; // expected-warning {{null}}
55}
56
57// Test that in ARC mode that blocks are correctly automatically copied
58// and not flagged as warnings by the analyzer.
59typedef void (^Block)(void);
60void testblock_bar(int x);
61
62Block testblock_foo(int x) {
63  Block b = ^{ testblock_bar(x); };
64  return b; // no-warning
65}
66
67Block testblock_baz(int x) {
68  return ^{ testblock_bar(x); }; // no-warning
69}
70
71Block global_block;
72
73void testblock_qux(int x) {
74  global_block = ^{ testblock_bar(x); }; // no-warning
75}
76
77// Test that Objective-C pointers are null initialized.
78void test_nil_initialized() {
79  id x;
80  if (x == 0)
81    return;
82  int *p = 0;
83  *p = 0xDEADBEEF; // no-warning
84}
85
86// Test that we don't flag leaks of Objective-C objects.
87void test_alloc() {
88  [NSObject alloc]; // no-warning
89}
90
91// Test that CF allocations are still caught as leaks.
92void test_cf_leak() {
93  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
94  CFDateRef date = CFDateCreate(0, t); // expected-warning {{Potential leak}}
95  (void) date;
96}
97
98// Test that 'init' methods do not try to claim ownerhip of an *unowned* allocated object
99// in ARC mode.
100@interface RDar9424890_A :  NSObject
101- (id)initWithCleaner:(int)pop mop:(NSString *)mop ;
102- (RDar9424890_A *)rdar9424890:(NSString *)identifier;
103@end
104@interface RDar9424890_B : NSObject
105@end
106@implementation RDar9424890_B
107- (RDar9424890_A *)obj:(RDar9424890_A *)obj {
108  static NSString *WhizFiz = @"WhizFiz";
109  RDar9424890_A *cell = [obj rdar9424890:WhizFiz];
110  if (cell == ((void*)0)) {
111    cell = [[RDar9424890_A alloc] initWithCleaner:0 mop:WhizFiz]; // no-warning
112  }
113  return cell;
114}
115@end
116
117// Test that dead store checking works in the prescence of "cleanups" in the AST.
118void rdar9424882() {
119  id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}}
120}
121
122// Test
123typedef const void *CFTypeRef;
124typedef const struct __CFString *CFStringRef;
125
126@interface NSString : NSObject
127- (id) self;
128@end
129
130CFTypeRef CFCreateSomething();
131CFStringRef CFCreateString();
132CFTypeRef CFGetSomething();
133CFStringRef CFGetString();
134
135id CreateSomething();
136NSString *CreateNSString();
137
138void from_cf() {
139  id obj1 = (__bridge_transfer id)CFCreateSomething(); // expected-warning{{never read}}
140  id obj2 = (__bridge_transfer NSString*)CFCreateString();
141  [obj2 self]; // Add a use, to show we can use the object after it has been transferred.
142  id obj3 = (__bridge id)CFGetSomething();
143  [obj3 self]; // Add a use, to show we can use the object after it has been bridged.
144  id obj4 = (__bridge NSString*)CFGetString(); // expected-warning{{never read}}
145  id obj5 = (__bridge id)CFCreateSomething(); // expected-warning{{never read}} expected-warning{{leak}}
146  id obj6 = (__bridge NSString*)CFCreateString(); // expected-warning{{never read}} expected-warning{{leak}}
147}
148
149void to_cf(id obj) {
150  CFTypeRef cf1 = (__bridge_retained CFTypeRef)CreateSomething(); // expected-warning{{never read}}
151  CFStringRef cf2 = (__bridge_retained CFStringRef)CreateNSString(); // expected-warning{{never read}}
152  CFTypeRef cf3 = (__bridge CFTypeRef)CreateSomething(); // expected-warning{{never read}}
153  CFStringRef cf4 = (__bridge CFStringRef)CreateNSString();  // expected-warning{{never read}}
154}
155
156void test_objc_retainedObject() {
157  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
158  CFDateRef date = CFDateCreate(0, t);
159  id x = objc_retainedObject(date);
160  (void) x;
161}
162
163void test_objc_unretainedObject() {
164  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
165  CFDateRef date = CFDateCreate(0, t);  // expected-warning {{Potential leak}}
166  id x = objc_unretainedObject(date);
167  (void) x;
168}
169
170// Previously this resulted in a "return of stack address" warning.
171id test_return() {
172  id x = (__bridge_transfer id) CFCreateString();
173  return x; // no-warning
174}
175
176void test_objc_arrays() {
177    { // CASE ONE -- OBJECT IN ARRAY CREATED DIRECTLY
178        NSObject *o = [[NSObject alloc] init];
179        NSArray *a = [[NSArray alloc] initWithObjects:o, (void*)0];
180        [a description];
181        [o description];
182    }
183
184    { // CASE TWO -- OBJECT IN ARRAY CREATED BY DUPING AUTORELEASED ARRAY
185        NSObject *o = [[NSObject alloc] init];
186        NSArray *a1 = [NSArray arrayWithObjects:o, (void*)0];
187        NSArray *a2 = [[NSArray alloc] initWithArray:a1];
188        [a2 description];
189        [o description];
190    }
191
192    { // CASE THREE -- OBJECT IN RETAINED @[]
193        NSObject *o = [[NSObject alloc] init];
194        NSArray *a3 = @[o];
195        [a3 description];
196        [o description];
197    }
198    {
199      // CASE 4, verify analyzer still working.
200      CFCreateString(); // expected-warning {{leak}}
201    }
202}
203
204// <rdar://problem/11059275> - dispatch_set_context and ARC.
205__attribute__((cf_returns_retained)) CFTypeRef CFBridgingRetain(id X);
206typedef void* dispatch_object_t;
207void dispatch_set_context(dispatch_object_t object, const void *context);
208
209void rdar11059275(dispatch_object_t object) {
210  NSObject *o = [[NSObject alloc] init];
211  dispatch_set_context(object, CFBridgingRetain(o)); // no-warning
212}
213void rdar11059275_positive() {
214  NSObject *o = [[NSObject alloc] init]; // expected-warning {{leak}}
215  CFBridgingRetain(o);
216}
217void rdar11059275_negative() {
218  NSObject *o = [[NSObject alloc] init]; // no-warning
219  (void) o;
220}
221
222__attribute__((ns_returns_retained)) id rdar14061675_helper() {
223  return [[NSObject alloc] init];
224}
225
226id rdar14061675() {
227  // ARC produces an implicit cast here. We need to make sure the combination
228  // of that and the inlined call don't produce a spurious edge cycle.
229  id result = rdar14061675_helper();
230  *(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
231  return result;
232}
233
234typedef const void * CFTypeRef;
235typedef const struct __CFString * CFStringRef;
236typedef const struct __CFAllocator * CFAllocatorRef;
237extern const CFAllocatorRef kCFAllocatorDefault;
238
239extern CFTypeRef CFRetain(CFTypeRef cf);
240extern void CFRelease(CFTypeRef cf);
241
242
243void check_bridge_retained_cast() {
244    NSString *nsStr = [[NSString alloc] init];
245    CFStringRef cfStr = (__bridge_retained CFStringRef)nsStr;
246    CFRelease(cfStr); // no-warning
247}
248
249@interface A;
250@end
251
252void check_bridge_to_non_cocoa(CFStringRef s) {
253  A *a = (__bridge_transfer A *) s; // no-crash
254}
255
256struct B;
257
258struct B * check_bridge_to_non_cf() {
259  NSString *s = [[NSString alloc] init];
260  return (__bridge struct B*) s;
261}
262