objc-arc.m revision 05a4652fe679939b4641f967bdf900fce3cb56c3
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-checker=deadcode -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-nonfragile-abi -fobjc-arc %s 2 3typedef signed char BOOL; 4typedef struct _NSZone NSZone; 5@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 6 7@protocol NSObject 8- (BOOL)isEqual:(id)object; 9@end 10@protocol NSCopying 11- (id)copyWithZone:(NSZone *)zone; 12@end 13@protocol NSCoding 14- (void)encodeWithCoder:(NSCoder *)aCoder; 15@end 16@interface NSObject <NSObject> {} 17+ (id)alloc; 18@end 19typedef const struct __CFAllocator * CFAllocatorRef; 20extern const CFAllocatorRef kCFAllocatorDefault; 21typedef double CFTimeInterval; 22typedef CFTimeInterval CFAbsoluteTime; 23extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); 24typedef const struct __CFDate * CFDateRef; 25extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); 26 27typedef const void* objc_objectptr_t; 28__attribute__((ns_returns_retained)) id objc_retainedObject(objc_objectptr_t __attribute__((cf_consumed)) pointer); 29__attribute__((ns_returns_not_retained)) id objc_unretainedObject(objc_objectptr_t pointer); 30 31// Test the analyzer is working at all. 32void test_working() { 33 int *p = 0; 34 *p = 0xDEADBEEF; // expected-warning {{null}} 35} 36 37// Test that in ARC mode that blocks are correctly automatically copied 38// and not flagged as warnings by the analyzer. 39typedef void (^Block)(void); 40void testblock_bar(int x); 41 42Block testblock_foo(int x) { 43 Block b = ^{ testblock_bar(x); }; 44 return b; // no-warning 45} 46 47Block testblock_baz(int x) { 48 return ^{ testblock_bar(x); }; // no-warning 49} 50 51Block global_block; 52 53void testblock_qux(int x) { 54 global_block = ^{ testblock_bar(x); }; // no-warning 55} 56 57// Test that Objective-C pointers are null initialized. 58void test_nil_initialized() { 59 id x; 60 if (x == 0) 61 return; 62 int *p = 0; 63 *p = 0xDEADBEEF; // no-warning 64} 65 66// Test that we don't flag leaks of Objective-C objects. 67void test_alloc() { 68 [NSObject alloc]; // no-warning 69} 70 71// Test that CF allocations are still caught as leaks. 72void test_cf_leak() { 73 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 74 CFDateRef date = CFDateCreate(0, t); // expected-warning {{Potential leak}} 75 (void) date; 76} 77 78// Test that 'init' methods do not try to claim ownerhip of an *unowned* allocated object 79// in ARC mode. 80@interface RDar9424890_A : NSObject 81- (id)initWithCleaner:(int)pop mop:(NSString *)mop ; 82- (RDar9424890_A *)rdar9424890:(NSString *)identifier; 83@end 84@interface RDar9424890_B : NSObject 85@end 86@implementation RDar9424890_B 87- (RDar9424890_A *)obj:(RDar9424890_A *)obj { 88 static NSString *WhizFiz = @"WhizFiz"; 89 RDar9424890_A *cell = [obj rdar9424890:WhizFiz]; 90 if (cell == ((void*)0)) { 91 cell = [[RDar9424890_A alloc] initWithCleaner:0 mop:WhizFiz]; // no-warning 92 } 93 return cell; 94} 95@end 96 97// Test that dead store checking works in the prescence of "cleanups" in the AST. 98void rdar9424882() { 99 id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}} 100} 101 102// Test 103typedef const void *CFTypeRef; 104typedef const struct __CFString *CFStringRef; 105 106@interface NSString 107- (id) self; 108@end 109 110CFTypeRef CFCreateSomething(); 111CFStringRef CFCreateString(); 112CFTypeRef CFGetSomething(); 113CFStringRef CFGetString(); 114 115id CreateSomething(); 116NSString *CreateNSString(); 117 118void from_cf() { 119 id obj1 = (__bridge_transfer id)CFCreateSomething(); // expected-warning{{never read}} 120 id obj2 = (__bridge_transfer NSString*)CFCreateString(); 121 [obj2 self]; // Add a use, to show we can use the object after it has been transfered. 122 id obj3 = (__bridge id)CFGetSomething(); 123 [obj3 self]; // Add a use, to show we can use the object after it has been bridged. 124 id obj4 = (__bridge NSString*)CFGetString(); // expected-warning{{never read}} 125 id obj5 = (__bridge id)CFCreateSomething(); // expected-warning{{never read}} expected-warning{{leak}} 126 id obj6 = (__bridge NSString*)CFCreateString(); // expected-warning{{never read}} expected-warning{{leak}} 127} 128 129void to_cf(id obj) { 130 CFTypeRef cf1 = (__bridge_retained CFTypeRef)CreateSomething(); // expected-warning{{never read}} 131 CFStringRef cf2 = (__bridge_retained CFStringRef)CreateNSString(); // expected-warning{{never read}} 132 CFTypeRef cf3 = (__bridge CFTypeRef)CreateSomething(); // expected-warning{{never read}} 133 CFStringRef cf4 = (__bridge CFStringRef)CreateNSString(); // expected-warning{{never read}} 134} 135 136void test_objc_retainedObject() { 137 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 138 CFDateRef date = CFDateCreate(0, t); 139 id x = objc_retainedObject(date); 140 (void) x; 141} 142 143void test_objc_unretainedObject() { 144 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 145 CFDateRef date = CFDateCreate(0, t); // expected-warning {{Potential leak}} 146 id x = objc_unretainedObject(date); 147 (void) x; 148} 149 150// Previously this resulted in a "return of stack address" warning. 151id test_return() { 152 id x = (__bridge_transfer id) CFCreateString(); 153 return x; // no-warning 154} 155 156