Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -fblocks -Wno-objc-root-class -analyze -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s
      2 
      3 int clang_analyzer_eval(int);
      4 
      5 @interface Super
      6 - (void)superMethod;
      7 @end
      8 
      9 @interface Sub : Super {
     10   int _ivar1;
     11   int _ivar2;
     12 }
     13 @end
     14 
     15 @implementation Sub
     16 - (void)callMethodOnSuperInCXXLambda; {
     17   // Explicit capture.
     18   [self]() {
     19     [super superMethod];
     20   }();
     21 
     22   // Implicit capture.
     23   [=]() {
     24     [super superMethod];
     25   }();
     26 }
     27 
     28 // Make sure to properly handle super-calls when a block captures
     29 // a local variable named 'self'.
     30 - (void)callMethodOnSuperInCXXLambdaWithRedefinedSelf; {
     31   /*__weak*/ Sub *weakSelf = self;
     32   // Implicit capture. (Sema outlaws explicit capture of a redefined self
     33   // and a call to super [which uses the original self]).
     34   [=]() {
     35     Sub *self = weakSelf;
     36     [=]() {
     37       [super superMethod];
     38     }();
     39   }();
     40 }
     41 
     42 - (void)swapIvars {
     43   int tmp = _ivar1;
     44   _ivar1 = _ivar2;
     45   _ivar2 = tmp;
     46 }
     47 
     48 - (void)callMethodOnSelfInCXXLambda; {
     49   _ivar1 = 7;
     50   _ivar2 = 8;
     51   [self]() {
     52     [self swapIvars];
     53   }();
     54 
     55   clang_analyzer_eval(_ivar1 == 8); // expected-warning{{TRUE}}
     56   clang_analyzer_eval(_ivar2 == 7); // expected-warning{{TRUE}}
     57 }
     58 
     59 @end
     60 
     61 int getValue();
     62 void useValue(int v);
     63 
     64 void castToBlockNoDeadStore() {
     65   int v = getValue(); // no-warning
     66 
     67   (void)(void(^)())[v]() { // This capture should count as a use, so no dead store warning above.
     68   };
     69 }
     70 
     71 void takesBlock(void(^block)());
     72 
     73 void passToFunctionTakingBlockNoDeadStore() {
     74   int v = 7; // no-warning
     75   int x = 8; // no-warning
     76   takesBlock([&v, x]() {
     77     (void)v;
     78   });
     79 }
     80 
     81 void castToBlockAndInline() {
     82   int result = ((int(^)(int))[](int p) {
     83     return p;
     84   })(7);
     85 
     86   clang_analyzer_eval(result == 7); // expected-warning{{TRUE}}
     87 }
     88 
     89 void castToBlockWithCaptureAndInline() {
     90   int y = 7;
     91 
     92   auto lambda = [y]{ return y; };
     93   int(^block)() = lambda;
     94 
     95   int result = block();
     96   clang_analyzer_eval(result == 7); // expected-warning{{TRUE}}
     97 }
     98 
     99 void castMutableLambdaToBlock() {
    100   int x = 0;
    101 
    102   auto lambda = [x]() mutable {
    103     x = x + 1;
    104     return x;
    105    };
    106 
    107   // The block should copy the lambda before capturing.
    108   int(^block)() = lambda;
    109 
    110   int r1 = block();
    111   clang_analyzer_eval(r1 == 1); // expected-warning{{TRUE}}
    112 
    113   int r2 = block();
    114   clang_analyzer_eval(r2 == 2); // expected-warning{{TRUE}}
    115 
    116   // Because block copied the lambda, r3 should be 1.
    117   int r3 = lambda();
    118   clang_analyzer_eval(r3 == 1); // expected-warning{{TRUE}}
    119 
    120   // Aliasing the block shouldn't copy the lambda.
    121   int(^blockAlias)() = block;
    122 
    123   int r4 = blockAlias();
    124   clang_analyzer_eval(r4 == 3); // expected-warning{{TRUE}}
    125 
    126   int r5 = block();
    127   clang_analyzer_eval(r5 == 4); // expected-warning{{TRUE}}
    128 
    129   // Another copy of lambda
    130   int(^blockSecondCopy)() = lambda;
    131   int r6 = blockSecondCopy();
    132   clang_analyzer_eval(r6 == 2); // expected-warning{{TRUE}}
    133 }
    134 
    135 void castLambdaInLocalBlock() {
    136   // Make sure we don't emit a spurious diagnostic about the address of a block
    137   // escaping in the implicit conversion operator method for lambda-to-block
    138   // conversions.
    139   auto lambda = []{ }; // no-warning
    140 
    141   void(^block)() = lambda;
    142   (void)block;
    143 }
    144