• Home
  • History
  • Annotate
  • 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 
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