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 
     16 @implementation Sub
     17 - (void)callMethodOnSuperInCXXLambda; {
     18   // Explicit capture.
     19   [self]() {
     20     [super superMethod];
     21   }();
     22 
     23   // Implicit capture.
     24   [=]() {
     25     [super superMethod];
     26   }();
     27 }
     28 
     29 - (void)swapIvars {
     30   int tmp = _ivar1;
     31   _ivar1 = _ivar2;
     32   _ivar2 = tmp;
     33 }
     34 
     35 - (void)callMethodOnSelfInCXXLambda; {
     36   _ivar1 = 7;
     37   _ivar2 = 8;
     38   [self]() {
     39     [self swapIvars];
     40   }();
     41 
     42   clang_analyzer_eval(_ivar1 == 8); // expected-warning{{TRUE}}
     43   clang_analyzer_eval(_ivar2 == 7); // expected-warning{{TRUE}}
     44 }
     45 
     46 @end
     47 
     48 int getValue();
     49 void useValue(int v);
     50 
     51 void castToBlockNoDeadStore() {
     52   int v = getValue(); // no-warning
     53 
     54   (void)(void(^)())[v]() { // This capture should count as a use, so no dead store warning above.
     55   };
     56 }
     57 
     58 void takesBlock(void(^block)());
     59 
     60 void passToFunctionTakingBlockNoDeadStore() {
     61   int v = 7; // no-warning
     62   int x = 8; // no-warning
     63   takesBlock([&v, x]() {
     64     (void)v;
     65   });
     66 }
     67 
     68 void castToBlockAndInline() {
     69   int result = ((int(^)(int))[](int p) {
     70     return p;
     71   })(7);
     72 
     73   clang_analyzer_eval(result == 7); // expected-warning{{TRUE}}
     74 }
     75 
     76 void castToBlockWithCaptureAndInline() {
     77   int y = 7;
     78 
     79   auto lambda = [y]{ return y; };
     80   int(^block)() = lambda;
     81 
     82   int result = block();
     83   clang_analyzer_eval(result == 7); // expected-warning{{TRUE}}
     84 }
     85 
     86 void castMutableLambdaToBlock() {
     87   int x = 0;
     88 
     89   auto lambda = [x]() mutable {
     90     x = x + 1;
     91     return x;
     92    };
     93 
     94   // The block should copy the lambda before capturing.
     95   int(^block)() = lambda;
     96 
     97   int r1 = block();
     98   clang_analyzer_eval(r1 == 1); // expected-warning{{TRUE}}
     99 
    100   int r2 = block();
    101   clang_analyzer_eval(r2 == 2); // expected-warning{{TRUE}}
    102 
    103   // Because block copied the lambda, r3 should be 1.
    104   int r3 = lambda();
    105   clang_analyzer_eval(r3 == 1); // expected-warning{{TRUE}}
    106 
    107   // Aliasing the block shouldn't copy the lambda.
    108   int(^blockAlias)() = block;
    109 
    110   int r4 = blockAlias();
    111   clang_analyzer_eval(r4 == 3); // expected-warning{{TRUE}}
    112 
    113   int r5 = block();
    114   clang_analyzer_eval(r5 == 4); // expected-warning{{TRUE}}
    115 
    116   // Another copy of lambda
    117   int(^blockSecondCopy)() = lambda;
    118   int r6 = blockSecondCopy();
    119   clang_analyzer_eval(r6 == 2); // expected-warning{{TRUE}}
    120 }
    121 
    122 void castLambdaInLocalBlock() {
    123   // Make sure we don't emit a spurious diagnostic about the address of a block
    124   // escaping in the implicit conversion operator method for lambda-to-block
    125   // conversions.
    126   auto lambda = []{ }; // no-warning
    127 
    128   void(^block)() = lambda;
    129   (void)block;
    130 }
    131