Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify %s
      2 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify -x objective-c++ %s
      3 
      4 //===----------------------------------------------------------------------===//
      5 // The following code is reduced using delta-debugging from Mac OS X headers:
      6 //===----------------------------------------------------------------------===//
      7 
      8 typedef __builtin_va_list va_list;
      9 typedef unsigned int uint32_t;
     10 typedef struct dispatch_queue_s *dispatch_queue_t;
     11 typedef struct dispatch_queue_attr_s *dispatch_queue_attr_t;
     12 typedef void (^dispatch_block_t)(void);
     13 void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
     14 __attribute__((visibility("default"))) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__nothrow__)) dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
     15 typedef long dispatch_once_t;
     16 void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
     17 dispatch_queue_t
     18 dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
     19 
     20 
     21 typedef signed char BOOL;
     22 typedef unsigned long NSUInteger;
     23 typedef struct _NSZone NSZone;
     24 @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
     25 @protocol NSObject
     26 - (BOOL)isEqual:(id)object;
     27 - (oneway void)release;
     28 @end
     29 @protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
     30 @protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
     31 @protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
     32 @interface NSObject <NSObject> {}
     33 + (id)alloc;
     34 - (id)init;
     35 - (id)copy;
     36 @end
     37 extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
     38 @interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
     39 - (NSUInteger)length;
     40 - (const char *)UTF8String;
     41 - (id)initWithFormat:(NSString *)format arguments:(va_list)argList __attribute__((format(__NSString__, 1, 0)));
     42 @end
     43 @class NSString, NSData;
     44 typedef struct cssm_sample {} CSSM_SAMPLEGROUP, *CSSM_SAMPLEGROUP_PTR;
     45 typedef struct __aslclient *aslclient;
     46 typedef struct __aslmsg *aslmsg;
     47 aslclient asl_open(const char *ident, const char *facility, uint32_t opts);
     48 int asl_log(aslclient asl, aslmsg msg, int level, const char *format, ...) __attribute__((__format__ (__printf__, 4, 5)));
     49 
     50 //===----------------------------------------------------------------------===//
     51 // Begin actual test cases.
     52 //===----------------------------------------------------------------------===//
     53 
     54 // test1 - This test case exposed logic that caused the analyzer to crash because of a memory bug
     55 //  in BlockDataRegion.  It represents real code that contains two block literals.  Eventually
     56 //  via IPA 'logQueue' and 'client' should be updated after the call to 'dispatch_once'.
     57 void test1(NSString *format, ...) {
     58   static dispatch_queue_t logQueue;
     59   static aslclient client;
     60   static dispatch_once_t pred;
     61   do {
     62     if (__builtin_expect(*(&pred), ~0l) != ~0l)
     63       dispatch_once(&pred, ^{
     64         logQueue = dispatch_queue_create("com.mycompany.myproduct.asl", 0);
     65         client = asl_open(((char*)0), "com.mycompany.myproduct", 0);
     66       });
     67   } while (0);
     68 
     69   va_list args;
     70   __builtin_va_start(args, format);
     71 
     72   NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
     73   dispatch_async(logQueue, ^{ asl_log(client, ((aslmsg)0), 4, "%s", [str UTF8String]); });
     74   [str release];
     75 
     76   __builtin_va_end(args);
     77 }
     78 
     79 // test2 - Test that captured variables that are uninitialized are flagged
     80 // as such.
     81 void test2() {
     82   static int y = 0;
     83   int x;
     84   ^{ y = x + 1; }();  // expected-warning{{Variable 'x' is uninitialized when captured by block}}
     85 }
     86 
     87 void test2_b() {
     88   static int y = 0;
     89   __block int x;
     90   ^{ y = x + 1; }(); // expected-warning {{left operand of '+' is a garbage value}}
     91 }
     92 
     93 void test2_c() {
     94   typedef void (^myblock)(void);
     95   myblock f = ^() { f(); }; // expected-warning{{Variable 'f' is uninitialized when captured by block}}
     96 }
     97 
     98 
     99 void testMessaging() {
    100   // <rdar://problem/12119814>
    101   [[^(){} copy] release];
    102 }
    103 
    104 
    105 @interface rdar12415065 : NSObject
    106 @end
    107 
    108 @implementation rdar12415065
    109 - (void)test {
    110   // At one point this crashed because we created a path note at a
    111   // PreStmtPurgeDeadSymbols point but only knew how to deal with PostStmt
    112   // points. <rdar://problem/12687586>
    113 
    114   extern dispatch_queue_t queue;
    115 
    116   if (!queue)
    117     return;
    118 
    119   // This previously was a false positive with 'x' being flagged as being
    120   // uninitialized when captured by the exterior block (when it is only
    121   // captured by the interior block).
    122   dispatch_async(queue, ^{
    123     double x = 0.0;
    124     if (24.0f < x) {
    125       dispatch_async(queue, ^{ (void)x; });
    126       [self test];
    127     }
    128   });
    129 }
    130 @end
    131 
    132 void testReturnVariousSignatures() {
    133   (void)^int(){
    134     return 42;
    135   }();
    136 
    137   (void)^int{
    138     return 42;
    139   }();
    140 
    141   (void)^(){
    142     return 42;
    143   }();
    144 
    145   (void)^{
    146     return 42;
    147   }();
    148 }
    149 
    150 // This test used to cause infinite loop in the region invalidation.
    151 void blockCapturesItselfInTheLoop(int x, int m) {
    152   void (^assignData)(int) = ^(int x){
    153     x++;
    154   };
    155   while (m < 0) {
    156     void (^loop)(int);
    157     loop = ^(int x) {
    158       assignData(x);
    159     };
    160     assignData = loop;
    161     m++;
    162   }
    163   assignData(x);
    164 }
    165 
    166 // Blocks that called the function they were contained in that also have
    167 // static locals caused crashes.
    168 // rdar://problem/21698099
    169 void takeNonnullBlock(void (^)(void)) __attribute__((nonnull));
    170 void takeNonnullIntBlock(int (^)(void)) __attribute__((nonnull));
    171 
    172 void testCallContainingWithSignature1()
    173 {
    174   takeNonnullBlock(^{
    175     static const char str[] = "Lost connection to sharingd";
    176     testCallContainingWithSignature1();
    177   });
    178 }
    179 
    180 void testCallContainingWithSignature2()
    181 {
    182   takeNonnullBlock(^void{
    183     static const char str[] = "Lost connection to sharingd";
    184     testCallContainingWithSignature2();
    185   });
    186 }
    187 
    188 void testCallContainingWithSignature3()
    189 {
    190   takeNonnullBlock(^void(){
    191     static const char str[] = "Lost connection to sharingd";
    192     testCallContainingWithSignature3();
    193   });
    194 }
    195 
    196 void testCallContainingWithSignature4()
    197 {
    198   takeNonnullBlock(^void(void){
    199     static const char str[] = "Lost connection to sharingd";
    200     testCallContainingWithSignature4();
    201   });
    202 }
    203 
    204 void testCallContainingWithSignature5()
    205 {
    206   takeNonnullIntBlock(^{
    207     static const char str[] = "Lost connection to sharingd";
    208     testCallContainingWithSignature5();
    209     return 0;
    210   });
    211 }
    212 
    213 __attribute__((objc_root_class))
    214 @interface SuperClass
    215 - (void)someMethod;
    216 @end
    217 
    218 @interface SomeClass : SuperClass
    219 @end
    220 
    221 // Make sure to properly handle super-calls when a block captures
    222 // a local variable named 'self'.
    223 @implementation SomeClass
    224 -(void)foo; {
    225   /*__weak*/ SomeClass *weakSelf = self;
    226   (void)(^(void) {
    227     SomeClass *self = weakSelf;
    228     (void)(^(void) {
    229       (void)self;
    230       [super someMethod]; // no-warning
    231     });
    232   });
    233 }
    234 @end
    235