144 lines · plain
1// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -Wno-objc-root-class -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s2 3int clang_analyzer_eval(int);4 5@interface Super6- (void)superMethod;7@end8 9@interface Sub : Super {10 int _ivar1;11 int _ivar2;12}13@end14 15@implementation Sub16- (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 captures29// a local variable named 'self'.30- (void)callMethodOnSuperInCXXLambdaWithRedefinedSelf; {31 /*__weak*/ Sub *weakSelf = self;32 // Implicit capture. (Sema outlaws explicit capture of a redefined self33 // 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@end60 61int getValue();62void useValue(int v);63 64void castToBlockNoDeadStore() {65 int v = getValue(); // no-warning66 67 (void)(void(^)())[v]() { // This capture should count as a use, so no dead store warning above.68 };69}70 71void takesBlock(void(^block)());72 73void passToFunctionTakingBlockNoDeadStore() {74 int v = 7; // no-warning75 int x = 8; // no-warning76 takesBlock([&v, x]() {77 (void)v;78 });79}80 81void 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 89void 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 99void 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 lambda130 int(^blockSecondCopy)() = lambda;131 int r6 = blockSecondCopy();132 clang_analyzer_eval(r6 == 2); // expected-warning{{TRUE}}133}134 135void castLambdaInLocalBlock() {136 // Make sure we don't emit a spurious diagnostic about the address of a block137 // escaping in the implicit conversion operator method for lambda-to-block138 // conversions.139 auto lambda = []{ }; // no-warning140 141 void(^block)() = lambda;142 (void)block;143}144