Home | History | Annotate | Download | only in Analysis
      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