1 // 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 2 3 typedef signed char BOOL; 4 typedef struct _NSZone NSZone; 5 @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 6 typedef unsigned long NSUInteger; 7 8 @protocol NSObject 9 - (BOOL)isEqual:(id)object; 10 @end 11 @protocol NSCopying 12 - (id)copyWithZone:(NSZone *)zone; 13 @end 14 @protocol NSCoding; 15 @protocol NSMutableCopying; 16 @protocol NSFastEnumeration 17 - (void)encodeWithCoder:(NSCoder *)aCoder; 18 @end 19 @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; 20 @end 21 @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; 22 @end 23 @interface NSObject <NSObject> {} 24 + (id)alloc; 25 - (id)init; 26 - (NSString *)description; 27 @end 28 @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 38 typedef const struct __CFAllocator * CFAllocatorRef; 39 extern const CFAllocatorRef kCFAllocatorDefault; 40 typedef double CFTimeInterval; 41 typedef CFTimeInterval CFAbsoluteTime; 42 extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); 43 typedef const struct __CFDate * CFDateRef; 44 extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); 45 46 typedef 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. 51 void 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. 58 typedef void (^Block)(void); 59 void testblock_bar(int x); 60 61 Block testblock_foo(int x) { 62 Block b = ^{ testblock_bar(x); }; 63 return b; // no-warning 64 } 65 66 Block testblock_baz(int x) { 67 return ^{ testblock_bar(x); }; // no-warning 68 } 69 70 Block global_block; 71 72 void testblock_qux(int x) { 73 global_block = ^{ testblock_bar(x); }; // no-warning 74 } 75 76 // Test that Objective-C pointers are null initialized. 77 void 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. 86 void test_alloc() { 87 [NSObject alloc]; // no-warning 88 } 89 90 // Test that CF allocations are still caught as leaks. 91 void 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. 117 void rdar9424882() { 118 id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}} 119 } 120 121 // Test 122 typedef const void *CFTypeRef; 123 typedef const struct __CFString *CFStringRef; 124 125 @interface NSString 126 - (id) self; 127 @end 128 129 CFTypeRef CFCreateSomething(); 130 CFStringRef CFCreateString(); 131 CFTypeRef CFGetSomething(); 132 CFStringRef CFGetString(); 133 134 id CreateSomething(); 135 NSString *CreateNSString(); 136 137 void 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 148 void 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 155 void test_objc_retainedObject() { 156 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 157 CFDateRef date = CFDateCreate(0, t); 158 id x = objc_retainedObject(date); 159 (void) x; 160 } 161 162 void 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 169 // Previously this resulted in a "return of stack address" warning. 170 id test_return() { 171 id x = (__bridge_transfer id) CFCreateString(); 172 return x; // no-warning 173 } 174 175 void 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 203 // <rdar://problem/11059275> - dispatch_set_context and ARC. 204 __attribute__((cf_returns_retained)) CFTypeRef CFBridgingRetain(id X); 205 typedef void* dispatch_object_t; 206 void dispatch_set_context(dispatch_object_t object, const void *context); 207 208 void rdar11059275(dispatch_object_t object) { 209 NSObject *o = [[NSObject alloc] init]; 210 dispatch_set_context(object, CFBridgingRetain(o)); // no-warning 211 } 212 void rdar11059275_positive() { 213 NSObject *o = [[NSObject alloc] init]; // expected-warning {{leak}} 214 CFBridgingRetain(o); 215 } 216 void rdar11059275_negative() { 217 NSObject *o = [[NSObject alloc] init]; // no-warning 218 (void) o; 219 } 220 221