Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Analysis / lambdas.cpp
blob554ed342a4279be49bed37258c1cd67fac76d783
1 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s
2 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-config inline-lambdas=false -DNO_INLINING=1 -verify %s
3 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -analyzer-config inline-lambdas=true %s > %t 2>&1
4 // RUN: FileCheck --input-file=%t %s
6 #include "Inputs/system-header-simulator-cxx.h"
8 void clang_analyzer_warnIfReached();
9 void clang_analyzer_eval(int);
11 #ifdef NO_INLINING
13 // expected-no-diagnostics
15 int& invalidate_static_on_unknown_lambda() {
16 static int* z;
17 auto f = [] {
18 z = nullptr;
19 }; // should invalidate "z" when inlining is disabled.
20 f();
21 return *z; // no-warning
24 #else
26 struct X { X(const X&); };
27 void f(X x) { (void) [x]{}; }
30 // Lambda semantics tests.
32 void basicCapture() {
33 int i = 5;
34 [i]() mutable {
35 // clang_analyzer_eval does nothing in inlined functions.
36 if (i != 5)
37 clang_analyzer_warnIfReached();
38 ++i;
39 }();
40 [&i] {
41 if (i != 5)
42 clang_analyzer_warnIfReached();
43 }();
44 [&i] {
45 if (i != 5)
46 clang_analyzer_warnIfReached();
47 i++;
48 }();
49 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
52 void deferredLambdaCall() {
53 int i = 5;
54 auto l1 = [i]() mutable {
55 if (i != 5)
56 clang_analyzer_warnIfReached();
57 ++i;
59 auto l2 = [&i] {
60 if (i != 5)
61 clang_analyzer_warnIfReached();
63 auto l3 = [&i] {
64 if (i != 5)
65 clang_analyzer_warnIfReached();
66 i++;
68 l1();
69 l2();
70 l3();
71 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
74 void multipleCaptures() {
75 int i = 5, j = 5;
76 [i, &j]() mutable {
77 if (i != 5 && j != 5)
78 clang_analyzer_warnIfReached();
79 ++i;
80 ++j;
81 }();
82 clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
83 clang_analyzer_eval(j == 6); // expected-warning{{TRUE}}
84 [=]() mutable {
85 if (i != 5 && j != 6)
86 clang_analyzer_warnIfReached();
87 ++i;
88 ++j;
89 }();
90 clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
91 clang_analyzer_eval(j == 6); // expected-warning{{TRUE}}
92 [&]() mutable {
93 if (i != 5 && j != 6)
94 clang_analyzer_warnIfReached();
95 ++i;
96 ++j;
97 }();
98 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
99 clang_analyzer_eval(j == 7); // expected-warning{{TRUE}}
102 void testReturnValue() {
103 int i = 5;
104 auto l = [i] (int a) {
105 return i + a;
107 int b = l(3);
108 clang_analyzer_eval(b == 8); // expected-warning{{TRUE}}
111 void testAliasingBetweenParameterAndCapture() {
112 int i = 5;
114 auto l = [&i](int &p) {
115 i++;
116 p++;
118 l(i);
119 clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
122 // Nested lambdas.
124 void testNestedLambdas() {
125 int i = 5;
126 auto l = [i]() mutable {
127 [&i]() {
128 ++i;
129 }();
130 if (i != 6)
131 clang_analyzer_warnIfReached();
133 l();
134 clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
137 // Captured this.
139 class RandomClass {
140 int i;
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 }();
150 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
155 // Nested this capture.
157 class RandomClass2 {
158 int i;
160 void captureFields() {
161 i = 5;
162 [this]() {
163 // clang_analyzer_eval does nothing in inlined functions.
164 if (i != 5)
165 clang_analyzer_warnIfReached();
166 ++i;
167 [this]() {
168 // clang_analyzer_eval does nothing in inlined functions.
169 if (i != 6)
170 clang_analyzer_warnIfReached();
171 ++i;
172 }();
173 }();
174 clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
179 // Captured function pointers.
181 void inc(int &x) {
182 ++x;
185 void testFunctionPointerCapture() {
186 void (*func)(int &) = inc;
187 int i = 5;
188 [&i, func] {
189 func(i);
190 }();
191 clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
194 // Captured variable-length array.
196 void testVariableLengthArrayCaptured() {
197 int n = 2; // expected-note {{declared here}}
198 int array[n]; // expected-warning {{variable length arrays in C++ are a Clang extension}} \
199 expected-note {{read of non-const variable 'n' is not allowed in a constant expression}}
200 array[0] = 7;
202 int i = [&]{
203 return array[0];
204 }();
206 clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
209 // Test inline defensive checks
210 int getNum();
212 void inlineDefensiveChecks() {
213 int i = getNum();
214 [=]() {
215 if (i == 0)
217 }();
218 int p = 5/i;
219 (void)p;
223 template<typename T>
224 void callLambda(T t) {
225 t();
228 struct DontCrash {
229 int x;
230 void f() {
231 callLambda([&](){ ++x; });
232 callLambdaFromStatic([&](){ ++x; });
235 template<typename T>
236 static void callLambdaFromStatic(T t) {
237 t();
242 // Capture constants
244 void captureConstants() {
245 const int i = 5;
246 [=]() {
247 if (i != 5)
248 clang_analyzer_warnIfReached();
249 }();
250 [&] {
251 if (i != 5)
252 clang_analyzer_warnIfReached();
253 }();
256 void captureReferenceByCopy(int &p) {
257 int v = 7;
258 p = 8;
260 // p is a reference captured by copy
261 [&v,p]() mutable {
262 v = p;
263 p = 22;
264 }();
266 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
267 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
270 void captureReferenceByReference(int &p) {
271 int v = 7;
272 p = 8;
274 // p is a reference captured by reference
275 [&v,&p]() {
276 v = p;
277 p = 22;
278 }();
280 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
281 clang_analyzer_eval(p == 22); // expected-warning{{TRUE}}
284 void callMutableLambdaMultipleTimes(int &p) {
285 int v = 0;
286 p = 8;
288 auto l = [&v, p]() mutable {
289 v = p;
290 p++;
293 l();
295 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
296 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
298 l();
300 clang_analyzer_eval(v == 9); // expected-warning{{TRUE}}
301 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
304 // PR 24914
305 struct StructPR24914{
306 int x;
309 void takesConstStructArgument(const StructPR24914&);
310 void captureStructReference(const StructPR24914& s) {
311 [s]() {
312 takesConstStructArgument(s);
313 }();
316 // Lambda capture counts as use for dead-store checking.
318 int returnsValue();
320 void captureByCopyCausesUse() {
321 int local1 = returnsValue(); // no-warning
322 int local2 = returnsValue(); // no-warning
323 int local3 = returnsValue(); // expected-warning{{Value stored to 'local3' during its initialization is never read}}
325 (void)[local1, local2]() { }; // Explicit capture by copy counts as use.
327 int local4 = returnsValue(); // no-warning
328 int local5 = returnsValue(); // expected-warning{{Value stored to 'local5' during its initialization is never read}}
330 (void)[=]() {
331 (void)local4; // Implicit capture by copy counts as use
335 void captureByReference() {
336 int local1 = returnsValue(); // no-warning
338 auto lambda1 = [&local1]() { // Explicit capture by reference
339 local1++;
342 // Don't treat as a dead store because local1 was captured by reference.
343 local1 = 7; // no-warning
345 lambda1();
347 int local2 = returnsValue(); // no-warning
349 auto lambda2 = [&]() {
350 local2++; // Implicit capture by reference
353 // Don't treat as a dead store because local2 was captured by reference.
354 local2 = 7; // no-warning
356 lambda2();
359 void testCapturedConstExprFloat() {
360 constexpr float localConstant = 4.0;
361 auto lambda = []{
362 // Don't treat localConstant as containing a garbage value
363 float copy = localConstant; // no-warning
364 (void)copy;
367 lambda();
370 void escape(void*);
372 int& invalidate_static_on_unknown_lambda() {
373 static int* z;
374 auto lambda = [] {
375 static float zz;
376 z = new int(120);
378 escape(&lambda);
379 return *z; // no-warning
383 static int b = 0;
385 int f() {
386 b = 0;
387 auto &bm = b;
388 [&] {
389 bm++;
390 bm++;
391 }();
392 if (bm != 2) {
393 int *y = 0;
394 return *y; // no-warning
396 return 0;
399 #endif
401 // CHECK: [B2 (ENTRY)]
402 // CHECK: Succs (1): B1
403 // CHECK: [B1]
404 // CHECK: 1: x
405 // CHECK: 2: [B1.1] (ImplicitCastExpr, NoOp, const X)
406 // CHECK: 3: [B1.2] (CXXConstructExpr[B1.4]+0, X)
407 // CHECK: 4: [x] {
408 // CHECK: }
409 // CHECK: 5: (void)[B1.4] (CStyleCastExpr, ToVoid, void)
410 // CHECK: Preds (1): B2
411 // CHECK: Succs (1): B0
412 // CHECK: [B0 (EXIT)]
413 // CHECK: Preds (1): B1