blob: a906cedb3a94034b003713f513528da1891ebccc [file] [log] [blame]
Gabor Horvath15843342015-09-11 16:55:01 +00001// RUN: %clang_cc1 -std=c++11 -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s
2// 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
176
177// Test inline defensive checks
178int getNum();
179
180void inlineDefensiveChecks() {
181 int i = getNum();
182 [=]() {
183 if (i == 0)
184 ;
185 }();
186 int p = 5/i;
187 (void)p;
188}
189
Gabor Horvath2f929b42015-10-26 17:42:14 +0000190
191template<typename T>
192void callLambda(T t) {
193 t();
194}
195
196struct DontCrash {
197 int x;
198 void f() {
199 callLambda([&](){ ++x; });
Gabor Horvath244d2712015-10-27 12:36:26 +0000200 callLambdaFromStatic([&](){ ++x; });
201 }
202
203 template<typename T>
204 static void callLambdaFromStatic(T t) {
205 t();
Gabor Horvath2f929b42015-10-26 17:42:14 +0000206 }
207};
208
Gabor Horvathba7d9072015-10-27 13:46:39 +0000209
210// Capture constants
211
212void captureConstants() {
213 const int i = 5;
214 [=]() {
215 if (i != 5)
216 clang_analyzer_warnIfReached();
217 }();
218 [&] {
219 if (i != 5)
220 clang_analyzer_warnIfReached();
221 }();
222}
223
Devin Coughline69b0432015-11-15 03:07:17 +0000224void captureReferenceByCopy(int &p) {
225 int v = 7;
226 p = 8;
227
228 // p is a reference captured by copy
229 [&v,p]() mutable {
230 v = p;
231 p = 22;
232 }();
233
234 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
235 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
236}
237
238void captureReferenceByReference(int &p) {
239 int v = 7;
240 p = 8;
241
242 // p is a reference captured by reference
243 [&v,&p]() {
244 v = p;
245 p = 22;
246 }();
247
248 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
249 clang_analyzer_eval(p == 22); // expected-warning{{TRUE}}
250}
251
252void callMutableLambdaMultipleTimes(int &p) {
253 int v = 0;
254 p = 8;
255
256 auto l = [&v, p]() mutable {
257 v = p;
258 p++;
259 };
260
261 l();
262
263 clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}
264 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
265
266 l();
267
268 clang_analyzer_eval(v == 9); // expected-warning{{TRUE}}
269 clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}
270}
271
272// PR 24914
273struct StructPR24914{
274 int x;
275};
276
277void takesConstStructArgument(const StructPR24914&);
278void captureStructReference(const StructPR24914& s) {
279 [s]() {
280 takesConstStructArgument(s);
281 }();
282}
283
284
Ted Kremenekda76a942012-04-12 20:34:52 +0000285// CHECK: [B2 (ENTRY)]
286// CHECK: Succs (1): B1
287// CHECK: [B1]
288// CHECK: 1: x
289// CHECK: 2: [B1.1] (ImplicitCastExpr, NoOp, const struct X)
290// CHECK: 3: [B1.2] (CXXConstructExpr, struct X)
Richard Smithbb13c9a2013-09-28 04:02:39 +0000291// CHECK: 4: [x] {
Ted Kremenekda76a942012-04-12 20:34:52 +0000292// CHECK: }
293// CHECK: 5: (void)[B1.4] (CStyleCastExpr, ToVoid, void)
294// CHECK: Preds (1): B2
295// CHECK: Succs (1): B0
296// CHECK: [B0 (EXIT)]
297// CHECK: Preds (1): B1
298