Devin Coughlin | b6029b7 | 2015-11-25 22:35:37 +0000 | [diff] [blame] | 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 |
Devin Coughlin | 1d40583 | 2015-11-15 17:48:22 +0000 | [diff] [blame] | 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 |
Devin Coughlin | b6029b7 | 2015-11-25 22:35:37 +0000 | [diff] [blame] | 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 | // FIXME: This should be TRUE. We're not handling lambda to block conversions |
| 74 | // properly in ExprEngine::VisitBlockExpr. |
| 75 | clang_analyzer_eval(result == 7); // expected-warning{{UNKNOWN}} |
| 76 | } |
| 77 | |
| 78 | void castLambdaInLocalBlock() { |
| 79 | // FIXME: This results in a spurious |
| 80 | // "Address of stack-allocated block declared on line XX returned to caller" warning |
| 81 | // because we're not handling lambda to block conversions properly in ExprEngine. |
| 82 | auto lambda = []{ }; // expected-warning {{Address of stack-allocated block declared on line}} |
| 83 | |
| 84 | void(^block)() = lambda; |
| 85 | (void)block; |
| 86 | } |