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);
13 // expected-no-diagnostics
15 int& invalidate_static_on_unknown_lambda() {
19 }; // should invalidate "z" when inlining is disabled.
21 return *z
; // no-warning
26 struct X
{ X(const X
&); };
27 void f(X x
) { (void) [x
]{}; }
30 // Lambda semantics tests.
35 // clang_analyzer_eval does nothing in inlined functions.
37 clang_analyzer_warnIfReached();
42 clang_analyzer_warnIfReached();
46 clang_analyzer_warnIfReached();
49 clang_analyzer_eval(i
== 6); // expected-warning{{TRUE}}
52 void deferredLambdaCall() {
54 auto l1
= [i
]() mutable {
56 clang_analyzer_warnIfReached();
61 clang_analyzer_warnIfReached();
65 clang_analyzer_warnIfReached();
71 clang_analyzer_eval(i
== 6); // expected-warning{{TRUE}}
74 void multipleCaptures() {
78 clang_analyzer_warnIfReached();
82 clang_analyzer_eval(i
== 5); // expected-warning{{TRUE}}
83 clang_analyzer_eval(j
== 6); // expected-warning{{TRUE}}
86 clang_analyzer_warnIfReached();
90 clang_analyzer_eval(i
== 5); // expected-warning{{TRUE}}
91 clang_analyzer_eval(j
== 6); // expected-warning{{TRUE}}
94 clang_analyzer_warnIfReached();
98 clang_analyzer_eval(i
== 6); // expected-warning{{TRUE}}
99 clang_analyzer_eval(j
== 7); // expected-warning{{TRUE}}
102 void testReturnValue() {
104 auto l
= [i
] (int a
) {
108 clang_analyzer_eval(b
== 8); // expected-warning{{TRUE}}
111 void testAliasingBetweenParameterAndCapture() {
114 auto l
= [&i
](int &p
) {
119 clang_analyzer_eval(i
== 7); // expected-warning{{TRUE}}
124 void testNestedLambdas() {
126 auto l
= [i
]() mutable {
131 clang_analyzer_warnIfReached();
134 clang_analyzer_eval(i
== 5); // expected-warning{{TRUE}}
142 void captureFields() {
145 // clang_analyzer_eval does nothing in inlined functions.
147 clang_analyzer_warnIfReached();
150 clang_analyzer_eval(i
== 6); // expected-warning{{TRUE}}
155 // Nested this capture.
160 void captureFields() {
163 // clang_analyzer_eval does nothing in inlined functions.
165 clang_analyzer_warnIfReached();
168 // clang_analyzer_eval does nothing in inlined functions.
170 clang_analyzer_warnIfReached();
174 clang_analyzer_eval(i
== 7); // expected-warning{{TRUE}}
179 // Captured function pointers.
185 void testFunctionPointerCapture() {
186 void (*func
)(int &) = inc
;
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
}}
206 clang_analyzer_eval(i
== 7); // expected-warning{{TRUE}}
209 // Test inline defensive checks
212 void inlineDefensiveChecks() {
224 void callLambda(T t
) {
231 callLambda([&](){ ++x
; });
232 callLambdaFromStatic([&](){ ++x
; });
236 static void callLambdaFromStatic(T t
) {
244 void captureConstants() {
248 clang_analyzer_warnIfReached();
252 clang_analyzer_warnIfReached();
256 void captureReferenceByCopy(int &p
) {
260 // p is a reference captured by copy
266 clang_analyzer_eval(v
== 8); // expected-warning{{TRUE}}
267 clang_analyzer_eval(p
== 8); // expected-warning{{TRUE}}
270 void captureReferenceByReference(int &p
) {
274 // p is a reference captured by reference
280 clang_analyzer_eval(v
== 8); // expected-warning{{TRUE}}
281 clang_analyzer_eval(p
== 22); // expected-warning{{TRUE}}
284 void callMutableLambdaMultipleTimes(int &p
) {
288 auto l
= [&v
, p
]() mutable {
295 clang_analyzer_eval(v
== 8); // expected-warning{{TRUE}}
296 clang_analyzer_eval(p
== 8); // expected-warning{{TRUE}}
300 clang_analyzer_eval(v
== 9); // expected-warning{{TRUE}}
301 clang_analyzer_eval(p
== 8); // expected-warning{{TRUE}}
305 struct StructPR24914
{
309 void takesConstStructArgument(const StructPR24914
&);
310 void captureStructReference(const StructPR24914
& s
) {
312 takesConstStructArgument(s
);
316 // Lambda capture counts as use for dead-store checking.
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}}
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
342 // Don't treat as a dead store because local1 was captured by reference.
343 local1
= 7; // no-warning
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
359 void testCapturedConstExprFloat() {
360 constexpr float localConstant
= 4.0;
362 // Don't treat localConstant as containing a garbage value
363 float copy
= localConstant
; // no-warning
372 int& invalidate_static_on_unknown_lambda() {
379 return *z
; // no-warning
394 return *y
; // no-warning
401 // CHECK: [B2 (ENTRY)]
402 // CHECK: Succs (1): B1
405 // CHECK: 2: [B1.1] (ImplicitCastExpr, NoOp, const X)
406 // CHECK: 3: [B1.2] (CXXConstructExpr[B1.4]+0, X)
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