• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3int 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
48int getValue();
49void useValue(int v);
50
51void 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
58void takesBlock(void(^block)());
59
60void passToFunctionTakingBlockNoDeadStore() {
61  int v = 7; // no-warning
62  int x = 8; // no-warning
63  takesBlock([&v, x]() {
64    (void)v;
65  });
66}
67
68void 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
76void 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
86void 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
122void 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