262 lines · plain
1// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -fobjc-arc -analyzer-output=plist-multi-file -analyzer-config deadcode.DeadStores:ShowFixIts=true -o %t.plist %s2// 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 NSObject10- (BOOL)isEqual:(id)object;11@end12@protocol NSCopying13- (id)copyWithZone:(NSZone *)zone;14@end15@protocol NSCoding;16@protocol NSMutableCopying;17@protocol NSFastEnumeration18- (void)encodeWithCoder:(NSCoder *)aCoder;19@end20@protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone;21@end22@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;23@end24@interface NSObject <NSObject> {}25+ (id)alloc;26- (id)init;27- (NSString *)description;28@end29@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@end38 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(void) {53 int *p = 0;54 *p = 0xDEADBEEF; // expected-warning {{null}}55}56 57// Test that in ARC mode that blocks are correctly automatically copied58// 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-warning65}66 67Block testblock_baz(int x) {68 return ^{ testblock_bar(x); }; // no-warning69}70 71Block global_block;72 73void testblock_qux(int x) {74 global_block = ^{ testblock_bar(x); }; // no-warning75}76 77// Test that Objective-C pointers are null initialized.78void test_nil_initialized(void) {79 id x;80 if (x == 0)81 return;82 int *p = 0;83 *p = 0xDEADBEEF; // no-warning84}85 86// Test that we don't flag leaks of Objective-C objects.87void test_alloc(void) {88 [NSObject alloc]; // no-warning89}90 91// Test that CF allocations are still caught as leaks.92void test_cf_leak(void) {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 object99// in ARC mode.100@interface RDar9424890_A : NSObject101- (id)initWithCleaner:(int)pop mop:(NSString *)mop ;102- (RDar9424890_A *)rdar9424890:(NSString *)identifier;103@end104@interface RDar9424890_B : NSObject105@end106@implementation RDar9424890_B107- (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-warning112 }113 return cell;114}115@end116 117// Test that dead store checking works in the prescence of "cleanups" in the AST.118void rdar9424882(void) {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 : NSObject127- (id) self;128@end129 130CFTypeRef CFCreateSomething(void);131CFStringRef CFCreateString(void);132CFTypeRef CFGetSomething(void);133CFStringRef CFGetString(void);134 135id CreateSomething(void);136NSString *CreateNSString(void);137 138void from_cf(void) {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(void) {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(void) {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(void) {172 id x = (__bridge_transfer id) CFCreateString();173 return x; // no-warning174}175 176void test_objc_arrays(void) {177 { // CASE ONE -- OBJECT IN ARRAY CREATED DIRECTLY178 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 ARRAY185 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// 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(void) {214 NSObject *o = [[NSObject alloc] init]; // expected-warning {{leak}}215 CFBridgingRetain(o);216}217void rdar11059275_negative(void) {218 NSObject *o = [[NSObject alloc] init]; // no-warning219 (void) o;220}221 222__attribute__((ns_returns_retained)) id rdar14061675_helper(void) {223 return [[NSObject alloc] init];224}225 226id rdar14061675(void) {227 // ARC produces an implicit cast here. We need to make sure the combination228 // 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(void) {244 NSString *nsStr = [[NSString alloc] init];245 CFStringRef cfStr = (__bridge_retained CFStringRef)nsStr;246 CFRelease(cfStr); // no-warning247}248 249@interface A;250@end251 252void check_bridge_to_non_cocoa(CFStringRef s) {253 A *a = (__bridge_transfer A *) s; // no-crash254}255 256struct B;257 258struct B * check_bridge_to_non_cf(void) {259 NSString *s = [[NSString alloc] init];260 return (__bridge struct B*) s;261}262