blob: 0b66e6b92fa66b8649ae70f3496b1204ac03b616 [file] [log] [blame]
Devin Coughlinc7315b32015-11-20 01:53:44 +00001// RUN: %clang_cc1 -std=c++11 -fsyntax-only -analyze -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s
Gabor Horvath15843342015-09-11 16:55:01 +00002// RUN: %clang_cc1 -std=c++11 -fsyntax-only -analyze -analyzer-checker=core,debug.DumpCFG -analyzer-config inline-lambdas=true %s > %t 2>&1
Ted Kremenekda76a942012-04-12 20:34:52 +00003// RUN: FileCheck --input-file=%t %s
4
Gabor Horvath15843342015-09-11 16:55:01 +00005void clang_analyzer_warnIfReached();
6void clang_analyzer_eval(int);
7
Ted Kremenekda76a942012-04-12 20:34:52 +00008struct X { X(const X&); };
9void f(X x) { (void) [x]{}; }
10
Gabor Horvath15843342015-09-11 16:55:01 +000011
12// Lambda semantics tests.
13
14void basicCapture() {
15 int i = 5;
16 [i]() mutable {
17 // clang_analyzer_eval does nothing in inlined functions.
18 if (i != 5)
19 clang_analyzer_warnIfReached();
20 ++i;
21 }();
22 [&i] {
23 if (i != 5)
24 clang_analyzer_warnIfReached();
25 }();
26 [&i] {
27 if (i != 5)
28 clang_analyzer_warnIfReached();
29 i++;
30 }();
31 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
32}
33
34void deferredLambdaCall() {
35 int i = 5;
36 auto l1 = [i]() mutable {
37 if (i != 5)
38 clang_analyzer_warnIfReached();
39 ++i;
40 };
41 auto l2 = [&i] {
42 if (i != 5)
43 clang_analyzer_warnIfReached();
44 };
45 auto l3 = [&i] {
46 if (i != 5)
47 clang_analyzer_warnIfReached();
48 i++;
49 };
50 l1();
51 l2();
52 l3();
53 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
54}
55
56void multipleCaptures() {
57 int i = 5, j = 5;
58 [i, &j]() mutable {
59 if (i != 5 && j != 5)
60 clang_analyzer_warnIfReached();
61 ++i;
62 ++j;
63 }();
64 clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
65 clang_analyzer_eval(j == 6); // expected-warning{{TRUE}}
66 [=]() mutable {
67 if (i != 5 && j != 6)
68 clang_analyzer_warnIfReached();
69 ++i;
70 ++j;
71 }();
72 clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
73 clang_analyzer_eval(j == 6); // expected-warning{{TRUE}}
74 [&]() mutable {
75 if (i != 5 && j != 6)
76 clang_analyzer_warnIfReached();
77 ++i;
78 ++j;
79 }();
80 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
81 clang_analyzer_eval(j == 7); // expected-warning{{TRUE}}
82}
83
84void testReturnValue() {
85 int i = 5;
86 auto l = [i] (int a) {
87 return i + a;
88 };
89 int b = l(3);
90 clang_analyzer_eval(b == 8); // expected-warning{{TRUE}}
91}
92
Devin Coughline69b0432015-11-15 03:07:17 +000093void testAliasingBetweenParameterAndCapture() {
94 int i = 5;
95
96 auto l = [&i](int &p) {
97 i++;
98 p++;
99 };
100 l(i);
101 clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
102}
103
Gabor Horvath15843342015-09-11 16:55:01 +0000104// Nested lambdas.
105
106void testNestedLambdas() {
107 int i = 5;
108 auto l = [i]() mutable {
109 [&i]() {
110 ++i;
111 }();
112 if (i != 6)
113 clang_analyzer_warnIfReached();
114 };
115 l();
116 clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
117}
118
119// Captured this.
120
121class RandomClass {
122 int i;
123
124 void captureFields() {
125 i = 5;
126 [this]() {
127 // clang_analyzer_eval does nothing in inlined functions.
128 if (i != 5)
129 clang_analyzer_warnIfReached();
130 ++i;
131 }();
132 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
133 }
134};
135
136
137// Nested this capture.
138
139class RandomClass2 {
140 int i;
141
142 void captureFields() {
143 i = 5;
144 [this]() {
145 // clang_analyzer_eval does nothing in inlined functions.
146 if (i != 5)
147 clang_analyzer_warnIfReached();
148 ++i;
149 [this]() {
150 // clang_analyzer_eval does nothing in inlined functions.
151 if (i != 6)
152 clang_analyzer_warnIfReached();
153 ++i;
154 }();
155 }();
156 clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
157 }
158};
159
160
161// Captured function pointers.
162
163void inc(int &x) {
164 ++x;
165}
166
167void testFunctionPointerCapture() {
168 void (*func)(int &) = inc;
169 int i = 5;
170 [&i, func] {
171 func(i);
172 }();
173 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
174}
175
Devin Coughlin7bdca8b2015-12-07 23:01:53 +0000176// Captured variable-length array.
177
178void testVariableLengthArrayCaptured() {
179 int n = 2;
180 int array[n];
181 array[0] = 7;
182
183 int i = [&]{
184 return array[0];
185 }();
186
187 clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
188}
Gabor Horvath15843342015-09-11 16:55:01 +0000189
190// Test inline defensive checks
191int getNum();
192
193void inlineDefensiveChecks() {
194 int i = getNum();
195 [=]() {
196 if (i == 0)
197 ;
198 }();
199 int p = 5/i;
200 (void)p;
201}
202
Gabor Horvath2f929b42015-10-26 17:42:14 +0000203
204template<typename T>
205void callLambda(T t) {
206 t();
207}
208
209struct DontCrash {
210 int x;
211 void f() {
212 callLambda([&](){ ++x; });
Gabor Horvath244d2712015-10-27 12:36:26 +0000213 callLambdaFromStatic([&](){ ++x; });
214 }
215
216 template<typename T>
217 static void callLambdaFromStatic(T t) {
218 t();
Gabor Horvath2f929b42015-10-26 17:42:14 +0000219 }
220};
221
Gabor Horvathba7d9072015-10-27 13:46:39 +0000222
223// Capture constants
224
225void captureConstants() {
226 const int i = 5;
227 [=]() {
228 if (i != 5)
229 clang_analyzer_warnIfReached();
230 }();
231 [&] {
232 if (i != 5)
233 clang_analyzer_warnIfReached();
234 }();
235}
236
Devin Coughline69b0432015-11-15 03:07:17 +0000237void captureReferenceByCopy(int &p) {
238 int v = 7;
239 p = 8;
240
241 // p is a reference captured by copy
242 [&v,p]() mutable {
243 v = p;
244 p = 22;
245 }();
246
247 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
248 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
249}
250
251void captureReferenceByReference(int &p) {
252 int v = 7;
253 p = 8;
254
255 // p is a reference captured by reference
256 [&v,&p]() {
257 v = p;
258 p = 22;
259 }();
260
261 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
262 clang_analyzer_eval(p == 22); // expected-warning{{TRUE}}
263}
264
265void callMutableLambdaMultipleTimes(int &p) {
266 int v = 0;
267 p = 8;
268
269 auto l = [&v, p]() mutable {
270 v = p;
271 p++;
272 };
273
274 l();
275
276 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
277 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
278
279 l();
280
281 clang_analyzer_eval(v == 9); // expected-warning{{TRUE}}
282 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
283}
284
285// PR 24914
286struct StructPR24914{
287 int x;
288};
289
290void takesConstStructArgument(const StructPR24914&);
291void captureStructReference(const StructPR24914& s) {
292 [s]() {
293 takesConstStructArgument(s);
294 }();
295}
296
Devin Coughlinc7315b32015-11-20 01:53:44 +0000297// Lambda capture counts as use for dead-store checking.
298
299int returnsValue();
300
301void captureByCopyCausesUse() {
302 int local1 = returnsValue(); // no-warning
303 int local2 = returnsValue(); // no-warning
304 int local3 = returnsValue(); // expected-warning{{Value stored to 'local3' during its initialization is never read}}
305
306 (void)[local1, local2]() { }; // Explicit capture by copy counts as use.
307
308 int local4 = returnsValue(); // no-warning
309 int local5 = returnsValue(); // expected-warning{{Value stored to 'local5' during its initialization is never read}}
310
311 (void)[=]() {
312 (void)local4; // Implicit capture by copy counts as use
313 };
314}
315
316void captureByReference() {
317 int local1 = returnsValue(); // no-warning
318
319 auto lambda1 = [&local1]() { // Explicit capture by reference
320 local1++;
321 };
322
323 // Don't treat as a dead store because local1 was was captured by reference.
324 local1 = 7; // no-warning
325
326 lambda1();
327
328 int local2 = returnsValue(); // no-warning
329
330 auto lambda2 = [&]() {
331 local2++; // Implicit capture by reference
332 };
333
334 // Don't treat as a dead store because local2 was was captured by reference.
335 local2 = 7; // no-warning
336
337 lambda2();
338}
339
Devin Coughline69b0432015-11-15 03:07:17 +0000340
Ted Kremenekda76a942012-04-12 20:34:52 +0000341// CHECK: [B2 (ENTRY)]
342// CHECK: Succs (1): B1
343// CHECK: [B1]
344// CHECK: 1: x
345// CHECK: 2: [B1.1] (ImplicitCastExpr, NoOp, const struct X)
346// CHECK: 3: [B1.2] (CXXConstructExpr, struct X)
Richard Smithbb13c9a2013-09-28 04:02:39 +0000347// CHECK: 4: [x] {
Ted Kremenekda76a942012-04-12 20:34:52 +0000348// CHECK: }
349// CHECK: 5: (void)[B1.4] (CStyleCastExpr, ToVoid, void)
350// CHECK: Preds (1): B2
351// CHECK: Succs (1): B0
352// CHECK: [B0 (EXIT)]
353// CHECK: Preds (1): B1
354