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