Coverage Report

Created: 2025-01-24 06:31

/src/cppcheck/oss-fuzz/build/valueflow.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "matchcompiler.h"
2
#include <string>
3
#include <cstring>
4
#include "errorlogger.h"
5
#include "token.h"
6
// pattern: <|<=
7
5.03k
static inline bool match1(const Token* tok) {
8
5.03k
    if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<="))))
9
3.09k
        return false;
10
1.94k
    return true;
11
5.03k
}
12
// pattern: >|>=
13
3.09k
static inline bool match2(const Token* tok) {
14
3.09k
    if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">="))))
15
1.74k
        return false;
16
1.34k
    return true;
17
3.09k
}
18
// pattern: ==|!=|>=|<=
19
2.51k
static inline bool match3(const Token* tok) {
20
2.51k
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!=")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">=")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<="))))
21
1.29k
        return false;
22
1.22k
    return true;
23
2.51k
}
24
// pattern: {
25
1.30k
static inline bool match4(const Token* tok) {
26
1.30k
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
27
392
        return false;
28
910
    return true;
29
1.30k
}
30
// pattern: return|continue|break|throw|goto
31
30
template<class T> static inline T * findmatch5(T * start_tok, const Token * end) {
32
60
    for (; start_tok && start_tok != end; start_tok = start_tok->next()) {
33
34
31
    T * tok = start_tok;
35
31
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("continue")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("break")) || (tok->str() == MatchCompiler::makeConstString("throw")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("goto"))))
36
30
        continue;
37
1
    return start_tok;
38
31
    }
39
29
    return nullptr;
40
30
}
41
// pattern: false|true
42
10.9k
static inline bool match6(const Token* tok) {
43
10.9k
    if (!tok || !(((tok->tokType() == Token::eBoolean) && tok->str() == MatchCompiler::makeConstString("false")) || ((tok->tokType() == Token::eBoolean) && tok->str() == MatchCompiler::makeConstString("true"))))
44
10.9k
        return false;
45
0
    return true;
46
10.9k
}
47
// pattern: [(,] NULL [,)]
48
54.9k
static inline bool match7(const Token* tok) {
49
54.9k
    if (!tok || tok->str().size() != 1U || !strchr("(,", tok->str()[0]))
50
52.8k
        return false;
51
2.09k
    tok = tok->next();
52
2.09k
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("NULL")))
53
2.09k
        return false;
54
0
    tok = tok->next();
55
0
    if (!tok || tok->str().size() != 1U || !strchr(",)", tok->str()[0]))
56
0
        return false;
57
0
    return true;
58
0
}
59
// pattern: %var% [ %num%| ] = {
60
0
static inline bool match8(const Token* tok) {
61
0
    if (!tok || !(tok->varId() != 0))
62
0
        return false;
63
0
    tok = tok->next();
64
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))
65
0
        return false;
66
0
    tok = tok->next();
67
0
    if (tok && (tok->isNumber()))
68
0
        tok = tok->next();
69
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")))
70
0
        return false;
71
0
    tok = tok->next();
72
0
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
73
0
        return false;
74
0
    tok = tok->next();
75
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
76
0
        return false;
77
0
    return true;
78
0
}
79
// pattern: =
80
24.9k
static inline bool match9(const Token* tok) {
81
24.9k
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
82
22.4k
        return false;
83
2.53k
    return true;
84
24.9k
}
85
// pattern: const %type% %var% [ %num%| ] = {
86
43.2k
static inline bool match10(const Token* tok) {
87
43.2k
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const")))
88
43.2k
        return false;
89
0
    tok = tok->next();
90
0
    if (!tok || !(tok->isName() && tok->varId() == 0U))
91
0
        return false;
92
0
    tok = tok->next();
93
0
    if (!tok || !(tok->varId() != 0))
94
0
        return false;
95
0
    tok = tok->next();
96
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))
97
0
        return false;
98
0
    tok = tok->next();
99
0
    if (tok && (tok->isNumber()))
100
0
        tok = tok->next();
101
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")))
102
0
        return false;
103
0
    tok = tok->next();
104
0
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
105
0
        return false;
106
0
    tok = tok->next();
107
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
108
0
        return false;
109
0
    return true;
110
0
}
111
// pattern: const char %var% [ %num%| ] = %str% ;
112
43.2k
static inline bool match11(const Token* tok) {
113
43.2k
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const")))
114
43.2k
        return false;
115
0
    tok = tok->next();
116
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("char")))
117
0
        return false;
118
0
    tok = tok->next();
119
0
    if (!tok || !(tok->varId() != 0))
120
0
        return false;
121
0
    tok = tok->next();
122
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))
123
0
        return false;
124
0
    tok = tok->next();
125
0
    if (tok && (tok->isNumber()))
126
0
        tok = tok->next();
127
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")))
128
0
        return false;
129
0
    tok = tok->next();
130
0
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
131
0
        return false;
132
0
    tok = tok->next();
133
0
    if (!tok || !(tok->tokType() == Token::eString))
134
0
        return false;
135
0
    tok = tok->next();
136
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
137
0
        return false;
138
0
    return true;
139
0
}
140
// pattern: %comp%
141
89.7k
static inline bool match12(const Token* tok) {
142
89.7k
    if (!tok || !tok->isComparisonOp())
143
86.7k
        return false;
144
3.00k
    return true;
145
89.7k
}
146
// pattern: (|%name%
147
0
static inline bool match13(const Token* tok) {
148
0
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || tok->isName()))
149
0
        return false;
150
0
    return true;
151
0
}
152
// pattern: if|while|for (
153
585k
static inline bool match14(const Token* tok) {
154
585k
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("if")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("while")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("for"))))
155
510k
        return false;
156
75.5k
    tok = tok->next();
157
75.5k
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
158
0
        return false;
159
75.5k
    return true;
160
75.5k
}
161
// pattern: [
162
177k
static inline bool match15(const Token* tok) {
163
177k
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))
164
177k
        return false;
165
0
    return true;
166
177k
}
167
// pattern: . %name% (
168
115k
static inline bool match16(const Token* tok) {
169
115k
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
170
115k
        return false;
171
0
    tok = tok->next();
172
0
    if (!tok || !tok->isName())
173
0
        return false;
174
0
    tok = tok->next();
175
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
176
0
        return false;
177
0
    return true;
178
0
}
179
// pattern: ==|>=|<=|/
180
4.11k
static inline bool match17(const Token* tok) {
181
4.11k
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">=")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<=")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("/"))))
182
3.76k
        return false;
183
350
    return true;
184
4.11k
}
185
// pattern: !=|>|<|%|-
186
3.76k
static inline bool match18(const Token* tok) {
187
3.76k
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!=")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("%")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-"))))
188
3.04k
        return false;
189
717
    return true;
190
3.76k
}
191
// pattern: -|%|&|^
192
0
static inline bool match19(const Token* tok) {
193
0
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("%")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("^"))))
194
0
        return false;
195
0
    return true;
196
0
}
197
// pattern: true|false
198
75.5k
static inline bool match20(const Token* tok) {
199
75.5k
    if (!tok || !(((tok->tokType() == Token::eBoolean) && tok->str() == MatchCompiler::makeConstString("true")) || ((tok->tokType() == Token::eBoolean) && tok->str() == MatchCompiler::makeConstString("false"))))
200
75.5k
        return false;
201
0
    return true;
202
75.5k
}
203
// pattern: <|<=|>|>=
204
0
static inline bool match21(const Token* tok) {
205
0
    if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<=")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">="))))
206
0
        return false;
207
0
    return true;
208
0
}
209
// pattern: ?
210
77.9k
static inline bool match22(const Token* tok) {
211
77.9k
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("?")))
212
77.9k
        return false;
213
0
    return true;
214
77.9k
}
215
// pattern: %
216
75.5k
static inline bool match23(const Token* tok) {
217
75.5k
    if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("%")))
218
75.4k
        return false;
219
134
    return true;
220
75.5k
}
221
// pattern: abs|labs|llabs|fabs|fabsf|fabsl (
222
113k
static inline bool match24(const Token* tok) {
223
113k
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("abs")) || (tok->str() == MatchCompiler::makeConstString("labs")) || (tok->str() == MatchCompiler::makeConstString("llabs")) || (tok->str() == MatchCompiler::makeConstString("fabs")) || (tok->str() == MatchCompiler::makeConstString("fabsf")) || (tok->str() == MatchCompiler::makeConstString("fabsl"))))
224
113k
        return false;
225
0
    tok = tok->next();
226
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
227
0
        return false;
228
0
    return true;
229
0
}
230
// pattern: . data|c_str (
231
75.5k
static inline bool match25(const Token* tok) {
232
75.5k
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
233
75.5k
        return false;
234
0
    tok = tok->next();
235
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("data")) || (tok->str() == MatchCompiler::makeConstString("c_str"))))
236
0
        return false;
237
0
    tok = tok->next();
238
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
239
0
        return false;
240
0
    return true;
241
0
}
242
// pattern: make_shared|make_unique <
243
75.5k
static inline bool match26(const Token* tok) {
244
75.5k
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("make_shared")) || (tok->str() == MatchCompiler::makeConstString("make_unique"))))
245
75.5k
        return false;
246
0
    tok = tok->next();
247
0
    if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))
248
0
        return false;
249
0
    return true;
250
0
}
251
// pattern: > (
252
0
static inline bool match27(const Token* tok) {
253
0
    if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))
254
0
        return false;
255
0
    tok = tok->next();
256
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
257
0
        return false;
258
0
    return true;
259
0
}
260
// pattern: this
261
75.5k
static inline bool match28(const Token* tok) {
262
75.5k
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("this")))
263
75.5k
        return false;
264
0
    return true;
265
75.5k
}
266
// pattern: %name% =
267
0
static inline bool match29(const Token* tok) {
268
0
    if (!tok || !tok->isName())
269
0
        return false;
270
0
    tok = tok->next();
271
0
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
272
0
        return false;
273
0
    return true;
274
0
}
275
// pattern: ++|--|&
276
7.87k
static inline bool match30(const Token* tok) {
277
7.87k
    if (!tok || !(((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("++")) || ((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("--")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&"))))
278
7.18k
        return false;
279
692
    return true;
280
7.87k
}
281
// pattern: & %name% =
282
1.58k
static inline bool match31(const Token* tok) {
283
1.58k
    if (!tok || !((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")))
284
1.58k
        return false;
285
0
    tok = tok->next();
286
0
    if (!tok || !tok->isName())
287
0
        return false;
288
0
    tok = tok->next();
289
0
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
290
0
        return false;
291
0
    return true;
292
0
}
293
// pattern: [(,]
294
1.59k
static inline bool match32(const Token* tok) {
295
1.59k
    if (!tok || tok->str().size() != 1U || !strchr("(,", tok->str()[0]))
296
1.59k
        return false;
297
0
    return true;
298
1.59k
}
299
// pattern: ;
300
686
static inline bool match33(const Token* tok) {
301
686
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
302
686
        return false;
303
0
    return true;
304
686
}
305
// pattern: ...
306
11.2k
static inline bool match34(const Token* tok) {
307
11.2k
    if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("...")))
308
11.2k
        return false;
309
0
    return true;
310
11.2k
}
311
// pattern: =|{
312
0
static inline bool match35(const Token* tok) {
313
0
    if (!tok || !(((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))))
314
0
        return false;
315
0
    return true;
316
0
}
317
// pattern: :
318
0
static inline bool match36(const Token* tok) {
319
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")))
320
0
        return false;
321
0
    return true;
322
0
}
323
// pattern: for (
324
156
static inline bool match37(const Token* tok) {
325
156
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("for")))
326
156
        return false;
327
0
    tok = tok->next();
328
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
329
0
        return false;
330
0
    return true;
331
0
}
332
// pattern: %name% (
333
102k
static inline bool match38(const Token* tok) {
334
102k
    if (!tok || !tok->isName())
335
64.2k
        return false;
336
38.4k
    tok = tok->next();
337
38.4k
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
338
34.9k
        return false;
339
3.48k
    return true;
340
38.4k
}
341
// pattern: .|::|[
342
0
static inline bool match39(const Token* tok) {
343
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString(".")) || (tok->str() == MatchCompiler::makeConstString("::")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("["))))
344
0
        return false;
345
0
    return true;
346
0
}
347
// pattern: .
348
187
static inline bool match40(const Token* tok) {
349
187
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
350
187
        return false;
351
0
    return true;
352
187
}
353
// pattern: ,
354
0
static inline bool match41(const Token* tok) {
355
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")))
356
0
        return false;
357
0
    return true;
358
0
}
359
// pattern: const|volatile|auto|&|&&
360
0
static inline bool match42(const Token* tok) {
361
0
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("volatile")) || ((tok->tokType() == Token::eKeyword || tok->tokType() == Token::eType) && tok->str() == MatchCompiler::makeConstString("auto")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&"))))
362
0
        return false;
363
0
    return true;
364
0
}
365
// pattern: auto
366
0
static inline bool match43(const Token* tok) {
367
0
    if (!tok || !((tok->tokType() == Token::eKeyword || tok->tokType() == Token::eType) && tok->str() == MatchCompiler::makeConstString("auto")))
368
0
        return false;
369
0
    return true;
370
0
}
371
// pattern: ) {
372
3.55k
static inline bool match44(const Token* tok) {
373
3.55k
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
374
0
        return false;
375
3.55k
    tok = tok->next();
376
3.55k
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
377
187
        return false;
378
3.37k
    return true;
379
3.55k
}
380
// pattern: if (
381
4.89k
static inline bool match45(const Token* tok) {
382
4.89k
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("if")))
383
3.93k
        return false;
384
957
    tok = tok->next();
385
957
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
386
0
        return false;
387
957
    return true;
388
957
}
389
// pattern: } else {
390
1.25k
static inline bool match46(const Token* tok) {
391
1.25k
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")))
392
0
        return false;
393
1.25k
    tok = tok->next();
394
1.25k
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("else")))
395
705
        return false;
396
547
    tok = tok->next();
397
547
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
398
0
        return false;
399
547
    return true;
400
547
}
401
// pattern: %var% {|(
402
392
static inline bool match47(const Token* tok) {
403
392
    if (!tok || !(tok->varId() != 0))
404
386
        return false;
405
6
    tok = tok->next();
406
6
    if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))))
407
6
        return false;
408
0
    return true;
409
6
}
410
// pattern: (
411
0
static inline bool match48(const Token* tok) {
412
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
413
0
        return false;
414
0
    return true;
415
0
}
416
// pattern: std :: ref|cref|tie|front_inserter|back_inserter
417
187
static inline bool match49(const Token* tok) {
418
187
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("std")))
419
187
        return false;
420
0
    tok = tok->next();
421
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("::")))
422
0
        return false;
423
0
    tok = tok->next();
424
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("ref")) || (tok->str() == MatchCompiler::makeConstString("cref")) || (tok->str() == MatchCompiler::makeConstString("tie")) || (tok->str() == MatchCompiler::makeConstString("front_inserter")) || (tok->str() == MatchCompiler::makeConstString("back_inserter"))))
425
0
        return false;
426
0
    return true;
427
0
}
428
// pattern: std :: make_tuple|tuple_cat|make_pair|make_reverse_iterator|next|prev|move|bind
429
187
static inline bool match50(const Token* tok) {
430
187
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("std")))
431
187
        return false;
432
0
    tok = tok->next();
433
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("::")))
434
0
        return false;
435
0
    tok = tok->next();
436
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("make_tuple")) || (tok->str() == MatchCompiler::makeConstString("tuple_cat")) || (tok->str() == MatchCompiler::makeConstString("make_pair")) || (tok->str() == MatchCompiler::makeConstString("make_reverse_iterator")) || (tok->str() == MatchCompiler::makeConstString("next")) || (tok->str() == MatchCompiler::makeConstString("prev")) || (tok->str() == MatchCompiler::makeConstString("move")) || (tok->str() == MatchCompiler::makeConstString("bind"))))
437
0
        return false;
438
0
    return true;
439
0
}
440
// pattern: . push_back|push_front|insert|push|assign
441
0
static inline bool match51(const Token* tok) {
442
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
443
0
        return false;
444
0
    tok = tok->next();
445
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("push_back")) || (tok->str() == MatchCompiler::makeConstString("push_front")) || (tok->str() == MatchCompiler::makeConstString("insert")) || (tok->str() == MatchCompiler::makeConstString("push")) || (tok->str() == MatchCompiler::makeConstString("assign"))))
446
0
        return false;
447
0
    return true;
448
0
}
449
// pattern: (|{
450
187
static inline bool match52(const Token* tok) {
451
187
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))))
452
0
        return false;
453
187
    return true;
454
187
}
455
// pattern: %var% (
456
0
static inline bool match53(const Token* tok) {
457
0
    if (!tok || !(tok->varId() != 0))
458
0
        return false;
459
0
    tok = tok->next();
460
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
461
0
        return false;
462
0
    return true;
463
0
}
464
// pattern: %name%
465
0
static inline bool match54(const Token* tok) {
466
0
    if (!tok || !tok->isName())
467
0
        return false;
468
0
    return true;
469
0
}
470
// pattern: ] (
471
0
static inline bool match55(const Token* tok) {
472
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")))
473
0
        return false;
474
0
    tok = tok->next();
475
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
476
0
        return false;
477
0
    return true;
478
0
}
479
// pattern: {
480
0
template<class T> static inline T * findmatch56(T * start_tok) {
481
0
    for (; start_tok; start_tok = start_tok->next()) {
482
483
0
    T * tok = start_tok;
484
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
485
0
        continue;
486
0
    return start_tok;
487
0
    }
488
0
    return nullptr;
489
0
}
490
// pattern: this !!.
491
0
static inline bool match57(const Token* tok) {
492
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("this")))
493
0
        return false;
494
0
    tok = tok->next();
495
0
    if (tok && tok->str() == MatchCompiler::makeConstString("."))
496
0
        return false;
497
0
    return true;
498
0
}
499
// pattern: * this
500
0
static inline bool match58(const Token* tok) {
501
0
    if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")))
502
0
        return false;
503
0
    tok = tok->next();
504
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("this")))
505
0
        return false;
506
0
    return true;
507
0
}
508
// pattern: %var%
509
0
static inline bool match59(const Token* tok) {
510
0
    if (!tok || !(tok->varId() != 0))
511
0
        return false;
512
0
    return true;
513
0
}
514
// pattern: return
515
425
static inline bool match60(const Token* tok) {
516
425
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")))
517
425
        return false;
518
0
    return true;
519
425
}
520
// pattern: *
521
12
static inline bool match61(const Token* tok) {
522
12
    if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")))
523
12
        return false;
524
0
    return true;
525
12
}
526
// pattern: .|[
527
12
static inline bool match62(const Token* tok) {
528
12
    if (!tok || !((tok->str() == MatchCompiler::makeConstString(".")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("["))))
529
12
        return false;
530
0
    return true;
531
12
}
532
// pattern: data|c_str
533
0
static inline bool match63(const Token* tok) {
534
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("data")) || (tok->str() == MatchCompiler::makeConstString("c_str"))))
535
0
        return false;
536
0
    return true;
537
0
}
538
// pattern: =|return|%name%|{|,|> {
539
65.1k
static inline bool match64(const Token* tok) {
540
65.1k
    if (!tok || !(((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || tok->isName() || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))))
541
27.9k
        return false;
542
37.1k
    tok = tok->next();
543
37.1k
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
544
36.3k
        return false;
545
796
    return true;
546
37.1k
}
547
// pattern: . get ( )
548
0
static inline bool match65(const Token* tok) {
549
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
550
0
        return false;
551
0
    tok = tok->next();
552
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("get")))
553
0
        return false;
554
0
    tok = tok->next();
555
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
556
0
        return false;
557
0
    tok = tok->next();
558
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
559
0
        return false;
560
0
    return true;
561
0
}
562
// pattern: std :: move ( %var% )
563
0
static inline bool match66(const Token* tok) {
564
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("std")))
565
0
        return false;
566
0
    tok = tok->next();
567
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("::")))
568
0
        return false;
569
0
    tok = tok->next();
570
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("move")))
571
0
        return false;
572
0
    tok = tok->next();
573
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
574
0
        return false;
575
0
    tok = tok->next();
576
0
    if (!tok || !(tok->varId() != 0))
577
0
        return false;
578
0
    tok = tok->next();
579
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
580
0
        return false;
581
0
    return true;
582
0
}
583
// pattern: std :: forward <
584
0
static inline bool match67(const Token* tok) {
585
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("std")))
586
0
        return false;
587
0
    tok = tok->next();
588
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("::")))
589
0
        return false;
590
0
    tok = tok->next();
591
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("forward")))
592
0
        return false;
593
0
    tok = tok->next();
594
0
    if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))
595
0
        return false;
596
0
    return true;
597
0
}
598
// pattern: > ( %var% )
599
0
static inline bool match68(const Token* tok) {
600
0
    if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))
601
0
        return false;
602
0
    tok = tok->next();
603
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
604
0
        return false;
605
0
    tok = tok->next();
606
0
    if (!tok || !(tok->varId() != 0))
607
0
        return false;
608
0
    tok = tok->next();
609
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
610
0
        return false;
611
0
    return true;
612
0
}
613
// pattern: %varid% . %name% (
614
0
static inline bool match69(const Token* tok, const int varid) {
615
0
    if (varid==0U)
616
0
        throw InternalError(tok, "Internal error. Token::Match called with varid 0. Please report this to Cppcheck developers");
617
0
    if (!tok || !(tok->isName() && tok->varId() == varid))
618
0
        return false;
619
0
    tok = tok->next();
620
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
621
0
        return false;
622
0
    tok = tok->next();
623
0
    if (!tok || !tok->isName())
624
0
        return false;
625
0
    tok = tok->next();
626
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
627
0
        return false;
628
0
    return true;
629
0
}
630
// pattern: [({]
631
25
static inline bool match70(const Token* tok) {
632
25
    if (!tok || tok->str().size() != 1U || !strchr("({", tok->str()[0]))
633
25
        return false;
634
0
    return true;
635
25
}
636
// pattern: %var% . reset|clear (
637
39.6k
static inline bool match71(const Token* tok) {
638
39.6k
    if (!tok || !(tok->varId() != 0))
639
32.4k
        return false;
640
7.20k
    tok = tok->next();
641
7.20k
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
642
7.20k
        return false;
643
0
    tok = tok->next();
644
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("reset")) || (tok->str() == MatchCompiler::makeConstString("clear"))))
645
0
        return false;
646
0
    tok = tok->next();
647
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
648
0
        return false;
649
0
    return true;
650
0
}
651
// pattern: %var%|.
652
0
static inline bool match72(const Token* tok) {
653
0
    if (!tok || !((tok->varId() != 0) || (tok->str() == MatchCompiler::makeConstString("."))))
654
0
        return false;
655
0
    return true;
656
0
}
657
// pattern: }
658
162
static inline bool match73(const Token* tok) {
659
162
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")))
660
0
        return false;
661
162
    return true;
662
162
}
663
// pattern: break|continue ;
664
78
static inline bool match74(const Token* tok) {
665
78
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("break")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("continue"))))
666
78
        return false;
667
0
    tok = tok->next();
668
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
669
0
        return false;
670
0
    return true;
671
0
}
672
// pattern: %comp%|%oror%|&&
673
0
static inline bool match75(const Token* tok) {
674
0
    if (!tok || !(tok->isComparisonOp() || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&"))))
675
0
        return false;
676
0
    return true;
677
0
}
678
// pattern: strlen (
679
0
static inline bool match76(const Token* tok) {
680
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("strlen")))
681
0
        return false;
682
0
    tok = tok->next();
683
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
684
0
        return false;
685
0
    return true;
686
0
}
687
// pattern: *|/|<<|>>|^|+|-|%or%
688
37.7k
static inline bool match77(const Token* tok) {
689
37.7k
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("/")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("^")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")) || (tok->tokType() == Token::eBitOp && tok->str() == MatchCompiler::makeConstString("|") )))
690
36.9k
        return false;
691
826
    return true;
692
37.7k
}
693
// pattern: <<|>>|/
694
67
static inline bool match78(const Token* tok) {
695
67
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("/"))))
696
61
        return false;
697
6
    return true;
698
67
}
699
// pattern: <<|>>|^|+|-|%or%
700
61
static inline bool match79(const Token* tok) {
701
61
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("^")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")) || (tok->tokType() == Token::eBitOp && tok->str() == MatchCompiler::makeConstString("|") )))
702
10
        return false;
703
51
    return true;
704
61
}
705
// pattern: *|/
706
40
static inline bool match80(const Token* tok) {
707
40
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("/"))))
708
30
        return false;
709
10
    return true;
710
40
}
711
// pattern: -|%comp%
712
39.6k
static inline bool match81(const Token* tok) {
713
39.6k
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")) || tok->isComparisonOp()))
714
37.7k
        return false;
715
1.94k
    return true;
716
39.6k
}
717
// pattern: ++
718
0
static inline bool match82(const Token* tok) {
719
0
    if (!tok || !((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("++")))
720
0
        return false;
721
0
    return true;
722
0
}
723
// pattern: --
724
0
static inline bool match83(const Token* tok) {
725
0
    if (!tok || !((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("--")))
726
0
        return false;
727
0
    return true;
728
0
}
729
// pattern: %var% ; %var%
730
10
static inline bool match84(const Token* tok) {
731
10
    if (!tok || !(tok->varId() != 0))
732
7
        return false;
733
3
    tok = tok->next();
734
3
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
735
1
        return false;
736
2
    tok = tok->next();
737
2
    if (!tok || !(tok->varId() != 0))
738
2
        return false;
739
0
    return true;
740
2
}
741
// pattern: bool|_Bool
742
10
static inline bool match85(const Token* tok) {
743
10
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("bool")) || (tok->str() == MatchCompiler::makeConstString("_Bool"))))
744
10
        return false;
745
0
    return true;
746
10
}
747
// pattern: %var% (|{
748
35.7k
static inline bool match86(const Token* tok) {
749
35.7k
    if (!tok || !(tok->varId() != 0))
750
29.0k
        return false;
751
6.73k
    tok = tok->next();
752
6.73k
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))))
753
6.73k
        return false;
754
0
    return true;
755
6.73k
}
756
// pattern: swap (
757
39.6k
static inline bool match87(const Token* tok) {
758
39.6k
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("swap")))
759
39.6k
        return false;
760
0
    tok = tok->next();
761
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
762
0
        return false;
763
0
    return true;
764
0
}
765
// pattern: ==|!|(
766
1.00k
static inline bool match88(const Token* tok) {
767
1.00k
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))))
768
801
        return false;
769
205
    return true;
770
1.00k
}
771
// pattern: !=|%var%|(
772
511
static inline bool match89(const Token* tok) {
773
511
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!=")) || (tok->varId() != 0) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))))
774
463
        return false;
775
48
    return true;
776
511
}
777
// pattern: break|goto
778
84
template<class T> static inline T * findmatch90(T * start_tok, const Token * end) {
779
888
    for (; start_tok && start_tok != end; start_tok = start_tok->next()) {
780
781
804
    T * tok = start_tok;
782
804
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("break")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("goto"))))
783
804
        continue;
784
0
    return start_tok;
785
804
    }
786
84
    return nullptr;
787
84
}
788
// pattern: !=|=|(|.
789
1.26k
static inline bool match91(const Token* tok) {
790
1.26k
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!=")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || (tok->str() == MatchCompiler::makeConstString("."))))
791
1.00k
        return false;
792
262
    return true;
793
1.26k
}
794
// pattern: ==|!
795
1.26k
static inline bool match92(const Token* tok) {
796
1.26k
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!"))))
797
1.04k
        return false;
798
226
    return true;
799
1.26k
}
800
// pattern: :|;|,
801
307k
static inline bool match93(const Token* tok) {
802
307k
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(","))))
803
265k
        return false;
804
42.7k
    return true;
805
307k
}
806
// pattern: &&|%oror%|?|!
807
202k
static inline bool match94(const Token* tok) {
808
202k
    if (!tok || !(((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("?")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!"))))
809
202k
        return false;
810
0
    return true;
811
202k
}
812
// pattern: %assign%
813
1.24k
static inline bool match95(const Token* tok) {
814
1.24k
    if (!tok || !tok->isAssignmentOp())
815
1.24k
        return false;
816
0
    return true;
817
1.24k
}
818
// pattern: %assign%|++|--
819
1.24k
static inline bool match96(const Token* tok) {
820
1.24k
    if (!tok || !(tok->isAssignmentOp() || ((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("++")) || ((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("--"))))
821
1.14k
        return false;
822
96
    return true;
823
1.24k
}
824
// pattern: <|>|<=|>=
825
1.12k
static inline bool match97(const Token* tok) {
826
1.12k
    if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<=")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">="))))
827
413
        return false;
828
715
    return true;
829
1.12k
}
830
// pattern: for|while (
831
653
static inline bool match98(const Token* tok) {
832
653
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("for")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("while"))))
833
497
        return false;
834
156
    tok = tok->next();
835
156
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
836
0
        return false;
837
156
    return true;
838
156
}
839
// pattern: !
840
2.02k
static inline bool match99(const Token* tok) {
841
2.02k
    if (!tok || !((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!")))
842
2.02k
        return false;
843
0
    return true;
844
2.02k
}
845
// pattern: ==|!=
846
31.0k
static inline bool match100(const Token* tok) {
847
31.0k
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!="))))
848
28.4k
        return false;
849
2.62k
    return true;
850
31.0k
}
851
// pattern: !=
852
0
static inline bool match101(const Token* tok) {
853
0
    if (!tok || !((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!=")))
854
0
        return false;
855
0
    return true;
856
0
}
857
// pattern: %oror%|&&
858
4.29k
static inline bool match102(const Token* tok) {
859
4.29k
    if (!tok || !((tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&"))))
860
4.29k
        return false;
861
0
    return true;
862
4.29k
}
863
// pattern: ++|--
864
0
static inline bool match103(const Token* tok) {
865
0
    if (!tok || !(((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("++")) || ((tok->tokType() == Token::eIncDecOp) && tok->str() == MatchCompiler::makeConstString("--"))))
866
0
        return false;
867
0
    return true;
868
0
}
869
// pattern: while (
870
50
static inline bool match104(const Token* tok) {
871
50
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("while")))
872
36
        return false;
873
14
    tok = tok->next();
874
14
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
875
0
        return false;
876
14
    return true;
877
14
}
878
// pattern: while|for (
879
331
static inline bool match105(const Token* tok) {
880
331
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("while")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("for"))))
881
247
        return false;
882
84
    tok = tok->next();
883
84
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
884
0
        return false;
885
84
    return true;
886
84
}
887
// pattern: &&|%oror%
888
115
static inline bool match106(const Token* tok) {
889
115
    if (!tok || !(((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||"))))
890
115
        return false;
891
0
    return true;
892
115
}
893
// pattern: == false
894
0
static inline bool match107(const Token* tok) {
895
0
    if (!tok || !((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")))
896
0
        return false;
897
0
    tok = tok->next();
898
0
    if (!tok || !((tok->tokType() == Token::eBoolean) && tok->str() == MatchCompiler::makeConstString("false")))
899
0
        return false;
900
0
    return true;
901
0
}
902
// pattern: } while (
903
0
static inline bool match108(const Token* tok) {
904
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")))
905
0
        return false;
906
0
    tok = tok->next();
907
0
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("while")))
908
0
        return false;
909
0
    tok = tok->next();
910
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
911
0
        return false;
912
0
    return true;
913
0
}
914
// pattern: %oror%|&&|?
915
12.9k
static inline bool match109(const Token* tok) {
916
12.9k
    if (!tok || !((tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("?"))))
917
12.9k
        return false;
918
0
    return true;
919
12.9k
}
920
// pattern: if|while (
921
35.0k
static inline bool match110(const Token* tok) {
922
35.0k
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("if")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("while"))))
923
31.2k
        return false;
924
3.76k
    tok = tok->next();
925
3.76k
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
926
0
        return false;
927
3.76k
    return true;
928
3.76k
}
929
// pattern: %comp%|%assign%
930
2.01k
static inline bool match111(const Token* tok) {
931
2.01k
    if (!tok || !(tok->isComparisonOp() || tok->isAssignmentOp()))
932
272
        return false;
933
1.74k
    return true;
934
2.01k
}
935
// pattern: %|<<|>>|&|^|~|%or%
936
1.64k
static inline bool match112(const Token* tok) {
937
1.64k
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("%")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("^")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("~")) || (tok->tokType() == Token::eBitOp && tok->str() == MatchCompiler::makeConstString("|") )))
938
1.55k
        return false;
939
91
    return true;
940
1.64k
}
941
// pattern: NULL|nullptr
942
868
static inline bool match113(const Token* tok) {
943
868
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("NULL")) || (tok->str() == MatchCompiler::makeConstString("nullptr"))))
944
868
        return false;
945
0
    return true;
946
868
}
947
// pattern: +|-|*|/
948
777
static inline bool match114(const Token* tok) {
949
777
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("/"))))
950
636
        return false;
951
141
    return true;
952
777
}
953
// pattern: %comp%|-
954
23.6k
static inline bool match115(const Token* tok) {
955
23.6k
    if (!tok || !(tok->isComparisonOp() || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-"))))
956
22.1k
        return false;
957
1.56k
    return true;
958
23.6k
}
959
// pattern: ?|&&|!|%oror%
960
22.1k
static inline bool match116(const Token* tok) {
961
22.1k
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("?")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||"))))
962
22.1k
        return false;
963
0
    return true;
964
22.1k
}
965
// pattern: ) (
966
0
static inline bool match117(const Token* tok) {
967
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
968
0
        return false;
969
0
    tok = tok->next();
970
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
971
0
        return false;
972
0
    return true;
973
0
}
974
// pattern: %varid%
975
0
template<class T> static inline T * findmatch118(T * start_tok, const Token * end, int varid) {
976
0
    for (; start_tok && start_tok != end; start_tok = start_tok->next()) {
977
978
0
    T * tok = start_tok;
979
0
    if (varid==0U)
980
0
        throw InternalError(tok, "Internal error. Token::Match called with varid 0. Please report this to Cppcheck developers");
981
0
    if (!tok || !(tok->isName() && tok->varId() == varid))
982
0
        continue;
983
0
    return start_tok;
984
0
    }
985
0
    return nullptr;
986
0
}
987
// pattern: switch ( %var% ) {
988
0
static inline bool match119(const Token* tok) {
989
0
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("switch")))
990
0
        return false;
991
0
    tok = tok->next();
992
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
993
0
        return false;
994
0
    tok = tok->next();
995
0
    if (!tok || !(tok->varId() != 0))
996
0
        return false;
997
0
    tok = tok->next();
998
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
999
0
        return false;
1000
0
    tok = tok->next();
1001
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
1002
0
        return false;
1003
0
    return true;
1004
0
}
1005
// pattern: case %num% :
1006
0
static inline bool match120(const Token* tok) {
1007
0
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))
1008
0
        return false;
1009
0
    tok = tok->next();
1010
0
    if (!tok || !tok->isNumber())
1011
0
        return false;
1012
0
    tok = tok->next();
1013
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")))
1014
0
        return false;
1015
0
    return true;
1016
0
}
1017
// pattern: break ;
1018
0
static inline bool match121(const Token* tok) {
1019
0
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("break")))
1020
0
        return false;
1021
0
    tok = tok->next();
1022
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
1023
0
        return false;
1024
0
    return true;
1025
0
}
1026
// pattern: ;| case
1027
0
static inline bool match122(const Token* tok) {
1028
0
    if (tok && ((tok->str() == MatchCompiler::makeConstString(";"))))
1029
0
        tok = tok->next();
1030
0
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))
1031
0
        return false;
1032
0
    return true;
1033
0
}
1034
// pattern: ;| case %num% :
1035
0
static inline bool match123(const Token* tok) {
1036
0
    if (tok && ((tok->str() == MatchCompiler::makeConstString(";"))))
1037
0
        tok = tok->next();
1038
0
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))
1039
0
        return false;
1040
0
    tok = tok->next();
1041
0
    if (!tok || !tok->isNumber())
1042
0
        return false;
1043
0
    tok = tok->next();
1044
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")))
1045
0
        return false;
1046
0
    return true;
1047
0
}
1048
// pattern: %comp%|%oror%|&&|!
1049
0
static inline bool match124(const Token* tok) {
1050
0
    if (!tok || !(tok->isComparisonOp() || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!"))))
1051
0
        return false;
1052
0
    return true;
1053
0
}
1054
// pattern: %var% = %num%|%str%|%char%|%name% [,)]
1055
0
static inline bool match125(const Token* tok) {
1056
0
    if (!tok || !(tok->varId() != 0))
1057
0
        return false;
1058
0
    tok = tok->next();
1059
0
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
1060
0
        return false;
1061
0
    tok = tok->next();
1062
0
    if (!tok || !(tok->isNumber() || (tok->tokType() == Token::eString) || (tok->tokType() == Token::eChar) || tok->isName()))
1063
0
        return false;
1064
0
    tok = tok->next();
1065
0
    if (!tok || tok->str().size() != 1U || !strchr(",)", tok->str()[0]))
1066
0
        return false;
1067
0
    return true;
1068
0
}
1069
// pattern: goto|asm|setjmp|longjmp
1070
0
template<class T> static inline T * findmatch126(T * start_tok, const Token * end) {
1071
0
    for (; start_tok && start_tok != end; start_tok = start_tok->next()) {
1072
1073
0
    T * tok = start_tok;
1074
0
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("goto")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("asm")) || (tok->str() == MatchCompiler::makeConstString("setjmp")) || (tok->str() == MatchCompiler::makeConstString("longjmp"))))
1075
0
        continue;
1076
0
    return start_tok;
1077
0
    }
1078
0
    return nullptr;
1079
0
}
1080
// pattern: [&*(]
1081
0
static inline bool match127(const Token* tok) {
1082
0
    if (!tok || tok->str().size() != 1U || !strchr("&*(", tok->str()[0]))
1083
0
        return false;
1084
0
    return true;
1085
0
}
1086
// pattern: %var% ;|[
1087
41.3k
static inline bool match128(const Token* tok) {
1088
41.3k
    if (!tok || !(tok->varId() != 0))
1089
34.1k
        return false;
1090
7.20k
    tok = tok->next();
1091
7.20k
    if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("["))))
1092
3.68k
        return false;
1093
3.51k
    return true;
1094
7.20k
}
1095
// pattern: union
1096
0
template<class T> static inline T * findmatch129(T * start_tok, const Token * end) {
1097
0
    for (; start_tok && start_tok != end; start_tok = start_tok->next()) {
1098
1099
0
    T * tok = start_tok;
1100
0
    if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("union")))
1101
0
        continue;
1102
0
    return start_tok;
1103
0
    }
1104
0
    return nullptr;
1105
0
}
1106
// pattern: %name% . %name% (
1107
0
static inline bool match130(const Token* tok) {
1108
0
    if (!tok || !tok->isName())
1109
0
        return false;
1110
0
    tok = tok->next();
1111
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
1112
0
        return false;
1113
0
    tok = tok->next();
1114
0
    if (!tok || !tok->isName())
1115
0
        return false;
1116
0
    tok = tok->next();
1117
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
1118
0
        return false;
1119
0
    return true;
1120
0
}
1121
// pattern: +|-
1122
4.39k
static inline bool match131(const Token* tok) {
1123
4.39k
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-"))))
1124
4.34k
        return false;
1125
58
    return true;
1126
4.39k
}
1127
// pattern: -
1128
0
static inline bool match132(const Token* tok) {
1129
0
    if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")))
1130
0
        return false;
1131
0
    return true;
1132
0
}
1133
// pattern: %assign%|<<
1134
0
static inline bool match133(const Token* tok) {
1135
0
    if (!tok || !(tok->isAssignmentOp() || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<"))))
1136
0
        return false;
1137
0
    return true;
1138
0
}
1139
// pattern: %var% (|{|;
1140
0
static inline bool match134(const Token* tok) {
1141
0
    if (!tok || !(tok->varId() != 0))
1142
0
        return false;
1143
0
    tok = tok->next();
1144
0
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || (tok->str() == MatchCompiler::makeConstString(";"))))
1145
0
        return false;
1146
0
    return true;
1147
0
}
1148
// pattern: %var% ;
1149
0
static inline bool match135(const Token* tok) {
1150
0
    if (!tok || !(tok->varId() != 0))
1151
0
        return false;
1152
0
    tok = tok->next();
1153
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
1154
0
        return false;
1155
0
    return true;
1156
0
}
1157
// pattern: . reset (
1158
0
static inline bool match136(const Token* tok) {
1159
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
1160
0
        return false;
1161
0
    tok = tok->next();
1162
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("reset")))
1163
0
        return false;
1164
0
    tok = tok->next();
1165
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
1166
0
        return false;
1167
0
    return true;
1168
0
}
1169
// pattern: ( )
1170
0
static inline bool match137(const Token* tok) {
1171
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
1172
0
        return false;
1173
0
    tok = tok->next();
1174
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
1175
0
        return false;
1176
0
    return true;
1177
0
}
1178
// pattern: . release ( )
1179
0
static inline bool match138(const Token* tok) {
1180
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
1181
0
        return false;
1182
0
    tok = tok->next();
1183
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("release")))
1184
0
        return false;
1185
0
    tok = tok->next();
1186
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
1187
0
        return false;
1188
0
    tok = tok->next();
1189
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))
1190
0
        return false;
1191
0
    return true;
1192
0
}
1193
// pattern: . release|reset (
1194
0
static inline bool match139(const Token* tok) {
1195
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
1196
0
        return false;
1197
0
    tok = tok->next();
1198
0
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("release")) || (tok->str() == MatchCompiler::makeConstString("reset"))))
1199
0
        return false;
1200
0
    tok = tok->next();
1201
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
1202
0
        return false;
1203
0
    return true;
1204
0
}
1205
// pattern: %name%|> (|{
1206
0
static inline bool match140(const Token* tok) {
1207
0
    if (!tok || !(tok->isName() || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))))
1208
0
        return false;
1209
0
    tok = tok->next();
1210
0
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))))
1211
0
        return false;
1212
0
    return true;
1213
0
}
1214
// pattern: +
1215
3.91k
static inline bool match141(const Token* tok) {
1216
3.91k
    if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")))
1217
3.87k
        return false;
1218
41
    return true;
1219
3.91k
}
1220
// pattern: %str%
1221
2.25k
static inline bool match142(const Token* tok) {
1222
2.25k
    if (!tok || !(tok->tokType() == Token::eString))
1223
2.25k
        return false;
1224
0
    return true;
1225
2.25k
}
1226
// pattern: %name% ;
1227
0
static inline bool match143(const Token* tok) {
1228
0
    if (!tok || !tok->isName())
1229
0
        return false;
1230
0
    tok = tok->next();
1231
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
1232
0
        return false;
1233
0
    return true;
1234
0
}
1235
// pattern: %name% {
1236
0
static inline bool match144(const Token* tok) {
1237
0
    if (!tok || !tok->isName())
1238
0
        return false;
1239
0
    tok = tok->next();
1240
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
1241
0
        return false;
1242
0
    return true;
1243
0
}
1244
// pattern: } ;
1245
0
static inline bool match145(const Token* tok) {
1246
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")))
1247
0
        return false;
1248
0
    tok = tok->next();
1249
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
1250
0
        return false;
1251
0
    return true;
1252
0
}
1253
// pattern: for|while
1254
0
static inline bool match146(const Token* tok) {
1255
0
    if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("for")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("while"))))
1256
0
        return false;
1257
0
    return true;
1258
0
}
1259
// pattern: %name%|;|{|} %var% = %str% ;
1260
39.6k
static inline bool match147(const Token* tok) {
1261
39.6k
    if (!tok || !(tok->isName() || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}"))))
1262
13.4k
        return false;
1263
26.2k
    tok = tok->next();
1264
26.2k
    if (!tok || !(tok->varId() != 0))
1265
26.0k
        return false;
1266
198
    tok = tok->next();
1267
198
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
1268
143
        return false;
1269
55
    tok = tok->next();
1270
55
    if (!tok || !(tok->tokType() == Token::eString))
1271
55
        return false;
1272
0
    tok = tok->next();
1273
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
1274
0
        return false;
1275
0
    return true;
1276
0
}
1277
// pattern: >|return (|{
1278
39.6k
static inline bool match148(const Token* tok) {
1279
39.6k
    if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return"))))
1280
37.3k
        return false;
1281
2.34k
    tok = tok->next();
1282
2.34k
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))))
1283
2.19k
        return false;
1284
147
    return true;
1285
2.34k
}
1286
// pattern: ;|{|} %var% =
1287
39.6k
static inline bool match149(const Token* tok) {
1288
39.6k
    if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}"))))
1289
29.1k
        return false;
1290
10.5k
    tok = tok->next();
1291
10.5k
    if (!tok || !(tok->varId() != 0))
1292
10.4k
        return false;
1293
25
    tok = tok->next();
1294
25
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
1295
0
        return false;
1296
25
    return true;
1297
25
}
1298
// pattern: %type%
1299
0
static inline bool match150(const Token* tok) {
1300
0
    if (!tok || !(tok->isName() && tok->varId() == 0U))
1301
0
        return false;
1302
0
    return true;
1303
0
}
1304
// pattern: [;{}] %var% =
1305
22.6k
static inline bool match151(const Token* tok) {
1306
22.6k
    if (!tok || tok->str().size() != 1U || !strchr(";{}", tok->str()[0]))
1307
16.5k
        return false;
1308
6.15k
    tok = tok->next();
1309
6.15k
    if (!tok || !(tok->varId() != 0))
1310
6.14k
        return false;
1311
14
    tok = tok->next();
1312
14
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
1313
0
        return false;
1314
14
    return true;
1315
14
}
1316
// pattern: [{[(<]
1317
0
static inline bool match152(const Token* tok) {
1318
0
    if (!tok || tok->str().size() != 1U || !strchr("{[(<", tok->str()[0]))
1319
0
        return false;
1320
0
    return true;
1321
0
}
1322
// pattern: %name%|%num% %name%|%num%
1323
0
static inline bool match153(const Token* tok) {
1324
0
    if (!tok || !(tok->isName() || tok->isNumber()))
1325
0
        return false;
1326
0
    tok = tok->next();
1327
0
    if (!tok || !(tok->isName() || tok->isNumber()))
1328
0
        return false;
1329
0
    return true;
1330
0
}
1331
/*
1332
 * Cppcheck - A tool for static C/C++ code analysis
1333
 * Copyright (C) 2007-2024 Cppcheck team.
1334
 *
1335
 * This program is free software: you can redistribute it and/or modify
1336
 * it under the terms of the GNU General Public License as published by
1337
 * the Free Software Foundation, either version 3 of the License, or
1338
 * (at your option) any later version.
1339
 *
1340
 * This program is distributed in the hope that it will be useful,
1341
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1342
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1343
 * GNU General Public License for more details.
1344
 *
1345
 * You should have received a copy of the GNU General Public License
1346
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1347
 */
1348
1349
/**
1350
 * @brief This is the ValueFlow component in Cppcheck.
1351
 *
1352
 * Each @sa Token in the token list has a list of values. These are
1353
 * the "possible" values for the Token at runtime.
1354
 *
1355
 * In the --debug and --debug-normal output you can see the ValueFlow data. For example:
1356
 *
1357
 *     int f()
1358
 *     {
1359
 *         int x = 10;
1360
 *         return 4 * x + 2;
1361
 *     }
1362
 *
1363
 * The --debug-normal output says:
1364
 *
1365
 *     ##Value flow
1366
 *     Line 3
1367
 *       10 always 10
1368
 *     Line 4
1369
 *       4 always 4
1370
 *       * always 40
1371
 *       x always 10
1372
 *       + always 42
1373
 *       2 always 2
1374
 *
1375
 * All value flow analysis is executed in the ValueFlow::setValues() function. The ValueFlow analysis is executed after
1376
 * the tokenizer/ast/symboldatabase/etc.. The ValueFlow analysis is done in a series of valueFlow* function calls, where
1377
 * each such function call can only use results from previous function calls. The function calls should be arranged so
1378
 * that valueFlow* that do not require previous ValueFlow information should be first.
1379
 *
1380
 * Type of analysis
1381
 * ================
1382
 *
1383
 * This is "flow sensitive" value flow analysis. We _usually_ track the value for 1 variable at a time.
1384
 *
1385
 * How are calculations handled
1386
 * ============================
1387
 *
1388
 * Here is an example code:
1389
 *
1390
 *   x = 3 + 4;
1391
 *
1392
 * The valueFlowNumber set the values for the "3" and "4" tokens by calling setTokenValue().
1393
 * The setTokenValue() handle the calculations automatically. When both "3" and "4" have values, the "+" can be
1394
 * calculated. setTokenValue() recursively calls itself when parents in calculations can be calculated.
1395
 *
1396
 * Forward / Reverse flow analysis
1397
 * ===============================
1398
 *
1399
 * In forward value flow analysis we know a value and see what happens when we are stepping the program forward. Like
1400
 * normal execution. The valueFlowForward is used in this analysis.
1401
 *
1402
 * In reverse value flow analysis we know the value of a variable at line X. And try to "execute backwards" to determine
1403
 * possible values before line X. The valueFlowReverse is used in this analysis.
1404
 *
1405
 *
1406
 */
1407
1408
#include "valueflow.h"
1409
1410
#include "analyzer.h"
1411
#include "astutils.h"
1412
#include "calculate.h"
1413
#include "checkuninitvar.h"
1414
#include "config.h"
1415
#include "errorlogger.h"
1416
#include "errortypes.h"
1417
#include "findtoken.h"
1418
#include "forwardanalyzer.h"
1419
#include "infer.h"
1420
#include "library.h"
1421
#include "mathlib.h"
1422
#include "path.h"
1423
#include "platform.h"
1424
#include "programmemory.h"
1425
#include "reverseanalyzer.h"
1426
#include "settings.h"
1427
#include "smallvector.h"
1428
#include "sourcelocation.h"
1429
#include "standards.h"
1430
#include "symboldatabase.h"
1431
#include "timer.h"
1432
#include "token.h"
1433
#include "tokenlist.h"
1434
#include "utils.h"
1435
#include "valueptr.h"
1436
#include "vfvalue.h"
1437
1438
#include "vf_analyzers.h"
1439
#include "vf_common.h"
1440
#include "vf_settokenvalue.h"
1441
1442
#include <algorithm>
1443
#include <array>
1444
#include <cassert>
1445
#include <chrono>
1446
#include <cstdint>
1447
#include <cstdlib>
1448
#include <cstring>
1449
#include <functional>
1450
#include <initializer_list>
1451
#include <iterator>
1452
#include <limits>
1453
#include <map>
1454
#include <memory>
1455
#include <numeric>
1456
#include <set>
1457
#include <sstream>
1458
#include <string>
1459
#include <unordered_map>
1460
#include <unordered_set>
1461
#include <vector>
1462
1463
static void bailoutInternal(const std::string& type,
1464
                            const TokenList& tokenlist,
1465
                            ErrorLogger& errorLogger,
1466
                            const Token* tok,
1467
                            const std::string& what,
1468
                            const std::string& file,
1469
                            int line,
1470
                            std::string function)
1471
0
{
1472
0
    if (function.find("operator") != std::string::npos)
1473
0
        function = "(valueFlow)";
1474
0
    ErrorMessage::FileLocation loc(tok, &tokenlist);
1475
0
    const std::string location = Path::stripDirectoryPart(file) + ":" + std::to_string(line) + ":";
1476
0
    ErrorMessage errmsg({std::move(loc)},
1477
0
                        tokenlist.getSourceFilePath(),
1478
0
                        Severity::debug,
1479
0
                        (file.empty() ? "" : location) + function + " bailout: " + what,
1480
0
                        type,
1481
0
                        Certainty::normal);
1482
0
    errorLogger.reportErr(errmsg);
1483
0
}
1484
1485
#define bailout2(type, tokenlist, errorLogger, tok, what)                                                              \
1486
0
    bailoutInternal((type), (tokenlist), (errorLogger), (tok), (what), __FILE__, __LINE__, __func__)
1487
1488
#define bailout(tokenlist, errorLogger, tok, what)                                                                     \
1489
0
    bailout2("valueFlowBailout", (tokenlist), (errorLogger), (tok), (what))
1490
1491
#define bailoutIncompleteVar(tokenlist, errorLogger, tok, what)                                                        \
1492
0
    bailoutInternal("valueFlowBailoutIncompleteVar", (tokenlist), (errorLogger), (tok), (what), "", 0, __func__)
1493
1494
static void changeKnownToPossible(std::list<ValueFlow::Value>& values, int indirect = -1)
1495
1.28k
{
1496
1.97k
    for (ValueFlow::Value& v : values) {
1497
1.97k
        if (indirect >= 0 && v.indirect != indirect)
1498
0
            continue;
1499
1.97k
        v.changeKnownToPossible();
1500
1.97k
    }
1501
1.28k
}
1502
1503
static void removeImpossible(std::list<ValueFlow::Value>& values, int indirect = -1)
1504
0
{
1505
0
    values.remove_if([&](const ValueFlow::Value& v) {
1506
0
        if (indirect >= 0 && v.indirect != indirect)
1507
0
            return false;
1508
0
        return v.isImpossible();
1509
0
    });
1510
0
}
1511
1512
static void lowerToPossible(std::list<ValueFlow::Value>& values, int indirect = -1)
1513
0
{
1514
0
    changeKnownToPossible(values, indirect);
1515
0
    removeImpossible(values, indirect);
1516
0
}
1517
1518
static void changePossibleToKnown(std::list<ValueFlow::Value>& values, int indirect = -1)
1519
253
{
1520
253
    for (ValueFlow::Value& v : values) {
1521
253
        if (indirect >= 0 && v.indirect != indirect)
1522
0
            continue;
1523
253
        if (!v.isPossible())
1524
23
            continue;
1525
230
        if (v.bound != ValueFlow::Value::Bound::Point)
1526
0
            continue;
1527
230
        v.setKnown();
1528
230
    }
1529
253
}
1530
1531
static bool isNonConditionalPossibleIntValue(const ValueFlow::Value& v)
1532
0
{
1533
0
    if (v.conditional)
1534
0
        return false;
1535
0
    if (v.condition)
1536
0
        return false;
1537
0
    if (!v.isPossible())
1538
0
        return false;
1539
0
    if (!v.isIntValue())
1540
0
        return false;
1541
0
    return true;
1542
0
}
1543
1544
static void setValueUpperBound(ValueFlow::Value& value, bool upper)
1545
3.28k
{
1546
3.28k
    if (upper)
1547
1.64k
        value.bound = ValueFlow::Value::Bound::Upper;
1548
1.64k
    else
1549
1.64k
        value.bound = ValueFlow::Value::Bound::Lower;
1550
3.28k
}
1551
1552
static void setValueBound(ValueFlow::Value& value, const Token* tok, bool invert)
1553
5.03k
{
1554
5.03k
    if (match1(tok)) {
1555
1.94k
        setValueUpperBound(value, !invert);
1556
3.09k
    } else if (match2(tok)) {
1557
1.34k
        setValueUpperBound(value, invert);
1558
1.34k
    }
1559
5.03k
}
1560
1561
static void setConditionalValue(ValueFlow::Value& value, const Token* tok, MathLib::bigint i)
1562
5.03k
{
1563
5.03k
    assert(value.isIntValue());
1564
5.03k
    value.intvalue = i;
1565
5.03k
    value.assumeCondition(tok);
1566
5.03k
    value.setPossible();
1567
5.03k
}
1568
1569
static void setConditionalValues(const Token* tok,
1570
                                 bool lhs,
1571
                                 MathLib::bigint value,
1572
                                 ValueFlow::Value& true_value,
1573
                                 ValueFlow::Value& false_value)
1574
2.51k
{
1575
2.51k
    if (match3(tok)) {
1576
1.22k
        setConditionalValue(true_value, tok, value);
1577
1.22k
        const char* greaterThan = ">=";
1578
1.22k
        const char* lessThan = "<=";
1579
1.22k
        if (lhs)
1580
658
            std::swap(greaterThan, lessThan);
1581
1.22k
        if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
1582
180
            setConditionalValue(false_value, tok, value - 1);
1583
1.04k
        } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) {
1584
170
            setConditionalValue(false_value, tok, value + 1);
1585
874
        } else {
1586
874
            setConditionalValue(false_value, tok, value);
1587
874
        }
1588
1.29k
    } else {
1589
1.29k
        const char* greaterThan = ">";
1590
1.29k
        const char* lessThan = "<";
1591
1.29k
        if (lhs)
1592
656
            std::swap(greaterThan, lessThan);
1593
1.29k
        if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
1594
650
            setConditionalValue(true_value, tok, value + 1);
1595
650
            setConditionalValue(false_value, tok, value);
1596
650
        } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) {
1597
644
            setConditionalValue(true_value, tok, value - 1);
1598
644
            setConditionalValue(false_value, tok, value);
1599
644
        }
1600
1.29k
    }
1601
2.51k
    setValueBound(true_value, tok, lhs);
1602
2.51k
    setValueBound(false_value, tok, !lhs);
1603
2.51k
}
1604
1605
static bool isSaturated(MathLib::bigint value)
1606
578
{
1607
578
    return value == std::numeric_limits<MathLib::bigint>::max() || value == std::numeric_limits<MathLib::bigint>::min();
1608
578
}
1609
1610
static void parseCompareEachInt(
1611
    const Token* tok,
1612
    const std::function<void(const Token* varTok, ValueFlow::Value true_value, ValueFlow::Value false_value)>& each,
1613
    const std::function<std::vector<ValueFlow::Value>(const Token*)>& evaluate)
1614
32.5k
{
1615
32.5k
    if (!tok->astOperand1() || !tok->astOperand2())
1616
17.1k
        return;
1617
15.4k
    if (tok->isComparisonOp()) {
1618
7.23k
        std::vector<ValueFlow::Value> value1 = evaluate(tok->astOperand1());
1619
7.23k
        std::vector<ValueFlow::Value> value2 = evaluate(tok->astOperand2());
1620
7.23k
        if (!value1.empty() && !value2.empty()) {
1621
18
            if (tok->astOperand1()->hasKnownIntValue())
1622
0
                value2.clear();
1623
18
            if (tok->astOperand2()->hasKnownIntValue())
1624
4
                value1.clear();
1625
18
        }
1626
7.23k
        for (const ValueFlow::Value& v1 : value1) {
1627
344
            if (isSaturated(v1.intvalue) || astIsFloat(tok->astOperand2(), /*unknown*/ false))
1628
0
                continue;
1629
344
            ValueFlow::Value true_value = v1;
1630
344
            ValueFlow::Value false_value = v1;
1631
344
            setConditionalValues(tok, true, v1.intvalue, true_value, false_value);
1632
344
            each(tok->astOperand2(), std::move(true_value), std::move(false_value));
1633
344
        }
1634
7.23k
        for (const ValueFlow::Value& v2 : value2) {
1635
234
            if (isSaturated(v2.intvalue) || astIsFloat(tok->astOperand1(), /*unknown*/ false))
1636
0
                continue;
1637
234
            ValueFlow::Value true_value = v2;
1638
234
            ValueFlow::Value false_value = v2;
1639
234
            setConditionalValues(tok, false, v2.intvalue, true_value, false_value);
1640
234
            each(tok->astOperand1(), std::move(true_value), std::move(false_value));
1641
234
        }
1642
7.23k
    }
1643
15.4k
}
1644
1645
static void parseCompareEachInt(
1646
    const Token* tok,
1647
    const std::function<void(const Token* varTok, ValueFlow::Value true_value, ValueFlow::Value false_value)>& each)
1648
31.2k
{
1649
31.2k
    parseCompareEachInt(tok, each, [](const Token* t) -> std::vector<ValueFlow::Value> {
1650
12.0k
        if (t->hasKnownIntValue())
1651
496
            return {t->values().front()};
1652
11.5k
        std::vector<ValueFlow::Value> result;
1653
11.5k
        std::copy_if(t->values().cbegin(), t->values().cend(), std::back_inserter(result), [&](const ValueFlow::Value& v) {
1654
2.01k
            if (v.path < 1)
1655
2.01k
                return false;
1656
0
            if (!isNonConditionalPossibleIntValue(v))
1657
0
                return false;
1658
0
            return true;
1659
0
        });
1660
11.5k
        return result;
1661
12.0k
    });
1662
31.2k
}
1663
1664
const Token* ValueFlow::parseCompareInt(const Token* tok,
1665
                                        ValueFlow::Value& true_value,
1666
                                        ValueFlow::Value& false_value,
1667
                                        const std::function<std::vector<MathLib::bigint>(const Token*)>& evaluate)
1668
1.23k
{
1669
1.23k
    const Token* result = nullptr;
1670
1.23k
    parseCompareEachInt(
1671
1.23k
        tok,
1672
1.23k
        [&](const Token* vartok, ValueFlow::Value true_value2, ValueFlow::Value false_value2) {
1673
82
        if (result)
1674
14
            return;
1675
68
        result = vartok;
1676
68
        true_value = std::move(true_value2);
1677
68
        false_value = std::move(false_value2);
1678
68
    },
1679
2.47k
        [&](const Token* t) -> std::vector<ValueFlow::Value> {
1680
2.47k
        std::vector<ValueFlow::Value> r;
1681
2.47k
        std::vector<MathLib::bigint> v = evaluate(t);
1682
1683
2.47k
        std::transform(v.cbegin(), v.cend(), std::back_inserter(r), [&](MathLib::bigint i) {
1684
86
            return ValueFlow::Value{i};
1685
86
        });
1686
2.47k
        return r;
1687
2.47k
    });
1688
1.23k
    return result;
1689
1.23k
}
1690
1691
const Token *ValueFlow::parseCompareInt(const Token *tok, ValueFlow::Value &true_value, ValueFlow::Value &false_value)
1692
0
{
1693
0
    return parseCompareInt(tok, true_value, false_value, [](const Token* t) -> std::vector<MathLib::bigint> {
1694
0
        if (t->hasKnownIntValue())
1695
0
            return {t->values().front().intvalue};
1696
0
        return std::vector<MathLib::bigint>{};
1697
0
    });
1698
0
}
1699
1700
static bool isEscapeScope(const Token* tok, const Settings& settings, bool unknown = false)
1701
30
{
1702
30
    if (!match4(tok))
1703
0
        return false;
1704
    // TODO this search for termTok in all subscopes. It should check the end of the scope.
1705
30
    const Token* termTok = findmatch5(tok, tok->link()) ;
1706
30
    if (termTok && termTok->scope() == tok->scope())
1707
1
        return true;
1708
29
    std::string unknownFunction;
1709
29
    if (settings.library.isScopeNoReturn(tok->link(), &unknownFunction))
1710
0
        return unknownFunction.empty() || unknown;
1711
29
    return false;
1712
29
}
1713
1714
void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value &result)
1715
7
{
1716
7
    if (value1.isKnown() && value2.isKnown())
1717
1
        result.setKnown();
1718
6
    else if (value1.isImpossible() || value2.isImpossible())
1719
0
        result.setImpossible();
1720
6
    else if (value1.isInconclusive() || value2.isInconclusive())
1721
0
        result.setInconclusive();
1722
6
    else
1723
6
        result.setPossible();
1724
7
    if (value1.tokvalue)
1725
1
        result.tokvalue = value1.tokvalue;
1726
6
    else if (value2.tokvalue)
1727
1
        result.tokvalue = value2.tokvalue;
1728
7
    if (value1.isSymbolicValue()) {
1729
0
        result.valueType = value1.valueType;
1730
0
        result.tokvalue = value1.tokvalue;
1731
0
    }
1732
7
    if (value2.isSymbolicValue()) {
1733
0
        result.valueType = value2.valueType;
1734
0
        result.tokvalue = value2.tokvalue;
1735
0
    }
1736
7
    if (value1.isIteratorValue())
1737
0
        result.valueType = value1.valueType;
1738
7
    if (value2.isIteratorValue())
1739
0
        result.valueType = value2.valueType;
1740
7
    result.condition = value1.condition ? value1.condition : value2.condition;
1741
7
    result.varId = (value1.varId != 0) ? value1.varId : value2.varId;
1742
7
    result.varvalue = (result.varId == value1.varId) ? value1.varvalue : value2.varvalue;
1743
7
    result.errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath;
1744
7
    result.safe = value1.safe || value2.safe;
1745
7
    if (value1.bound == ValueFlow::Value::Bound::Point || value2.bound == ValueFlow::Value::Bound::Point) {
1746
7
        if (value1.bound == ValueFlow::Value::Bound::Upper || value2.bound == ValueFlow::Value::Bound::Upper)
1747
0
            result.bound = ValueFlow::Value::Bound::Upper;
1748
7
        if (value1.bound == ValueFlow::Value::Bound::Lower || value2.bound == ValueFlow::Value::Bound::Lower)
1749
0
            result.bound = ValueFlow::Value::Bound::Lower;
1750
7
    }
1751
7
    if (value1.path != value2.path)
1752
0
        result.path = -1;
1753
7
    else
1754
7
        result.path = value1.path;
1755
7
}
1756
1757
1758
template<class F>
1759
static size_t accumulateStructMembers(const Scope* scope, F f)
1760
0
{
1761
0
    size_t total = 0;
1762
0
    std::set<const Scope*> anonScopes;
1763
0
    for (const Variable& var : scope->varlist) {
1764
0
        if (var.isStatic())
1765
0
            continue;
1766
0
        if (const ValueType* vt = var.valueType()) {
1767
0
            if (vt->type == ValueType::Type::RECORD && vt->typeScope == scope)
1768
0
                return 0;
1769
0
            const MathLib::bigint dim = std::accumulate(var.dimensions().cbegin(), var.dimensions().cend(), 1LL, [](MathLib::bigint i1, const Dimension& dim) {
1770
0
                return i1 * dim.num;
1771
0
            });
Unexecuted instantiation: valueflow.cpp:accumulateStructMembers<getAlignOf(ValueType const&, Settings const&, int)::$_0>(Scope const*, getAlignOf(ValueType const&, Settings const&, int)::$_0)::{lambda(long long, Dimension const&)#1}::operator()(long long, Dimension const&) const
Unexecuted instantiation: valueflow.cpp:accumulateStructMembers<ValueFlow::getSizeOf(ValueType const&, Settings const&, int)::$_0>(Scope const*, ValueFlow::getSizeOf(ValueType const&, Settings const&, int)::$_0)::{lambda(long long, Dimension const&)#1}::operator()(long long, Dimension const&) const
1772
0
            if (var.nameToken()->scope() != scope && var.nameToken()->scope()->definedType) { // anonymous union
1773
0
                const auto ret = anonScopes.insert(var.nameToken()->scope());
1774
0
                if (ret.second)
1775
0
                    total = f(total, *vt, dim);
1776
0
            }
1777
0
            else
1778
0
                total = f(total, *vt, dim);
1779
0
        }
1780
0
        if (total == 0)
1781
0
            return 0;
1782
0
    }
1783
0
    return total;
1784
0
}
Unexecuted instantiation: valueflow.cpp:unsigned long accumulateStructMembers<getAlignOf(ValueType const&, Settings const&, int)::$_0>(Scope const*, getAlignOf(ValueType const&, Settings const&, int)::$_0)
Unexecuted instantiation: valueflow.cpp:unsigned long accumulateStructMembers<ValueFlow::getSizeOf(ValueType const&, Settings const&, int)::$_0>(Scope const*, ValueFlow::getSizeOf(ValueType const&, Settings const&, int)::$_0)
1785
1786
static size_t bitCeil(size_t x)
1787
0
{
1788
0
    if (x <= 1)
1789
0
        return 1;
1790
0
    --x;
1791
0
    x |= x >> 1;
1792
0
    x |= x >> 2;
1793
0
    x |= x >> 4;
1794
0
    x |= x >> 8;
1795
0
    x |= x >> 16;
1796
0
    x |= x >> 32;
1797
0
    return x + 1;
1798
0
}
1799
1800
static size_t getAlignOf(const ValueType& vt, const Settings& settings, int maxRecursion = 0)
1801
0
{
1802
0
    if (maxRecursion == settings.vfOptions.maxAlignOfRecursion) {
1803
        // TODO: add bailout message
1804
0
        return 0;
1805
0
    }
1806
0
    if (vt.pointer || vt.reference != Reference::None || vt.isPrimitive()) {
1807
0
        auto align = ValueFlow::getSizeOf(vt, settings);
1808
0
        return align == 0 ? 0 : bitCeil(align);
1809
0
    }
1810
0
    if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
1811
0
        auto accHelper = [&](size_t max, const ValueType& vt2, size_t /*dim*/) {
1812
0
            size_t a = getAlignOf(vt2, settings, ++maxRecursion);
1813
0
            return std::max(max, a);
1814
0
        };
1815
0
        size_t total = 0;
1816
0
        if (const Type* dt = vt.typeScope->definedType) {
1817
0
            total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const Type::BaseInfo& bi) {
1818
0
                if (bi.type && bi.type->classScope)
1819
0
                    v += accumulateStructMembers(bi.type->classScope, accHelper);
1820
0
                return v;
1821
0
            });
1822
0
        }
1823
0
        return total + accumulateStructMembers(vt.typeScope, accHelper);
1824
0
    }
1825
0
    if (vt.type == ValueType::Type::CONTAINER)
1826
0
        return settings.platform.sizeof_pointer; // Just guess
1827
0
    return 0;
1828
0
}
1829
1830
size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, int maxRecursion)
1831
280
{
1832
280
    if (maxRecursion == settings.vfOptions.maxSizeOfRecursion) {
1833
        // TODO: add bailout message
1834
0
        return 0;
1835
0
    }
1836
280
    if (vt.pointer || vt.reference != Reference::None)
1837
0
        return settings.platform.sizeof_pointer;
1838
280
    if (vt.type == ValueType::Type::BOOL || vt.type == ValueType::Type::CHAR)
1839
59
        return 1;
1840
221
    if (vt.type == ValueType::Type::SHORT)
1841
0
        return settings.platform.sizeof_short;
1842
221
    if (vt.type == ValueType::Type::WCHAR_T)
1843
0
        return settings.platform.sizeof_wchar_t;
1844
221
    if (vt.type == ValueType::Type::INT)
1845
221
        return settings.platform.sizeof_int;
1846
0
    if (vt.type == ValueType::Type::LONG)
1847
0
        return settings.platform.sizeof_long;
1848
0
    if (vt.type == ValueType::Type::LONGLONG)
1849
0
        return settings.platform.sizeof_long_long;
1850
0
    if (vt.type == ValueType::Type::FLOAT)
1851
0
        return settings.platform.sizeof_float;
1852
0
    if (vt.type == ValueType::Type::DOUBLE)
1853
0
        return settings.platform.sizeof_double;
1854
0
    if (vt.type == ValueType::Type::LONGDOUBLE)
1855
0
        return settings.platform.sizeof_long_double;
1856
0
    if (vt.type == ValueType::Type::CONTAINER)
1857
0
        return 3 * settings.platform.sizeof_pointer; // Just guess
1858
0
    if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
1859
0
        auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim) -> size_t {
1860
0
            size_t n = ValueFlow::getSizeOf(vt2, settings, ++maxRecursion);
1861
0
            size_t a = getAlignOf(vt2, settings);
1862
0
            if (n == 0 || a == 0)
1863
0
                return 0;
1864
0
            n *= dim;
1865
0
            size_t padding = (a - (total % a)) % a;
1866
0
            return vt.typeScope->type == Scope::eUnion ? std::max(total, n) : total + padding + n;
1867
0
        };
1868
0
        size_t total = accumulateStructMembers(vt.typeScope, accHelper);
1869
0
        if (const Type* dt = vt.typeScope->definedType) {
1870
0
            total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const Type::BaseInfo& bi) {
1871
0
                if (bi.type && bi.type->classScope)
1872
0
                    v += accumulateStructMembers(bi.type->classScope, accHelper);
1873
0
                return v;
1874
0
            });
1875
0
        }
1876
0
        if (total == 0)
1877
0
            return 0;
1878
0
        size_t align = getAlignOf(vt, settings);
1879
0
        if (align == 0)
1880
0
            return 0;
1881
0
        total += (align - (total % align)) % align;
1882
0
        return total;
1883
0
    }
1884
0
    return 0;
1885
0
}
1886
1887
static void valueFlowNumber(TokenList &tokenlist, const Settings& settings)
1888
764
{
1889
55.6k
    for (Token *tok = tokenlist.front(); tok;) {
1890
54.9k
        tok = ValueFlow::valueFlowSetConstantValue(tok, settings);
1891
54.9k
    }
1892
1893
764
    if (tokenlist.isCPP() || settings.standards.c >= Standards::C23) {
1894
55.6k
        for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1895
54.9k
            if (tok->isName() && !tok->varId() && match6(tok)) {
1896
0
                ValueFlow::Value value(tok->str() == MatchCompiler::makeConstString("true"));
1897
0
                if (!tok->isTemplateArg())
1898
0
                    value.setKnown();
1899
0
                setTokenValue(tok, std::move(value), settings);
1900
54.9k
            } else if (match7(tok)) {
1901
                // NULL function parameters are not simplified in the
1902
                // normal tokenlist
1903
0
                ValueFlow::Value value(0);
1904
0
                if (!tok->isTemplateArg())
1905
0
                    value.setKnown();
1906
0
                setTokenValue(tok->next(), std::move(value), settings);
1907
0
            }
1908
54.9k
        }
1909
764
    }
1910
764
}
1911
1912
static void valueFlowString(TokenList& tokenlist, const Settings& settings)
1913
764
{
1914
55.6k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
1915
54.9k
        if (tok->tokType() == Token::eString) {
1916
0
            ValueFlow::Value strvalue;
1917
0
            strvalue.valueType = ValueFlow::Value::ValueType::TOK;
1918
0
            strvalue.tokvalue = tok;
1919
0
            strvalue.setKnown();
1920
0
            setTokenValue(tok, std::move(strvalue), settings);
1921
0
        }
1922
54.9k
    }
1923
764
}
1924
1925
static void valueFlowArray(TokenList& tokenlist, const Settings& settings)
1926
764
{
1927
764
    std::map<nonneg int, const Token*> constantArrays;
1928
1929
55.6k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
1930
54.9k
        if (tok->varId() > 0) {
1931
            // array
1932
11.6k
            const auto it = utils::as_const(constantArrays).find(tok->varId());
1933
11.6k
            if (it != constantArrays.end()) {
1934
0
                ValueFlow::Value value;
1935
0
                value.valueType = ValueFlow::Value::ValueType::TOK;
1936
0
                value.tokvalue = it->second;
1937
0
                value.setKnown();
1938
0
                setTokenValue(tok, std::move(value), settings);
1939
0
            }
1940
1941
            // const array decl
1942
11.6k
            else if (tok->variable() && tok->variable()->isArray() && tok->variable()->isConst() &&
1943
11.6k
                     tok->variable()->nameToken() == tok && match8(tok)) {
1944
0
                Token* rhstok = tok->linkAt(1)->tokAt(2);
1945
0
                constantArrays[tok->varId()] = rhstok;
1946
0
                tok = rhstok->link();
1947
0
            }
1948
1949
            // pointer = array
1950
11.6k
            else if (tok->variable() && tok->variable()->isArray() && match9(tok->astParent()) &&
1951
11.6k
                     astIsRHS(tok) && tok->astParent()->astOperand1() && tok->astParent()->astOperand1()->variable() &&
1952
11.6k
                     tok->astParent()->astOperand1()->variable()->isPointer()) {
1953
0
                ValueFlow::Value value;
1954
0
                value.valueType = ValueFlow::Value::ValueType::TOK;
1955
0
                value.tokvalue = tok;
1956
0
                value.setKnown();
1957
0
                setTokenValue(tok, std::move(value), settings);
1958
0
            }
1959
11.6k
            continue;
1960
11.6k
        }
1961
1962
43.2k
        if (match10(tok)) {
1963
0
            Token* vartok = tok->tokAt(2);
1964
0
            Token* rhstok = vartok->linkAt(1)->tokAt(2);
1965
0
            constantArrays[vartok->varId()] = rhstok;
1966
0
            tok = rhstok->link();
1967
0
            continue;
1968
0
        }
1969
1970
43.2k
        if (match11(tok)) {
1971
0
            Token* vartok = tok->tokAt(2);
1972
0
            Token* strtok = vartok->linkAt(1)->tokAt(2);
1973
0
            constantArrays[vartok->varId()] = strtok;
1974
0
            tok = strtok->next();
1975
0
            continue;
1976
0
        }
1977
43.2k
    }
1978
764
}
1979
1980
static bool isNonZero(const Token* tok)
1981
0
{
1982
0
    return tok && (!tok->hasKnownIntValue() || tok->values().front().intvalue != 0);
1983
0
}
1984
1985
static const Token* getOtherOperand(const Token* tok)
1986
0
{
1987
0
    if (!tok)
1988
0
        return nullptr;
1989
0
    if (!tok->astParent())
1990
0
        return nullptr;
1991
0
    if (tok->astParent()->astOperand1() != tok)
1992
0
        return tok->astParent()->astOperand1();
1993
0
    if (tok->astParent()->astOperand2() != tok)
1994
0
        return tok->astParent()->astOperand2();
1995
0
    return nullptr;
1996
0
}
1997
1998
static void valueFlowArrayBool(TokenList& tokenlist, const Settings& settings)
1999
1.17k
{
2000
90.3k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
2001
89.1k
        if (tok->hasKnownIntValue())
2002
13.6k
            continue;
2003
75.5k
        const Variable* var = nullptr;
2004
75.5k
        bool known = false;
2005
75.5k
        const auto val =
2006
75.5k
            std::find_if(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isTokValue));
2007
75.5k
        if (val == tok->values().end()) {
2008
75.5k
            var = tok->variable();
2009
75.5k
            known = true;
2010
75.5k
        } else {
2011
0
            var = val->tokvalue->variable();
2012
0
            known = val->isKnown();
2013
0
        }
2014
75.5k
        if (!var)
2015
56.6k
            continue;
2016
18.9k
        if (!var->isArray() || var->isArgument() || var->isStlType())
2017
18.9k
            continue;
2018
0
        if (isNonZero(getOtherOperand(tok)) && match12(tok->astParent()))
2019
0
            continue;
2020
        // TODO: Check for function argument
2021
0
        if ((astIsBool(tok->astParent()) && !match13(tok->astParent())) ||
2022
0
            (tok->astParent() && match14(tok->astParent()->previous()))) {
2023
0
            ValueFlow::Value value{1};
2024
0
            if (known)
2025
0
                value.setKnown();
2026
0
            setTokenValue(tok, std::move(value), settings);
2027
0
        }
2028
0
    }
2029
1.17k
}
2030
2031
static void valueFlowArrayElement(TokenList& tokenlist, const Settings& settings)
2032
1.17k
{
2033
90.3k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
2034
89.1k
        if (tok->hasKnownIntValue())
2035
13.6k
            continue;
2036
75.5k
        const Token* indexTok = nullptr;
2037
75.5k
        const Token* arrayTok = nullptr;
2038
75.5k
        if (match15(tok) && tok->isBinaryOp()) {
2039
0
            indexTok = tok->astOperand2();
2040
0
            arrayTok = tok->astOperand1();
2041
75.5k
        } else if (match16(tok->tokAt(-2)) && astIsContainer(tok->tokAt(-2)->astOperand1())) {
2042
0
            arrayTok = tok->tokAt(-2)->astOperand1();
2043
0
            const Library::Container* container = getLibraryContainer(arrayTok);
2044
0
            if (!container || container->stdAssociativeLike)
2045
0
                continue;
2046
0
            const Library::Container::Yield yield = container->getYield(tok->strAt(-1));
2047
0
            if (yield != Library::Container::Yield::AT_INDEX)
2048
0
                continue;
2049
0
            indexTok = tok->astOperand2();
2050
0
        }
2051
2052
75.5k
        if (!indexTok || !arrayTok)
2053
75.5k
            continue;
2054
2055
0
        for (const ValueFlow::Value& arrayValue : arrayTok->values()) {
2056
0
            if (!arrayValue.isTokValue())
2057
0
                continue;
2058
0
            if (arrayValue.isImpossible())
2059
0
                continue;
2060
0
            for (const ValueFlow::Value& indexValue : indexTok->values()) {
2061
0
                if (!indexValue.isIntValue())
2062
0
                    continue;
2063
0
                if (indexValue.isImpossible())
2064
0
                    continue;
2065
0
                if (!arrayValue.isKnown() && !indexValue.isKnown() && arrayValue.varId != 0 && indexValue.varId != 0 &&
2066
0
                    !(arrayValue.varId == indexValue.varId && arrayValue.varvalue == indexValue.varvalue))
2067
0
                    continue;
2068
2069
0
                ValueFlow::Value result(0);
2070
0
                result.condition = arrayValue.condition ? arrayValue.condition : indexValue.condition;
2071
0
                result.setInconclusive(arrayValue.isInconclusive() || indexValue.isInconclusive());
2072
0
                result.varId = (arrayValue.varId != 0) ? arrayValue.varId : indexValue.varId;
2073
0
                result.varvalue = (result.varId == arrayValue.varId) ? arrayValue.intvalue : indexValue.intvalue;
2074
0
                if (arrayValue.valueKind == indexValue.valueKind)
2075
0
                    result.valueKind = arrayValue.valueKind;
2076
2077
0
                result.errorPath.insert(result.errorPath.end(),
2078
0
                                        arrayValue.errorPath.cbegin(),
2079
0
                                        arrayValue.errorPath.cend());
2080
0
                result.errorPath.insert(result.errorPath.end(),
2081
0
                                        indexValue.errorPath.cbegin(),
2082
0
                                        indexValue.errorPath.cend());
2083
2084
0
                const MathLib::bigint index = indexValue.intvalue;
2085
2086
0
                if (arrayValue.tokvalue->tokType() == Token::eString) {
2087
0
                    const std::string s = arrayValue.tokvalue->strValue();
2088
0
                    if (index == s.size()) {
2089
0
                        result.intvalue = 0;
2090
0
                        setTokenValue(tok, std::move(result), settings);
2091
0
                    } else if (index >= 0 && index < s.size()) {
2092
0
                        result.intvalue = s[static_cast<std::size_t>(index)];
2093
0
                        setTokenValue(tok, std::move(result), settings);
2094
0
                    }
2095
0
                } else if (match4(arrayValue.tokvalue)) {
2096
0
                    std::vector<const Token*> args = getArguments(arrayValue.tokvalue);
2097
0
                    if (index < 0 || index >= args.size())
2098
0
                        continue;
2099
0
                    const Token* arg = args[static_cast<std::size_t>(index)];
2100
0
                    if (!arg->hasKnownIntValue())
2101
0
                        continue;
2102
0
                    const ValueFlow::Value& v = arg->values().front();
2103
0
                    result.intvalue = v.intvalue;
2104
0
                    result.errorPath.insert(result.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
2105
0
                    setTokenValue(tok, std::move(result), settings);
2106
0
                }
2107
0
            }
2108
0
        }
2109
0
    }
2110
1.17k
}
2111
2112
static void valueFlowPointerAlias(TokenList& tokenlist, const Settings& settings)
2113
764
{
2114
55.6k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
2115
        // not address of
2116
54.9k
        if (!tok->isUnaryOp("&"))
2117
54.9k
            continue;
2118
2119
        // parent should be a '='
2120
4
        if (!match9(tok->astParent()))
2121
4
            continue;
2122
2123
        // child should be some buffer or variable
2124
0
        const Token* vartok = tok->astOperand1();
2125
0
        while (vartok) {
2126
0
            if (vartok->str() == MatchCompiler::makeConstString("["))
2127
0
                vartok = vartok->astOperand1();
2128
0
            else if (vartok->str() == MatchCompiler::makeConstString(".") || vartok->str() == MatchCompiler::makeConstString("::"))
2129
0
                vartok = vartok->astOperand2();
2130
0
            else
2131
0
                break;
2132
0
        }
2133
0
        if (!(vartok && vartok->variable() && !vartok->variable()->isPointer()))
2134
0
            continue;
2135
2136
0
        ValueFlow::Value value;
2137
0
        value.valueType = ValueFlow::Value::ValueType::TOK;
2138
0
        value.tokvalue = tok;
2139
0
        setTokenValue(tok, std::move(value), settings);
2140
0
    }
2141
764
}
2142
2143
static void valueFlowBitAnd(TokenList& tokenlist, const Settings& settings)
2144
764
{
2145
55.6k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
2146
54.9k
        if (tok->str() != MatchCompiler::makeConstString("&"))
2147
54.7k
            continue;
2148
2149
139
        if (tok->hasKnownValue())
2150
2
            continue;
2151
2152
137
        if (!tok->astOperand1() || !tok->astOperand2())
2153
10
            continue;
2154
2155
127
        MathLib::bigint number;
2156
127
        if (MathLib::isInt(tok->astOperand1()->str()))
2157
1
            number = MathLib::toBigNumber(tok->astOperand1());
2158
126
        else if (MathLib::isInt(tok->astOperand2()->str()))
2159
3
            number = MathLib::toBigNumber(tok->astOperand2());
2160
123
        else
2161
123
            continue;
2162
2163
4
        int bit = 0;
2164
8
        while (bit <= (MathLib::bigint_bits - 2) && ((((MathLib::bigint)1) << bit) < number))
2165
4
            ++bit;
2166
2167
4
        if ((((MathLib::bigint)1) << bit) == number) {
2168
3
            setTokenValue(tok, ValueFlow::Value(0), settings);
2169
3
            setTokenValue(tok, ValueFlow::Value(number), settings);
2170
3
        }
2171
4
    }
2172
764
}
2173
2174
static void valueFlowSameExpressions(TokenList& tokenlist, const Settings& settings)
2175
764
{
2176
55.6k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
2177
54.9k
        if (tok->hasKnownIntValue())
2178
8.49k
            continue;
2179
2180
46.4k
        if (!tok->astOperand1() || !tok->astOperand2())
2181
41.9k
            continue;
2182
2183
4.49k
        if (tok->astOperand1()->isLiteral() || tok->astOperand2()->isLiteral())
2184
21
            continue;
2185
2186
4.47k
        if (!astIsIntegral(tok->astOperand1(), false) && !astIsIntegral(tok->astOperand2(), false))
2187
361
            continue;
2188
2189
4.11k
        long long val;
2190
2191
4.11k
        if (match17(tok)) {
2192
350
            val = 1;
2193
350
        }
2194
3.76k
        else if (match18(tok)) {
2195
717
            val = 0;
2196
717
        }
2197
3.04k
        else
2198
3.04k
            continue;
2199
2200
1.06k
        ValueFlow::Value value(val);
2201
1.06k
        value.setKnown();
2202
2203
1.06k
        if (isSameExpression(false, tok->astOperand1(), tok->astOperand2(), settings, true, true, &value.errorPath)) {
2204
265
            setTokenValue(tok, std::move(value), settings);
2205
265
        }
2206
1.06k
    }
2207
764
}
2208
2209
static bool getExpressionRange(const Token* expr, MathLib::bigint* minvalue, MathLib::bigint* maxvalue)
2210
0
{
2211
0
    if (expr->hasKnownIntValue()) {
2212
0
        if (minvalue)
2213
0
            *minvalue = expr->values().front().intvalue;
2214
0
        if (maxvalue)
2215
0
            *maxvalue = expr->values().front().intvalue;
2216
0
        return true;
2217
0
    }
2218
2219
0
    if (expr->str() == MatchCompiler::makeConstString("&") && expr->astOperand1() && expr->astOperand2()) {
2220
0
        MathLib::bigint vals[4];
2221
0
        const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]);
2222
0
        const bool rhsHasKnownRange = getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]);
2223
0
        if (!lhsHasKnownRange && !rhsHasKnownRange)
2224
0
            return false;
2225
0
        if (!lhsHasKnownRange || !rhsHasKnownRange) {
2226
0
            if (minvalue)
2227
0
                *minvalue = lhsHasKnownRange ? vals[0] : vals[2];
2228
0
            if (maxvalue)
2229
0
                *maxvalue = lhsHasKnownRange ? vals[1] : vals[3];
2230
0
        } else {
2231
0
            if (minvalue)
2232
0
                *minvalue = vals[0] & vals[2];
2233
0
            if (maxvalue)
2234
0
                *maxvalue = vals[1] & vals[3];
2235
0
        }
2236
0
        return true;
2237
0
    }
2238
2239
0
    if (expr->str() == MatchCompiler::makeConstString("%") && expr->astOperand1() && expr->astOperand2()) {
2240
0
        MathLib::bigint vals[4];
2241
0
        if (!getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]))
2242
0
            return false;
2243
0
        if (vals[2] <= 0)
2244
0
            return false;
2245
0
        const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]);
2246
0
        if (lhsHasKnownRange && vals[0] < 0)
2247
0
            return false;
2248
        // If lhs has unknown value, it must be unsigned
2249
0
        if (!lhsHasKnownRange &&
2250
0
            (!expr->astOperand1()->valueType() || expr->astOperand1()->valueType()->sign != ValueType::Sign::UNSIGNED))
2251
0
            return false;
2252
0
        if (minvalue)
2253
0
            *minvalue = 0;
2254
0
        if (maxvalue)
2255
0
            *maxvalue = vals[3] - 1;
2256
0
        return true;
2257
0
    }
2258
2259
0
    return false;
2260
0
}
2261
2262
static void valueFlowRightShift(TokenList& tokenList, const Settings& settings)
2263
1.17k
{
2264
90.3k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
2265
89.1k
        if (tok->str() != MatchCompiler::makeConstString(">>"))
2266
89.1k
            continue;
2267
2268
0
        if (tok->hasKnownValue())
2269
0
            continue;
2270
2271
0
        if (!tok->astOperand1() || !tok->astOperand2())
2272
0
            continue;
2273
2274
0
        if (!tok->astOperand2()->hasKnownValue())
2275
0
            continue;
2276
2277
0
        const MathLib::bigint rhsvalue = tok->astOperand2()->values().front().intvalue;
2278
0
        if (rhsvalue < 0)
2279
0
            continue;
2280
2281
0
        if (!tok->astOperand1()->valueType() || !tok->astOperand1()->valueType()->isIntegral())
2282
0
            continue;
2283
2284
0
        if (!tok->astOperand2()->valueType() || !tok->astOperand2()->valueType()->isIntegral())
2285
0
            continue;
2286
2287
0
        MathLib::bigint lhsmax = 0;
2288
0
        if (!getExpressionRange(tok->astOperand1(), nullptr, &lhsmax))
2289
0
            continue;
2290
0
        if (lhsmax < 0)
2291
0
            continue;
2292
0
        int lhsbits;
2293
0
        if ((tok->astOperand1()->valueType()->type == ValueType::Type::CHAR) ||
2294
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::SHORT) ||
2295
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::WCHAR_T) ||
2296
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::BOOL) ||
2297
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::INT))
2298
0
            lhsbits = settings.platform.int_bit;
2299
0
        else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONG)
2300
0
            lhsbits = settings.platform.long_bit;
2301
0
        else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONGLONG)
2302
0
            lhsbits = settings.platform.long_long_bit;
2303
0
        else
2304
0
            continue;
2305
0
        if (rhsvalue >= lhsbits || rhsvalue >= MathLib::bigint_bits || (1ULL << rhsvalue) <= lhsmax)
2306
0
            continue;
2307
2308
0
        ValueFlow::Value val(0);
2309
0
        val.setKnown();
2310
0
        setTokenValue(tok, std::move(val), settings);
2311
0
    }
2312
1.17k
}
2313
2314
static std::vector<MathLib::bigint> minUnsignedValue(const Token* tok, int depth = 8)
2315
0
{
2316
0
    std::vector<MathLib::bigint> result;
2317
0
    if (!tok)
2318
0
        return result;
2319
0
    if (depth < 0)
2320
0
        return result;
2321
0
    if (tok->hasKnownIntValue()) {
2322
0
        result = {tok->values().front().intvalue};
2323
0
    } else if (!match19(tok) && tok->isConstOp() && tok->astOperand1() && tok->astOperand2()) {
2324
0
        std::vector<MathLib::bigint> op1 = minUnsignedValue(tok->astOperand1(), depth - 1);
2325
0
        if (!op1.empty()) {
2326
0
            std::vector<MathLib::bigint> op2 = minUnsignedValue(tok->astOperand2(), depth - 1);
2327
0
            if (!op2.empty()) {
2328
0
                result = calculate<std::vector<MathLib::bigint>>(tok->str(), op1.front(), op2.front());
2329
0
            }
2330
0
        }
2331
0
    }
2332
0
    if (result.empty() && astIsUnsigned(tok))
2333
0
        result = {0};
2334
0
    return result;
2335
0
}
2336
2337
static bool isConvertedToIntegral(const Token* tok, const Settings& settings)
2338
2
{
2339
2
    if (!tok)
2340
0
        return false;
2341
2
    std::vector<ValueType> parentTypes = getParentValueTypes(tok, settings);
2342
2
    if (parentTypes.empty())
2343
2
        return false;
2344
0
    const ValueType& vt = parentTypes.front();
2345
0
    return vt.type != ValueType::UNKNOWN_INT && vt.isIntegral();
2346
2
}
2347
2348
static bool isSameToken(const Token* tok1, const Token* tok2)
2349
0
{
2350
0
    if (!tok1 || !tok2)
2351
0
        return false;
2352
0
    if (tok1->exprId() != 0 && tok1->exprId() == tok2->exprId())
2353
0
        return true;
2354
0
    if (tok1->hasKnownIntValue() && tok2->hasKnownIntValue())
2355
0
        return tok1->values().front().intvalue == tok2->values().front().intvalue;
2356
0
    return false;
2357
0
}
2358
2359
static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& settings)
2360
1.17k
{
2361
90.3k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
2362
89.1k
        if (tok->hasKnownIntValue())
2363
13.6k
            continue;
2364
75.5k
        if (match20(tok))
2365
0
            continue;
2366
75.5k
        if (astIsBool(tok) || match12(tok)) {
2367
1.45k
            ValueFlow::Value lower{-1};
2368
1.45k
            lower.bound = ValueFlow::Value::Bound::Upper;
2369
1.45k
            lower.setImpossible();
2370
1.45k
            setTokenValue(tok, std::move(lower), settings);
2371
2372
1.45k
            ValueFlow::Value upper{2};
2373
1.45k
            upper.bound = ValueFlow::Value::Bound::Lower;
2374
1.45k
            upper.setImpossible();
2375
1.45k
            setTokenValue(tok, std::move(upper), settings);
2376
74.0k
        } else if (astIsUnsigned(tok) && !astIsPointer(tok)) {
2377
0
            std::vector<MathLib::bigint> minvalue = minUnsignedValue(tok);
2378
0
            if (minvalue.empty())
2379
0
                continue;
2380
0
            ValueFlow::Value value{std::max<MathLib::bigint>(0, minvalue.front()) - 1};
2381
0
            value.bound = ValueFlow::Value::Bound::Upper;
2382
0
            value.setImpossible();
2383
0
            setTokenValue(tok, std::move(value), settings);
2384
0
        }
2385
75.5k
        if (match22(tok) && match21(tok->astOperand1())) {
2386
0
            const Token* condTok = tok->astOperand1();
2387
0
            const Token* branchesTok = tok->astOperand2();
2388
2389
0
            auto tokens = makeArray(condTok->astOperand1(), condTok->astOperand2());
2390
0
            auto branches = makeArray(branchesTok->astOperand1(), branchesTok->astOperand2());
2391
0
            bool flipped = false;
2392
0
            if (std::equal(tokens.cbegin(), tokens.cend(), branches.crbegin(), &isSameToken))
2393
0
                flipped = true;
2394
0
            else if (!std::equal(tokens.cbegin(), tokens.cend(), branches.cbegin(), &isSameToken))
2395
0
                continue;
2396
0
            std::vector<ValueFlow::Value> values;
2397
0
            for (const Token* tok2 : tokens) {
2398
0
                if (tok2->hasKnownIntValue()) {
2399
0
                    values.emplace_back(tok2->values().front());
2400
0
                } else {
2401
0
                    ValueFlow::Value symValue{};
2402
0
                    symValue.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
2403
0
                    symValue.tokvalue = tok2;
2404
0
                    values.push_back(symValue);
2405
0
                    std::copy_if(tok2->values().cbegin(),
2406
0
                                 tok2->values().cend(),
2407
0
                                 std::back_inserter(values),
2408
0
                                 [](const ValueFlow::Value& v) {
2409
0
                        if (!v.isKnown())
2410
0
                            return false;
2411
0
                        return v.isSymbolicValue();
2412
0
                    });
2413
0
                }
2414
0
            }
2415
0
            const bool isMin = match1(condTok) ^ flipped;
2416
0
            for (ValueFlow::Value& value : values) {
2417
0
                value.setImpossible();
2418
0
                if (isMin) {
2419
0
                    value.intvalue++;
2420
0
                    value.bound = ValueFlow::Value::Bound::Lower;
2421
0
                } else {
2422
0
                    value.intvalue--;
2423
0
                    value.bound = ValueFlow::Value::Bound::Upper;
2424
0
                }
2425
0
                setTokenValue(tok, std::move(value), settings);
2426
0
            }
2427
2428
75.5k
        } else if (match23(tok) && tok->astOperand2() && tok->astOperand2()->hasKnownIntValue()) {
2429
0
            ValueFlow::Value value{tok->astOperand2()->values().front()};
2430
0
            value.bound = ValueFlow::Value::Bound::Lower;
2431
0
            value.setImpossible();
2432
0
            setTokenValue(tok, std::move(value), settings);
2433
75.5k
        } else if (match24(tok)) {
2434
0
            ValueFlow::Value value{-1};
2435
0
            value.bound = ValueFlow::Value::Bound::Upper;
2436
0
            value.setImpossible();
2437
0
            setTokenValue(tok->next(), std::move(value), settings);
2438
75.5k
        } else if (match25(tok) && astIsContainerOwned(tok->astOperand1())) {
2439
0
            const Library::Container* container = getLibraryContainer(tok->astOperand1());
2440
0
            if (!container)
2441
0
                continue;
2442
0
            if (!container->stdStringLike)
2443
0
                continue;
2444
0
            if (container->view)
2445
0
                continue;
2446
0
            ValueFlow::Value value{0};
2447
0
            value.setImpossible();
2448
0
            setTokenValue(tok->tokAt(2), std::move(value), settings);
2449
75.5k
        } else if (match26(tok) && match27(tok->linkAt(1))) {
2450
0
            ValueFlow::Value value{0};
2451
0
            value.setImpossible();
2452
0
            setTokenValue(tok->linkAt(1)->next(), std::move(value), settings);
2453
75.5k
        } else if ((tokenList.isCPP() && match28(tok)) || tok->isUnaryOp("&")) {
2454
8
            ValueFlow::Value value{0};
2455
8
            value.setImpossible();
2456
8
            setTokenValue(tok, std::move(value), settings);
2457
75.5k
        } else if (tok->variable() && tok->variable()->isArray() && !tok->variable()->isArgument() &&
2458
75.5k
                   !tok->variable()->isStlType()) {
2459
0
            ValueFlow::Value value{0};
2460
0
            value.setImpossible();
2461
0
            setTokenValue(tok, std::move(value), settings);
2462
75.5k
        } else if (tok->isIncompleteVar() && tok->astParent() && tok->astParent()->isUnaryOp("-") &&
2463
75.5k
                   isConvertedToIntegral(tok->astParent(), settings)) {
2464
0
            ValueFlow::Value value{0};
2465
0
            value.setImpossible();
2466
0
            setTokenValue(tok, std::move(value), settings);
2467
0
        }
2468
75.5k
    }
2469
1.17k
}
2470
2471
static void valueFlowEnumValue(SymbolDatabase & symboldatabase, const Settings & settings)
2472
1.52k
{
2473
5.59k
    for (Scope & scope : symboldatabase.scopeList) {
2474
5.59k
        if (scope.type != Scope::eEnum)
2475
5.59k
            continue;
2476
0
        MathLib::bigint value = 0;
2477
0
        bool prev_enum_is_known = true;
2478
2479
0
        for (Enumerator & enumerator : scope.enumeratorList) {
2480
0
            if (enumerator.start) {
2481
0
                auto* rhs = const_cast<Token*>(enumerator.start->previous()->astOperand2());
2482
0
                ValueFlow::valueFlowConstantFoldAST(rhs, settings);
2483
0
                if (rhs && rhs->hasKnownIntValue()) {
2484
0
                    enumerator.value = rhs->values().front().intvalue;
2485
0
                    enumerator.value_known = true;
2486
0
                    value = enumerator.value + 1;
2487
0
                    prev_enum_is_known = true;
2488
0
                } else
2489
0
                    prev_enum_is_known = false;
2490
0
            } else if (prev_enum_is_known) {
2491
0
                enumerator.value = value++;
2492
0
                enumerator.value_known = true;
2493
0
            }
2494
0
        }
2495
0
    }
2496
1.52k
}
2497
2498
static void valueFlowGlobalConstVar(TokenList& tokenList, const Settings& settings)
2499
764
{
2500
    // Get variable values...
2501
764
    std::map<const Variable*, ValueFlow::Value> vars;
2502
55.6k
    for (const Token* tok = tokenList.front(); tok; tok = tok->next()) {
2503
54.9k
        if (!tok->variable())
2504
43.2k
            continue;
2505
        // Initialization...
2506
11.6k
        if (tok == tok->variable()->nameToken() && !tok->variable()->isVolatile() && !tok->variable()->isArgument() &&
2507
11.6k
            tok->variable()->isConst() && tok->valueType() && tok->valueType()->isIntegral() &&
2508
11.6k
            tok->valueType()->pointer == 0 && tok->valueType()->constness == 1 && match29(tok) &&
2509
11.6k
            tok->next()->astOperand2() && tok->next()->astOperand2()->hasKnownIntValue()) {
2510
0
            vars[tok->variable()] = tok->next()->astOperand2()->values().front();
2511
0
        }
2512
11.6k
    }
2513
2514
    // Set values..
2515
55.6k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
2516
54.9k
        if (!tok->variable())
2517
43.2k
            continue;
2518
11.6k
        const auto var = utils::as_const(vars).find(tok->variable());
2519
11.6k
        if (var == vars.end())
2520
11.6k
            continue;
2521
0
        setTokenValue(tok, var->second, settings);
2522
0
    }
2523
764
}
2524
2525
static void valueFlowGlobalStaticVar(TokenList& tokenList, const Settings& settings)
2526
764
{
2527
    // Get variable values...
2528
764
    std::map<const Variable*, ValueFlow::Value> vars;
2529
55.6k
    for (const Token* tok = tokenList.front(); tok; tok = tok->next()) {
2530
54.9k
        if (!tok->variable())
2531
43.2k
            continue;
2532
        // Initialization...
2533
11.6k
        if (tok == tok->variable()->nameToken() && tok->variable()->isStatic() && !tok->variable()->isConst() &&
2534
11.6k
            tok->valueType() && tok->valueType()->isIntegral() && tok->valueType()->pointer == 0 &&
2535
11.6k
            tok->valueType()->constness == 0 && match29(tok) && tok->next()->astOperand2() &&
2536
11.6k
            tok->next()->astOperand2()->hasKnownIntValue()) {
2537
0
            vars[tok->variable()] = tok->next()->astOperand2()->values().front();
2538
11.6k
        } else {
2539
            // If variable is written anywhere in TU then remove it from vars
2540
11.6k
            if (!tok->astParent())
2541
3.82k
                continue;
2542
7.87k
            if (match30(tok->astParent()) && !tok->astParent()->astOperand2())
2543
633
                vars.erase(tok->variable());
2544
7.24k
            else if (tok->astParent()->isAssignmentOp()) {
2545
5.64k
                if (tok == tok->astParent()->astOperand1())
2546
4.06k
                    vars.erase(tok->variable());
2547
1.58k
                else if (tok->isCpp() && match31(tok->astParent()->tokAt(-2)))
2548
0
                    vars.erase(tok->variable());
2549
5.64k
            } else if (isLikelyStreamRead(tok->astParent())) {
2550
0
                vars.erase(tok->variable());
2551
1.59k
            } else if (match32(tok->astParent()))
2552
0
                vars.erase(tok->variable());
2553
7.87k
        }
2554
11.6k
    }
2555
2556
    // Set values..
2557
55.6k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
2558
54.9k
        if (!tok->variable())
2559
43.2k
            continue;
2560
11.6k
        const auto var = utils::as_const(vars).find(tok->variable());
2561
11.6k
        if (var == vars.end())
2562
11.6k
            continue;
2563
0
        setTokenValue(tok, var->second, settings);
2564
0
    }
2565
764
}
2566
2567
static Analyzer::Result valueFlowForward(Token* startToken,
2568
                                         const Token* endToken,
2569
                                         const Token* exprTok,
2570
                                         ValueFlow::Value value,
2571
                                         const TokenList& tokenlist,
2572
                                         ErrorLogger& errorLogger,
2573
                                         const Settings& settings,
2574
                                         SourceLocation loc = SourceLocation::current())
2575
3.03k
{
2576
3.03k
    if (settings.debugnormal)
2577
0
        setSourceLocation(value, loc, startToken);
2578
3.03k
    return valueFlowGenericForward(startToken,
2579
3.03k
                                   endToken,
2580
3.03k
                                   makeAnalyzer(exprTok, std::move(value), settings),
2581
3.03k
                                   tokenlist,
2582
3.03k
                                   errorLogger,
2583
3.03k
                                   settings);
2584
3.03k
}
2585
2586
static Analyzer::Result valueFlowForward(Token* startToken,
2587
                                         const Token* endToken,
2588
                                         const Token* exprTok,
2589
                                         std::list<ValueFlow::Value> values,
2590
                                         const TokenList& tokenlist,
2591
                                         ErrorLogger& errorLogger,
2592
                                         const Settings& settings,
2593
                                         SourceLocation loc = SourceLocation::current())
2594
2.03k
{
2595
2.03k
    Analyzer::Result result{};
2596
2.96k
    for (ValueFlow::Value& v : values) {
2597
2.96k
        result.update(valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, errorLogger, settings, loc));
2598
2.96k
    }
2599
2.03k
    return result;
2600
2.03k
}
2601
2602
template<class ValueOrValues>
2603
static Analyzer::Result valueFlowForward(Token* startToken,
2604
                                         const Token* exprTok,
2605
                                         ValueOrValues v,
2606
                                         const TokenList& tokenlist,
2607
                                         ErrorLogger& errorLogger,
2608
                                         const Settings& settings,
2609
                                         SourceLocation loc = SourceLocation::current())
2610
0
{
2611
0
    const Token* endToken = nullptr;
2612
0
    const Function* f = Scope::nestedInFunction(startToken->scope());
2613
0
    if (f && f->functionScope)
2614
0
        endToken = f->functionScope->bodyEnd;
2615
0
    if (!endToken && exprTok && exprTok->variable() && !exprTok->variable()->isLocal())
2616
0
        endToken = startToken->scope()->bodyEnd;
2617
0
    return valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, errorLogger, settings, loc);
2618
0
}
2619
2620
static Analyzer::Result valueFlowForwardRecursive(Token* top,
2621
                                                  const Token* exprTok,
2622
                                                  std::list<ValueFlow::Value> values,
2623
                                                  const TokenList& tokenlist,
2624
                                                  ErrorLogger& errorLogger,
2625
                                                  const Settings& settings,
2626
                                                  SourceLocation loc = SourceLocation::current())
2627
0
{
2628
0
    Analyzer::Result result{};
2629
0
    for (ValueFlow::Value& v : values) {
2630
0
        if (settings.debugnormal)
2631
0
            setSourceLocation(v, loc, top);
2632
0
        result.update(
2633
0
            valueFlowGenericForward(top, makeAnalyzer(exprTok, std::move(v), settings), tokenlist, errorLogger, settings));
2634
0
    }
2635
0
    return result;
2636
0
}
2637
2638
static void valueFlowReverse(Token* tok,
2639
                             const Token* const endToken,
2640
                             const Token* const varToken,
2641
                             std::list<ValueFlow::Value> values,
2642
                             const TokenList& tokenlist,
2643
                             ErrorLogger& errorLogger,
2644
                             const Settings& settings,
2645
                             SourceLocation loc = SourceLocation::current())
2646
633
{
2647
865
    for (ValueFlow::Value& v : values) {
2648
865
        if (settings.debugnormal)
2649
0
            setSourceLocation(v, loc, tok);
2650
865
        valueFlowGenericReverse(tok,
2651
865
                                endToken,
2652
865
                                makeReverseAnalyzer(varToken, std::move(v), settings),
2653
865
                                tokenlist,
2654
865
                                errorLogger,
2655
865
                                settings);
2656
865
    }
2657
633
}
2658
2659
// Deprecated
2660
static void valueFlowReverse(const TokenList& tokenlist,
2661
                             Token* tok,
2662
                             const Token* const varToken,
2663
                             ValueFlow::Value val,
2664
                             ErrorLogger& errorLogger,
2665
                             const Settings& settings,
2666
                             SourceLocation loc = SourceLocation::current())
2667
0
{
2668
0
    valueFlowReverse(tok, nullptr, varToken, {std::move(val)}, tokenlist, errorLogger, settings, loc);
2669
0
}
2670
2671
static bool isConditionKnown(const Token* tok, bool then)
2672
2.24k
{
2673
2.24k
    const char* op = "||";
2674
2.24k
    if (then)
2675
1.24k
        op = "&&";
2676
2.24k
    const Token* parent = tok->astParent();
2677
2.24k
    while (parent && (parent->str() == op || parent->str() == MatchCompiler::makeConstString("!") || parent->isCast()))
2678
0
        parent = parent->astParent();
2679
2.24k
    const Token* top = tok->astTop();
2680
2.24k
    if (match14(top->previous()))
2681
2.24k
        return parent == top || match33(parent);
2682
0
    return parent && parent->str() != op;
2683
2.24k
}
2684
2685
enum class LifetimeCapture : std::uint8_t { Undefined, ByValue, ByReference };
2686
2687
static std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
2688
0
{
2689
0
    std::string result;
2690
0
    if (!val)
2691
0
        return "object";
2692
0
    switch (val->lifetimeKind) {
2693
0
    case ValueFlow::Value::LifetimeKind::Lambda:
2694
0
        result = "lambda";
2695
0
        break;
2696
0
    case ValueFlow::Value::LifetimeKind::Iterator:
2697
0
        result = "iterator";
2698
0
        break;
2699
0
    case ValueFlow::Value::LifetimeKind::Object:
2700
0
    case ValueFlow::Value::LifetimeKind::SubObject:
2701
0
    case ValueFlow::Value::LifetimeKind::Address:
2702
0
        if (astIsPointer(tok))
2703
0
            result = "pointer";
2704
0
        else if (match9(tok) && astIsPointer(tok->astOperand2()))
2705
0
            result = "pointer";
2706
0
        else
2707
0
            result = "object";
2708
0
        break;
2709
0
    }
2710
0
    return result;
2711
0
}
2712
2713
std::string ValueFlow::lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ErrorPath &errorPath)
2714
0
{
2715
0
    const Token *tokvalue = val ? val->tokvalue : nullptr;
2716
0
    const Variable *tokvar = tokvalue ? tokvalue->variable() : nullptr;
2717
0
    const Token *vartok = tokvar ? tokvar->nameToken() : nullptr;
2718
0
    const bool classVar = tokvar ? (!tokvar->isLocal() && !tokvar->isArgument() && !tokvar->isGlobal()) : false;
2719
0
    std::string type = lifetimeType(tok, val);
2720
0
    std::string msg = type;
2721
0
    if (vartok) {
2722
0
        if (!classVar)
2723
0
            errorPath.emplace_back(vartok, "Variable created here.");
2724
0
        const Variable * var = vartok->variable();
2725
0
        if (var) {
2726
0
            std::string submessage;
2727
0
            switch (val->lifetimeKind) {
2728
0
            case ValueFlow::Value::LifetimeKind::SubObject:
2729
0
            case ValueFlow::Value::LifetimeKind::Object:
2730
0
            case ValueFlow::Value::LifetimeKind::Address:
2731
0
                if (type == MatchCompiler::makeConstString("pointer"))
2732
0
                    submessage = " to local variable";
2733
0
                else
2734
0
                    submessage = " that points to local variable";
2735
0
                break;
2736
0
            case ValueFlow::Value::LifetimeKind::Lambda:
2737
0
                submessage = " that captures local variable";
2738
0
                break;
2739
0
            case ValueFlow::Value::LifetimeKind::Iterator:
2740
0
                submessage = " to local container";
2741
0
                break;
2742
0
            }
2743
0
            if (classVar)
2744
0
                submessage.replace(submessage.find("local"), 5, "member");
2745
0
            msg += submessage + " '" + var->name() + "'";
2746
0
        }
2747
0
    }
2748
0
    return msg;
2749
0
}
2750
2751
std::vector<ValueFlow::Value> ValueFlow::getLifetimeObjValues(const Token* tok, bool inconclusive, MathLib::bigint path)
2752
2.04k
{
2753
2.04k
    std::vector<ValueFlow::Value> result;
2754
2.04k
    auto pred = [&](const ValueFlow::Value& v) {
2755
386
        if (!v.isLocalLifetimeValue() && !(path != 0 && v.isSubFunctionLifetimeValue()))
2756
383
            return false;
2757
3
        if (!inconclusive && v.isInconclusive())
2758
0
            return false;
2759
3
        if (!v.tokvalue)
2760
0
            return false;
2761
3
        if (path >= 0 && v.path != 0 && v.path != path)
2762
0
            return false;
2763
3
        return true;
2764
3
    };
2765
2.04k
    std::copy_if(tok->values().cbegin(), tok->values().cend(), std::back_inserter(result), pred);
2766
2.04k
    return result;
2767
2.04k
}
2768
2769
static bool hasUniqueOwnership(const Token* tok)
2770
0
{
2771
0
    if (!tok)
2772
0
        return false;
2773
0
    const Variable* var = tok->variable();
2774
0
    if (var && var->isArray() && !var->isArgument())
2775
0
        return true;
2776
0
    if (astIsPointer(tok))
2777
0
        return false;
2778
0
    if (astIsUniqueSmartPointer(tok))
2779
0
        return true;
2780
0
    if (astIsContainerOwned(tok))
2781
0
        return true;
2782
0
    return false;
2783
0
}
2784
2785
// Check if dereferencing an object that doesn't have unique ownership
2786
static bool derefShared(const Token* tok)
2787
0
{
2788
0
    if (!tok)
2789
0
        return false;
2790
0
    if (!tok->isUnaryOp("*") && tok->str() != MatchCompiler::makeConstString("[") && tok->str() != MatchCompiler::makeConstString("."))
2791
0
        return false;
2792
0
    if (tok->str() == MatchCompiler::makeConstString(".") && tok->originalName() != MatchCompiler::makeConstString("->"))
2793
0
        return false;
2794
0
    const Token* ptrTok = tok->astOperand1();
2795
0
    return !hasUniqueOwnership(ptrTok);
2796
0
}
2797
2798
ValueFlow::Value ValueFlow::getLifetimeObjValue(const Token *tok, bool inconclusive)
2799
2
{
2800
2
    std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(tok, inconclusive);
2801
    // There should only be one lifetime
2802
2
    if (values.size() != 1)
2803
2
        return ValueFlow::Value{};
2804
0
    return values.front();
2805
2
}
2806
2807
template<class Predicate>
2808
static std::vector<ValueFlow::LifetimeToken> getLifetimeTokens(const Token* tok,
2809
                                                               bool escape,
2810
                                                               ErrorPath errorPath,
2811
                                                               Predicate pred,
2812
                                                               const Settings& settings,
2813
                                                               int depth = 20)
2814
11.2k
{
2815
11.2k
    if (!tok)
2816
0
        return std::vector<ValueFlow::LifetimeToken> {};
2817
11.2k
    if (match34(tok))
2818
0
        return std::vector<ValueFlow::LifetimeToken>{};
2819
11.2k
    const Variable *var = tok->variable();
2820
11.2k
    if (pred(tok))
2821
0
        return {{tok, std::move(errorPath)}};
2822
11.2k
    if (depth < 0)
2823
0
        return {{tok, std::move(errorPath)}};
2824
11.2k
    if (var && var->declarationId() == tok->varId()) {
2825
11.2k
        if (var->isReference() || var->isRValueReference()) {
2826
0
            const Token * const varDeclEndToken = var->declEndToken();
2827
0
            if (!varDeclEndToken)
2828
0
                return {{tok, true, std::move(errorPath)}};
2829
0
            if (var->isArgument()) {
2830
0
                errorPath.emplace_back(varDeclEndToken, "Passed to reference.");
2831
0
                return {{tok, true, std::move(errorPath)}};
2832
0
            }
2833
0
            if (match35(varDeclEndToken)) {
2834
0
                errorPath.emplace_back(varDeclEndToken, "Assigned to reference.");
2835
0
                const Token *vartok = varDeclEndToken->astOperand2();
2836
0
                const bool temporary = isTemporary(vartok, nullptr, true);
2837
0
                const bool nonlocal = var->isStatic() || var->isGlobal();
2838
0
                if (vartok == tok || (nonlocal && temporary) ||
2839
0
                    (!escape && (var->isConst() || var->isRValueReference()) && temporary))
2840
0
                    return {{tok, true, std::move(errorPath)}};
2841
0
                if (vartok)
2842
0
                    return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, settings, depth - 1);
2843
0
            } else if (match36(var->nameToken()->astParent()) &&
2844
0
                       var->nameToken()->astParent()->astParent() &&
2845
0
                       match37(var->nameToken()->astParent()->astParent()->previous())) {
2846
0
                errorPath.emplace_back(var->nameToken(), "Assigned to reference.");
2847
0
                const Token* vartok = var->nameToken();
2848
0
                if (vartok == tok)
2849
0
                    return {{tok, true, std::move(errorPath)}};
2850
0
                const Token* contok = var->nameToken()->astParent()->astOperand2();
2851
0
                if (astIsContainer(contok))
2852
0
                    return ValueFlow::LifetimeToken::setAddressOf(
2853
0
                        getLifetimeTokens(contok, escape, std::move(errorPath), pred, settings, depth - 1),
2854
0
                        false);
2855
0
                return std::vector<ValueFlow::LifetimeToken>{};
2856
0
            } else {
2857
0
                return std::vector<ValueFlow::LifetimeToken> {};
2858
0
            }
2859
0
        }
2860
11.2k
    } else if (match38(tok->previous())) {
2861
0
        const Function *f = tok->previous()->function();
2862
0
        if (f) {
2863
0
            if (!Function::returnsReference(f))
2864
0
                return {{tok, std::move(errorPath)}};
2865
0
            std::vector<ValueFlow::LifetimeToken> result;
2866
0
            std::vector<const Token*> returns = Function::findReturns(f);
2867
0
            for (const Token* returnTok : returns) {
2868
0
                if (returnTok == tok)
2869
0
                    continue;
2870
0
                for (ValueFlow::LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, settings, depth - returns.size())) {
2871
0
                    const Token* argvarTok = lt.token;
2872
0
                    const Variable* argvar = argvarTok->variable();
2873
0
                    if (!argvar)
2874
0
                        continue;
2875
0
                    const Token* argTok = nullptr;
2876
0
                    if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
2877
0
                        const int n = getArgumentPos(argvar, f);
2878
0
                        if (n < 0)
2879
0
                            return std::vector<ValueFlow::LifetimeToken> {};
2880
0
                        std::vector<const Token*> args = getArguments(tok->previous());
2881
                        // TODO: Track lifetimes of default parameters
2882
0
                        if (n >= args.size())
2883
0
                            return std::vector<ValueFlow::LifetimeToken> {};
2884
0
                        argTok = args[n];
2885
0
                        lt.errorPath.emplace_back(returnTok, "Return reference.");
2886
0
                        lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
2887
0
                    } else if (match16(tok->tokAt(-2)) && !derefShared(tok->tokAt(-2)) &&
2888
0
                               exprDependsOnThis(argvarTok)) {
2889
0
                        argTok = tok->tokAt(-2)->astOperand1();
2890
0
                        lt.errorPath.emplace_back(returnTok, "Return reference that depends on 'this'.");
2891
0
                        lt.errorPath.emplace_back(tok->previous(),
2892
0
                                                  "Calling member function on '" + argTok->expressionString() + "'.");
2893
0
                    }
2894
0
                    if (argTok) {
2895
0
                        std::vector<ValueFlow::LifetimeToken> arglts = ValueFlow::LifetimeToken::setInconclusive(
2896
0
                            getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, settings, depth - returns.size()),
2897
0
                            returns.size() > 1);
2898
0
                        result.insert(result.end(), arglts.cbegin(), arglts.cend());
2899
0
                    }
2900
0
                }
2901
0
            }
2902
0
            return result;
2903
0
        }
2904
0
        if (match16(tok->tokAt(-2)) && tok->tokAt(-2)->originalName() != MatchCompiler::makeConstString("->") && astIsContainer(tok->tokAt(-2)->astOperand1())) {
2905
0
            const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1());
2906
0
            const Library::Container::Yield y = library->getYield(tok->strAt(-1));
2907
0
            if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {
2908
0
                errorPath.emplace_back(tok->previous(), "Accessing container.");
2909
0
                return ValueFlow::LifetimeToken::setAddressOf(
2910
0
                    getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, settings, depth - 1),
2911
0
                    false);
2912
0
            }
2913
0
        }
2914
0
    } else if (match39(tok) || tok->isUnaryOp("*")) {
2915
2916
0
        const Token *vartok = tok;
2917
0
        while (vartok) {
2918
0
            if (vartok->str() == MatchCompiler::makeConstString("[") || vartok->isUnaryOp("*"))
2919
0
                vartok = vartok->astOperand1();
2920
0
            else if (vartok->str() == MatchCompiler::makeConstString(".")) {
2921
0
                if (!match40(vartok->astOperand1()) &&
2922
0
                    !(vartok->astOperand2() && vartok->astOperand2()->valueType() && vartok->astOperand2()->valueType()->reference != Reference::None))
2923
0
                    vartok = vartok->astOperand1();
2924
0
                else
2925
0
                    break;
2926
0
            }
2927
0
            else if (vartok->str() == MatchCompiler::makeConstString("::"))
2928
0
                vartok = vartok->astOperand2();
2929
0
            else
2930
0
                break;
2931
0
        }
2932
2933
0
        if (!vartok)
2934
0
            return {{tok, std::move(errorPath)}};
2935
0
        if (derefShared(vartok->astParent())) {
2936
0
            for (const ValueFlow::Value &v : vartok->values()) {
2937
0
                if (!v.isLocalLifetimeValue())
2938
0
                    continue;
2939
0
                if (v.tokvalue == tok)
2940
0
                    continue;
2941
0
                errorPath.insert(errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
2942
0
                return ValueFlow::LifetimeToken::setAddressOf(
2943
0
                    getLifetimeTokens(v.tokvalue, escape, std::move(errorPath), pred, settings, depth - 1),
2944
0
                    false);
2945
0
            }
2946
0
        } else {
2947
0
            return ValueFlow::LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, settings, depth - 1),
2948
0
                                                          !(astIsContainer(vartok) && match15(vartok->astParent())));
2949
0
        }
2950
0
    } else if (match4(tok) && getArgumentStart(tok) &&
2951
0
               !match41(getArgumentStart(tok)) && getArgumentStart(tok)->valueType()) {
2952
0
        const Token* vartok = getArgumentStart(tok);
2953
0
        auto vts = getParentValueTypes(tok, settings);
2954
0
        auto it = std::find_if(vts.cbegin(), vts.cend(), [&](const ValueType& vt) {
2955
0
            return vt.isTypeEqual(vartok->valueType());
2956
0
        });
Unexecuted instantiation: valueflow.cpp:getLifetimeTokens<ValueFlow::getLifetimeTokens(Token const*, Settings const&, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >)::$_0>(Token const*, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, ValueFlow::getLifetimeTokens(Token const*, Settings const&, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >)::$_0, Settings const&, int)::{lambda(ValueType const&)#1}::operator()(ValueType const&) const
Unexecuted instantiation: valueflow.cpp:getLifetimeTokens<ValueFlow::hasLifetimeToken(Token const*, Token const*, Settings const&)::$_0>(Token const*, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, ValueFlow::hasLifetimeToken(Token const*, Token const*, Settings const&)::$_0, Settings const&, int)::{lambda(ValueType const&)#1}::operator()(ValueType const&) const
2957
0
        if (it != vts.end())
2958
0
            return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, settings, depth - 1);
2959
0
    }
2960
11.2k
    return {{tok, std::move(errorPath)}};
2961
11.2k
}
valueflow.cpp:std::__1::vector<ValueFlow::LifetimeToken, std::__1::allocator<ValueFlow::LifetimeToken> > getLifetimeTokens<ValueFlow::getLifetimeTokens(Token const*, Settings const&, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >)::$_0>(Token const*, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, ValueFlow::getLifetimeTokens(Token const*, Settings const&, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >)::$_0, Settings const&, int)
Line
Count
Source
2814
11.2k
{
2815
11.2k
    if (!tok)
2816
0
        return std::vector<ValueFlow::LifetimeToken> {};
2817
11.2k
    if (match34(tok))
2818
0
        return std::vector<ValueFlow::LifetimeToken>{};
2819
11.2k
    const Variable *var = tok->variable();
2820
11.2k
    if (pred(tok))
2821
0
        return {{tok, std::move(errorPath)}};
2822
11.2k
    if (depth < 0)
2823
0
        return {{tok, std::move(errorPath)}};
2824
11.2k
    if (var && var->declarationId() == tok->varId()) {
2825
11.2k
        if (var->isReference() || var->isRValueReference()) {
2826
0
            const Token * const varDeclEndToken = var->declEndToken();
2827
0
            if (!varDeclEndToken)
2828
0
                return {{tok, true, std::move(errorPath)}};
2829
0
            if (var->isArgument()) {
2830
0
                errorPath.emplace_back(varDeclEndToken, "Passed to reference.");
2831
0
                return {{tok, true, std::move(errorPath)}};
2832
0
            }
2833
0
            if (match35(varDeclEndToken)) {
2834
0
                errorPath.emplace_back(varDeclEndToken, "Assigned to reference.");
2835
0
                const Token *vartok = varDeclEndToken->astOperand2();
2836
0
                const bool temporary = isTemporary(vartok, nullptr, true);
2837
0
                const bool nonlocal = var->isStatic() || var->isGlobal();
2838
0
                if (vartok == tok || (nonlocal && temporary) ||
2839
0
                    (!escape && (var->isConst() || var->isRValueReference()) && temporary))
2840
0
                    return {{tok, true, std::move(errorPath)}};
2841
0
                if (vartok)
2842
0
                    return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, settings, depth - 1);
2843
0
            } else if (match36(var->nameToken()->astParent()) &&
2844
0
                       var->nameToken()->astParent()->astParent() &&
2845
0
                       match37(var->nameToken()->astParent()->astParent()->previous())) {
2846
0
                errorPath.emplace_back(var->nameToken(), "Assigned to reference.");
2847
0
                const Token* vartok = var->nameToken();
2848
0
                if (vartok == tok)
2849
0
                    return {{tok, true, std::move(errorPath)}};
2850
0
                const Token* contok = var->nameToken()->astParent()->astOperand2();
2851
0
                if (astIsContainer(contok))
2852
0
                    return ValueFlow::LifetimeToken::setAddressOf(
2853
0
                        getLifetimeTokens(contok, escape, std::move(errorPath), pred, settings, depth - 1),
2854
0
                        false);
2855
0
                return std::vector<ValueFlow::LifetimeToken>{};
2856
0
            } else {
2857
0
                return std::vector<ValueFlow::LifetimeToken> {};
2858
0
            }
2859
0
        }
2860
11.2k
    } else if (match38(tok->previous())) {
2861
0
        const Function *f = tok->previous()->function();
2862
0
        if (f) {
2863
0
            if (!Function::returnsReference(f))
2864
0
                return {{tok, std::move(errorPath)}};
2865
0
            std::vector<ValueFlow::LifetimeToken> result;
2866
0
            std::vector<const Token*> returns = Function::findReturns(f);
2867
0
            for (const Token* returnTok : returns) {
2868
0
                if (returnTok == tok)
2869
0
                    continue;
2870
0
                for (ValueFlow::LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, settings, depth - returns.size())) {
2871
0
                    const Token* argvarTok = lt.token;
2872
0
                    const Variable* argvar = argvarTok->variable();
2873
0
                    if (!argvar)
2874
0
                        continue;
2875
0
                    const Token* argTok = nullptr;
2876
0
                    if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
2877
0
                        const int n = getArgumentPos(argvar, f);
2878
0
                        if (n < 0)
2879
0
                            return std::vector<ValueFlow::LifetimeToken> {};
2880
0
                        std::vector<const Token*> args = getArguments(tok->previous());
2881
                        // TODO: Track lifetimes of default parameters
2882
0
                        if (n >= args.size())
2883
0
                            return std::vector<ValueFlow::LifetimeToken> {};
2884
0
                        argTok = args[n];
2885
0
                        lt.errorPath.emplace_back(returnTok, "Return reference.");
2886
0
                        lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
2887
0
                    } else if (match16(tok->tokAt(-2)) && !derefShared(tok->tokAt(-2)) &&
2888
0
                               exprDependsOnThis(argvarTok)) {
2889
0
                        argTok = tok->tokAt(-2)->astOperand1();
2890
0
                        lt.errorPath.emplace_back(returnTok, "Return reference that depends on 'this'.");
2891
0
                        lt.errorPath.emplace_back(tok->previous(),
2892
0
                                                  "Calling member function on '" + argTok->expressionString() + "'.");
2893
0
                    }
2894
0
                    if (argTok) {
2895
0
                        std::vector<ValueFlow::LifetimeToken> arglts = ValueFlow::LifetimeToken::setInconclusive(
2896
0
                            getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, settings, depth - returns.size()),
2897
0
                            returns.size() > 1);
2898
0
                        result.insert(result.end(), arglts.cbegin(), arglts.cend());
2899
0
                    }
2900
0
                }
2901
0
            }
2902
0
            return result;
2903
0
        }
2904
0
        if (match16(tok->tokAt(-2)) && tok->tokAt(-2)->originalName() != MatchCompiler::makeConstString("->") && astIsContainer(tok->tokAt(-2)->astOperand1())) {
2905
0
            const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1());
2906
0
            const Library::Container::Yield y = library->getYield(tok->strAt(-1));
2907
0
            if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {
2908
0
                errorPath.emplace_back(tok->previous(), "Accessing container.");
2909
0
                return ValueFlow::LifetimeToken::setAddressOf(
2910
0
                    getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, settings, depth - 1),
2911
0
                    false);
2912
0
            }
2913
0
        }
2914
0
    } else if (match39(tok) || tok->isUnaryOp("*")) {
2915
2916
0
        const Token *vartok = tok;
2917
0
        while (vartok) {
2918
0
            if (vartok->str() == MatchCompiler::makeConstString("[") || vartok->isUnaryOp("*"))
2919
0
                vartok = vartok->astOperand1();
2920
0
            else if (vartok->str() == MatchCompiler::makeConstString(".")) {
2921
0
                if (!match40(vartok->astOperand1()) &&
2922
0
                    !(vartok->astOperand2() && vartok->astOperand2()->valueType() && vartok->astOperand2()->valueType()->reference != Reference::None))
2923
0
                    vartok = vartok->astOperand1();
2924
0
                else
2925
0
                    break;
2926
0
            }
2927
0
            else if (vartok->str() == MatchCompiler::makeConstString("::"))
2928
0
                vartok = vartok->astOperand2();
2929
0
            else
2930
0
                break;
2931
0
        }
2932
2933
0
        if (!vartok)
2934
0
            return {{tok, std::move(errorPath)}};
2935
0
        if (derefShared(vartok->astParent())) {
2936
0
            for (const ValueFlow::Value &v : vartok->values()) {
2937
0
                if (!v.isLocalLifetimeValue())
2938
0
                    continue;
2939
0
                if (v.tokvalue == tok)
2940
0
                    continue;
2941
0
                errorPath.insert(errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
2942
0
                return ValueFlow::LifetimeToken::setAddressOf(
2943
0
                    getLifetimeTokens(v.tokvalue, escape, std::move(errorPath), pred, settings, depth - 1),
2944
0
                    false);
2945
0
            }
2946
0
        } else {
2947
0
            return ValueFlow::LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, settings, depth - 1),
2948
0
                                                          !(astIsContainer(vartok) && match15(vartok->astParent())));
2949
0
        }
2950
0
    } else if (match4(tok) && getArgumentStart(tok) &&
2951
0
               !match41(getArgumentStart(tok)) && getArgumentStart(tok)->valueType()) {
2952
0
        const Token* vartok = getArgumentStart(tok);
2953
0
        auto vts = getParentValueTypes(tok, settings);
2954
0
        auto it = std::find_if(vts.cbegin(), vts.cend(), [&](const ValueType& vt) {
2955
0
            return vt.isTypeEqual(vartok->valueType());
2956
0
        });
2957
0
        if (it != vts.end())
2958
0
            return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, settings, depth - 1);
2959
0
    }
2960
11.2k
    return {{tok, std::move(errorPath)}};
2961
11.2k
}
Unexecuted instantiation: valueflow.cpp:std::__1::vector<ValueFlow::LifetimeToken, std::__1::allocator<ValueFlow::LifetimeToken> > getLifetimeTokens<ValueFlow::hasLifetimeToken(Token const*, Token const*, Settings const&)::$_0>(Token const*, bool, std::__1::list<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<Token const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, ValueFlow::hasLifetimeToken(Token const*, Token const*, Settings const&)::$_0, Settings const&, int)
2962
2963
std::vector<ValueFlow::LifetimeToken> ValueFlow::getLifetimeTokens(const Token* tok, const Settings& settings, bool escape, ErrorPath errorPath)
2964
11.2k
{
2965
11.2k
    return getLifetimeTokens(tok, escape, std::move(errorPath), [](const Token*) {
2966
11.2k
        return false;
2967
11.2k
    }, settings);
2968
11.2k
}
2969
2970
bool ValueFlow::hasLifetimeToken(const Token* tok, const Token* lifetime, const Settings& settings)
2971
0
{
2972
0
    bool result = false;
2973
0
    getLifetimeTokens(tok, false, ErrorPath{}, [&](const Token* tok2) {
2974
0
        result = tok2->exprId() == lifetime->exprId();
2975
0
        return result;
2976
0
    }, settings);
2977
0
    return result;
2978
0
}
2979
2980
static const Token* getLifetimeToken(const Token* tok, ErrorPath& errorPath, const Settings& settings, bool* addressOf = nullptr)
2981
11.2k
{
2982
11.2k
    std::vector<ValueFlow::LifetimeToken> lts = ValueFlow::getLifetimeTokens(tok, settings);
2983
11.2k
    if (lts.size() != 1)
2984
0
        return nullptr;
2985
11.2k
    if (lts.front().inconclusive)
2986
0
        return nullptr;
2987
11.2k
    if (addressOf)
2988
0
        *addressOf = lts.front().addressOf;
2989
11.2k
    errorPath.insert(errorPath.end(), lts.front().errorPath.cbegin(), lts.front().errorPath.cend());
2990
11.2k
    return lts.front().token;
2991
11.2k
}
2992
2993
const Variable* ValueFlow::getLifetimeVariable(const Token* tok, ErrorPath& errorPath, const Settings& settings, bool* addressOf)
2994
11.2k
{
2995
11.2k
    const Token* tok2 = getLifetimeToken(tok, errorPath, settings, addressOf);
2996
11.2k
    if (tok2 && tok2->variable())
2997
11.2k
        return tok2->variable();
2998
0
    return nullptr;
2999
11.2k
}
3000
3001
const Variable* ValueFlow::getLifetimeVariable(const Token* tok, const Settings& settings)
3002
0
{
3003
0
    ErrorPath errorPath;
3004
0
    return getLifetimeVariable(tok, errorPath, settings, nullptr);
3005
0
}
3006
3007
static bool isNotLifetimeValue(const ValueFlow::Value& val)
3008
0
{
3009
0
    return !val.isLifetimeValue();
3010
0
}
3011
3012
static bool isLifetimeOwned(const ValueType* vtParent)
3013
2
{
3014
2
    if (vtParent->container)
3015
0
        return !vtParent->container->view;
3016
2
    return vtParent->type == ValueType::CONTAINER;
3017
2
}
3018
3019
static bool isLifetimeOwned(const ValueType *vt, const ValueType *vtParent)
3020
1
{
3021
1
    if (!vtParent)
3022
0
        return false;
3023
1
    if (isLifetimeOwned(vtParent))
3024
0
        return true;
3025
1
    if (!vt)
3026
0
        return false;
3027
    // If converted from iterator to pointer then the iterator is most likely a pointer
3028
1
    if (vtParent->pointer == 1 && vt->pointer == 0 && vt->type == ValueType::ITERATOR)
3029
0
        return false;
3030
1
    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE) {
3031
1
        if (vt->pointer != vtParent->pointer)
3032
0
            return true;
3033
1
        if (vt->type != vtParent->type) {
3034
1
            if (vtParent->type == ValueType::RECORD)
3035
0
                return true;
3036
1
            if (isLifetimeOwned(vtParent))
3037
0
                return true;
3038
1
        }
3039
1
    }
3040
3041
1
    return false;
3042
1
}
3043
3044
static bool isLifetimeBorrowed(const ValueType *vt, const ValueType *vtParent)
3045
4
{
3046
4
    if (!vtParent)
3047
0
        return false;
3048
4
    if (!vt)
3049
0
        return false;
3050
4
    if (vt->pointer > 0 && vt->pointer == vtParent->pointer)
3051
0
        return true;
3052
4
    if (vtParent->container && vtParent->container->view)
3053
0
        return true;
3054
4
    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE && vtParent->container == vt->container) {
3055
4
        if (vtParent->pointer > vt->pointer)
3056
0
            return true;
3057
4
        if (vtParent->pointer < vt->pointer && vtParent->isIntegral())
3058
2
            return true;
3059
2
        if (vtParent->str() == vt->str())
3060
1
            return true;
3061
2
    }
3062
3063
1
    return false;
3064
4
}
3065
3066
static const Token* skipCVRefs(const Token* tok, const Token* endTok)
3067
0
{
3068
0
    while (tok != endTok && match42(tok))
3069
0
        tok = tok->next();
3070
0
    return tok;
3071
0
}
3072
3073
static bool isNotEqual(std::pair<const Token*, const Token*> x, std::pair<const Token*, const Token*> y)
3074
1.73k
{
3075
1.73k
    const Token* start1 = x.first;
3076
1.73k
    const Token* start2 = y.first;
3077
1.73k
    if (start1 == nullptr || start2 == nullptr)
3078
1.73k
        return false;
3079
0
    while (start1 != x.second && start2 != y.second) {
3080
0
        const Token* tok1 = skipCVRefs(start1, x.second);
3081
0
        if (tok1 != start1) {
3082
0
            start1 = tok1;
3083
0
            continue;
3084
0
        }
3085
0
        const Token* tok2 = skipCVRefs(start2, y.second);
3086
0
        if (tok2 != start2) {
3087
0
            start2 = tok2;
3088
0
            continue;
3089
0
        }
3090
0
        if (start1->str() != start2->str())
3091
0
            return true;
3092
0
        start1 = start1->next();
3093
0
        start2 = start2->next();
3094
0
    }
3095
0
    start1 = skipCVRefs(start1, x.second);
3096
0
    start2 = skipCVRefs(start2, y.second);
3097
0
    return !(start1 == x.second && start2 == y.second);
3098
0
}
3099
static bool isNotEqual(std::pair<const Token*, const Token*> x, const std::string& y, bool cpp)
3100
0
{
3101
0
    TokenList tokenList(nullptr);
3102
0
    std::istringstream istr(y);
3103
0
    tokenList.createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C); // TODO: check result?
3104
0
    return isNotEqual(x, std::make_pair(tokenList.front(), tokenList.back()));
3105
0
}
3106
static bool isNotEqual(std::pair<const Token*, const Token*> x, const ValueType* y, bool cpp)
3107
3.46k
{
3108
3.46k
    if (y == nullptr)
3109
1.89k
        return false;
3110
1.57k
    if (y->originalTypeName.empty())
3111
1.57k
        return false;
3112
0
    return isNotEqual(x, y->originalTypeName, cpp);
3113
1.57k
}
3114
3115
static bool isDifferentType(const Token* src, const Token* dst)
3116
1.73k
{
3117
1.73k
    const Type* t = Token::typeOf(src);
3118
1.73k
    const Type* parentT = Token::typeOf(dst);
3119
1.73k
    if (t && parentT) {
3120
0
        if (t->classDef && parentT->classDef && t->classDef != parentT->classDef)
3121
0
            return true;
3122
1.73k
    } else {
3123
1.73k
        std::pair<const Token*, const Token*> decl = Token::typeDecl(src);
3124
1.73k
        std::pair<const Token*, const Token*> parentdecl = Token::typeDecl(dst);
3125
1.73k
        const bool isCpp = (src && src->isCpp()) || (dst && dst->isCpp());
3126
1.73k
        if (isNotEqual(decl, parentdecl) && !(isCpp && (match43(decl.first) || match43(parentdecl.first))))
3127
0
            return true;
3128
1.73k
        if (isNotEqual(decl, dst->valueType(), isCpp))
3129
0
            return true;
3130
1.73k
        if (isNotEqual(parentdecl, src->valueType(), isCpp))
3131
0
            return true;
3132
1.73k
    }
3133
1.73k
    return false;
3134
1.73k
}
3135
3136
bool ValueFlow::isLifetimeBorrowed(const Token *tok, const Settings &settings)
3137
6
{
3138
6
    if (!tok)
3139
0
        return true;
3140
6
    if (tok->str() == MatchCompiler::makeConstString(","))
3141
0
        return true;
3142
6
    if (!tok->astParent())
3143
0
        return true;
3144
6
    const Token* parent = nullptr;
3145
6
    const ValueType* vt = tok->valueType();
3146
6
    std::vector<ValueType> vtParents = getParentValueTypes(tok, settings, &parent);
3147
6
    for (const ValueType& vtParent : vtParents) {
3148
4
        if (isLifetimeBorrowed(vt, &vtParent))
3149
3
            return true;
3150
1
        if (isLifetimeOwned(vt, &vtParent))
3151
0
            return false;
3152
1
    }
3153
3
    if (parent) {
3154
1
        if (isDifferentType(tok, parent))
3155
0
            return false;
3156
1
    }
3157
3
    return true;
3158
3
}
3159
3160
static void valueFlowLifetimeFunction(Token *tok, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings);
3161
3162
static void valueFlowLifetimeConstructor(Token *tok,
3163
                                         const TokenList &tokenlist,
3164
                                         ErrorLogger &errorLogger,
3165
                                         const Settings &settings);
3166
3167
static bool isRangeForScope(const Scope* scope)
3168
0
{
3169
0
    if (!scope)
3170
0
        return false;
3171
0
    if (scope->type != Scope::eFor)
3172
0
        return false;
3173
0
    if (!scope->bodyStart)
3174
0
        return false;
3175
0
    if (!match44(scope->bodyStart->previous()))
3176
0
        return false;
3177
0
    return match36(scope->bodyStart->linkAt(-1)->astOperand2());
3178
0
}
3179
3180
static const Token* getEndOfVarScope(const Variable* var)
3181
0
{
3182
0
    if (!var)
3183
0
        return nullptr;
3184
0
    const Scope* innerScope = var->scope();
3185
0
    const Scope* outerScope = innerScope;
3186
0
    if (var->typeStartToken() && var->typeStartToken()->scope())
3187
0
        outerScope = var->typeStartToken()->scope();
3188
0
    if (!innerScope && outerScope)
3189
0
        innerScope = outerScope;
3190
0
    if (!innerScope || !outerScope)
3191
0
        return nullptr;
3192
0
    if (!innerScope->isExecutable())
3193
0
        return nullptr;
3194
    // If the variable is defined in a for/while initializer then we want to
3195
    // pick one token after the end so forward analysis can analyze the exit
3196
    // conditions
3197
0
    if (innerScope != outerScope && outerScope->isExecutable() && innerScope->isLoopScope() &&
3198
0
        !isRangeForScope(innerScope))
3199
0
        return innerScope->bodyEnd->next();
3200
0
    return innerScope->bodyEnd;
3201
0
}
3202
3203
const Token* ValueFlow::getEndOfExprScope(const Token* tok, const Scope* defaultScope, bool smallest)
3204
2.86k
{
3205
2.86k
    const Token* end = nullptr;
3206
2.86k
    bool local = false;
3207
2.93k
    visitAstNodes(tok, [&](const Token* child) {
3208
2.93k
        if (const Variable* var = child->variable()) {
3209
483
            local |= var->isLocal();
3210
483
            if (var->isLocal() || var->isArgument()) {
3211
0
                const Token* varEnd = getEndOfVarScope(var);
3212
0
                if (!end || (smallest ? precedes(varEnd, end) : succeeds(varEnd, end)))
3213
0
                    end = varEnd;
3214
3215
0
                const Token* top = var->nameToken()->astTop();
3216
0
                if (match45(top->tokAt(-1))) { // variable declared in if (...)
3217
0
                    const Token* elseTok = top->link()->linkAt(1);
3218
0
                    if (match46(elseTok) && tok->scope()->isNestedIn(elseTok->tokAt(2)->scope()))
3219
0
                        end = tok->scope()->bodyEnd;
3220
0
                }
3221
0
            }
3222
483
        }
3223
2.93k
        return ChildrenToVisit::op1_and_op2;
3224
2.93k
    });
3225
2.86k
    if (!end && defaultScope)
3226
2.43k
        end = defaultScope->bodyEnd;
3227
2.86k
    if (!end) {
3228
425
        const Scope* scope = tok->scope();
3229
425
        if (scope)
3230
425
            end = scope->bodyEnd;
3231
        // If there is no local variables then pick the function scope
3232
425
        if (!local) {
3233
654
            while (scope && scope->isLocal())
3234
229
                scope = scope->nestedIn;
3235
425
            if (scope && scope->isExecutable())
3236
425
                end = scope->bodyEnd;
3237
425
        }
3238
425
    }
3239
2.86k
    return end;
3240
2.86k
}
3241
3242
static void valueFlowForwardLifetime(Token * tok, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings)
3243
205
{
3244
    // Forward lifetimes to constructed variable
3245
205
    if (match47(tok->previous()) && isVariableDecl(tok->previous())) {
3246
0
        std::list<ValueFlow::Value> values = tok->values();
3247
0
        values.remove_if(&isNotLifetimeValue);
3248
0
        valueFlowForward(nextAfterAstRightmostLeaf(tok), ValueFlow::getEndOfExprScope(tok), tok->previous(), std::move(values), tokenlist, errorLogger, settings);
3249
0
        return;
3250
0
    }
3251
205
    Token *parent = tok->astParent();
3252
205
    while (parent && parent->str() == MatchCompiler::makeConstString(","))
3253
0
        parent = parent->astParent();
3254
205
    if (!parent)
3255
187
        return;
3256
    // Assignment
3257
18
    if (parent->str() == MatchCompiler::makeConstString("=") && (!parent->astParent() || match33(parent->astParent()))) {
3258
        // Rhs values..
3259
0
        if (!parent->astOperand2() || parent->astOperand2()->values().empty())
3260
0
            return;
3261
3262
0
        if (!ValueFlow::isLifetimeBorrowed(parent->astOperand2(), settings))
3263
0
            return;
3264
3265
0
        const Token* expr = getLHSVariableToken(parent);
3266
0
        if (!expr)
3267
0
            return;
3268
3269
0
        if (expr->exprId() == 0)
3270
0
            return;
3271
3272
0
        const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
3273
3274
        // Only forward lifetime values
3275
0
        std::list<ValueFlow::Value> values = parent->astOperand2()->values();
3276
0
        values.remove_if(&isNotLifetimeValue);
3277
        // Dont forward lifetimes that overlap
3278
0
        values.remove_if([&](const ValueFlow::Value& value) {
3279
0
            return findAstNode(value.tokvalue, [&](const Token* child) {
3280
0
                return child->exprId() == expr->exprId();
3281
0
            });
3282
0
        });
3283
3284
        // Skip RHS
3285
0
        Token* nextExpression = nextAfterAstRightmostLeaf(parent);
3286
3287
0
        if (expr->exprId() > 0) {
3288
0
            valueFlowForward(nextExpression, endOfVarScope->next(), expr, values, tokenlist, errorLogger, settings);
3289
3290
0
            for (ValueFlow::Value& val : values) {
3291
0
                if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address)
3292
0
                    val.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject;
3293
0
            }
3294
            // TODO: handle `[`
3295
0
            if (match40(parent->astOperand1())) {
3296
0
                const Token* parentLifetime =
3297
0
                    getParentLifetime(parent->astOperand1()->astOperand2(), settings.library);
3298
0
                if (parentLifetime && parentLifetime->exprId() > 0) {
3299
0
                    valueFlowForward(nextExpression, endOfVarScope, parentLifetime, std::move(values), tokenlist, errorLogger, settings);
3300
0
                }
3301
0
            }
3302
0
        }
3303
        // Constructor
3304
18
    } else if (match4(parent) && !isScopeBracket(parent)) {
3305
0
        valueFlowLifetimeConstructor(parent, tokenlist, errorLogger, settings);
3306
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
3307
        // Function call
3308
18
    } else if (match38(parent->previous())) {
3309
0
        valueFlowLifetimeFunction(parent->previous(), tokenlist, errorLogger, settings);
3310
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
3311
        // Variable
3312
18
    } else if (tok->variable() && tok->variable()->scope()) {
3313
0
        const Variable *var = tok->variable();
3314
0
        const Token *endOfVarScope = var->scope()->bodyEnd;
3315
3316
0
        std::list<ValueFlow::Value> values = tok->values();
3317
0
        Token *nextExpression = nextAfterAstRightmostLeaf(parent);
3318
        // Only forward lifetime values
3319
0
        values.remove_if(&isNotLifetimeValue);
3320
0
        valueFlowForward(nextExpression, endOfVarScope, tok, std::move(values), tokenlist, errorLogger, settings);
3321
        // Cast
3322
18
    } else if (parent->isCast()) {
3323
0
        std::list<ValueFlow::Value> values = tok->values();
3324
        // Only forward lifetime values
3325
0
        values.remove_if(&isNotLifetimeValue);
3326
0
        for (ValueFlow::Value& value:values)
3327
0
            setTokenValue(parent, std::move(value), settings);
3328
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
3329
0
    }
3330
18
}
3331
3332
struct LifetimeStore {
3333
    const Token* argtok{};
3334
    std::string message;
3335
    ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object;
3336
    ErrorPath errorPath;
3337
    bool inconclusive{};
3338
    bool forward = true;
3339
3340
0
    LifetimeStore() = default;
3341
3342
    LifetimeStore(const Token* argtok,
3343
                  std::string message,
3344
                  ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object,
3345
                  bool inconclusive = false)
3346
0
        : argtok(argtok),
3347
0
        message(std::move(message)),
3348
0
        type(type),
3349
0
        inconclusive(inconclusive)
3350
0
    {}
3351
3352
    template<class F>
3353
    static void forEach(const TokenList& tokenlist,
3354
                        ErrorLogger& errorLogger,
3355
                        const Settings& settings,
3356
                        const std::vector<const Token*>& argtoks,
3357
                        const std::string& message,
3358
                        ValueFlow::Value::LifetimeKind type,
3359
0
                        F f) {
3360
0
        std::set<Token*> forwardToks;
3361
0
        for (const Token* arg : argtoks) {
3362
0
            LifetimeStore ls{arg, message, type};
3363
0
            ls.forward = false;
3364
0
            f(ls);
3365
0
            if (ls.forwardTok)
3366
0
                forwardToks.emplace(ls.forwardTok);
3367
0
        }
3368
0
        for (auto* tok : forwardToks) {
3369
0
            valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
3370
0
        }
3371
0
    }
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeConstructor(Token*, TokenList const&, ErrorLogger&, Settings const&)::$_0>(TokenList const&, ErrorLogger&, Settings const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value::LifetimeKind, valueFlowLifetimeConstructor(Token*, TokenList const&, ErrorLogger&, Settings const&)::$_0)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeConstructor(Token*, TokenList const&, ErrorLogger&, Settings const&)::$_1>(TokenList const&, ErrorLogger&, Settings const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value::LifetimeKind, valueFlowLifetimeConstructor(Token*, TokenList const&, ErrorLogger&, Settings const&)::$_1)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeConstructor(Token*, TokenList const&, ErrorLogger&, Settings const&)::$_2>(TokenList const&, ErrorLogger&, Settings const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value::LifetimeKind, valueFlowLifetimeConstructor(Token*, TokenList const&, ErrorLogger&, Settings const&)::$_2)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeClassConstructor(Token*, Type const*, TokenList const&, ErrorLogger&, Settings const&)::$_0>(TokenList const&, ErrorLogger&, Settings const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value::LifetimeKind, valueFlowLifetimeClassConstructor(Token*, Type const*, TokenList const&, ErrorLogger&, Settings const&)::$_0)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeClassConstructor(Token*, Type const*, TokenList const&, ErrorLogger&, Settings const&)::$_1>(TokenList const&, ErrorLogger&, Settings const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value::LifetimeKind, valueFlowLifetimeClassConstructor(Token*, Type const*, TokenList const&, ErrorLogger&, Settings const&)::$_1)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeUserConstructor(Token*, Function const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, TokenList const&, ErrorLogger&, Settings const&)::$_0>(TokenList const&, ErrorLogger&, Settings const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value::LifetimeKind, valueFlowLifetimeUserConstructor(Token*, Function const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, TokenList const&, ErrorLogger&, Settings const&)::$_0)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeUserConstructor(Token*, Function const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, TokenList const&, ErrorLogger&, Settings const&)::$_1>(TokenList const&, ErrorLogger&, Settings const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value::LifetimeKind, valueFlowLifetimeUserConstructor(Token*, Function const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, TokenList const&, ErrorLogger&, Settings const&)::$_1)
3372
3373
0
    static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, const TokenList &tokenlist, const Settings& settings, ErrorLogger &errorLogger) {
3374
0
        if (!var)
3375
0
            return LifetimeStore{};
3376
0
        if (!var->isArgument())
3377
0
            return LifetimeStore{};
3378
0
        const int n = getArgumentPos(var, f);
3379
0
        if (n < 0)
3380
0
            return LifetimeStore{};
3381
0
        std::vector<const Token *> args = getArguments(tok);
3382
0
        if (n >= args.size()) {
3383
0
            if (settings.debugwarnings)
3384
0
                bailout(tokenlist,
3385
0
                        errorLogger,
3386
0
                        tok,
3387
0
                        "Argument mismatch: Function '" + tok->str() + "' returning lifetime from argument index " +
3388
0
                        std::to_string(n) + " but only " + std::to_string(args.size()) +
3389
0
                        " arguments are available.");
3390
0
            return LifetimeStore{};
3391
0
        }
3392
0
        const Token *argtok2 = args[n];
3393
0
        return LifetimeStore{argtok2, "Passed to '" + tok->expressionString() + "'.", ValueFlow::Value::LifetimeKind::Object};
3394
0
    }
3395
3396
    template<class Predicate>
3397
    bool byRef(Token* tok,
3398
               const TokenList& tokenlist,
3399
               ErrorLogger& errorLogger,
3400
               const Settings& settings,
3401
               const Predicate& pred,
3402
               SourceLocation loc = SourceLocation::current())
3403
0
    {
3404
0
        if (!argtok)
3405
0
            return false;
3406
0
        bool update = false;
3407
0
        for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok, settings)) {
3408
0
            if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
3409
0
                continue;
3410
0
            if (!lt.token)
3411
0
                return false;
3412
0
            if (!pred(lt.token))
3413
0
                return false;
3414
0
            ErrorPath er = errorPath;
3415
0
            er.insert(er.end(), lt.errorPath.cbegin(), lt.errorPath.cend());
3416
0
            er.emplace_back(argtok, message);
3417
3418
0
            ValueFlow::Value value;
3419
0
            value.valueType = ValueFlow::Value::ValueType::LIFETIME;
3420
0
            value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
3421
0
            value.tokvalue = lt.token;
3422
0
            value.errorPath = std::move(er);
3423
0
            value.lifetimeKind = type;
3424
0
            value.setInconclusive(lt.inconclusive || inconclusive);
3425
            // Don't add the value a second time
3426
0
            if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
3427
0
                return false;
3428
0
            if (settings.debugnormal)
3429
0
                setSourceLocation(value, loc, tok);
3430
0
            setTokenValue(tok, std::move(value), settings);
3431
0
            update = true;
3432
0
        }
3433
0
        if (update && forward)
3434
0
            forwardLifetime(tok, tokenlist, errorLogger, settings);
3435
0
        return update;
3436
0
    }
Unexecuted instantiation: bool LifetimeStore::byRef<std::__1::function<bool (Token const*)> >(Token*, TokenList const&, ErrorLogger&, Settings const&, std::__1::function<bool (Token const*)> const&, SourceLocation)
Unexecuted instantiation: bool LifetimeStore::byRef<LifetimeStore::byRef(Token*, TokenList const&, ErrorLogger&, Settings const&, SourceLocation)::{lambda(Token const*)#1}>(Token*, TokenList const&, ErrorLogger&, Settings const&, LifetimeStore::byRef(Token*, TokenList const&, ErrorLogger&, Settings const&, SourceLocation)::{lambda(Token const*)#1} const&, SourceLocation)
3437
3438
    bool byRef(Token* tok,
3439
               const TokenList& tokenlist,
3440
               ErrorLogger& errorLogger,
3441
               const Settings& settings,
3442
               SourceLocation loc = SourceLocation::current())
3443
0
    {
3444
0
        return byRef(
3445
0
            tok,
3446
0
            tokenlist,
3447
0
            errorLogger,
3448
0
            settings,
3449
0
            [](const Token*) {
3450
0
            return true;
3451
0
        },
3452
0
            loc);
3453
0
    }
3454
3455
    template<class Predicate>
3456
    bool byVal(Token* tok,
3457
               const TokenList& tokenlist,
3458
               ErrorLogger& errorLogger,
3459
               const Settings& settings,
3460
               const Predicate& pred,
3461
               SourceLocation loc = SourceLocation::current())
3462
0
    {
3463
0
        if (!argtok)
3464
0
            return false;
3465
0
        bool update = false;
3466
0
        if (argtok->values().empty()) {
3467
0
            ErrorPath er;
3468
0
            er.emplace_back(argtok, message);
3469
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok, settings)) {
3470
0
                if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
3471
0
                    continue;
3472
0
                ValueFlow::Value value;
3473
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
3474
0
                value.tokvalue = lt.token;
3475
0
                value.capturetok = argtok;
3476
0
                value.errorPath = er;
3477
0
                value.lifetimeKind = type;
3478
0
                value.setInconclusive(inconclusive || lt.inconclusive);
3479
0
                const Variable* var = lt.token->variable();
3480
0
                if (var && var->isArgument()) {
3481
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::Argument;
3482
0
                } else {
3483
0
                    continue;
3484
0
                }
3485
                // Don't add the value a second time
3486
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
3487
0
                    continue;
3488
0
                if (settings.debugnormal)
3489
0
                    setSourceLocation(value, loc, tok);
3490
0
                setTokenValue(tok, std::move(value), settings);
3491
0
                update = true;
3492
0
            }
3493
0
        }
3494
0
        for (const ValueFlow::Value &v : argtok->values()) {
3495
0
            if (!v.isLifetimeValue())
3496
0
                continue;
3497
0
            const Token *tok3 = v.tokvalue;
3498
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok3, settings)) {
3499
0
                if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
3500
0
                    continue;
3501
0
                ErrorPath er = v.errorPath;
3502
0
                er.insert(er.end(), lt.errorPath.cbegin(), lt.errorPath.cend());
3503
0
                if (!lt.token)
3504
0
                    return false;
3505
0
                if (!pred(lt.token))
3506
0
                    return false;
3507
0
                er.emplace_back(argtok, message);
3508
0
                er.insert(er.end(), errorPath.cbegin(), errorPath.cend());
3509
3510
0
                ValueFlow::Value value;
3511
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
3512
0
                value.lifetimeScope = v.lifetimeScope;
3513
0
                value.path = v.path;
3514
0
                value.tokvalue = lt.token;
3515
0
                value.capturetok = argtok;
3516
0
                value.errorPath = std::move(er);
3517
0
                value.lifetimeKind = type;
3518
0
                value.setInconclusive(lt.inconclusive || v.isInconclusive() || inconclusive);
3519
                // Don't add the value a second time
3520
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
3521
0
                    continue;
3522
0
                if (settings.debugnormal)
3523
0
                    setSourceLocation(value, loc, tok);
3524
0
                setTokenValue(tok, std::move(value), settings);
3525
0
                update = true;
3526
0
            }
3527
0
        }
3528
0
        if (update && forward)
3529
0
            forwardLifetime(tok, tokenlist, errorLogger, settings);
3530
0
        return update;
3531
0
    }
Unexecuted instantiation: bool LifetimeStore::byVal<std::__1::function<bool (Token const*)> >(Token*, TokenList const&, ErrorLogger&, Settings const&, std::__1::function<bool (Token const*)> const&, SourceLocation)
Unexecuted instantiation: bool LifetimeStore::byVal<LifetimeStore::byVal(Token*, TokenList const&, ErrorLogger&, Settings const&, SourceLocation)::{lambda(Token const*)#1}>(Token*, TokenList const&, ErrorLogger&, Settings const&, LifetimeStore::byVal(Token*, TokenList const&, ErrorLogger&, Settings const&, SourceLocation)::{lambda(Token const*)#1} const&, SourceLocation)
Unexecuted instantiation: bool LifetimeStore::byVal<LifetimeStore::byDerefCopy(Token*, TokenList const&, ErrorLogger&, Settings const&, SourceLocation) const::{lambda(Token const*)#1}>(Token*, TokenList const&, ErrorLogger&, Settings const&, LifetimeStore::byDerefCopy(Token*, TokenList const&, ErrorLogger&, Settings const&, SourceLocation) const::{lambda(Token const*)#1} const&, SourceLocation)
3532
3533
    bool byVal(Token* tok,
3534
               const TokenList& tokenlist,
3535
               ErrorLogger& errorLogger,
3536
               const Settings& settings,
3537
               SourceLocation loc = SourceLocation::current())
3538
0
    {
3539
0
        return byVal(
3540
0
            tok,
3541
0
            tokenlist,
3542
0
            errorLogger,
3543
0
            settings,
3544
0
            [](const Token*) {
3545
0
            return true;
3546
0
        },
3547
0
            loc);
3548
0
    }
3549
3550
    template<class Predicate>
3551
    bool byDerefCopy(Token* tok,
3552
                     const TokenList& tokenlist,
3553
                     ErrorLogger& errorLogger,
3554
                     const Settings& settings,
3555
                     Predicate pred,
3556
                     SourceLocation loc = SourceLocation::current()) const
3557
0
    {
3558
0
        bool update = false;
3559
0
        if (!settings.certainty.isEnabled(Certainty::inconclusive) && inconclusive)
3560
0
            return update;
3561
0
        if (!argtok)
3562
0
            return update;
3563
0
        if (!tok)
3564
0
            return update;
3565
0
        for (const ValueFlow::Value &v : argtok->values()) {
3566
0
            if (!v.isLifetimeValue())
3567
0
                continue;
3568
0
            const Token *tok2 = v.tokvalue;
3569
0
            ErrorPath er = v.errorPath;
3570
0
            const Variable *var = ValueFlow::getLifetimeVariable(tok2, er, settings);
3571
            // TODO: the inserted data is never used
3572
0
            er.insert(er.end(), errorPath.cbegin(), errorPath.cend());
3573
0
            if (!var)
3574
0
                continue;
3575
0
            const Token * const varDeclEndToken = var->declEndToken();
3576
0
            for (const Token *tok3 = tok; tok3 && tok3 != varDeclEndToken; tok3 = tok3->previous()) {
3577
0
                if (tok3->varId() == var->declarationId()) {
3578
0
                    update |= LifetimeStore{tok3, message, type, inconclusive}
3579
0
                    .byVal(tok, tokenlist, errorLogger, settings, pred, loc);
3580
0
                    break;
3581
0
                }
3582
0
            }
3583
0
        }
3584
0
        return update;
3585
0
    }
3586
3587
    bool byDerefCopy(Token* tok,
3588
                     const TokenList& tokenlist,
3589
                     ErrorLogger& errorLogger,
3590
                     const Settings& settings,
3591
                     SourceLocation loc = SourceLocation::current()) const
3592
0
    {
3593
0
        return byDerefCopy(
3594
0
            tok,
3595
0
            tokenlist,
3596
0
            errorLogger,
3597
0
            settings,
3598
0
            [](const Token*) {
3599
0
            return true;
3600
0
        },
3601
0
            loc);
3602
0
    }
3603
3604
private:
3605
    // cppcheck-suppress naming-privateMemberVariable
3606
    Token* forwardTok{};
3607
0
    void forwardLifetime(Token* tok, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) {
3608
0
        forwardTok = tok;
3609
0
        valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
3610
0
    }
3611
};
3612
3613
static bool hasBorrowingVariables(const std::list<Variable>& vars, const std::vector<const Token*>& args, int depth = 10)
3614
0
{
3615
0
    if (depth < 0)
3616
0
        return true;
3617
0
    return std::any_of(vars.cbegin(), vars.cend(), [&](const Variable& var) {
3618
0
        if (const ValueType* vt = var.valueType()) {
3619
0
            if (vt->pointer > 0 &&
3620
0
                std::none_of(args.begin(), args.end(), [vt](const Token* arg) {
3621
0
                return arg->valueType() && arg->valueType()->type == vt->type;
3622
0
            }))
3623
0
                return false;
3624
0
            if (vt->pointer > 0)
3625
0
                return true;
3626
0
            if (vt->reference != Reference::None)
3627
0
                return true;
3628
0
            if (vt->isPrimitive())
3629
0
                return false;
3630
0
            if (vt->isEnum())
3631
0
                return false;
3632
            // TODO: Check container inner type
3633
0
            if (vt->type == ValueType::CONTAINER && vt->container)
3634
0
                return vt->container->view;
3635
0
            if (vt->typeScope)
3636
0
                return hasBorrowingVariables(vt->typeScope->varlist, args, depth - 1);
3637
0
        }
3638
0
        return true;
3639
0
    });
3640
0
}
3641
3642
static void valueFlowLifetimeUserConstructor(Token* tok,
3643
                                             const Function* constructor,
3644
                                             const std::string& name,
3645
                                             const std::vector<const Token*>& args,
3646
                                             const TokenList& tokenlist,
3647
                                             ErrorLogger& errorLogger,
3648
                                             const Settings& settings)
3649
0
{
3650
0
    if (!constructor)
3651
0
        return;
3652
0
    std::unordered_map<const Token*, const Variable*> argToParam;
3653
0
    for (std::size_t i = 0; i < args.size(); i++)
3654
0
        argToParam[args[i]] = constructor->getArgumentVar(i);
3655
0
    if (const Token* initList = constructor->constructorMemberInitialization()) {
3656
0
        std::unordered_map<const Variable*, LifetimeCapture> paramCapture;
3657
0
        for (const Token* tok2 : astFlatten(initList->astOperand2(), ",")) {
3658
0
            if (!match48(tok2))
3659
0
                continue;
3660
0
            if (!tok2->astOperand1())
3661
0
                continue;
3662
0
            if (!tok2->astOperand2())
3663
0
                continue;
3664
0
            const Variable* var = tok2->astOperand1()->variable();
3665
0
            const Token* expr = tok2->astOperand2();
3666
0
            if (!var)
3667
0
                continue;
3668
0
            if (!ValueFlow::isLifetimeBorrowed(expr, settings))
3669
0
                continue;
3670
0
            const Variable* argvar = ValueFlow::getLifetimeVariable(expr, settings);
3671
0
            if (var->isReference() || var->isRValueReference()) {
3672
0
                if (argvar && argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
3673
0
                    paramCapture[argvar] = LifetimeCapture::ByReference;
3674
0
                }
3675
0
            } else {
3676
0
                bool found = false;
3677
0
                for (const ValueFlow::Value& v : expr->values()) {
3678
0
                    if (!v.isLifetimeValue())
3679
0
                        continue;
3680
0
                    if (v.path > 0)
3681
0
                        continue;
3682
0
                    if (!v.tokvalue)
3683
0
                        continue;
3684
0
                    const Variable* lifeVar = v.tokvalue->variable();
3685
0
                    if (!lifeVar)
3686
0
                        continue;
3687
0
                    LifetimeCapture c = LifetimeCapture::Undefined;
3688
0
                    if (!v.isArgumentLifetimeValue() && (lifeVar->isReference() || lifeVar->isRValueReference()))
3689
0
                        c = LifetimeCapture::ByReference;
3690
0
                    else if (v.isArgumentLifetimeValue())
3691
0
                        c = LifetimeCapture::ByValue;
3692
0
                    if (c != LifetimeCapture::Undefined) {
3693
0
                        paramCapture[lifeVar] = c;
3694
0
                        found = true;
3695
0
                    }
3696
0
                }
3697
0
                if (!found && argvar && argvar->isArgument())
3698
0
                    paramCapture[argvar] = LifetimeCapture::ByValue;
3699
0
            }
3700
0
        }
3701
        // TODO: Use SubExpressionAnalyzer for members
3702
0
        LifetimeStore::forEach(tokenlist,
3703
0
                               errorLogger,
3704
0
                               settings,
3705
0
                               args,
3706
0
                               "Passed to constructor of '" + name + "'.",
3707
0
                               ValueFlow::Value::LifetimeKind::SubObject,
3708
0
                               [&](LifetimeStore& ls) {
3709
0
            const Variable* paramVar = argToParam.at(ls.argtok);
3710
0
            if (paramCapture.count(paramVar) == 0)
3711
0
                return;
3712
0
            const LifetimeCapture c = paramCapture.at(paramVar);
3713
0
            if (c == LifetimeCapture::ByReference)
3714
0
                ls.byRef(tok, tokenlist, errorLogger, settings);
3715
0
            else
3716
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
3717
0
        });
3718
0
    } else if (hasBorrowingVariables(constructor->nestedIn->varlist, args)) {
3719
0
        LifetimeStore::forEach(tokenlist,
3720
0
                               errorLogger,
3721
0
                               settings,
3722
0
                               args,
3723
0
                               "Passed to constructor of '" + name + "'.",
3724
0
                               ValueFlow::Value::LifetimeKind::SubObject,
3725
0
                               [&](LifetimeStore& ls) {
3726
0
            ls.inconclusive = true;
3727
0
            const Variable* var = argToParam.at(ls.argtok);
3728
0
            if (var && !var->isConst() && var->isReference())
3729
0
                ls.byRef(tok, tokenlist, errorLogger, settings);
3730
0
            else
3731
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
3732
0
        });
3733
0
    }
3734
0
}
3735
3736
static void valueFlowLifetimeFunction(Token *tok, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings)
3737
187
{
3738
187
    if (!match38(tok))
3739
0
        return;
3740
187
    Token* memtok = nullptr;
3741
187
    if (match16(tok->astParent()) && astIsRHS(tok))
3742
0
        memtok = tok->astParent()->astOperand1();
3743
187
    const int returnContainer = settings.library.returnValueContainer(tok);
3744
187
    if (returnContainer >= 0) {
3745
0
        std::vector<const Token *> args = getArguments(tok);
3746
0
        for (int argnr = 1; argnr <= args.size(); ++argnr) {
3747
0
            const Library::ArgumentChecks::IteratorInfo *i = settings.library.getArgIteratorInfo(tok, argnr);
3748
0
            if (!i)
3749
0
                continue;
3750
0
            if (i->container != returnContainer)
3751
0
                continue;
3752
0
            const Token * const argTok = args[argnr - 1];
3753
0
            bool forward = false;
3754
0
            for (ValueFlow::Value val : argTok->values()) {
3755
0
                if (!val.isLifetimeValue())
3756
0
                    continue;
3757
0
                val.errorPath.emplace_back(argTok, "Passed to '" + tok->str() + "'.");
3758
0
                setTokenValue(tok->next(), std::move(val), settings);
3759
0
                forward = true;
3760
0
            }
3761
            // Check if lifetime is available to avoid adding the lifetime twice
3762
0
            if (forward) {
3763
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
3764
0
                break;
3765
0
            }
3766
0
        }
3767
187
    } else if (match49(tok->tokAt(-2))) {
3768
0
        for (const Token *argtok : getArguments(tok)) {
3769
0
            LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byRef(
3770
0
                tok->next(), tokenlist, errorLogger, settings);
3771
0
        }
3772
187
    } else if (match50(tok->tokAt(-2))) {
3773
0
        for (const Token *argtok : getArguments(tok)) {
3774
0
            LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byVal(
3775
0
                tok->next(), tokenlist, errorLogger, settings);
3776
0
        }
3777
187
    } else if (memtok && match51(tok->astParent()) &&
3778
187
               astIsNonStringContainer(memtok)) {
3779
0
        std::vector<const Token *> args = getArguments(tok);
3780
0
        const std::size_t n = args.size();
3781
0
        if (n > 1 && Token::typeStr(args[n - 2]) == Token::typeStr(args[n - 1]) &&
3782
0
            (((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) ||
3783
0
              (astIsPointer(args[n - 2]) && astIsPointer(args[n - 1]))))) {
3784
0
            LifetimeStore{
3785
0
                args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
3786
0
            .byDerefCopy(memtok, tokenlist, errorLogger, settings);
3787
0
        } else if (!args.empty() && ValueFlow::isLifetimeBorrowed(args.back(), settings)) {
3788
0
            LifetimeStore{
3789
0
                args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
3790
0
            .byVal(memtok, tokenlist, errorLogger, settings);
3791
0
        }
3792
187
    } else if (tok->function()) {
3793
0
        const Function *f = tok->function();
3794
0
        if (f->isConstructor()) {
3795
0
            valueFlowLifetimeUserConstructor(tok->next(), f, tok->str(), getArguments(tok), tokenlist, errorLogger, settings);
3796
0
            return;
3797
0
        }
3798
0
        if (Function::returnsReference(f))
3799
0
            return;
3800
0
        std::vector<const Token*> returns = Function::findReturns(f);
3801
0
        const bool inconclusive = returns.size() > 1;
3802
0
        bool update = false;
3803
0
        for (const Token* returnTok : returns) {
3804
0
            if (returnTok == tok)
3805
0
                continue;
3806
0
            const Variable *returnVar = ValueFlow::getLifetimeVariable(returnTok, settings);
3807
0
            if (returnVar && returnVar->isArgument() && (returnVar->isConst() || !isVariableChanged(returnVar, settings))) {
3808
0
                LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, tokenlist, settings, errorLogger);
3809
0
                ls.inconclusive = inconclusive;
3810
0
                ls.forward = false;
3811
0
                update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
3812
0
            }
3813
0
            for (const ValueFlow::Value &v : returnTok->values()) {
3814
0
                if (!v.isLifetimeValue())
3815
0
                    continue;
3816
0
                if (!v.tokvalue)
3817
0
                    continue;
3818
0
                if (memtok &&
3819
0
                    (contains({ValueFlow::Value::LifetimeScope::ThisPointer, ValueFlow::Value::LifetimeScope::ThisValue},
3820
0
                              v.lifetimeScope) ||
3821
0
                     exprDependsOnThis(v.tokvalue))) {
3822
0
                    LifetimeStore ls = LifetimeStore{memtok,
3823
0
                                                     "Passed to member function '" + tok->expressionString() + "'.",
3824
0
                                                     ValueFlow::Value::LifetimeKind::Object};
3825
0
                    ls.inconclusive = inconclusive;
3826
0
                    ls.forward = false;
3827
0
                    ls.errorPath = v.errorPath;
3828
0
                    ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
3829
0
                    int thisIndirect = v.lifetimeScope == ValueFlow::Value::LifetimeScope::ThisValue ? 0 : 1;
3830
0
                    if (derefShared(memtok->astParent()))
3831
0
                        thisIndirect--;
3832
0
                    if (thisIndirect == -1)
3833
0
                        update |= ls.byDerefCopy(tok->next(), tokenlist, errorLogger, settings);
3834
0
                    else if (thisIndirect == 0)
3835
0
                        update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
3836
0
                    else if (thisIndirect == 1)
3837
0
                        update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings);
3838
0
                    continue;
3839
0
                }
3840
0
                const Variable *var = v.tokvalue->variable();
3841
0
                LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, var, tokenlist, settings, errorLogger);
3842
0
                if (!ls.argtok)
3843
0
                    continue;
3844
0
                ls.forward = false;
3845
0
                ls.inconclusive = inconclusive;
3846
0
                ls.errorPath = v.errorPath;
3847
0
                ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
3848
0
                if (!v.isArgumentLifetimeValue() && (var->isReference() || var->isRValueReference())) {
3849
0
                    update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings);
3850
0
                } else if (v.isArgumentLifetimeValue()) {
3851
0
                    update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
3852
0
                }
3853
0
            }
3854
0
        }
3855
0
        if (update)
3856
0
            valueFlowForwardLifetime(tok->next(), tokenlist, errorLogger, settings);
3857
187
    } else if (tok->valueType()) {
3858
        // TODO: Propagate lifetimes with library functions
3859
187
        if (settings.library.getFunction(tok->previous()))
3860
0
            return;
3861
187
        if (match40(tok->astParent()))
3862
0
            return;
3863
        // Assume constructing the valueType
3864
187
        valueFlowLifetimeConstructor(tok->next(), tokenlist, errorLogger, settings);
3865
187
        valueFlowForwardLifetime(tok->next(), tokenlist, errorLogger, settings);
3866
187
    } else {
3867
0
        const std::string& retVal = settings.library.returnValue(tok);
3868
0
        if (startsWith(retVal, "arg")) {
3869
0
            std::size_t iArg{};
3870
0
            try {
3871
0
                iArg = strToInt<std::size_t>(retVal.substr(3));
3872
0
            } catch (...) {
3873
0
                return;
3874
0
            }
3875
0
            std::vector<const Token*> args = getArguments(tok);
3876
0
            if (iArg > 0 && iArg <= args.size()) {
3877
0
                const Token* varTok = args[iArg - 1];
3878
0
                if (varTok->variable() && varTok->variable()->isLocal())
3879
0
                    LifetimeStore{ varTok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Address }.byRef(
3880
0
                    tok->next(), tokenlist, errorLogger, settings);
3881
0
            }
3882
0
        }
3883
0
    }
3884
187
}
3885
3886
static bool isScope(const Token* tok)
3887
983
{
3888
983
    if (!tok)
3889
0
        return false;
3890
983
    if (!match4(tok))
3891
187
        return false;
3892
796
    const Scope* scope = tok->scope();
3893
796
    if (!scope)
3894
0
        return false;
3895
796
    if (!scope->bodyStart)
3896
0
        return false;
3897
796
    return scope->bodyStart == tok;
3898
796
}
3899
3900
static const Function* findConstructor(const Scope* scope, const Token* tok, const std::vector<const Token*>& args)
3901
0
{
3902
0
    if (!tok)
3903
0
        return nullptr;
3904
0
    const Function* f = tok->function();
3905
0
    if (!f && tok->astOperand1())
3906
0
        f = tok->astOperand1()->function();
3907
    // Search for a constructor
3908
0
    if (!f || !f->isConstructor()) {
3909
0
        f = nullptr;
3910
0
        std::vector<const Function*> candidates;
3911
0
        for (const Function& function : scope->functionList) {
3912
0
            if (function.minArgCount() > args.size())
3913
0
                continue;
3914
0
            if (!function.isConstructor())
3915
0
                continue;
3916
0
            candidates.push_back(&function);
3917
0
        }
3918
        // TODO: Narrow the candidates
3919
0
        if (candidates.size() == 1)
3920
0
            f = candidates.front();
3921
0
    }
3922
0
    if (!f)
3923
0
        return nullptr;
3924
0
    return f;
3925
0
}
3926
3927
static void valueFlowLifetimeClassConstructor(Token* tok,
3928
                                              const Type* t,
3929
                                              const TokenList& tokenlist,
3930
                                              ErrorLogger& errorLogger,
3931
                                              const Settings& settings)
3932
0
{
3933
0
    if (!match52(tok))
3934
0
        return;
3935
0
    if (isScope(tok))
3936
0
        return;
3937
0
    if (!t) {
3938
0
        if (tok->valueType() && tok->valueType()->type != ValueType::RECORD)
3939
0
            return;
3940
0
        if (tok->str() != MatchCompiler::makeConstString("{") && !match53(tok->previous()) && !isVariableDecl(tok->previous()))
3941
0
            return;
3942
        // If the type is unknown then assume it captures by value in the
3943
        // constructor, but make each lifetime inconclusive
3944
0
        std::vector<const Token*> args = getArguments(tok);
3945
0
        LifetimeStore::forEach(tokenlist,
3946
0
                               errorLogger,
3947
0
                               settings,
3948
0
                               args,
3949
0
                               "Passed to initializer list.",
3950
0
                               ValueFlow::Value::LifetimeKind::SubObject,
3951
0
                               [&](LifetimeStore& ls) {
3952
0
            ls.inconclusive = true;
3953
0
            ls.byVal(tok, tokenlist, errorLogger, settings);
3954
0
        });
3955
0
        return;
3956
0
    }
3957
0
    const Scope* scope = t->classScope;
3958
0
    if (!scope)
3959
0
        return;
3960
    // Aggregate constructor
3961
0
    if (t->derivedFrom.empty() && (t->isClassType() || t->isStructType())) {
3962
0
        std::vector<const Token*> args = getArguments(tok);
3963
0
        if (scope->numConstructors == 0) {
3964
0
            auto it = scope->varlist.cbegin();
3965
0
            LifetimeStore::forEach(
3966
0
                tokenlist,
3967
0
                errorLogger,
3968
0
                settings,
3969
0
                args,
3970
0
                "Passed to constructor of '" + t->name() + "'.",
3971
0
                ValueFlow::Value::LifetimeKind::SubObject,
3972
0
                [&](LifetimeStore& ls) {
3973
                // Skip static variable
3974
0
                it = std::find_if(it, scope->varlist.cend(), [](const Variable& var) {
3975
0
                    return !var.isStatic();
3976
0
                });
3977
0
                if (it == scope->varlist.cend())
3978
0
                    return;
3979
0
                const Variable& var = *it;
3980
0
                if (var.valueType() && var.valueType()->container && var.valueType()->container->stdStringLike && !var.valueType()->container->view)
3981
0
                    return; // TODO: check in isLifetimeBorrowed()?
3982
0
                if (var.isReference() || var.isRValueReference()) {
3983
0
                    ls.byRef(tok, tokenlist, errorLogger, settings);
3984
0
                } else if (ValueFlow::isLifetimeBorrowed(ls.argtok, settings)) {
3985
0
                    ls.byVal(tok, tokenlist, errorLogger, settings);
3986
0
                }
3987
0
                it++;
3988
0
            });
3989
0
        } else {
3990
0
            const Function* constructor = findConstructor(scope, tok, args);
3991
0
            valueFlowLifetimeUserConstructor(tok, constructor, t->name(), args, tokenlist, errorLogger, settings);
3992
0
        }
3993
0
    }
3994
0
}
3995
3996
static void valueFlowLifetimeConstructor(Token* tok, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings)
3997
187
{
3998
187
    if (!match52(tok))
3999
0
        return;
4000
187
    if (isScope(tok))
4001
0
        return;
4002
187
    std::vector<ValueType> vts;
4003
187
    if (tok->valueType()) {
4004
0
        vts = {*tok->valueType()};
4005
187
    } else if (match47(tok->previous()) && isVariableDecl(tok->previous()) &&
4006
187
               tok->previous()->valueType()) {
4007
0
        vts = {*tok->previous()->valueType()};
4008
187
    } else if (match4(tok) && !match54(tok->previous())) {
4009
0
        vts = getParentValueTypes(tok, settings);
4010
0
    }
4011
4012
187
    for (const ValueType& vt : vts) {
4013
0
        if (vt.pointer > 0) {
4014
0
            std::vector<const Token*> args = getArguments(tok);
4015
0
            LifetimeStore::forEach(tokenlist,
4016
0
                                   errorLogger,
4017
0
                                   settings,
4018
0
                                   args,
4019
0
                                   "Passed to initializer list.",
4020
0
                                   ValueFlow::Value::LifetimeKind::SubObject,
4021
0
                                   [&](LifetimeStore& ls) {
4022
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
4023
0
            });
4024
0
        } else if (vt.container && vt.type == ValueType::CONTAINER) {
4025
0
            std::vector<const Token*> args = getArguments(tok);
4026
0
            if (args.size() == 1 && vt.container->view && astIsContainerOwned(args.front())) {
4027
0
                LifetimeStore{args.front(), "Passed to container view.", ValueFlow::Value::LifetimeKind::SubObject}
4028
0
                .byRef(tok, tokenlist, errorLogger, settings);
4029
0
            } else if (args.size() == 2 && (astIsIterator(args[0]) || astIsIterator(args[1]))) {
4030
0
                LifetimeStore::forEach(
4031
0
                    tokenlist,
4032
0
                    errorLogger,
4033
0
                    settings,
4034
0
                    args,
4035
0
                    "Passed to initializer list.",
4036
0
                    ValueFlow::Value::LifetimeKind::SubObject,
4037
0
                    [&](const LifetimeStore& ls) {
4038
0
                    ls.byDerefCopy(tok, tokenlist, errorLogger, settings);
4039
0
                });
4040
0
            } else if (vt.container->hasInitializerListConstructor) {
4041
0
                LifetimeStore::forEach(tokenlist,
4042
0
                                       errorLogger,
4043
0
                                       settings,
4044
0
                                       args,
4045
0
                                       "Passed to initializer list.",
4046
0
                                       ValueFlow::Value::LifetimeKind::SubObject,
4047
0
                                       [&](LifetimeStore& ls) {
4048
0
                    ls.byVal(tok, tokenlist, errorLogger, settings);
4049
0
                });
4050
0
            }
4051
0
        } else {
4052
0
            const Type* t = nullptr;
4053
0
            if (vt.typeScope && vt.typeScope->definedType)
4054
0
                t = vt.typeScope->definedType;
4055
0
            else
4056
0
                t = Token::typeOf(tok->previous());
4057
0
            valueFlowLifetimeClassConstructor(tok, t, tokenlist, errorLogger, settings);
4058
0
        }
4059
0
    }
4060
187
}
4061
4062
struct Lambda {
4063
    explicit Lambda(const Token* tok)
4064
65.1k
    {
4065
65.1k
        if (!match15(tok) || !tok->link())
4066
65.1k
            return;
4067
0
        capture = tok;
4068
4069
0
        if (match55(capture->link())) {
4070
0
            arguments = capture->link()->next();
4071
0
        }
4072
0
        const Token * afterArguments = arguments ? arguments->link()->next() : capture->link()->next();
4073
0
        if (afterArguments && afterArguments->originalName() == MatchCompiler::makeConstString("->")) {
4074
0
            returnTok = afterArguments->next();
4075
0
            bodyTok = findmatch56(returnTok) ;
4076
0
        } else if (match4(afterArguments)) {
4077
0
            bodyTok = afterArguments;
4078
0
        }
4079
0
        for (const Token* c:getCaptures()) {
4080
0
            if (match57(c)) {
4081
0
                explicitCaptures[c->variable()] = std::make_pair(c, LifetimeCapture::ByReference);
4082
0
            } else if (match58(c)) {
4083
0
                explicitCaptures[c->next()->variable()] = std::make_pair(c->next(), LifetimeCapture::ByValue);
4084
0
            } else if (c->variable()) {
4085
0
                explicitCaptures[c->variable()] = std::make_pair(c, LifetimeCapture::ByValue);
4086
0
            } else if (c->isUnaryOp("&") && match59(c->astOperand1())) {
4087
0
                explicitCaptures[c->astOperand1()->variable()] =
4088
0
                    std::make_pair(c->astOperand1(), LifetimeCapture::ByReference);
4089
0
            } else {
4090
0
                const std::string& s = c->expressionString();
4091
0
                if (s == MatchCompiler::makeConstString("="))
4092
0
                    implicitCapture = LifetimeCapture::ByValue;
4093
0
                else if (s == MatchCompiler::makeConstString("&"))
4094
0
                    implicitCapture = LifetimeCapture::ByReference;
4095
0
            }
4096
0
        }
4097
0
    }
4098
4099
    const Token* capture{};
4100
    const Token* arguments{};
4101
    const Token* returnTok{};
4102
    const Token* bodyTok{};
4103
    std::unordered_map<const Variable*, std::pair<const Token*, LifetimeCapture>> explicitCaptures;
4104
    LifetimeCapture implicitCapture = LifetimeCapture::Undefined;
4105
4106
0
    std::vector<const Token*> getCaptures() const {
4107
0
        return getArguments(capture);
4108
0
    }
4109
4110
65.1k
    bool isLambda() const {
4111
65.1k
        return capture && bodyTok;
4112
65.1k
    }
4113
};
4114
4115
static bool isDecayedPointer(const Token *tok)
4116
0
{
4117
0
    if (!tok)
4118
0
        return false;
4119
0
    if (!tok->astParent())
4120
0
        return false;
4121
0
    if (match9(tok->astParent()) && astIsRHS(tok))
4122
0
        return true;
4123
0
    if (astIsPointer(tok->astParent()) && !match60(tok->astParent()))
4124
0
        return true;
4125
0
    if (tok->astParent()->isConstOp())
4126
0
        return true;
4127
0
    if (!match60(tok->astParent()))
4128
0
        return false;
4129
0
    return astIsPointer(tok->astParent()) || astIsContainerView(tok->astParent());
4130
0
}
4131
4132
static bool isConvertedToView(const Token* tok, const Settings& settings)
4133
0
{
4134
0
    std::vector<ValueType> vtParents = getParentValueTypes(tok, settings);
4135
0
    return std::any_of(vtParents.cbegin(), vtParents.cend(), [&](const ValueType& vt) {
4136
0
        if (!vt.container)
4137
0
            return false;
4138
0
        return vt.container->view;
4139
0
    });
4140
0
}
4141
4142
static bool isContainerOfPointers(const Token* tok, const Settings& settings)
4143
0
{
4144
0
    if (!tok)
4145
0
    {
4146
0
        return true;
4147
0
    }
4148
4149
0
    ValueType vt = ValueType::parseDecl(tok, settings);
4150
0
    return vt.pointer > 0;
4151
0
}
4152
4153
static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings)
4154
1.93k
{
4155
146k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
4156
144k
        if (!tok->scope())
4157
0
            continue;
4158
144k
        if (tok->scope()->type == Scope::eGlobal)
4159
78.9k
            continue;
4160
65.1k
        Lambda lam(tok);
4161
        // Lambdas
4162
65.1k
        if (lam.isLambda()) {
4163
0
            const Scope * bodyScope = lam.bodyTok->scope();
4164
4165
0
            std::set<const Scope *> scopes;
4166
            // Avoid capturing a variable twice
4167
0
            std::set<nonneg int> varids;
4168
0
            bool capturedThis = false;
4169
4170
0
            auto isImplicitCapturingVariable = [&](const Token *varTok) {
4171
0
                const Variable *var = varTok->variable();
4172
0
                if (!var)
4173
0
                    return false;
4174
0
                if (varids.count(var->declarationId()) > 0)
4175
0
                    return false;
4176
0
                if (!var->isLocal() && !var->isArgument())
4177
0
                    return false;
4178
0
                const Scope *scope = var->scope();
4179
0
                if (!scope)
4180
0
                    return false;
4181
0
                if (scopes.count(scope) > 0)
4182
0
                    return false;
4183
0
                if (scope->isNestedIn(bodyScope))
4184
0
                    return false;
4185
0
                scopes.insert(scope);
4186
0
                varids.insert(var->declarationId());
4187
0
                return true;
4188
0
            };
4189
4190
0
            bool update = false;
4191
0
            auto captureVariable = [&](const Token* tok2, LifetimeCapture c, const std::function<bool(const Token*)> &pred) {
4192
0
                if (varids.count(tok->varId()) > 0)
4193
0
                    return;
4194
0
                if (c == LifetimeCapture::ByReference) {
4195
0
                    LifetimeStore ls{
4196
0
                        tok2, "Lambda captures variable by reference here.", ValueFlow::Value::LifetimeKind::Lambda};
4197
0
                    ls.forward = false;
4198
0
                    update |= ls.byRef(tok, tokenlist, errorLogger, settings, pred);
4199
0
                } else if (c == LifetimeCapture::ByValue) {
4200
0
                    LifetimeStore ls{
4201
0
                        tok2, "Lambda captures variable by value here.", ValueFlow::Value::LifetimeKind::Lambda};
4202
0
                    ls.forward = false;
4203
0
                    update |= ls.byVal(tok, tokenlist, errorLogger, settings, pred);
4204
0
                    pred(tok2);
4205
0
                }
4206
0
            };
4207
4208
0
            auto captureThisVariable = [&](const Token* tok2, LifetimeCapture c) {
4209
0
                ValueFlow::Value value;
4210
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4211
0
                if (c == LifetimeCapture::ByReference)
4212
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::ThisPointer;
4213
0
                else if (c == LifetimeCapture::ByValue)
4214
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::ThisValue;
4215
0
                value.tokvalue = tok2;
4216
0
                value.errorPath.emplace_back(tok2, "Lambda captures the 'this' variable here.");
4217
0
                value.lifetimeKind = ValueFlow::Value::LifetimeKind::Lambda;
4218
0
                capturedThis = true;
4219
                // Don't add the value a second time
4220
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4221
0
                    return;
4222
0
                setTokenValue(tok, std::move(value), settings);
4223
0
                update |= true;
4224
0
            };
4225
4226
            // Handle explicit capture
4227
0
            for (const auto& p:lam.explicitCaptures) {
4228
0
                const Variable* var = p.first;
4229
0
                const Token* tok2 = p.second.first;
4230
0
                const LifetimeCapture c = p.second.second;
4231
0
                if (match57(tok2)) {
4232
0
                    captureThisVariable(tok2, c);
4233
0
                } else if (var) {
4234
0
                    captureVariable(tok2, c, [](const Token*) {
4235
0
                        return true;
4236
0
                    });
4237
0
                    varids.insert(var->declarationId());
4238
0
                }
4239
0
            }
4240
4241
0
            auto isImplicitCapturingThis = [&](const Token* tok2) {
4242
0
                if (capturedThis)
4243
0
                    return false;
4244
0
                if (match28(tok2))
4245
0
                    return true;
4246
0
                if (tok2->variable()) {
4247
0
                    if (match40(tok2->previous()))
4248
0
                        return false;
4249
0
                    const Variable* var = tok2->variable();
4250
0
                    if (var->isLocal())
4251
0
                        return false;
4252
0
                    if (var->isArgument())
4253
0
                        return false;
4254
0
                    return exprDependsOnThis(tok2);
4255
0
                }
4256
0
                if (match48(tok2))
4257
0
                    return exprDependsOnThis(tok2);
4258
0
                return false;
4259
0
            };
4260
4261
0
            for (const Token * tok2 = lam.bodyTok; tok2 != lam.bodyTok->link(); tok2 = tok2->next()) {
4262
0
                if (isImplicitCapturingThis(tok2)) {
4263
0
                    captureThisVariable(tok2, LifetimeCapture::ByReference);
4264
0
                } else if (tok2->variable()) {
4265
0
                    captureVariable(tok2, lam.implicitCapture, isImplicitCapturingVariable);
4266
0
                }
4267
0
            }
4268
0
            if (update)
4269
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4270
0
        }
4271
        // address of
4272
65.1k
        else if (tok->isUnaryOp("&")) {
4273
12
            if (match61(tok->astParent()))
4274
0
                continue;
4275
12
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1(), settings)) {
4276
12
                if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4277
0
                    continue;
4278
12
                ErrorPath errorPath = lt.errorPath;
4279
12
                errorPath.emplace_back(tok, "Address of variable taken here.");
4280
4281
12
                ValueFlow::Value value;
4282
12
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4283
12
                value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4284
12
                value.tokvalue = lt.token;
4285
12
                value.errorPath = std::move(errorPath);
4286
12
                if (lt.addressOf || astIsPointer(lt.token) || !match62(lt.token->astParent()))
4287
12
                    value.lifetimeKind = ValueFlow::Value::LifetimeKind::Address;
4288
12
                value.setInconclusive(lt.inconclusive);
4289
12
                setTokenValue(tok, std::move(value), settings);
4290
4291
12
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4292
12
            }
4293
12
        }
4294
        // Converting to container view
4295
65.1k
        else if (astIsContainerOwned(tok) && isConvertedToView(tok, settings)) {
4296
0
            LifetimeStore ls =
4297
0
                LifetimeStore{tok, "Converted to container view", ValueFlow::Value::LifetimeKind::SubObject};
4298
0
            ls.byRef(tok, tokenlist, errorLogger, settings);
4299
0
            valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4300
0
        }
4301
        // container lifetimes
4302
65.1k
        else if (astIsContainer(tok)) {
4303
0
            Token * parent = astParentSkipParens(tok);
4304
0
            if (!parent)
4305
0
                continue;
4306
0
            if (!match16(parent) && !match38(parent->previous()))
4307
0
                continue;
4308
4309
            // Skip if its a free function that doesnt yield an iterator to the container
4310
0
            if (match38(parent->previous()) &&
4311
0
                !contains({Library::Container::Yield::START_ITERATOR, Library::Container::Yield::END_ITERATOR},
4312
0
                          astFunctionYield(parent->previous(), settings)))
4313
0
                continue;
4314
4315
0
            ValueFlow::Value master;
4316
0
            master.valueType = ValueFlow::Value::ValueType::LIFETIME;
4317
0
            master.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4318
4319
0
            if (astIsIterator(parent->tokAt(2))) {
4320
0
                master.errorPath.emplace_back(parent->tokAt(2), "Iterator to container is created here.");
4321
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator;
4322
0
            } else if (astIsIterator(parent) && match38(parent->previous()) &&
4323
0
                       contains({Library::Container::Yield::START_ITERATOR, Library::Container::Yield::END_ITERATOR},
4324
0
                                astFunctionYield(parent->previous(), settings))) {
4325
0
                master.errorPath.emplace_back(parent, "Iterator to container is created here.");
4326
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator;
4327
0
            } else if ((astIsPointer(parent->tokAt(2)) &&
4328
0
                        !isContainerOfPointers(tok->valueType()->containerTypeToken, settings)) ||
4329
0
                       match63(parent->next())) {
4330
0
                master.errorPath.emplace_back(parent->tokAt(2), "Pointer to container is created here.");
4331
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Object;
4332
0
            } else {
4333
0
                continue;
4334
0
            }
4335
4336
0
            std::vector<const Token*> toks;
4337
0
            if (tok->isUnaryOp("*") || parent->originalName() == MatchCompiler::makeConstString("->")) {
4338
0
                for (const ValueFlow::Value& v : tok->values()) {
4339
0
                    if (!v.isLocalLifetimeValue())
4340
0
                        continue;
4341
0
                    if (v.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
4342
0
                        continue;
4343
0
                    if (!v.tokvalue)
4344
0
                        continue;
4345
0
                    toks.push_back(v.tokvalue);
4346
0
                }
4347
0
            } else if (astIsContainerView(tok)) {
4348
0
                for (const ValueFlow::Value& v : tok->values()) {
4349
0
                    if (!v.isLocalLifetimeValue())
4350
0
                        continue;
4351
0
                    if (!v.tokvalue)
4352
0
                        continue;
4353
0
                    if (!astIsContainerOwned(v.tokvalue))
4354
0
                        continue;
4355
0
                    toks.push_back(v.tokvalue);
4356
0
                }
4357
0
            } else {
4358
0
                toks = {tok};
4359
0
            }
4360
4361
0
            for (const Token* tok2 : toks) {
4362
0
                for (const ReferenceToken& rt : followAllReferences(tok2, false)) {
4363
0
                    ValueFlow::Value value = master;
4364
0
                    value.tokvalue = rt.token;
4365
0
                    value.errorPath.insert(value.errorPath.begin(), rt.errors.cbegin(), rt.errors.cend());
4366
0
                    if (match48(parent))
4367
0
                        setTokenValue(parent, std::move(value), settings);
4368
0
                    else
4369
0
                        setTokenValue(parent->tokAt(2), std::move(value), settings);
4370
4371
0
                    if (!rt.token->variable()) {
4372
0
                        LifetimeStore ls = LifetimeStore{
4373
0
                            rt.token, master.errorPath.back().second, ValueFlow::Value::LifetimeKind::Object};
4374
0
                        ls.byRef(parent->tokAt(2), tokenlist, errorLogger, settings);
4375
0
                    }
4376
0
                }
4377
0
            }
4378
0
            valueFlowForwardLifetime(parent->tokAt(2), tokenlist, errorLogger, settings);
4379
0
        }
4380
        // Check constructors
4381
65.1k
        else if (match64(tok) && !isScope(tok->next())) {
4382
0
            valueFlowLifetimeConstructor(tok->next(), tokenlist, errorLogger, settings);
4383
0
        }
4384
        // Check function calls
4385
65.1k
        else if (match38(tok) && !match44(tok->linkAt(1))) {
4386
187
            valueFlowLifetimeFunction(tok, tokenlist, errorLogger, settings);
4387
187
        }
4388
        // Unique pointer lifetimes
4389
64.9k
        else if (astIsUniqueSmartPointer(tok) && astIsLHS(tok) && match65(tok->astParent())) {
4390
0
            Token* ptok = tok->astParent()->tokAt(2);
4391
0
            ErrorPath errorPath = {{ptok, "Raw pointer to smart pointer created here."}};
4392
0
            ValueFlow::Value value;
4393
0
            value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4394
0
            value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4395
0
            value.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject;
4396
0
            value.tokvalue = tok;
4397
0
            value.errorPath = std::move(errorPath);
4398
0
            setTokenValue(ptok, std::move(value), settings);
4399
0
            valueFlowForwardLifetime(ptok, tokenlist, errorLogger, settings);
4400
0
        }
4401
        // Check variables
4402
64.9k
        else if (tok->variable()) {
4403
11.2k
            ErrorPath errorPath;
4404
11.2k
            const Variable * var = ValueFlow::getLifetimeVariable(tok, errorPath, settings);
4405
11.2k
            if (!var)
4406
0
                continue;
4407
11.2k
            if (var->nameToken() == tok)
4408
0
                continue;
4409
11.2k
            if (var->isArray() && !var->isStlType() && !var->isArgument() && isDecayedPointer(tok)) {
4410
0
                errorPath.emplace_back(tok, "Array decayed to pointer here.");
4411
4412
0
                ValueFlow::Value value;
4413
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4414
0
                value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4415
0
                value.tokvalue = var->nameToken();
4416
0
                value.errorPath = std::move(errorPath);
4417
0
                setTokenValue(tok, std::move(value), settings);
4418
4419
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4420
0
            }
4421
11.2k
        }
4422
        // Forward any lifetimes
4423
53.6k
        else if (std::any_of(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
4424
6
            valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4425
6
        }
4426
65.1k
    }
4427
1.93k
}
4428
4429
static bool isStdMoveOrStdForwarded(Token * tok, ValueFlow::Value::MoveKind * moveKind, Token ** varTok = nullptr)
4430
39.6k
{
4431
39.6k
    if (tok->str() != MatchCompiler::makeConstString("std"))
4432
39.6k
        return false;
4433
0
    ValueFlow::Value::MoveKind kind = ValueFlow::Value::MoveKind::NonMovedVariable;
4434
0
    Token * variableToken = nullptr;
4435
0
    if (match66(tok)) {
4436
0
        variableToken = tok->tokAt(4);
4437
0
        kind = ValueFlow::Value::MoveKind::MovedVariable;
4438
0
    } else if (match67(tok)) {
4439
0
        Token * const leftAngle = tok->tokAt(3);
4440
0
        Token * rightAngle = leftAngle->link();
4441
0
        if (match68(rightAngle)) {
4442
0
            variableToken = rightAngle->tokAt(2);
4443
0
            kind = ValueFlow::Value::MoveKind::ForwardedVariable;
4444
0
        }
4445
0
    }
4446
0
    if (!variableToken)
4447
0
        return false;
4448
0
    if (variableToken->strAt(2) == MatchCompiler::makeConstString(".")) // Only partially moved
4449
0
        return false;
4450
0
    if (variableToken->valueType() && variableToken->valueType()->type >= ValueType::Type::VOID)
4451
0
        return false;
4452
0
    if (moveKind != nullptr)
4453
0
        *moveKind = kind;
4454
0
    if (varTok != nullptr)
4455
0
        *varTok = variableToken;
4456
0
    return true;
4457
0
}
4458
4459
static bool isOpenParenthesisMemberFunctionCallOfVarId(const Token * openParenthesisToken, nonneg int varId)
4460
0
{
4461
0
    const Token * varTok = openParenthesisToken->tokAt(-3);
4462
0
    return match69(varTok, varId) &&
4463
0
           varTok->next()->originalName().empty();
4464
0
}
4465
4466
static Token* findOpenParentesisOfMove(Token* moveVarTok)
4467
0
{
4468
0
    Token* tok = moveVarTok;
4469
0
    while (tok && tok->str() != MatchCompiler::makeConstString("("))
4470
0
        tok = tok->previous();
4471
0
    return tok;
4472
0
}
4473
4474
static Token* findEndOfFunctionCallForParameter(Token* parameterToken)
4475
0
{
4476
0
    if (!parameterToken)
4477
0
        return nullptr;
4478
0
    Token* parent = parameterToken->astParent();
4479
0
    while (parent && !parent->isOp() && !match70(parent))
4480
0
        parent = parent->astParent();
4481
0
    if (!parent)
4482
0
        return nullptr;
4483
0
    return nextAfterAstRightmostLeaf(parent);
4484
0
}
4485
4486
static void valueFlowAfterMove(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings)
4487
1.17k
{
4488
1.17k
    if (!tokenlist.isCPP() || settings.standards.cpp < Standards::CPP11)
4489
0
        return;
4490
1.67k
    for (const Scope * scope : symboldatabase.functionScopes) {
4491
1.67k
        if (!scope)
4492
0
            continue;
4493
1.67k
        const Token * start = scope->bodyStart;
4494
1.67k
        if (scope->function) {
4495
1.67k
            const Token * memberInitializationTok = scope->function->constructorMemberInitialization();
4496
1.67k
            if (memberInitializationTok)
4497
0
                start = memberInitializationTok;
4498
1.67k
        }
4499
4500
41.3k
        for (auto* tok = const_cast<Token*>(start); tok != scope->bodyEnd; tok = tok->next()) {
4501
39.6k
            Token * varTok;
4502
39.6k
            if (match71(tok) && tok->next()->originalName().empty()) {
4503
0
                varTok = tok;
4504
4505
0
                const Variable *var = tok->variable();
4506
0
                if (!var || (!var->isLocal() && !var->isArgument()))
4507
0
                    continue;
4508
4509
0
                ValueFlow::Value value;
4510
0
                value.valueType = ValueFlow::Value::ValueType::MOVED;
4511
0
                value.moveKind = ValueFlow::Value::MoveKind::NonMovedVariable;
4512
0
                value.errorPath.emplace_back(tok, "Calling " + tok->next()->expressionString() + " makes " + tok->str() + " 'non-moved'");
4513
0
                value.setKnown();
4514
4515
0
                setTokenValue(tok, value, settings);
4516
0
                if (var->scope()) {
4517
0
                    const Token* const endOfVarScope = var->scope()->bodyEnd;
4518
0
                    valueFlowForward(tok->next(), endOfVarScope, tok, std::move(value), tokenlist, errorLogger, settings);
4519
0
                }
4520
0
                continue;
4521
0
            }
4522
39.6k
            ValueFlow::Value::MoveKind moveKind;
4523
39.6k
            if (!isStdMoveOrStdForwarded(tok, &moveKind, &varTok))
4524
39.6k
                continue;
4525
0
            const nonneg int varId = varTok->varId();
4526
            // x is not MOVED after assignment if code is:  x = ... std::move(x) .. ;
4527
0
            const Token *parent = tok->astParent();
4528
0
            while (parent && parent->str() != MatchCompiler::makeConstString("=") && parent->str() != MatchCompiler::makeConstString("return") &&
4529
0
                   !(parent->str() == MatchCompiler::makeConstString("(") && isOpenParenthesisMemberFunctionCallOfVarId(parent, varId)))
4530
0
                parent = parent->astParent();
4531
0
            if (parent &&
4532
0
                (parent->str() == MatchCompiler::makeConstString("return") || // MOVED in return statement
4533
0
                 parent->str() == MatchCompiler::makeConstString("("))) // MOVED in self assignment, isOpenParenthesisMemberFunctionCallOfVarId == true
4534
0
                continue;
4535
0
            if (parent && parent->astOperand1() && parent->astOperand1()->varId() == varId)
4536
0
                continue;
4537
0
            const Token* const endOfVarScope = ValueFlow::getEndOfExprScope(varTok);
4538
4539
0
            Token* openParentesisOfMove = findOpenParentesisOfMove(varTok);
4540
0
            Token* endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
4541
0
            if (endOfFunctionCall) {
4542
0
                if (endOfFunctionCall->str() == MatchCompiler::makeConstString(")")) {
4543
0
                    Token* ternaryColon = endOfFunctionCall->link()->astParent();
4544
0
                    while (match48(ternaryColon))
4545
0
                        ternaryColon = ternaryColon->astParent();
4546
0
                    if (match36(ternaryColon)) {
4547
0
                        endOfFunctionCall = ternaryColon->astOperand2();
4548
0
                        if (match48(endOfFunctionCall))
4549
0
                            endOfFunctionCall = endOfFunctionCall->link();
4550
0
                    }
4551
0
                }
4552
0
                ValueFlow::Value value;
4553
0
                value.valueType = ValueFlow::Value::ValueType::MOVED;
4554
0
                value.moveKind = moveKind;
4555
0
                if (moveKind == ValueFlow::Value::MoveKind::MovedVariable)
4556
0
                    value.errorPath.emplace_back(tok, "Calling std::move(" + varTok->str() + ")");
4557
0
                else // if (moveKind == ValueFlow::Value::ForwardedVariable)
4558
0
                    value.errorPath.emplace_back(tok, "Calling std::forward(" + varTok->str() + ")");
4559
0
                value.setKnown();
4560
4561
0
                valueFlowForward(endOfFunctionCall, endOfVarScope, varTok, std::move(value), tokenlist, errorLogger, settings);
4562
0
            }
4563
0
        }
4564
1.67k
    }
4565
1.17k
}
4566
4567
static const Token* findIncompleteVar(const Token* start, const Token* end)
4568
1.10k
{
4569
6.44k
    for (const Token* tok = start; tok != end; tok = tok->next()) {
4570
5.98k
        if (tok->isIncompleteVar())
4571
647
            return tok;
4572
5.98k
    }
4573
456
    return nullptr;
4574
1.10k
}
4575
4576
static ValueFlow::Value makeConditionValue(long long val,
4577
                                           const Token* condTok,
4578
                                           bool assume,
4579
                                           bool impossible,
4580
                                           const Settings& settings,
4581
                                           SourceLocation loc = SourceLocation::current())
4582
87
{
4583
87
    ValueFlow::Value v(val);
4584
87
    v.setKnown();
4585
87
    if (impossible) {
4586
0
        v.intvalue = !v.intvalue;
4587
0
        v.setImpossible();
4588
0
    }
4589
87
    v.condition = condTok;
4590
87
    if (assume)
4591
54
        v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is true");
4592
33
    else
4593
33
        v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is false");
4594
87
    if (settings.debugnormal)
4595
0
        setSourceLocation(v, loc, condTok);
4596
87
    return v;
4597
87
}
4598
4599
static std::vector<const Token*> getConditions(const Token* tok, const char* op)
4600
60
{
4601
60
    std::vector<const Token*> conds = {tok};
4602
60
    if (tok->str() == op) {
4603
0
        std::vector<const Token*> args = astFlatten(tok, op);
4604
0
        std::copy_if(args.cbegin(), args.cend(), std::back_inserter(conds), [&](const Token* tok2) {
4605
0
            if (tok2->exprId() == 0)
4606
0
                return false;
4607
0
            if (tok2->hasKnownIntValue())
4608
0
                return false;
4609
0
            if (match72(tok2) && !astIsBool(tok2))
4610
0
                return false;
4611
0
            return true;
4612
0
        });
4613
0
    }
4614
60
    return conds;
4615
60
}
4616
4617
static bool isBreakOrContinueScope(const Token* endToken)
4618
78
{
4619
78
    if (!match73(endToken))
4620
0
        return false;
4621
78
    return match74(endToken->tokAt(-2));
4622
78
}
4623
4624
static const Scope* getLoopScope(const Token* tok)
4625
0
{
4626
0
    if (!tok)
4627
0
        return nullptr;
4628
0
    const Scope* scope = tok->scope();
4629
0
    while (scope && scope->type != Scope::eWhile && scope->type != Scope::eFor && scope->type != Scope::eDo)
4630
0
        scope = scope->nestedIn;
4631
0
    return scope;
4632
0
}
4633
4634
//
4635
static void valueFlowConditionExpressions(const TokenList& tokenlist,
4636
                                          const SymbolDatabase& symboldatabase,
4637
                                          ErrorLogger& errorLogger,
4638
                                          const Settings& settings)
4639
764
{
4640
764
    if (!settings.daca && !settings.vfOptions.doConditionExpressionAnalysis) {
4641
0
        if (settings.debugwarnings) {
4642
0
            ErrorMessage::FileLocation loc(tokenlist.getSourceFilePath(), 0, 0);
4643
0
            const ErrorMessage errmsg(
4644
0
                {std::move(loc)},
4645
0
                tokenlist.getSourceFilePath(),
4646
0
                Severity::debug,
4647
0
                "Analysis of condition expressions is disabled. Use --check-level=exhaustive to enable it.",
4648
0
                "normalCheckLevelConditionExpressions",
4649
0
                Certainty::normal);
4650
0
            errorLogger.reportErr(errmsg);
4651
0
        }
4652
0
        return;
4653
0
    }
4654
4655
1.10k
    for (const Scope* scope : symboldatabase.functionScopes) {
4656
1.10k
        if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) {
4657
647
            if (settings.debugwarnings)
4658
0
                bailoutIncompleteVar(tokenlist,
4659
647
                                     errorLogger,
4660
647
                                     incompleteTok,
4661
647
                                     "Skipping function due to incomplete variable " + incompleteTok->str());
4662
647
            continue;
4663
647
        }
4664
4665
456
        if (settings.daca && !settings.vfOptions.doConditionExpressionAnalysis)
4666
0
            continue;
4667
4668
4.22k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
4669
3.76k
            if (!match45(tok))
4670
3.65k
                continue;
4671
109
            Token* parenTok = tok->next();
4672
109
            if (!match44(parenTok->link()))
4673
0
                continue;
4674
109
            const Token* condTok = parenTok->astOperand2();
4675
109
            if (condTok->exprId() == 0)
4676
0
                continue;
4677
109
            if (condTok->hasKnownIntValue())
4678
42
                continue;
4679
67
            if (!isConstExpression(condTok, settings.library))
4680
37
                continue;
4681
30
            const bool isOp = condTok->isComparisonOp() || condTok->tokType() == Token::eLogicalOp;
4682
30
            const bool is1 = isOp || astIsBool(condTok);
4683
4684
30
            Token* blockTok = parenTok->link()->tokAt(1);
4685
30
            Token* startTok = blockTok;
4686
            // Inner condition
4687
30
            {
4688
30
                for (const Token* condTok2 : getConditions(condTok, "&&")) {
4689
30
                    if (is1) {
4690
24
                        const bool isBool = astIsBool(condTok2) || match75(condTok2);
4691
24
                        auto a1 = makeSameExpressionAnalyzer(
4692
24
                            condTok2,
4693
24
                            makeConditionValue(1, condTok2, /*assume*/ true, !isBool, settings),
4694
24
                            settings); // don't set '1' for non-boolean expressions
4695
24
                        valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings);
4696
24
                    }
4697
4698
30
                    auto a2 = makeOppositeExpressionAnalyzer(true,
4699
30
                                                             condTok2,
4700
30
                                                             makeConditionValue(0, condTok2, true, false, settings),
4701
30
                                                             settings);
4702
30
                    valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings);
4703
30
                }
4704
30
            }
4705
4706
30
            std::vector<const Token*> conds = getConditions(condTok, "||");
4707
30
            if (conds.empty())
4708
0
                continue;
4709
4710
            // Check else block
4711
30
            if (match46(startTok->link())) {
4712
18
                startTok = startTok->link()->tokAt(2);
4713
18
                for (const Token* condTok2 : conds) {
4714
18
                    auto a1 = makeSameExpressionAnalyzer(condTok2,
4715
18
                                                         makeConditionValue(0, condTok2, false, false, settings),
4716
18
                                                         settings);
4717
18
                    valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings);
4718
4719
18
                    if (is1) {
4720
13
                        auto a2 =
4721
13
                            makeOppositeExpressionAnalyzer(true,
4722
13
                                                           condTok2,
4723
13
                                                           makeConditionValue(isOp, condTok2, false, false, settings),
4724
13
                                                           settings);
4725
13
                        valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings);
4726
13
                    }
4727
18
                }
4728
18
            }
4729
4730
            // Check if the block terminates early
4731
30
            if (isEscapeScope(blockTok, settings)) {
4732
1
                const Scope* scope2 = scope;
4733
                // If escaping a loop then only use the loop scope
4734
1
                if (isBreakOrContinueScope(blockTok->link())) {
4735
0
                    scope2 = getLoopScope(blockTok->link());
4736
0
                    if (!scope2)
4737
0
                        continue;
4738
0
                }
4739
1
                for (const Token* condTok2 : conds) {
4740
1
                    auto a1 = makeSameExpressionAnalyzer(condTok2,
4741
1
                                                         makeConditionValue(0, condTok2, false, false, settings),
4742
1
                                                         settings);
4743
1
                    valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a1, tokenlist, errorLogger, settings);
4744
4745
1
                    if (is1) {
4746
1
                        auto a2 = makeOppositeExpressionAnalyzer(true,
4747
1
                                                                 condTok2,
4748
1
                                                                 makeConditionValue(1, condTok2, false, false, settings),
4749
1
                                                                 settings);
4750
1
                        valueFlowGenericForward(startTok->link()->next(),
4751
1
                                                scope2->bodyEnd,
4752
1
                                                a2,
4753
1
                                                tokenlist,
4754
1
                                                errorLogger,
4755
1
                                                settings);
4756
1
                    }
4757
1
                }
4758
1
            }
4759
30
        }
4760
456
    }
4761
764
}
4762
4763
static bool isTruncated(const ValueType* src, const ValueType* dst, const Settings& settings)
4764
11
{
4765
11
    if (src->pointer > 0 || dst->pointer > 0)
4766
0
        return src->pointer != dst->pointer;
4767
11
    if (src->smartPointer && dst->smartPointer)
4768
0
        return false;
4769
11
    if ((src->isIntegral() && dst->isIntegral()) || (src->isFloat() && dst->isFloat())) {
4770
11
        const size_t srcSize = ValueFlow::getSizeOf(*src, settings);
4771
11
        const size_t dstSize = ValueFlow::getSizeOf(*dst, settings);
4772
11
        if (srcSize > dstSize)
4773
0
            return true;
4774
11
        if (srcSize == dstSize && src->sign != dst->sign)
4775
0
            return true;
4776
11
    } else if (src->type == dst->type) {
4777
0
        if (src->type == ValueType::Type::RECORD)
4778
0
            return src->typeScope != dst->typeScope;
4779
0
    } else {
4780
0
        return true;
4781
0
    }
4782
11
    return false;
4783
11
}
4784
4785
static void setSymbolic(ValueFlow::Value& value, const Token* tok)
4786
3.91k
{
4787
3.91k
    assert(tok && tok->exprId() > 0 && "Missing expr id for symbolic value");
4788
3.91k
    value.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
4789
3.91k
    value.tokvalue = tok;
4790
3.91k
}
4791
4792
static ValueFlow::Value makeSymbolic(const Token* tok, MathLib::bigint delta = 0)
4793
36
{
4794
36
    ValueFlow::Value value;
4795
36
    value.setKnown();
4796
36
    setSymbolic(value, tok);
4797
36
    value.intvalue = delta;
4798
36
    return value;
4799
36
}
4800
4801
static std::set<nonneg int> getVarIds(const Token* tok)
4802
1.74k
{
4803
1.74k
    std::set<nonneg int> result;
4804
2.18k
    visitAstNodes(tok, [&](const Token* child) {
4805
2.18k
        if (child->varId() > 0)
4806
1.72k
            result.insert(child->varId());
4807
2.18k
        return ChildrenToVisit::op1_and_op2;
4808
2.18k
    });
4809
1.74k
    return result;
4810
1.74k
}
4811
4812
static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings)
4813
764
{
4814
1.10k
    for (const Scope* scope : symboldatabase.functionScopes) {
4815
23.7k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
4816
22.6k
            if (!match9(tok))
4817
20.4k
                continue;
4818
2.24k
            if (tok->astParent())
4819
247
                continue;
4820
2.00k
            if (!tok->astOperand1())
4821
2
                continue;
4822
1.99k
            if (!tok->astOperand2())
4823
0
                continue;
4824
1.99k
            if (tok->astOperand1()->hasKnownIntValue())
4825
0
                continue;
4826
1.99k
            if (tok->astOperand2()->hasKnownIntValue())
4827
15
                continue;
4828
1.98k
            if (tok->astOperand1()->exprId() == 0)
4829
0
                continue;
4830
1.98k
            if (tok->astOperand2()->exprId() == 0)
4831
2
                continue;
4832
1.98k
            if (!isConstExpression(tok->astOperand2(), settings.library))
4833
238
                continue;
4834
1.74k
            if (tok->astOperand1()->valueType() && tok->astOperand2()->valueType()) {
4835
11
                if (isTruncated(
4836
11
                        tok->astOperand2()->valueType(), tok->astOperand1()->valueType(), settings))
4837
0
                    continue;
4838
1.73k
            } else if (isDifferentType(tok->astOperand2(), tok->astOperand1())) {
4839
0
                continue;
4840
0
            }
4841
1.74k
            const std::set<nonneg int> rhsVarIds = getVarIds(tok->astOperand2());
4842
1.74k
            const std::vector<const Variable*> vars = getLHSVariables(tok);
4843
1.74k
            if (std::any_of(vars.cbegin(), vars.cend(), [&](const Variable* var) {
4844
14
                if (rhsVarIds.count(var->declarationId()) > 0)
4845
8
                    return true;
4846
6
                if (var->isLocal())
4847
0
                    return var->isStatic();
4848
6
                return !var->isArgument();
4849
6
            }))
4850
14
                continue;
4851
4852
3.45k
            if (findAstNode(tok, [](const Token* child) {
4853
3.45k
                return child->isIncompleteVar();
4854
3.45k
            }))
4855
1.72k
                continue;
4856
4857
0
            Token* start = nextAfterAstRightmostLeaf(tok);
4858
0
            const Token* end = ValueFlow::getEndOfExprScope(tok->astOperand1(), scope);
4859
4860
0
            ValueFlow::Value rhs = makeSymbolic(tok->astOperand2());
4861
0
            rhs.errorPath.emplace_back(tok,
4862
0
                                       tok->astOperand1()->expressionString() + " is assigned '" +
4863
0
                                       tok->astOperand2()->expressionString() + "' here.");
4864
0
            valueFlowForward(start, end, tok->astOperand1(), std::move(rhs), tokenlist, errorLogger, settings);
4865
4866
0
            ValueFlow::Value lhs = makeSymbolic(tok->astOperand1());
4867
0
            lhs.errorPath.emplace_back(tok,
4868
0
                                       tok->astOperand1()->expressionString() + " is assigned '" +
4869
0
                                       tok->astOperand2()->expressionString() + "' here.");
4870
0
            valueFlowForward(start, end, tok->astOperand2(), std::move(lhs), tokenlist, errorLogger, settings);
4871
0
        }
4872
1.10k
    }
4873
764
}
4874
4875
static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth = 10)
4876
0
{
4877
0
    if (depth < 0)
4878
0
        return nullptr;
4879
0
    if (!tok)
4880
0
        return nullptr;
4881
0
    if (!expr)
4882
0
        return nullptr;
4883
0
    if (expr->exprId() == 0)
4884
0
        return nullptr;
4885
0
    if (match76(tok->previous())) {
4886
0
        if (tok->astOperand2()->exprId() == expr->exprId())
4887
0
            return tok;
4888
0
    } else {
4889
0
        for (const ValueFlow::Value& v : tok->values()) {
4890
0
            if (!v.isSymbolicValue())
4891
0
                continue;
4892
0
            if (!v.isKnown())
4893
0
                continue;
4894
0
            if (v.intvalue != 0)
4895
0
                continue;
4896
0
            if (const Token* next = isStrlenOf(v.tokvalue, expr, depth - 1))
4897
0
                return next;
4898
0
        }
4899
0
    }
4900
0
    return nullptr;
4901
0
}
4902
4903
static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, const Settings& settings)
4904
1.17k
{
4905
1.67k
    for (const Scope* scope : symboldatabase.functionScopes) {
4906
41.3k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
4907
39.6k
            if (tok->hasKnownIntValue())
4908
1.90k
                continue;
4909
4910
37.7k
            if (match24(tok)) {
4911
0
                const Token* arg = tok->next()->astOperand2();
4912
0
                if (!arg)
4913
0
                    continue;
4914
0
                if (arg->exprId() == 0)
4915
0
                    continue;
4916
0
                ValueFlow::Value c = inferCondition(">=", arg, 0);
4917
0
                if (!c.isKnown())
4918
0
                    continue;
4919
4920
0
                ValueFlow::Value v = makeSymbolic(arg);
4921
0
                v.errorPath = c.errorPath;
4922
0
                v.errorPath.emplace_back(tok, "Passed to " + tok->str());
4923
0
                if (c.intvalue == 0)
4924
0
                    v.setImpossible();
4925
0
                else
4926
0
                    v.setKnown();
4927
0
                setTokenValue(tok->next(), std::move(v), settings);
4928
37.7k
            } else if (match77(tok)) {
4929
826
                if (!tok->astOperand1())
4930
6
                    continue;
4931
820
                if (!tok->astOperand2())
4932
17
                    continue;
4933
803
                if (!astIsIntegral(tok->astOperand1(), false) && !astIsIntegral(tok->astOperand2(), false))
4934
113
                    continue;
4935
690
                const ValueFlow::Value* constant = nullptr;
4936
690
                const Token* vartok = nullptr;
4937
690
                if (tok->astOperand1()->hasKnownIntValue()) {
4938
22
                    constant = &tok->astOperand1()->values().front();
4939
22
                    vartok = tok->astOperand2();
4940
22
                }
4941
690
                if (tok->astOperand2()->hasKnownIntValue()) {
4942
45
                    constant = &tok->astOperand2()->values().front();
4943
45
                    vartok = tok->astOperand1();
4944
45
                }
4945
690
                if (!constant)
4946
623
                    continue;
4947
67
                if (!vartok)
4948
0
                    continue;
4949
67
                if (vartok->exprId() == 0)
4950
0
                    continue;
4951
67
                if (match78(tok) && !astIsLHS(vartok))
4952
6
                    continue;
4953
61
                if (match79(tok) && constant->intvalue != 0)
4954
21
                    continue;
4955
40
                if (match80(tok) && constant->intvalue != 1)
4956
4
                    continue;
4957
36
                std::vector<ValueFlow::Value> values = {makeSymbolic(vartok)};
4958
36
                std::unordered_set<nonneg int> ids = {vartok->exprId()};
4959
36
                std::copy_if(vartok->values().cbegin(),
4960
36
                             vartok->values().cend(),
4961
36
                             std::back_inserter(values),
4962
36
                             [&](const ValueFlow::Value& v) {
4963
4
                    if (!v.isSymbolicValue())
4964
4
                        return false;
4965
0
                    if (!v.tokvalue)
4966
0
                        return false;
4967
0
                    return ids.insert(v.tokvalue->exprId()).second;
4968
0
                });
4969
36
                for (ValueFlow::Value& v : values)
4970
36
                    setTokenValue(tok, std::move(v), settings);
4971
36.9k
            } else if (match15(tok)) {
4972
0
                const Token* arrayTok = tok->astOperand1();
4973
0
                const Token* indexTok = tok->astOperand2();
4974
0
                if (!arrayTok)
4975
0
                    continue;
4976
0
                if (!indexTok)
4977
0
                    continue;
4978
0
                for (const ValueFlow::Value& value : indexTok->values()) {
4979
0
                    if (!value.isSymbolicValue())
4980
0
                        continue;
4981
0
                    if (value.intvalue != 0)
4982
0
                        continue;
4983
0
                    const Token* strlenTok = isStrlenOf(value.tokvalue, arrayTok);
4984
0
                    if (!strlenTok)
4985
0
                        continue;
4986
0
                    ValueFlow::Value v = value;
4987
0
                    v.bound = ValueFlow::Value::Bound::Point;
4988
0
                    v.valueType = ValueFlow::Value::ValueType::INT;
4989
0
                    v.errorPath.emplace_back(strlenTok, "Return index of first '\\0' character in string");
4990
0
                    setTokenValue(tok, std::move(v), settings);
4991
0
                }
4992
0
            }
4993
37.7k
        }
4994
1.67k
    }
4995
1.17k
}
4996
4997
struct SymbolicInferModel : InferModel {
4998
    const Token* expr;
4999
2.77k
    explicit SymbolicInferModel(const Token* tok) : expr(tok) {
5000
2.77k
        assert(expr->exprId() != 0);
5001
2.77k
    }
5002
    bool match(const ValueFlow::Value& value) const override
5003
1.90k
    {
5004
1.90k
        return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId();
5005
1.90k
    }
5006
    ValueFlow::Value yield(MathLib::bigint value) const override
5007
2.77k
    {
5008
2.77k
        ValueFlow::Value result(value);
5009
2.77k
        result.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
5010
2.77k
        result.tokvalue = expr;
5011
2.77k
        result.setKnown();
5012
2.77k
        return result;
5013
2.77k
    }
5014
};
5015
5016
static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings)
5017
1.17k
{
5018
1.67k
    for (const Scope* scope : symboldatabase.functionScopes) {
5019
41.3k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5020
39.6k
            if (!match81(tok))
5021
37.7k
                continue;
5022
1.94k
            if (tok->hasKnownIntValue())
5023
374
                continue;
5024
1.56k
            if (!tok->astOperand1())
5025
2
                continue;
5026
1.56k
            if (!tok->astOperand2())
5027
10
                continue;
5028
1.55k
            if (tok->astOperand1()->exprId() == 0)
5029
32
                continue;
5030
1.52k
            if (tok->astOperand2()->exprId() == 0)
5031
6
                continue;
5032
1.51k
            if (tok->astOperand1()->hasKnownIntValue())
5033
73
                continue;
5034
1.44k
            if (tok->astOperand2()->hasKnownIntValue())
5035
58
                continue;
5036
1.38k
            if (astIsFloat(tok->astOperand1(), false))
5037
0
                continue;
5038
1.38k
            if (astIsFloat(tok->astOperand2(), false))
5039
0
                continue;
5040
5041
1.38k
            std::vector<ValueFlow::Value> values;
5042
1.38k
            {
5043
1.38k
                SymbolicInferModel leftModel{tok->astOperand1()};
5044
1.38k
                values = infer(leftModel, tok->str(), 0, tok->astOperand2()->values());
5045
1.38k
            }
5046
1.38k
            if (values.empty()) {
5047
1.38k
                SymbolicInferModel rightModel{tok->astOperand2()};
5048
1.38k
                values = infer(rightModel, tok->str(), tok->astOperand1()->values(), 0);
5049
1.38k
            }
5050
1.38k
            for (ValueFlow::Value& value : values) {
5051
1
                setTokenValue(tok, std::move(value), settings);
5052
1
            }
5053
1.38k
        }
5054
1.67k
    }
5055
1.17k
}
5056
5057
template<class ContainerOfValue>
5058
static void valueFlowForwardConst(Token* start,
5059
                                  const Token* end,
5060
                                  const Variable* var,
5061
                                  const ContainerOfValue& values,
5062
                                  const Settings& settings,
5063
                                  int /*unused*/ = 0)
5064
0
{
5065
0
    if (!precedes(start, end))
5066
0
        throw InternalError(var->nameToken(), "valueFlowForwardConst: start token does not precede the end token.");
5067
0
    for (Token* tok = start; tok != end; tok = tok->next()) {
5068
0
        if (tok->varId() == var->declarationId()) {
5069
0
            for (const ValueFlow::Value& value : values)
5070
0
                setTokenValue(tok, value, settings);
5071
0
        } else {
5072
0
            [&] {
5073
                // Follow references
5074
0
                auto refs = followAllReferences(tok);
5075
0
                auto it = std::find_if(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
5076
0
                    return ref.token->varId() == var->declarationId();
5077
0
                });
Unexecuted instantiation: valueflow.cpp:valueFlowForwardConst<std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > >(Token*, Token const*, Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > const&, Settings const&, int)::{lambda()#1}::operator()() const::{lambda(ReferenceToken const&)#1}::operator()(ReferenceToken const) const
Unexecuted instantiation: valueflow.cpp:valueFlowForwardConst<std::initializer_list<ValueFlow::Value> >(Token*, Token const*, Variable const*, std::initializer_list<ValueFlow::Value> const&, Settings const&, int)::{lambda()#1}::operator()() const::{lambda(ReferenceToken const&)#1}::operator()(ReferenceToken const) const
Unexecuted instantiation: valueflow.cpp:valueFlowForwardConst<std::__1::vector<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > >(Token*, Token const*, Variable const*, std::__1::vector<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > const&, Settings const&, int)::{lambda()#1}::operator()() const::{lambda(ReferenceToken const&)#1}::operator()(ReferenceToken const) const
5078
0
                if (it != refs.end()) {
5079
0
                    for (ValueFlow::Value value : values) {
5080
0
                        if (refs.size() > 1)
5081
0
                            value.setInconclusive();
5082
0
                        value.errorPath.insert(value.errorPath.end(), it->errors.cbegin(), it->errors.cend());
5083
0
                        setTokenValue(tok, std::move(value), settings);
5084
0
                    }
5085
0
                    return;
5086
0
                }
5087
                // Follow symbolic values
5088
0
                for (const ValueFlow::Value& v : tok->values()) {
5089
0
                    if (!v.isSymbolicValue())
5090
0
                        continue;
5091
0
                    if (!v.tokvalue)
5092
0
                        continue;
5093
0
                    if (v.tokvalue->varId() != var->declarationId())
5094
0
                        continue;
5095
0
                    for (ValueFlow::Value value : values) {
5096
0
                        if (!v.isKnown() && value.isImpossible())
5097
0
                            continue;
5098
0
                        if (v.intvalue != 0) {
5099
0
                            if (!value.isIntValue())
5100
0
                                continue;
5101
0
                            value.intvalue += v.intvalue;
5102
0
                        }
5103
0
                        if (!value.isImpossible())
5104
0
                            value.valueKind = v.valueKind;
5105
0
                        value.bound = v.bound;
5106
0
                        value.errorPath.insert(value.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
5107
0
                        setTokenValue(tok, std::move(value), settings);
5108
0
                    }
5109
0
                }
5110
0
            }();
Unexecuted instantiation: valueflow.cpp:valueFlowForwardConst<std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > >(Token*, Token const*, Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > const&, Settings const&, int)::{lambda()#1}::operator()() const
Unexecuted instantiation: valueflow.cpp:valueFlowForwardConst<std::initializer_list<ValueFlow::Value> >(Token*, Token const*, Variable const*, std::initializer_list<ValueFlow::Value> const&, Settings const&, int)::{lambda()#1}::operator()() const
Unexecuted instantiation: valueflow.cpp:valueFlowForwardConst<std::__1::vector<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > >(Token*, Token const*, Variable const*, std::__1::vector<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > const&, Settings const&, int)::{lambda()#1}::operator()() const
5111
0
        }
5112
0
    }
5113
0
}
Unexecuted instantiation: valueflow.cpp:void valueFlowForwardConst<std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > >(Token*, Token const*, Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > const&, Settings const&, int)
Unexecuted instantiation: valueflow.cpp:void valueFlowForwardConst<std::initializer_list<ValueFlow::Value> >(Token*, Token const*, Variable const*, std::initializer_list<ValueFlow::Value> const&, Settings const&, int)
Unexecuted instantiation: valueflow.cpp:void valueFlowForwardConst<std::__1::vector<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > >(Token*, Token const*, Variable const*, std::__1::vector<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > const&, Settings const&, int)
5114
5115
static void valueFlowForwardConst(Token* start,
5116
                                  const Token* end,
5117
                                  const Variable* var,
5118
                                  const std::initializer_list<ValueFlow::Value>& values,
5119
                                  const Settings& settings)
5120
0
{
5121
0
    valueFlowForwardConst(start, end, var, values, settings, 0);
5122
0
}
5123
5124
static ValueFlow::Value::Bound findVarBound(const Variable* var,
5125
                                            const Token* start,
5126
                                            const Token* end,
5127
                                            const Settings& settings)
5128
0
{
5129
0
    ValueFlow::Value::Bound result = ValueFlow::Value::Bound::Point;
5130
0
    const Token* next = start;
5131
0
    while ((next = findExpressionChangedSkipDeadCode(
5132
0
                var->nameToken(), next->next(), end, settings, &evaluateKnownValues))) {
5133
0
        ValueFlow::Value::Bound b = ValueFlow::Value::Bound::Point;
5134
0
        if (next->varId() != var->declarationId())
5135
0
            return ValueFlow::Value::Bound::Point;
5136
0
        if (match82(next->astParent()))
5137
0
            b = ValueFlow::Value::Bound::Lower;
5138
0
        else if (match83(next->astParent()))
5139
0
            b = ValueFlow::Value::Bound::Upper;
5140
0
        else
5141
0
            return ValueFlow::Value::Bound::Point;
5142
0
        if (result == ValueFlow::Value::Bound::Point)
5143
0
            result = b;
5144
0
        else if (result != b)
5145
0
            return ValueFlow::Value::Bound::Point;
5146
0
    }
5147
0
    return result;
5148
0
}
5149
5150
static bool isInitialVarAssign(const Token* tok)
5151
425
{
5152
425
    if (!tok)
5153
0
        return false;
5154
425
    if (!tok->variable())
5155
415
        return false;
5156
10
    if (tok->variable()->nameToken() == tok)
5157
0
        return true;
5158
10
    const Token* prev = tok->tokAt(2);
5159
10
    if (!match84(prev))
5160
10
        return false;
5161
0
    return tok->varId() == prev->varId() && tok->variable()->nameToken() == prev;
5162
10
}
5163
5164
static void valueFlowForwardAssign(Token* const tok,
5165
                                   const Token* expr,
5166
                                   std::vector<const Variable*> vars,
5167
                                   std::list<ValueFlow::Value> values,
5168
                                   const bool init,
5169
                                   const TokenList& tokenlist,
5170
                                   ErrorLogger& errorLogger,
5171
                                   const Settings& settings)
5172
425
{
5173
425
    if (match60(tok->astParent()))
5174
0
        return;
5175
425
    const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
5176
425
    if (std::any_of(values.cbegin(), values.cend(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
5177
0
        valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
5178
0
        values.remove_if(std::mem_fn(&ValueFlow::Value::isLifetimeValue));
5179
0
    }
5180
425
    if (std::all_of(
5181
425
            vars.cbegin(), vars.cend(), [&](const Variable* var) {
5182
10
        return !var->isPointer() && !var->isSmartPointer();
5183
10
    }))
5184
425
        values.remove_if(std::mem_fn(&ValueFlow::Value::isTokValue));
5185
425
    if (tok->astParent()) {
5186
552
        for (ValueFlow::Value& value : values) {
5187
552
            std::string valueKind;
5188
552
            if (value.valueKind == ValueFlow::Value::ValueKind::Impossible) {
5189
249
                if (value.bound == ValueFlow::Value::Bound::Point)
5190
27
                    valueKind = "never ";
5191
222
                else if (value.bound == ValueFlow::Value::Bound::Lower)
5192
106
                    valueKind = "less than ";
5193
116
                else if (value.bound == ValueFlow::Value::Bound::Upper)
5194
116
                    valueKind = "greater than ";
5195
249
            }
5196
552
            std::string info = "Assignment '" + tok->astParent()->expressionString() + "', assigned value is " + valueKind + value.infoString();
5197
552
            value.errorPath.emplace_back(tok, std::move(info));
5198
552
        }
5199
425
    }
5200
5201
425
    if (tokenlist.isCPP() && vars.size() == 1 && match85(vars.front()->typeStartToken())) {
5202
0
        for (ValueFlow::Value& value : values) {
5203
0
            if (value.isImpossible())
5204
0
                continue;
5205
0
            if (value.isIntValue())
5206
0
                value.intvalue = (value.intvalue != 0);
5207
0
            if (value.isTokValue())
5208
0
                value.intvalue = (value.tokvalue != nullptr);
5209
0
        }
5210
0
    }
5211
5212
    // Static variable initialisation?
5213
425
    if (vars.size() == 1 && vars.front()->isStatic() && !vars.front()->isConst() && init)
5214
0
        lowerToPossible(values);
5215
5216
    // is volatile
5217
425
    if (std::any_of(vars.cbegin(), vars.cend(), [&](const Variable* var) {
5218
10
        return var->isVolatile();
5219
10
    }))
5220
0
        lowerToPossible(values);
5221
5222
    // Skip RHS
5223
425
    Token* nextExpression = tok->astParent() ? nextAfterAstRightmostLeaf(tok->astParent()) : tok->next();
5224
425
    if (!nextExpression)
5225
0
        return;
5226
5227
552
    for (ValueFlow::Value& value : values) {
5228
552
        if (value.isSymbolicValue())
5229
175
            continue;
5230
377
        if (value.isTokValue())
5231
0
            continue;
5232
377
        value.tokvalue = tok;
5233
377
    }
5234
    // Const variable
5235
425
    if (expr->variable() && expr->variable()->isConst() && !expr->variable()->isReference()) {
5236
0
        auto it = std::remove_if(values.begin(), values.end(), [](const ValueFlow::Value& value) {
5237
0
            if (!value.isKnown())
5238
0
                return false;
5239
0
            if (value.isIntValue())
5240
0
                return true;
5241
0
            if (value.isFloatValue())
5242
0
                return true;
5243
0
            if (value.isContainerSizeValue())
5244
0
                return true;
5245
0
            if (value.isIteratorValue())
5246
0
                return true;
5247
0
            return false;
5248
0
        });
5249
0
        std::list<ValueFlow::Value> constValues;
5250
0
        constValues.splice(constValues.end(), values, it, values.end());
5251
0
        valueFlowForwardConst(nextExpression, endOfVarScope, expr->variable(), constValues, settings);
5252
0
    }
5253
425
    if (isInitialVarAssign(expr)) {
5254
        // Check if variable is only incremented or decremented
5255
0
        ValueFlow::Value::Bound b = findVarBound(expr->variable(), nextExpression, endOfVarScope, settings);
5256
0
        if (b != ValueFlow::Value::Bound::Point) {
5257
0
            auto knownValueIt = std::find_if(values.begin(), values.end(), [](const ValueFlow::Value& value) {
5258
0
                if (!value.isKnown())
5259
0
                    return false;
5260
0
                return value.isIntValue();
5261
0
            });
5262
0
            if (knownValueIt != values.end()) {
5263
0
                ValueFlow::Value value = *knownValueIt;
5264
0
                value.bound = b;
5265
0
                value.invertRange();
5266
0
                value.setImpossible();
5267
0
                valueFlowForwardConst(nextExpression, endOfVarScope, expr->variable(), {std::move(value)}, settings);
5268
0
            }
5269
0
        }
5270
0
    }
5271
425
    valueFlowForward(nextExpression, endOfVarScope, expr, std::move(values), tokenlist, errorLogger, settings);
5272
425
}
5273
5274
static void valueFlowForwardAssign(Token* const tok,
5275
                                   const Variable* const var,
5276
                                   const std::list<ValueFlow::Value>& values,
5277
                                   const bool /*unused*/,
5278
                                   const bool init,
5279
                                   const TokenList& tokenlist,
5280
                                   ErrorLogger& errorLogger,
5281
                                   const Settings& settings)
5282
0
{
5283
0
    valueFlowForwardAssign(tok, var->nameToken(), {var}, values, init, tokenlist, errorLogger, settings);
5284
0
}
5285
5286
static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> values,
5287
                                                  const ValueType* dst,
5288
                                                  const ValueType* src,
5289
                                                  const Settings& settings)
5290
425
{
5291
425
    if (!dst || !dst->isIntegral())
5292
415
        return values;
5293
5294
10
    const size_t sz = ValueFlow::getSizeOf(*dst, settings);
5295
5296
10
    if (src) {
5297
10
        const size_t osz = ValueFlow::getSizeOf(*src, settings);
5298
10
        if (osz >= sz && dst->sign == ValueType::Sign::SIGNED && src->sign == ValueType::Sign::UNSIGNED) {
5299
0
            values.remove_if([&](const ValueFlow::Value& value) {
5300
0
                if (!value.isIntValue())
5301
0
                    return false;
5302
0
                if (!value.isImpossible())
5303
0
                    return false;
5304
0
                if (value.bound != ValueFlow::Value::Bound::Upper)
5305
0
                    return false;
5306
0
                if (osz == sz && value.intvalue < 0)
5307
0
                    return true;
5308
0
                if (osz > sz)
5309
0
                    return true;
5310
0
                return false;
5311
0
            });
5312
0
        }
5313
10
    }
5314
5315
10
    for (ValueFlow::Value &value : values) {
5316
        // Don't truncate impossible values since those can be outside of the valid range
5317
10
        if (value.isImpossible())
5318
1
            continue;
5319
9
        if (value.isFloatValue()) {
5320
0
            value.intvalue = static_cast<MathLib::bigint>(value.floatValue);
5321
0
            value.valueType = ValueFlow::Value::ValueType::INT;
5322
0
        }
5323
5324
9
        if (value.isIntValue() && sz > 0 && sz < sizeof(MathLib::biguint))
5325
9
            value.intvalue = ValueFlow::truncateIntValue(value.intvalue, sz, dst->sign);
5326
9
    }
5327
10
    return values;
5328
425
}
5329
5330
static bool isVariableInit(const Token *tok)
5331
35.7k
{
5332
35.7k
    if (!tok)
5333
0
        return false;
5334
35.7k
    if (!match86(tok->previous()))
5335
35.7k
        return false;
5336
0
    if (!tok->isBinaryOp() && !(tok->astOperand1() && tok->link() == tok->next()))
5337
0
        return false;
5338
0
    if (match41(tok->astOperand2()))
5339
0
        return false;
5340
0
    const Variable* var = tok->astOperand1()->variable();
5341
0
    if (!var)
5342
0
        return false;
5343
0
    if (var->nameToken() != tok->astOperand1())
5344
0
        return false;
5345
0
    const ValueType* vt = var->valueType();
5346
0
    if (!vt)
5347
0
        return false;
5348
0
    if (vt->type < ValueType::Type::VOID)
5349
0
        return false;
5350
0
    return true;
5351
0
}
5352
5353
// Return true if two associative containers intersect
5354
template<class C1, class C2>
5355
static bool intersects(const C1& c1, const C2& c2)
5356
175
{
5357
175
    if (c1.size() > c2.size())
5358
0
        return intersects(c2, c1);
5359
    // NOLINTNEXTLINE(readability-use-anyofallof) - TODO: fix if possible / also Cppcheck false negative
5360
175
    for (auto&& x : c1) {
5361
104
        if (c2.find(x) != c2.end())
5362
97
            return true;
5363
104
    }
5364
78
    return false;
5365
175
}
5366
5367
static void valueFlowAfterAssign(TokenList &tokenlist,
5368
                                 const SymbolDatabase& symboldatabase,
5369
                                 ErrorLogger &errorLogger,
5370
                                 const Settings &settings,
5371
                                 const std::set<const Scope*>& skippedFunctions)
5372
1.17k
{
5373
1.67k
    for (const Scope * scope : symboldatabase.functionScopes) {
5374
1.67k
        if (skippedFunctions.count(scope))
5375
0
            continue;
5376
1.67k
        std::unordered_map<nonneg int, std::unordered_set<nonneg int>> backAssigns;
5377
41.3k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5378
39.6k
            if (!tok->scope()->isExecutable()) {
5379
0
                tok = const_cast<Token*>(tok->scope()->bodyEnd); // skip local type definition
5380
0
                continue;
5381
0
            }
5382
5383
            // Assignment
5384
39.6k
            bool isInit = false;
5385
39.6k
            if (tok->str() != MatchCompiler::makeConstString("=") && !(isInit = isVariableInit(tok)))
5386
35.7k
                continue;
5387
5388
3.91k
            if (tok->astParent() && !((tok->astParent()->str() == MatchCompiler::makeConstString(";") && astIsLHS(tok)) || tok->astParent()->str() == MatchCompiler::makeConstString("*")))
5389
403
                continue;
5390
5391
            // Lhs should be a variable
5392
3.51k
            if (!tok->astOperand1() || !tok->astOperand1()->exprId())
5393
2
                continue;
5394
3.51k
            std::vector<const Variable*> vars = getLHSVariables(tok);
5395
5396
            // Rhs values..
5397
3.51k
            Token* rhs = tok->astOperand2();
5398
3.51k
            if (!rhs && isInit)
5399
0
                rhs = tok;
5400
3.51k
            if (!rhs || rhs->values().empty())
5401
3.08k
                continue;
5402
5403
425
            std::list<ValueFlow::Value> values = truncateValues(
5404
425
                rhs->values(), tok->astOperand1()->valueType(), rhs->valueType(), settings);
5405
            // Remove known values
5406
425
            std::set<ValueFlow::Value::ValueType> types;
5407
425
            if (tok->astOperand1()->hasKnownValue()) {
5408
0
                for (const ValueFlow::Value& value:tok->astOperand1()->values()) {
5409
0
                    if (value.isKnown() && !value.isSymbolicValue())
5410
0
                        types.insert(value.valueType);
5411
0
                }
5412
0
            }
5413
552
            values.remove_if([&](const ValueFlow::Value& value) {
5414
552
                return types.count(value.valueType) > 0;
5415
552
            });
5416
            // Remove container size if its not a container
5417
425
            if (!astIsContainer(tok->astOperand2()))
5418
552
                values.remove_if([&](const ValueFlow::Value& value) {
5419
552
                    return value.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE;
5420
552
                });
5421
            // Remove symbolic values that are the same as the LHS
5422
552
            values.remove_if([&](const ValueFlow::Value& value) {
5423
552
                if (value.isSymbolicValue() && value.tokvalue)
5424
175
                    return value.tokvalue->exprId() == tok->astOperand1()->exprId();
5425
377
                return false;
5426
552
            });
5427
            // Find references to LHS in RHS
5428
600
            auto isIncremental = [&](const Token* tok2) -> bool {
5429
600
                return findAstNode(tok2,
5430
1.38k
                                   [&](const Token* child) {
5431
1.38k
                    return child->exprId() == tok->astOperand1()->exprId();
5432
1.38k
                });
5433
600
            };
5434
            // Check symbolic values as well
5435
425
            const bool incremental = isIncremental(tok->astOperand2()) ||
5436
549
                                     std::any_of(values.cbegin(), values.cend(), [&](const ValueFlow::Value& value) {
5437
549
                if (!value.isSymbolicValue())
5438
374
                    return false;
5439
175
                return isIncremental(value.tokvalue);
5440
549
            });
5441
            // Remove values from the same assignment if it is incremental
5442
425
            if (incremental) {
5443
3
                values.remove_if([&](const ValueFlow::Value& value) {
5444
3
                    if (value.tokvalue)
5445
0
                        return value.tokvalue == tok->astOperand2();
5446
3
                    return false;
5447
3
                });
5448
3
            }
5449
            // If assignment copy by value, remove Uninit values..
5450
425
            if ((tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->pointer == 0) ||
5451
425
                (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isReference() && tok->astOperand1()->variable()->nameToken() == tok->astOperand1()))
5452
10
                values.remove_if([&](const ValueFlow::Value& value) {
5453
10
                    return value.isUninitValue();
5454
10
                });
5455
425
            if (values.empty())
5456
0
                continue;
5457
425
            const bool init = vars.size() == 1 && (vars.front()->nameToken() == tok->astOperand1() || tok->isSplittedVarDeclEq());
5458
425
            valueFlowForwardAssign(
5459
425
                rhs, tok->astOperand1(), std::move(vars), values, init, tokenlist, errorLogger, settings);
5460
            // Back propagate symbolic values
5461
425
            if (tok->astOperand1()->exprId() > 0) {
5462
425
                Token* start = nextAfterAstRightmostLeaf(tok);
5463
425
                const Token* end = scope->bodyEnd;
5464
                // Collect symbolic ids
5465
425
                std::unordered_set<nonneg int> ids;
5466
552
                for (const ValueFlow::Value& value : values) {
5467
552
                    if (!value.isSymbolicValue())
5468
377
                        continue;
5469
175
                    if (!value.tokvalue)
5470
0
                        continue;
5471
175
                    if (value.tokvalue->exprId() == 0)
5472
0
                        continue;
5473
175
                    ids.insert(value.tokvalue->exprId());
5474
175
                }
5475
552
                for (ValueFlow::Value value : values) {
5476
552
                    if (!value.isSymbolicValue())
5477
377
                        continue;
5478
175
                    const Token* expr = value.tokvalue;
5479
175
                    value.intvalue = -value.intvalue;
5480
175
                    value.tokvalue = tok->astOperand1();
5481
5482
                    // Skip if it intersects with an already assigned symbol
5483
175
                    auto& s = backAssigns[value.tokvalue->exprId()];
5484
175
                    if (intersects(s, ids))
5485
97
                        continue;
5486
78
                    s.insert(expr->exprId());
5487
5488
78
                    value.errorPath.emplace_back(tok,
5489
78
                                                 tok->astOperand1()->expressionString() + " is assigned '" +
5490
78
                                                 tok->astOperand2()->expressionString() + "' here.");
5491
78
                    valueFlowForward(start, end, expr, std::move(value), tokenlist, errorLogger, settings);
5492
78
                }
5493
425
            }
5494
425
        }
5495
1.67k
    }
5496
1.17k
}
5497
5498
static std::vector<const Variable*> getVariables(const Token* tok)
5499
0
{
5500
0
    std::vector<const Variable*> result;
5501
0
    visitAstNodes(tok, [&](const Token* child) {
5502
0
        if (child->variable())
5503
0
            result.push_back(child->variable());
5504
0
        return ChildrenToVisit::op1_and_op2;
5505
0
    });
5506
0
    return result;
5507
0
}
5508
5509
static void valueFlowAfterSwap(const TokenList& tokenlist,
5510
                               const SymbolDatabase& symboldatabase,
5511
                               ErrorLogger& errorLogger,
5512
                               const Settings& settings)
5513
1.17k
{
5514
1.67k
    for (const Scope* scope : symboldatabase.functionScopes) {
5515
41.3k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5516
39.6k
            if (!match87(tok))
5517
39.6k
                continue;
5518
0
            if (!match41(tok->next()->astOperand2()))
5519
0
                continue;
5520
0
            std::vector<Token*> args = astFlatten(tok->next()->astOperand2(), ",");
5521
0
            if (args.size() != 2)
5522
0
                continue;
5523
0
            if (args[0]->exprId() == 0)
5524
0
                continue;
5525
0
            if (args[1]->exprId() == 0)
5526
0
                continue;
5527
0
            for (int i = 0; i < 2; i++) {
5528
0
                std::vector<const Variable*> vars = getVariables(args[0]);
5529
0
                const std::list<ValueFlow::Value>& values = args[0]->values();
5530
0
                valueFlowForwardAssign(args[0], args[1], std::move(vars), values, false, tokenlist, errorLogger, settings);
5531
0
                std::swap(args[0], args[1]);
5532
0
            }
5533
0
        }
5534
1.67k
    }
5535
1.17k
}
5536
5537
static void valueFlowSetConditionToKnown(const Token* tok, std::list<ValueFlow::Value>& values, bool then)
5538
1.51k
{
5539
1.51k
    if (values.empty())
5540
0
        return;
5541
1.51k
    if (then && !match88(tok))
5542
801
        return;
5543
716
    if (!then && !match89(tok))
5544
463
        return;
5545
253
    if (isConditionKnown(tok, then))
5546
253
        changePossibleToKnown(values);
5547
253
}
5548
5549
static bool isBreakScope(const Token* const endToken)
5550
84
{
5551
84
    if (!match73(endToken))
5552
0
        return false;
5553
84
    if (!match4(endToken->link()))
5554
0
        return false;
5555
84
    return findmatch90(endToken->link(), endToken) ;
5556
84
}
5557
5558
ValueFlow::Value ValueFlow::asImpossible(ValueFlow::Value v)
5559
1.31k
{
5560
1.31k
    v.invertRange();
5561
1.31k
    v.setImpossible();
5562
1.31k
    return v;
5563
1.31k
}
5564
5565
static void insertImpossible(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
5566
1.30k
{
5567
1.30k
    std::transform(input.cbegin(), input.cend(), std::back_inserter(values), &ValueFlow::asImpossible);
5568
1.30k
}
5569
5570
static void insertNegateKnown(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
5571
60
{
5572
60
    for (ValueFlow::Value value:input) {
5573
60
        if (!value.isIntValue() && !value.isContainerSizeValue())
5574
34
            continue;
5575
26
        value.intvalue = !value.intvalue;
5576
26
        value.setKnown();
5577
26
        values.push_back(std::move(value));
5578
26
    }
5579
60
}
5580
5581
struct ConditionHandler {
5582
    struct Condition {
5583
        const Token* vartok{};
5584
        std::list<ValueFlow::Value> true_values;
5585
        std::list<ValueFlow::Value> false_values;
5586
        bool inverted = false;
5587
        // Whether to insert impossible values for the condition or only use possible values
5588
        bool impossible = true;
5589
5590
709
        bool isBool() const {
5591
709
            return astIsBool(vartok);
5592
709
        }
5593
5594
        static MathLib::bigint findPath(const std::list<ValueFlow::Value>& values)
5595
10.1k
        {
5596
10.1k
            auto it = std::find_if(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) {
5597
10.1k
                return v.path > 0;
5598
10.1k
            });
5599
10.1k
            if (it == values.end())
5600
10.1k
                return 0;
5601
0
            assert(std::all_of(it, values.end(), [&](const ValueFlow::Value& v) {
5602
0
                return v.path == 0 || v.path == it->path;
5603
0
            }));
5604
0
            return it->path;
5605
0
        }
5606
5607
        MathLib::bigint getPath() const
5608
2.53k
        {
5609
2.53k
            assert(std::abs(findPath(true_values) - findPath(false_values)) == 0);
5610
2.53k
            return findPath(true_values) | findPath(false_values);
5611
2.53k
        }
5612
5613
        Token* getContextAndValues(Token* condTok,
5614
                                   std::list<ValueFlow::Value>& thenValues,
5615
                                   std::list<ValueFlow::Value>& elseValues,
5616
                                   bool known = false) const
5617
1.26k
        {
5618
1.26k
            const MathLib::bigint path = getPath();
5619
1.26k
            const bool allowKnown = path == 0;
5620
1.26k
            const bool allowImpossible = impossible && allowKnown;
5621
5622
1.26k
            bool inverted2 = inverted;
5623
1.26k
            Token* ctx = skipNotAndCasts(condTok, &inverted2);
5624
1.26k
            bool then = !inverted || !inverted2;
5625
5626
1.26k
            if (!match91(condTok) && condTok != vartok) {
5627
948
                thenValues.insert(thenValues.end(), true_values.cbegin(), true_values.cend());
5628
948
                if (allowImpossible && (known || isConditionKnown(ctx, !then)))
5629
594
                    insertImpossible(elseValues, false_values);
5630
948
            }
5631
1.26k
            if (!match92(condTok)) {
5632
1.04k
                elseValues.insert(elseValues.end(), false_values.cbegin(), false_values.cend());
5633
1.04k
                if (allowImpossible && (known || isConditionKnown(ctx, then))) {
5634
709
                    insertImpossible(thenValues, true_values);
5635
709
                    if (isBool())
5636
60
                        insertNegateKnown(thenValues, true_values);
5637
709
                }
5638
1.04k
            }
5639
5640
1.26k
            if (inverted2)
5641
0
                std::swap(thenValues, elseValues);
5642
5643
1.26k
            return ctx;
5644
1.26k
        }
5645
    };
5646
5647
    virtual std::vector<Condition> parse(const Token* tok, const Settings& settings) const = 0;
5648
5649
    virtual Analyzer::Result forward(Token* start,
5650
                                     const Token* stop,
5651
                                     const Token* exprTok,
5652
                                     const std::list<ValueFlow::Value>& values,
5653
                                     TokenList& tokenlist,
5654
                                     ErrorLogger& errorLogger,
5655
                                     const Settings& settings,
5656
                                     SourceLocation loc = SourceLocation::current()) const
5657
1.60k
    {
5658
1.60k
        return valueFlowForward(start->next(), stop, exprTok, values, tokenlist, errorLogger, settings, loc);
5659
1.60k
    }
5660
5661
    virtual Analyzer::Result forward(Token* top,
5662
                                     const Token* exprTok,
5663
                                     const std::list<ValueFlow::Value>& values,
5664
                                     TokenList& tokenlist,
5665
                                     ErrorLogger& errorLogger,
5666
                                     const Settings& settings,
5667
                                     SourceLocation loc = SourceLocation::current()) const
5668
0
    {
5669
0
        return valueFlowForwardRecursive(top, exprTok, values, tokenlist, errorLogger, settings, loc);
5670
0
    }
5671
5672
    virtual void reverse(Token* start,
5673
                         const Token* endToken,
5674
                         const Token* exprTok,
5675
                         const std::list<ValueFlow::Value>& values,
5676
                         TokenList& tokenlist,
5677
                         ErrorLogger& errorLogger,
5678
                         const Settings& settings,
5679
                         SourceLocation loc = SourceLocation::current()) const
5680
633
    {
5681
633
        valueFlowReverse(start, endToken, exprTok, values, tokenlist, errorLogger, settings, loc);
5682
633
    }
5683
5684
    void traverseCondition(const SymbolDatabase& symboldatabase,
5685
                           const Settings& settings,
5686
                           const std::set<const Scope*>& skippedFunctions,
5687
                           const std::function<void(const Condition& cond, Token* tok, const Scope* scope)>& f) const
5688
9.39k
    {
5689
13.4k
        for (const Scope *scope : symboldatabase.functionScopes) {
5690
13.4k
            if (skippedFunctions.count(scope))
5691
0
                continue;
5692
331k
            for (auto *tok = const_cast<Token *>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5693
317k
                if (match14(tok))
5694
9.84k
                    continue;
5695
307k
                if (match93(tok))
5696
42.7k
                    continue;
5697
5698
265k
                const Token* top = tok->astTop();
5699
5700
265k
                if (!match14(top->previous()) && !match94(tok->astParent()))
5701
202k
                    continue;
5702
62.5k
                for (const Condition& cond : parse(tok, settings)) {
5703
18.4k
                    if (!cond.vartok)
5704
15.6k
                        continue;
5705
2.75k
                    if (cond.vartok->exprId() == 0)
5706
0
                        continue;
5707
2.75k
                    if (cond.vartok->hasKnownIntValue())
5708
28
                        continue;
5709
2.72k
                    if (cond.true_values.empty() || cond.false_values.empty())
5710
0
                        continue;
5711
2.72k
                    if (!isConstExpression(cond.vartok, settings.library))
5712
190
                        continue;
5713
2.53k
                    f(cond, tok, scope);
5714
2.53k
                }
5715
62.5k
            }
5716
13.4k
        }
5717
9.39k
    }
5718
5719
    void beforeCondition(TokenList& tokenlist,
5720
                         const SymbolDatabase& symboldatabase,
5721
                         ErrorLogger& errorLogger,
5722
                         const Settings& settings,
5723
4.69k
                         const std::set<const Scope*>& skippedFunctions) const {
5724
4.69k
        traverseCondition(symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* tok, const Scope*) {
5725
1.26k
            if (cond.vartok->exprId() == 0)
5726
0
                return;
5727
5728
            // If condition is known then don't propagate value
5729
1.26k
            if (tok->hasKnownIntValue())
5730
43
                return;
5731
5732
1.22k
            Token* top = tok->astTop();
5733
5734
1.22k
            if (match95(top))
5735
0
                return;
5736
1.22k
            if (match96(cond.vartok->astParent()))
5737
96
                return;
5738
5739
1.12k
            if (match22(tok->astParent()) && tok->astParent()->isExpandedMacro()) {
5740
0
                if (settings.debugwarnings)
5741
0
                    bailout(tokenlist,
5742
0
                            errorLogger,
5743
0
                            tok,
5744
0
                            "variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
5745
0
                return;
5746
0
            }
5747
5748
            // if,macro => bailout
5749
1.12k
            if (match45(top->previous()) && top->previous()->isExpandedMacro()) {
5750
0
                if (settings.debugwarnings)
5751
0
                    bailout(tokenlist,
5752
0
                            errorLogger,
5753
0
                            tok,
5754
0
                            "variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
5755
0
                return;
5756
0
            }
5757
5758
1.12k
            if (cond.true_values.empty() && cond.false_values.empty())
5759
0
                return;
5760
5761
1.12k
            std::list<ValueFlow::Value> values = cond.true_values;
5762
1.12k
            if (cond.true_values != cond.false_values)
5763
715
                values.insert(values.end(), cond.false_values.cbegin(), cond.false_values.cend());
5764
5765
            // extra logic for unsigned variables 'i>=1' => possible value can also be 0
5766
1.12k
            if (match97(tok)) {
5767
715
                if (cond.vartok->valueType() && cond.vartok->valueType()->sign != ValueType::Sign::UNSIGNED)
5768
473
                    return;
5769
5770
484
                values.remove_if([](const ValueFlow::Value& v) {
5771
484
                    if (v.isIntValue())
5772
16
                        return v.intvalue != 0;
5773
468
                    return false;
5774
484
                });
5775
242
            }
5776
655
            if (values.empty())
5777
2
                return;
5778
5779
            // bailout: for/while-condition, variable is changed in while loop
5780
653
            if (match98(top->previous()) && match44(top->link())) {
5781
5782
                // Variable changed in 3rd for-expression
5783
156
                if (match37(top->previous())) {
5784
0
                    if (top->astOperand2() && top->astOperand2()->astOperand2() &&
5785
0
                        findExpressionChanged(
5786
0
                            cond.vartok, top->astOperand2()->astOperand2(), top->link(), settings)) {
5787
0
                        if (settings.debugwarnings)
5788
0
                            bailout(tokenlist,
5789
0
                                    errorLogger,
5790
0
                                    tok,
5791
0
                                    "variable '" + cond.vartok->expressionString() + "' used in loop");
5792
0
                        return;
5793
0
                    }
5794
0
                }
5795
5796
                // Variable changed in loop code
5797
156
                const Token* const start = top;
5798
156
                const Token* const block = top->link()->next();
5799
156
                const Token* const end = block->link();
5800
5801
156
                if (findExpressionChanged(cond.vartok, start, end, settings)) {
5802
                    // If its reassigned in loop then analyze from the end
5803
20
                    if (!match96(tok) &&
5804
24
                        findExpression(cond.vartok->exprId(), start, end, [&](const Token* tok2) {
5805
24
                        return match95(tok2->astParent()) && astIsLHS(tok2);
5806
24
                    }) && !findEscapeStatement(block->scope(), &settings.library)) {
5807
                        // Start at the end of the loop body
5808
0
                        Token* bodyTok = top->link()->next();
5809
0
                        reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist, errorLogger, settings);
5810
0
                    }
5811
20
                    if (settings.debugwarnings)
5812
20
                        bailout(tokenlist,
5813
20
                                errorLogger,
5814
20
                                tok,
5815
20
                                "variable '" + cond.vartok->expressionString() + "' used in loop");
5816
20
                    return;
5817
20
                }
5818
156
            }
5819
5820
633
            Token* startTok = nullptr;
5821
633
            if (astIsRHS(tok))
5822
527
                startTok = tok->astParent();
5823
106
            else if (astIsLHS(tok))
5824
106
                startTok = previousBeforeAstLeftmostLeaf(tok->astParent());
5825
633
            if (!startTok)
5826
0
                startTok = tok->previous();
5827
5828
633
            reverse(startTok, nullptr, cond.vartok, values, tokenlist, errorLogger, settings);
5829
633
        });
5830
4.69k
    }
5831
5832
    static Token* skipNotAndCasts(Token* tok, bool* inverted = nullptr)
5833
1.26k
    {
5834
1.26k
        for (; tok->astParent(); tok = tok->astParent()) {
5835
1.26k
            if (match99(tok->astParent())) {
5836
0
                if (inverted)
5837
0
                    *inverted ^= true;
5838
0
                continue;
5839
0
            }
5840
1.26k
            if (match100(tok->astParent())) {
5841
46
                const Token* sibling = tok->astSibling();
5842
46
                if (sibling->hasKnownIntValue() && (astIsBool(tok) || astIsBool(sibling))) {
5843
0
                    const bool value = !!sibling->values().front().intvalue;
5844
0
                    if (inverted)
5845
0
                        *inverted ^= value == match101(tok->astParent());
5846
0
                    continue;
5847
0
                }
5848
46
            }
5849
1.26k
            if (tok->astParent()->isCast() && astIsBool(tok->astParent()))
5850
0
                continue;
5851
1.26k
            return tok;
5852
1.26k
        }
5853
0
        return tok;
5854
1.26k
    }
5855
5856
    static void fillFromPath(ProgramMemory& pm, const Token* top, MathLib::bigint path, const Settings& settings)
5857
0
    {
5858
0
        if (path < 1)
5859
0
            return;
5860
0
        visitAstNodes(top, [&](const Token* tok) {
5861
0
            const ValueFlow::Value* v = ValueFlow::findValue(tok->values(), settings, [&](const ValueFlow::Value& v) {
5862
0
                return v.path == path && isNonConditionalPossibleIntValue(v);
5863
0
            });
5864
0
            if (v == nullptr)
5865
0
                return ChildrenToVisit::op1_and_op2;
5866
0
            pm.setValue(tok, *v);
5867
0
            return ChildrenToVisit::op1_and_op2;
5868
0
        });
5869
0
    }
5870
5871
    void afterCondition(TokenList& tokenlist,
5872
                        const SymbolDatabase& symboldatabase,
5873
                        ErrorLogger& errorLogger,
5874
                        const Settings& settings,
5875
4.69k
                        const std::set<const Scope*>& skippedFunctions) const {
5876
4.69k
        traverseCondition(symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* condTok, const Scope* scope) {
5877
1.26k
            const MathLib::bigint path = cond.getPath();
5878
1.26k
            const bool allowKnown = path == 0;
5879
5880
1.26k
            std::list<ValueFlow::Value> thenValues;
5881
1.26k
            std::list<ValueFlow::Value> elseValues;
5882
5883
1.26k
            Token* ctx = cond.getContextAndValues(condTok, thenValues, elseValues);
5884
5885
1.26k
            if (match102(ctx->astParent())) {
5886
0
                Token* parent = ctx->astParent();
5887
0
                if (astIsRHS(ctx) && astIsLHS(parent) && parent->astParent() &&
5888
0
                    parent->str() == parent->astParent()->str())
5889
0
                    parent = parent->astParent();
5890
0
                else if (!astIsLHS(ctx)) {
5891
0
                    parent = nullptr;
5892
0
                }
5893
0
                if (parent) {
5894
0
                    std::vector<Token*> nextExprs = {parent->astOperand2()};
5895
0
                    if (astIsLHS(parent) && parent->astParent() && parent->astParent()->str() == parent->str()) {
5896
0
                        nextExprs.push_back(parent->astParent()->astOperand2());
5897
0
                    }
5898
0
                    std::list<ValueFlow::Value> andValues;
5899
0
                    std::list<ValueFlow::Value> orValues;
5900
0
                    cond.getContextAndValues(condTok, andValues, orValues, true);
5901
5902
0
                    const std::string& op(parent->str());
5903
0
                    std::list<ValueFlow::Value> values;
5904
0
                    if (op == MatchCompiler::makeConstString("&&"))
5905
0
                        values = std::move(andValues);
5906
0
                    else if (op == MatchCompiler::makeConstString("||"))
5907
0
                        values = std::move(orValues);
5908
0
                    if (allowKnown && (match100(condTok) || cond.isBool()))
5909
0
                        changePossibleToKnown(values);
5910
0
                    if (astIsFloat(cond.vartok, false) ||
5911
0
                        (!cond.vartok->valueType() &&
5912
0
                         std::all_of(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) {
5913
0
                        return v.isIntValue() || v.isFloatValue();
5914
0
                    })))
5915
0
                        values.remove_if([&](const ValueFlow::Value& v) {
5916
0
                            return v.isImpossible();
5917
0
                        });
5918
0
                    for (Token* start:nextExprs) {
5919
0
                        Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, errorLogger, settings);
5920
0
                        if (r.terminate != Analyzer::Terminate::None || r.action.isModified())
5921
0
                            return;
5922
0
                    }
5923
0
                }
5924
0
            }
5925
5926
1.26k
            {
5927
1.26k
                const Token* tok2 = condTok;
5928
1.26k
                std::string op;
5929
1.26k
                bool mixedOperators = false;
5930
3.03k
                while (tok2->astParent()) {
5931
1.76k
                    const Token* parent = tok2->astParent();
5932
1.76k
                    if (match102(parent)) {
5933
0
                        if (op.empty()) {
5934
0
                            op = parent->str();
5935
0
                        } else if (op != parent->str()) {
5936
0
                            mixedOperators = true;
5937
0
                            break;
5938
0
                        }
5939
0
                    }
5940
1.76k
                    if (parent->str() == MatchCompiler::makeConstString("!")) {
5941
0
                        op = (op == MatchCompiler::makeConstString("&&") ? "||" : "&&");
5942
0
                    }
5943
1.76k
                    tok2 = parent;
5944
1.76k
                }
5945
5946
1.26k
                if (mixedOperators) {
5947
0
                    return;
5948
0
                }
5949
1.26k
            }
5950
5951
1.26k
            Token* top = condTok->astTop();
5952
5953
1.26k
            if (top->previous()->isExpandedMacro()) {
5954
0
                for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
5955
0
                    for (ValueFlow::Value& v : *values)
5956
0
                        v.macro = true;
5957
0
                }
5958
0
            }
5959
5960
1.26k
            Token* condTop = ctx->astParent();
5961
1.26k
            {
5962
1.26k
                bool inverted2 = false;
5963
1.26k
                while (match102(condTop)) {
5964
0
                    Token* parent = skipNotAndCasts(condTop, &inverted2)->astParent();
5965
0
                    if (!parent)
5966
0
                        break;
5967
0
                    condTop = parent;
5968
0
                }
5969
1.26k
                if (inverted2)
5970
0
                    std::swap(thenValues, elseValues);
5971
1.26k
            }
5972
5973
1.26k
            if (!condTop)
5974
0
                return;
5975
5976
1.26k
            if (match22(condTop)) {
5977
0
                Token* colon = condTop->astOperand2();
5978
0
                forward(colon->astOperand1(), cond.vartok, thenValues, tokenlist, errorLogger, settings);
5979
0
                forward(colon->astOperand2(), cond.vartok, elseValues, tokenlist, errorLogger, settings);
5980
                // TODO: Handle after condition
5981
0
                return;
5982
0
            }
5983
5984
1.26k
            if (condTop != top && condTop->str() != MatchCompiler::makeConstString(";"))
5985
376
                return;
5986
5987
891
            if (!match14(top->previous()))
5988
0
                return;
5989
5990
891
            if (top->strAt(-1) == MatchCompiler::makeConstString("for")) {
5991
0
                if (!match12(condTok))
5992
0
                    return;
5993
0
                if (!match33(condTok->astParent()))
5994
0
                    return;
5995
0
                const Token* stepTok = getStepTok(top);
5996
0
                if (cond.vartok->varId() == 0)
5997
0
                    return;
5998
0
                if (!cond.vartok->variable())
5999
0
                    return;
6000
0
                if (!match103(stepTok))
6001
0
                    return;
6002
0
                std::set<ValueFlow::Value::Bound> bounds;
6003
0
                for (const ValueFlow::Value& v : thenValues) {
6004
0
                    if (v.bound != ValueFlow::Value::Bound::Point && v.isImpossible())
6005
0
                        continue;
6006
0
                    bounds.insert(v.bound);
6007
0
                }
6008
0
                if (match82(stepTok) && bounds.count(ValueFlow::Value::Bound::Lower) > 0)
6009
0
                    return;
6010
0
                if (match83(stepTok) && bounds.count(ValueFlow::Value::Bound::Upper) > 0)
6011
0
                    return;
6012
0
                const Token* childTok = condTok->astOperand1();
6013
0
                if (!childTok)
6014
0
                    childTok = condTok->astOperand2();
6015
0
                if (!childTok)
6016
0
                    return;
6017
0
                if (childTok->varId() != cond.vartok->varId())
6018
0
                    return;
6019
0
                const Token* startBlock = top->link()->next();
6020
0
                if (isVariableChanged(startBlock,
6021
0
                                      startBlock->link(),
6022
0
                                      cond.vartok->varId(),
6023
0
                                      cond.vartok->variable()->isGlobal(),
6024
0
                                      settings))
6025
0
                    return;
6026
                // Check if condition in for loop is always false
6027
0
                const Token* initTok = getInitTok(top);
6028
0
                ProgramMemory pm;
6029
0
                fillFromPath(pm, initTok, path, settings);
6030
0
                fillFromPath(pm, condTok, path, settings);
6031
0
                execute(initTok, pm, nullptr, nullptr, settings);
6032
0
                MathLib::bigint result = 1;
6033
0
                execute(condTok, pm, &result, nullptr, settings);
6034
0
                if (result == 0)
6035
0
                    return;
6036
                // Remove condition since for condition is not redundant
6037
0
                for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
6038
0
                    for (ValueFlow::Value& v : *values) {
6039
0
                        v.condition = nullptr;
6040
0
                        v.conditional = true;
6041
0
                    }
6042
0
                }
6043
0
            }
6044
6045
891
            bool deadBranch[] = {false, false};
6046
            // start token of conditional code
6047
891
            Token* startTokens[] = {nullptr, nullptr};
6048
            // determine startToken(s)
6049
891
            if (match44(top->link()))
6050
891
                startTokens[0] = top->link()->next();
6051
891
            if (match46(top->link()->linkAt(1)))
6052
396
                startTokens[1] = top->link()->linkAt(1)->tokAt(2);
6053
6054
891
            int changeBlock = -1;
6055
891
            int bailBlock = -1;
6056
6057
2.67k
            for (int i = 0; i < 2; i++) {
6058
1.78k
                const Token* const startToken = startTokens[i];
6059
1.78k
                if (!startToken)
6060
495
                    continue;
6061
1.28k
                std::list<ValueFlow::Value>& values = (i == 0 ? thenValues : elseValues);
6062
1.28k
                if (allowKnown)
6063
1.28k
                    valueFlowSetConditionToKnown(condTok, values, i == 0);
6064
6065
1.28k
                Analyzer::Result r = forward(startTokens[i], startTokens[i]->link(), cond.vartok, values, tokenlist, errorLogger, settings);
6066
1.28k
                deadBranch[i] = r.terminate == Analyzer::Terminate::Escape;
6067
1.28k
                if (r.action.isModified() && !deadBranch[i])
6068
50
                    changeBlock = i;
6069
1.28k
                if (r.terminate != Analyzer::Terminate::None && r.terminate != Analyzer::Terminate::Escape &&
6070
1.28k
                    r.terminate != Analyzer::Terminate::Modified)
6071
775
                    bailBlock = i;
6072
1.28k
                changeKnownToPossible(values);
6073
1.28k
            }
6074
891
            if (changeBlock >= 0 && !match104(top->previous())) {
6075
36
                if (settings.debugwarnings)
6076
36
                    bailout(tokenlist,
6077
36
                            errorLogger,
6078
36
                            startTokens[changeBlock]->link(),
6079
36
                            "valueFlowAfterCondition: " + cond.vartok->expressionString() +
6080
36
                            " is changed in conditional block");
6081
36
                return;
6082
36
            }
6083
855
            if (bailBlock >= 0) {
6084
524
                if (settings.debugwarnings)
6085
524
                    bailout(tokenlist,
6086
524
                            errorLogger,
6087
524
                            startTokens[bailBlock]->link(),
6088
524
                            "valueFlowAfterCondition: bailing in conditional block");
6089
524
                return;
6090
524
            }
6091
6092
            // After conditional code..
6093
331
            if (match44(top->link())) {
6094
331
                Token* after = top->link()->linkAt(1);
6095
331
                bool dead_if = deadBranch[0];
6096
331
                bool dead_else = deadBranch[1];
6097
331
                const Token* unknownFunction = nullptr;
6098
331
                if (condTok->astParent() && match105(top->previous()))
6099
84
                    dead_if = !isBreakScope(after);
6100
247
                else if (!dead_if)
6101
204
                    dead_if = isReturnScope(after, settings.library, &unknownFunction);
6102
6103
331
                if (!dead_if && unknownFunction) {
6104
0
                    if (settings.debugwarnings)
6105
0
                        bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
6106
0
                    return;
6107
0
                }
6108
6109
331
                if (match46(after)) {
6110
133
                    after = after->linkAt(2);
6111
133
                    unknownFunction = nullptr;
6112
133
                    if (!dead_else)
6113
121
                        dead_else = isReturnScope(after, settings.library, &unknownFunction);
6114
133
                    if (!dead_else && unknownFunction) {
6115
0
                        if (settings.debugwarnings)
6116
0
                            bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
6117
0
                        return;
6118
0
                    }
6119
133
                }
6120
6121
331
                if (dead_if && dead_else)
6122
12
                    return;
6123
6124
319
                std::list<ValueFlow::Value> values;
6125
319
                if (dead_if) {
6126
115
                    values = std::move(elseValues);
6127
204
                } else if (dead_else) {
6128
0
                    values = std::move(thenValues);
6129
204
                } else {
6130
204
                    std::copy_if(thenValues.cbegin(),
6131
204
                                 thenValues.cend(),
6132
204
                                 std::back_inserter(values),
6133
204
                                 std::mem_fn(&ValueFlow::Value::isPossible));
6134
204
                    std::copy_if(elseValues.cbegin(),
6135
204
                                 elseValues.cend(),
6136
204
                                 std::back_inserter(values),
6137
204
                                 std::mem_fn(&ValueFlow::Value::isPossible));
6138
204
                }
6139
6140
319
                if (values.empty())
6141
0
                    return;
6142
6143
319
                if (dead_if || dead_else) {
6144
115
                    const Token* parent = condTok->astParent();
6145
                    // Skip the not operator
6146
115
                    while (match99(parent))
6147
0
                        parent = parent->astParent();
6148
115
                    bool possible = false;
6149
115
                    if (match106(parent)) {
6150
0
                        const std::string& op(parent->str());
6151
0
                        while (parent && parent->str() == op)
6152
0
                            parent = parent->astParent();
6153
0
                        if (match99(parent) || match107(parent))
6154
0
                            possible = op == MatchCompiler::makeConstString("||");
6155
0
                        else
6156
0
                            possible = op == MatchCompiler::makeConstString("&&");
6157
0
                    }
6158
115
                    if (possible) {
6159
0
                        values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible));
6160
0
                        changeKnownToPossible(values);
6161
115
                    } else if (allowKnown) {
6162
115
                        valueFlowSetConditionToKnown(condTok, values, true);
6163
115
                        valueFlowSetConditionToKnown(condTok, values, false);
6164
115
                    }
6165
115
                }
6166
319
                if (values.empty())
6167
0
                    return;
6168
393
                const bool isKnown = std::any_of(values.cbegin(), values.cend(), [&](const ValueFlow::Value& v) {
6169
393
                    return v.isKnown() || v.isImpossible();
6170
393
                });
6171
319
                if (isKnown && isBreakOrContinueScope(after)) {
6172
0
                    const Scope* loopScope = getLoopScope(cond.vartok);
6173
0
                    if (loopScope) {
6174
0
                        Analyzer::Result r = forward(after, loopScope->bodyEnd, cond.vartok, values, tokenlist, errorLogger, settings);
6175
0
                        if (r.terminate != Analyzer::Terminate::None)
6176
0
                            return;
6177
0
                        if (r.action.isModified())
6178
0
                            return;
6179
0
                        auto* start = const_cast<Token*>(loopScope->bodyEnd);
6180
0
                        if (match108(start)) {
6181
0
                            start = start->tokAt(2);
6182
0
                            forward(start, start->link(), cond.vartok, values, tokenlist, errorLogger, settings);
6183
0
                            start = start->link();
6184
0
                        }
6185
0
                        values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible));
6186
0
                        changeKnownToPossible(values);
6187
0
                    }
6188
0
                }
6189
319
                forward(after, ValueFlow::getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, errorLogger, settings);
6190
319
            }
6191
331
        });
6192
4.69k
    }
6193
9.39k
    virtual ~ConditionHandler() = default;
6194
4.69k
    ConditionHandler(const ConditionHandler&) = default;
6195
protected:
6196
4.69k
    ConditionHandler() = default;
6197
};
6198
6199
static void valueFlowCondition(const ValuePtr<ConditionHandler>& handler,
6200
                               TokenList& tokenlist,
6201
                               SymbolDatabase& symboldatabase,
6202
                               ErrorLogger& errorLogger,
6203
                               const Settings& settings,
6204
                               const std::set<const Scope*>& skippedFunctions)
6205
4.69k
{
6206
4.69k
    handler->beforeCondition(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
6207
4.69k
    handler->afterCondition(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
6208
4.69k
}
6209
6210
struct SimpleConditionHandler : ConditionHandler {
6211
15.6k
    std::vector<Condition> parse(const Token* tok, const Settings& /*settings*/) const override {
6212
6213
15.6k
        std::vector<Condition> conds;
6214
15.6k
        parseCompareEachInt(tok, [&](const Token* vartok, ValueFlow::Value true_value, ValueFlow::Value false_value) {
6215
248
            if (vartok->hasKnownIntValue())
6216
0
                return;
6217
248
            if (vartok->str() == MatchCompiler::makeConstString("=") && vartok->astOperand1() && vartok->astOperand2())
6218
12
                vartok = vartok->astOperand1();
6219
248
            Condition cond;
6220
248
            cond.true_values.push_back(std::move(true_value));
6221
248
            cond.false_values.push_back(std::move(false_value));
6222
248
            cond.vartok = vartok;
6223
248
            conds.push_back(std::move(cond));
6224
248
        });
6225
15.6k
        if (!conds.empty())
6226
248
            return conds;
6227
6228
15.4k
        const Token* vartok = nullptr;
6229
6230
15.4k
        if (tok->str() == MatchCompiler::makeConstString("!")) {
6231
0
            vartok = tok->astOperand1();
6232
6233
15.4k
        } else if (tok->astParent() && (match109(tok->astParent()) ||
6234
12.9k
                                        match110(tok->astParent()->previous()))) {
6235
2.30k
            if (match9(tok))
6236
292
                vartok = tok->astOperand1();
6237
2.01k
            else if (!match111(tok))
6238
272
                vartok = tok;
6239
2.30k
        }
6240
6241
15.4k
        if (!vartok)
6242
14.8k
            return {};
6243
564
        Condition cond;
6244
564
        cond.true_values.emplace_back(tok, 0LL);
6245
564
        cond.false_values.emplace_back(tok, 0LL);
6246
564
        cond.vartok = vartok;
6247
6248
564
        return {std::move(cond)};
6249
15.4k
    }
6250
};
6251
6252
struct IteratorInferModel : InferModel {
6253
    virtual ValueFlow::Value::ValueType getType() const = 0;
6254
0
    bool match(const ValueFlow::Value& value) const override {
6255
0
        return value.valueType == getType();
6256
0
    }
6257
    ValueFlow::Value yield(MathLib::bigint value) const override
6258
0
    {
6259
0
        ValueFlow::Value result(value);
6260
0
        result.valueType = getType();
6261
0
        result.setKnown();
6262
0
        return result;
6263
0
    }
6264
};
6265
6266
struct EndIteratorInferModel : IteratorInferModel {
6267
0
    ValueFlow::Value::ValueType getType() const override {
6268
0
        return ValueFlow::Value::ValueType::ITERATOR_END;
6269
0
    }
6270
};
6271
6272
struct StartIteratorInferModel : IteratorInferModel {
6273
0
    ValueFlow::Value::ValueType getType() const override {
6274
0
        return ValueFlow::Value::ValueType::ITERATOR_END;
6275
0
    }
6276
};
6277
6278
1.64k
static bool isIntegralOnlyOperator(const Token* tok) {
6279
1.64k
    return match112(tok);
6280
1.64k
}
6281
6282
static bool isIntegralOrPointer(const Token* tok)
6283
2.85k
{
6284
2.85k
    if (!tok)
6285
0
        return false;
6286
2.85k
    if (astIsIntegral(tok, false))
6287
1.98k
        return true;
6288
870
    if (astIsPointer(tok))
6289
2
        return true;
6290
868
    if (match113(tok))
6291
0
        return true;
6292
868
    if (tok->valueType())
6293
0
        return false;
6294
    // These operators only work on integers
6295
868
    if (isIntegralOnlyOperator(tok))
6296
91
        return true;
6297
777
    if (isIntegralOnlyOperator(tok->astParent()))
6298
0
        return true;
6299
777
    if (match114(tok) && tok->isBinaryOp())
6300
135
        return isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2());
6301
642
    return false;
6302
777
}
6303
6304
static void valueFlowInferCondition(TokenList& tokenlist, const Settings& settings)
6305
1.17k
{
6306
90.3k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
6307
89.1k
        if (!tok->astParent())
6308
57.7k
            continue;
6309
31.3k
        if (tok->hasKnownIntValue())
6310
7.71k
            continue;
6311
23.6k
        if (match115(tok) && tok->astOperand1() && tok->astOperand2()) {
6312
1.55k
            if (astIsIterator(tok->astOperand1()) || astIsIterator(tok->astOperand2())) {
6313
0
                static const std::array<ValuePtr<InferModel>, 2> iteratorModels = {EndIteratorInferModel{},
6314
0
                                                                                   StartIteratorInferModel{}};
6315
0
                for (const ValuePtr<InferModel>& model : iteratorModels) {
6316
0
                    std::vector<ValueFlow::Value> result =
6317
0
                        infer(model, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
6318
0
                    for (ValueFlow::Value value : result) {
6319
0
                        value.valueType = ValueFlow::Value::ValueType::INT;
6320
0
                        setTokenValue(tok, std::move(value), settings);
6321
0
                    }
6322
0
                }
6323
1.55k
            } else if (isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2())) {
6324
911
                std::vector<ValueFlow::Value> result =
6325
911
                    infer(makeIntegralInferModel(), tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
6326
911
                for (ValueFlow::Value& value : result) {
6327
7
                    setTokenValue(tok, std::move(value), settings);
6328
7
                }
6329
911
            }
6330
22.1k
        } else if (match116(tok->astParent()) ||
6331
22.1k
                   match110(tok->astParent()->previous()) ||
6332
22.1k
                   (astIsPointer(tok) && isUsedAsBool(tok, settings))) {
6333
1.45k
            std::vector<ValueFlow::Value> result = infer(makeIntegralInferModel(), "!=", tok->values(), 0);
6334
1.45k
            if (result.size() != 1)
6335
1.45k
                continue;
6336
0
            ValueFlow::Value value = result.front();
6337
0
            setTokenValue(tok, std::move(value), settings);
6338
0
        }
6339
23.6k
    }
6340
1.17k
}
6341
6342
struct SymbolicConditionHandler : SimpleConditionHandler {
6343
6344
    static bool isNegatedBool(const Token* tok)
6345
644
    {
6346
644
        if (!match99(tok))
6347
644
            return false;
6348
0
        return (astIsBool(tok->astOperand1()));
6349
644
    }
6350
6351
    static const Token* skipNot(const Token* tok)
6352
0
    {
6353
0
        if (!match99(tok))
6354
0
            return tok;
6355
0
        return tok->astOperand1();
6356
0
    }
6357
6358
    std::vector<Condition> parse(const Token* tok, const Settings& settings) const override
6359
15.6k
    {
6360
15.6k
        if (!match12(tok))
6361
12.6k
            return {};
6362
3.00k
        if (tok->hasKnownIntValue())
6363
610
            return {};
6364
2.39k
        if (!tok->astOperand1() || tok->astOperand1()->hasKnownIntValue() || tok->astOperand1()->isLiteral())
6365
154
            return {};
6366
2.23k
        if (!tok->astOperand2() || tok->astOperand2()->hasKnownIntValue() || tok->astOperand2()->isLiteral())
6367
92
            return {};
6368
2.14k
        if (!isConstExpression(tok, settings.library))
6369
1.17k
            return {};
6370
6371
972
        std::vector<Condition> result;
6372
972
        auto addCond = [&](const Token* lhsTok, const Token* rhsTok, bool inverted) {
6373
2.91k
            for (int i = 0; i < 2; i++) {
6374
1.94k
                const bool lhs = i == 0;
6375
1.94k
                const Token* vartok = lhs ? lhsTok : rhsTok;
6376
1.94k
                const Token* valuetok = lhs ? rhsTok : lhsTok;
6377
1.94k
                if (valuetok->exprId() == 0)
6378
0
                    continue;
6379
1.94k
                if (valuetok->hasKnownSymbolicValue(vartok))
6380
2
                    continue;
6381
1.94k
                if (vartok->hasKnownSymbolicValue(valuetok))
6382
2
                    continue;
6383
1.94k
                ValueFlow::Value true_value;
6384
1.94k
                ValueFlow::Value false_value;
6385
1.94k
                setConditionalValues(tok, !lhs, 0, true_value, false_value);
6386
1.94k
                setSymbolic(true_value, valuetok);
6387
1.94k
                setSymbolic(false_value, valuetok);
6388
6389
1.94k
                Condition cond;
6390
1.94k
                cond.true_values = {std::move(true_value)};
6391
1.94k
                cond.false_values = {std::move(false_value)};
6392
1.94k
                cond.vartok = vartok;
6393
1.94k
                cond.inverted = inverted;
6394
1.94k
                result.push_back(std::move(cond));
6395
1.94k
            }
6396
972
        };
6397
972
        addCond(tok->astOperand1(), tok->astOperand2(), false);
6398
972
        if (match100(tok) && (isNegatedBool(tok->astOperand1()) || isNegatedBool(tok->astOperand2()))) {
6399
0
            const Token* lhsTok = skipNot(tok->astOperand1());
6400
0
            const Token* rhsTok = skipNot(tok->astOperand2());
6401
0
            addCond(lhsTok, rhsTok, !(isNegatedBool(tok->astOperand1()) && isNegatedBool(tok->astOperand2())));
6402
0
        }
6403
972
        return result;
6404
2.14k
    }
6405
};
6406
6407
static bool valueFlowForLoop2(const Token *tok,
6408
                              ProgramMemory *memory1,
6409
                              ProgramMemory *memory2,
6410
                              ProgramMemory *memoryAfter,
6411
                              const Settings& settings)
6412
0
{
6413
    // for ( firstExpression ; secondExpression ; thirdExpression )
6414
0
    const Token *firstExpression  = tok->next()->astOperand2()->astOperand1();
6415
0
    const Token *secondExpression = tok->next()->astOperand2()->astOperand2()->astOperand1();
6416
0
    const Token *thirdExpression = tok->next()->astOperand2()->astOperand2()->astOperand2();
6417
6418
0
    ProgramMemory programMemory;
6419
0
    MathLib::bigint result(0);
6420
0
    bool error = false;
6421
0
    execute(firstExpression, programMemory, &result, &error, settings);
6422
0
    if (error)
6423
0
        return false;
6424
0
    execute(secondExpression, programMemory, &result, &error, settings);
6425
0
    if (result == 0) // 2nd expression is false => no looping
6426
0
        return false;
6427
0
    if (error) {
6428
        // If a variable is reassigned in second expression, return false
6429
0
        bool reassign = false;
6430
0
        visitAstNodes(secondExpression,
6431
0
                      [&](const Token *t) {
6432
0
            if (t->str() == MatchCompiler::makeConstString("=") && t->astOperand1() && programMemory.hasValue(t->astOperand1()->varId()))
6433
                // TODO: investigate what variable is assigned.
6434
0
                reassign = true;
6435
0
            return reassign ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
6436
0
        });
6437
0
        if (reassign)
6438
0
            return false;
6439
0
    }
6440
6441
0
    ProgramMemory startMemory(programMemory);
6442
0
    ProgramMemory endMemory;
6443
6444
0
    int maxcount = settings.vfOptions.maxForLoopCount;
6445
0
    while (result != 0 && !error && --maxcount > 0) {
6446
0
        endMemory = programMemory;
6447
0
        execute(thirdExpression, programMemory, &result, &error, settings);
6448
0
        if (!error)
6449
0
            execute(secondExpression, programMemory, &result, &error, settings);
6450
0
    }
6451
    // TODO: add bailout message
6452
6453
0
    if (memory1)
6454
0
        memory1->swap(startMemory);
6455
0
    if (!error) {
6456
0
        if (memory2)
6457
0
            memory2->swap(endMemory);
6458
0
        if (memoryAfter)
6459
0
            memoryAfter->swap(programMemory);
6460
0
    }
6461
6462
0
    return true;
6463
0
}
6464
6465
static void valueFlowForLoopSimplify(Token* const bodyStart,
6466
                                     const Token* expr,
6467
                                     bool globalvar,
6468
                                     const MathLib::bigint value,
6469
                                     const TokenList& tokenlist,
6470
                                     ErrorLogger& errorLogger,
6471
                                     const Settings& settings)
6472
0
{
6473
    // TODO: Refactor this to use arbitrary expressions
6474
0
    assert(expr->varId() > 0);
6475
0
    const Token * const bodyEnd = bodyStart->link();
6476
6477
    // Is variable modified inside for loop
6478
0
    if (isVariableChanged(bodyStart, bodyEnd, expr->varId(), globalvar, settings))
6479
0
        return;
6480
6481
0
    if (const Token* escape = findEscapeStatement(bodyStart->scope(), &settings.library)) {
6482
0
        if (settings.debugwarnings)
6483
0
            bailout(tokenlist, errorLogger, escape, "For loop variable bailout on escape statement");
6484
0
        return;
6485
0
    }
6486
6487
0
    for (Token *tok2 = bodyStart->next(); tok2 != bodyEnd; tok2 = tok2->next()) {
6488
0
        if (tok2->varId() == expr->varId()) {
6489
0
            const Token * parent = tok2->astParent();
6490
0
            while (parent) {
6491
0
                const Token * const p = parent;
6492
0
                parent = parent->astParent();
6493
0
                if (!parent || parent->str() == MatchCompiler::makeConstString(":"))
6494
0
                    break;
6495
0
                if (parent->str() == MatchCompiler::makeConstString("?")) {
6496
0
                    if (parent->astOperand2() != p)
6497
0
                        parent = nullptr;
6498
0
                    break;
6499
0
                }
6500
0
            }
6501
0
            if (parent) {
6502
0
                if (settings.debugwarnings)
6503
0
                    bailout(tokenlist, errorLogger, tok2, "For loop variable " + tok2->str() + " stopping on ?");
6504
0
                continue;
6505
0
            }
6506
6507
0
            ValueFlow::Value value1(value);
6508
0
            value1.varId = tok2->varId();
6509
0
            setTokenValue(tok2, std::move(value1), settings);
6510
0
        }
6511
6512
0
        if (match102(tok2)) {
6513
0
            const ProgramMemory programMemory(getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings));
6514
0
            if ((tok2->str() == MatchCompiler::makeConstString("&&") && !conditionIsTrue(tok2->astOperand1(), programMemory, settings)) ||
6515
0
                (tok2->str() == MatchCompiler::makeConstString("||") && !conditionIsFalse(tok2->astOperand1(), programMemory, settings))) {
6516
                // Skip second expression..
6517
0
                Token *parent = tok2;
6518
0
                while (parent && parent->str() == tok2->str())
6519
0
                    parent = parent->astParent();
6520
                // Jump to end of condition
6521
0
                if (parent && parent->str() == MatchCompiler::makeConstString("(")) {
6522
0
                    tok2 = parent->link();
6523
                    // cast
6524
0
                    if (match117(tok2))
6525
0
                        tok2 = tok2->linkAt(1);
6526
0
                }
6527
0
            }
6528
0
        }
6529
0
        const Token* vartok = expr;
6530
0
        const Token* rml = nextAfterAstRightmostLeaf(vartok);
6531
0
        if (rml)
6532
0
            vartok = rml->str() == MatchCompiler::makeConstString("]") ? rml : rml->previous();
6533
0
        if (vartok->str() == MatchCompiler::makeConstString("]") && vartok->link()->previous())
6534
0
            vartok = vartok->link()->previous();
6535
6536
0
        if ((tok2->str() == MatchCompiler::makeConstString("&&") &&
6537
0
             conditionIsFalse(tok2->astOperand1(),
6538
0
                              getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings),
6539
0
                              settings)) ||
6540
0
            (tok2->str() == MatchCompiler::makeConstString("||") &&
6541
0
             conditionIsTrue(tok2->astOperand1(),
6542
0
                             getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings),
6543
0
                             settings)))
6544
0
            break;
6545
6546
0
        if (match44(tok2)) {
6547
0
            if (vartok->varId() && findmatch118(tok2->link(), tok2, vartok->varId()) ) {
6548
0
                if (settings.debugwarnings)
6549
0
                    bailout(tokenlist, errorLogger, tok2, "For loop variable skipping conditional scope");
6550
0
                tok2 = tok2->linkAt(1);
6551
0
                if (match46(tok2)) {
6552
0
                    tok2 = tok2->linkAt(2);
6553
0
                }
6554
0
            }
6555
0
            else {
6556
0
                if (settings.debugwarnings)
6557
0
                    bailout(tokenlist, errorLogger, tok2, "For loop skipping {} code");
6558
0
                tok2 = tok2->linkAt(1);
6559
0
                if (match46(tok2))
6560
0
                    tok2 = tok2->linkAt(2);
6561
0
            }
6562
0
        }
6563
0
    }
6564
0
}
6565
6566
static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, ErrorLogger & errorLogger, const Settings& settings)
6567
0
{
6568
0
    const Token *vartok = nullptr;
6569
0
    for (const Token *tok = fortok; tok; tok = tok->next()) {
6570
0
        if (tok->varId() == varid) {
6571
0
            vartok = tok;
6572
0
            break;
6573
0
        }
6574
0
    }
6575
0
    if (!vartok || !vartok->variable())
6576
0
        return;
6577
6578
0
    const Variable *var = vartok->variable();
6579
0
    const Token *endToken = nullptr;
6580
0
    if (var->isLocal())
6581
0
        endToken = var->scope()->bodyEnd;
6582
0
    else
6583
0
        endToken = fortok->scope()->bodyEnd;
6584
6585
0
    Token* blockTok = fortok->linkAt(1)->linkAt(1);
6586
0
    if (blockTok != endToken) {
6587
0
        ValueFlow::Value v{num};
6588
0
        v.errorPath.emplace_back(fortok,"After for loop, " + var->name() + " has value " + v.infoString());
6589
6590
0
        valueFlowForward(blockTok->next(), endToken, vartok, std::move(v), tokenlist, errorLogger, settings);
6591
0
    }
6592
0
}
6593
6594
static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger &errorLogger, const Settings &settings)
6595
1.17k
{
6596
4.60k
    for (const Scope &scope : symboldatabase.scopeList) {
6597
4.60k
        if (scope.type != Scope::eFor)
6598
4.60k
            continue;
6599
6600
0
        auto* tok = const_cast<Token*>(scope.classDef);
6601
0
        auto* const bodyStart = const_cast<Token*>(scope.bodyStart);
6602
6603
0
        if (!match33(tok->next()->astOperand2()) ||
6604
0
            !match33(tok->next()->astOperand2()->astOperand2()))
6605
0
            continue;
6606
6607
0
        nonneg int varid;
6608
0
        bool knownInitValue, partialCond;
6609
0
        MathLib::bigint initValue, stepValue, lastValue;
6610
6611
0
        if (extractForLoopValues(tok, varid, knownInitValue, initValue, partialCond, stepValue, lastValue)) {
6612
0
            const bool executeBody = !knownInitValue || initValue <= lastValue;
6613
0
            const Token* vartok = findmatch118(tok, bodyStart, varid) ;
6614
0
            if (executeBody && vartok) {
6615
0
                std::list<ValueFlow::Value> initValues;
6616
0
                initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower);
6617
0
                initValues.push_back(ValueFlow::asImpossible(initValues.back()));
6618
0
                Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, std::move(initValues), tokenlist, errorLogger, settings);
6619
6620
0
                if (!result.action.isModified()) {
6621
0
                    std::list<ValueFlow::Value> lastValues;
6622
0
                    lastValues.emplace_back(lastValue, ValueFlow::Value::Bound::Upper);
6623
0
                    lastValues.back().conditional = true;
6624
0
                    lastValues.push_back(ValueFlow::asImpossible(lastValues.back()));
6625
0
                    if (stepValue != 1)
6626
0
                        lastValues.pop_front();
6627
0
                    valueFlowForward(bodyStart, bodyStart->link(), vartok, std::move(lastValues), tokenlist, errorLogger, settings);
6628
0
                }
6629
0
            }
6630
0
            const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue;
6631
0
            valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, errorLogger, settings);
6632
0
        } else {
6633
0
            ProgramMemory mem1, mem2, memAfter;
6634
0
            if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter, settings)) {
6635
0
                for (const auto& p : mem1) {
6636
0
                    if (!p.second.isIntValue())
6637
0
                        continue;
6638
0
                    if (p.second.isImpossible())
6639
0
                        continue;
6640
0
                    if (p.first.tok->varId() == 0)
6641
0
                        continue;
6642
0
                    valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
6643
0
                }
6644
0
                for (const auto& p : mem2) {
6645
0
                    if (!p.second.isIntValue())
6646
0
                        continue;
6647
0
                    if (p.second.isImpossible())
6648
0
                        continue;
6649
0
                    if (p.first.tok->varId() == 0)
6650
0
                        continue;
6651
0
                    valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
6652
0
                }
6653
0
                for (const auto& p : memAfter) {
6654
0
                    if (!p.second.isIntValue())
6655
0
                        continue;
6656
0
                    if (p.second.isImpossible())
6657
0
                        continue;
6658
0
                    if (p.first.tok->varId() == 0)
6659
0
                        continue;
6660
0
                    valueFlowForLoopSimplifyAfter(tok, p.first.getExpressionId(), p.second.intvalue, tokenlist, errorLogger, settings);
6661
0
                }
6662
0
            }
6663
0
        }
6664
0
    }
6665
1.17k
}
6666
6667
template<class Key, class F>
6668
static bool productParams(const Settings& settings, const std::unordered_map<Key, std::list<ValueFlow::Value>>& vars, F f)
6669
0
{
6670
0
    using Args = std::vector<std::unordered_map<Key, ValueFlow::Value>>;
6671
0
    Args args(1);
6672
    // Compute cartesian product of all arguments
6673
0
    for (const auto& p : vars) {
6674
0
        if (p.second.empty())
6675
0
            continue;
6676
0
        args.back()[p.first] = p.second.front();
6677
0
    }
6678
0
    bool bail = false;
6679
0
    int max = settings.vfOptions.maxSubFunctionArgs;
6680
0
    for (const auto& p : vars) {
6681
0
        if (args.size() > max) {
6682
0
            bail = true;
6683
0
            break;
6684
0
        }
6685
0
        if (p.second.empty())
6686
0
            continue;
6687
0
        std::for_each(std::next(p.second.begin()), p.second.end(), [&](const ValueFlow::Value& value) {
6688
0
            Args new_args;
6689
0
            for (auto arg : args) {
6690
0
                if (value.path != 0) {
6691
0
                    for (const auto& q : arg) {
6692
0
                        if (q.first == p.first)
6693
0
                            continue;
6694
0
                        if (q.second.path == 0)
6695
0
                            continue;
6696
0
                        if (q.second.path != value.path)
6697
0
                            return;
6698
0
                    }
6699
0
                }
6700
0
                arg[p.first] = value;
6701
0
                new_args.push_back(std::move(arg));
6702
0
            }
6703
0
            std::copy(new_args.cbegin(), new_args.cend(), std::back_inserter(args));
6704
0
        });
Unexecuted instantiation: valueflow.cpp:productParams<int, valueFlowLibraryFunction(Token*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Settings const&)::$_0>(Settings const&, std::__1::unordered_map<int, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&, valueFlowLibraryFunction(Token*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Settings const&)::$_0)::{lambda(ValueFlow::Value const&)#1}::operator()(ValueFlow::Value const&) const
Unexecuted instantiation: valueflow.cpp:productParams<Variable const*, valueFlowInjectParameter(TokenList const&, ErrorLogger&, Settings const&, Scope const*, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&)::$_0>(Settings const&, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&, valueFlowInjectParameter(TokenList const&, ErrorLogger&, Settings const&, Scope const*, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&)::$_0)::{lambda(ValueFlow::Value const&)#1}::operator()(ValueFlow::Value const&) const
6705
0
    }
6706
6707
0
    if (args.size() > max) {
6708
0
        bail = true;
6709
0
        args.resize(max);
6710
        // TODO: add bailout message
6711
0
    }
6712
6713
0
    for (const auto& arg : args) {
6714
0
        if (arg.empty())
6715
0
            continue;
6716
        // Make sure all arguments are the same path
6717
0
        const MathLib::bigint path = arg.cbegin()->second.path;
6718
0
        if (std::any_of(arg.cbegin(), arg.cend(), [&](const std::pair<Key, ValueFlow::Value>& p) {
6719
0
            return p.second.path != path;
6720
0
        }))
Unexecuted instantiation: valueflow.cpp:productParams<int, valueFlowLibraryFunction(Token*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Settings const&)::$_0>(Settings const&, std::__1::unordered_map<int, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&, valueFlowLibraryFunction(Token*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Settings const&)::$_0)::{lambda(std::__1::pair<int, ValueFlow::Value> const&)#1}::operator()(std::__1::pair<int, ValueFlow::Value> const&) const
Unexecuted instantiation: valueflow.cpp:productParams<Variable const*, valueFlowInjectParameter(TokenList const&, ErrorLogger&, Settings const&, Scope const*, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&)::$_0>(Settings const&, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&, valueFlowInjectParameter(TokenList const&, ErrorLogger&, Settings const&, Scope const*, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&)::$_0)::{lambda(std::__1::pair<Variable const*, ValueFlow::Value> const&)#1}::operator()(std::__1::pair<Variable const*, ValueFlow::Value> const&) const
6721
0
            continue;
6722
0
        f(arg);
6723
0
    }
6724
0
    return !bail;
6725
0
}
Unexecuted instantiation: valueflow.cpp:bool productParams<int, valueFlowLibraryFunction(Token*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Settings const&)::$_0>(Settings const&, std::__1::unordered_map<int, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&, valueFlowLibraryFunction(Token*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Settings const&)::$_0)
Unexecuted instantiation: valueflow.cpp:bool productParams<Variable const*, valueFlowInjectParameter(TokenList const&, ErrorLogger&, Settings const&, Scope const*, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&)::$_0>(Settings const&, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&, valueFlowInjectParameter(TokenList const&, ErrorLogger&, Settings const&, Scope const*, std::__1::unordered_map<Variable const*, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> >, std::__1::hash<Variable const*>, std::__1::equal_to<Variable const*>, std::__1::allocator<std::__1::pair<Variable const* const, std::__1::list<ValueFlow::Value, std::__1::allocator<ValueFlow::Value> > > > > const&)::$_0)
6726
6727
static void valueFlowInjectParameter(const TokenList& tokenlist,
6728
                                     ErrorLogger& errorLogger,
6729
                                     const Settings& settings,
6730
                                     const Scope* functionScope,
6731
                                     const std::unordered_map<const Variable*, std::list<ValueFlow::Value>>& vars)
6732
0
{
6733
0
    const bool r = productParams(settings, vars, [&](const std::unordered_map<const Variable*, ValueFlow::Value>& arg) {
6734
0
        auto a = makeMultiValueFlowAnalyzer(arg, settings);
6735
0
        valueFlowGenericForward(const_cast<Token*>(functionScope->bodyStart),
6736
0
                                functionScope->bodyEnd,
6737
0
                                a,
6738
0
                                tokenlist,
6739
0
                                errorLogger,
6740
0
                                settings);
6741
0
    });
6742
0
    if (!r) {
6743
0
        std::string fname = "<unknown>";
6744
0
        if (const Function* f = functionScope->function)
6745
0
            fname = f->name();
6746
0
        if (settings.debugwarnings)
6747
0
            bailout(tokenlist, errorLogger, functionScope->bodyStart, "Too many argument passed to " + fname);
6748
0
    }
6749
0
}
6750
6751
static void valueFlowInjectParameter(const TokenList& tokenlist,
6752
                                     ErrorLogger& errorLogger,
6753
                                     const Settings& settings,
6754
                                     const Variable* arg,
6755
                                     const Scope* functionScope,
6756
                                     const std::list<ValueFlow::Value>& argvalues)
6757
0
{
6758
    // Is argument passed by value or const reference, and is it a known non-class type?
6759
0
    if (arg->isReference() && !arg->isConst() && !arg->isClass())
6760
0
        return;
6761
6762
    // Set value in function scope..
6763
0
    const nonneg int varid2 = arg->declarationId();
6764
0
    if (!varid2)
6765
0
        return;
6766
6767
0
    valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
6768
0
                     functionScope->bodyEnd,
6769
0
                     arg->nameToken(),
6770
0
                     argvalues,
6771
0
                     tokenlist,
6772
0
                     errorLogger,
6773
0
                     settings);
6774
0
}
6775
6776
static void valueFlowSwitchVariable(const TokenList& tokenlist,
6777
                                    const SymbolDatabase& symboldatabase,
6778
                                    ErrorLogger& errorLogger,
6779
                                    const Settings& settings)
6780
1.17k
{
6781
4.60k
    for (const Scope& scope : symboldatabase.scopeList) {
6782
4.60k
        if (scope.type != Scope::ScopeType::eSwitch)
6783
4.60k
            continue;
6784
0
        if (!match119(scope.classDef))
6785
0
            continue;
6786
0
        const Token* vartok = scope.classDef->tokAt(2);
6787
0
        const Variable* var = vartok->variable();
6788
0
        if (!var)
6789
0
            continue;
6790
6791
        // bailout: global non-const variables
6792
0
        if (!(var->isLocal() || var->isArgument()) && !var->isConst()) {
6793
0
            if (settings.debugwarnings)
6794
0
                bailout(tokenlist, errorLogger, vartok, "switch variable " + var->name() + " is global");
6795
0
            continue;
6796
0
        }
6797
6798
0
        for (const Token* tok = scope.bodyStart->next(); tok != scope.bodyEnd; tok = tok->next()) {
6799
0
            if (tok->str() == MatchCompiler::makeConstString("{")) {
6800
0
                tok = tok->link();
6801
0
                continue;
6802
0
            }
6803
0
            if (match120(tok)) {
6804
0
                std::list<ValueFlow::Value> values;
6805
0
                values.emplace_back(MathLib::toBigNumber(tok->tokAt(1)));
6806
0
                values.back().condition = tok;
6807
0
                values.back().errorPath.emplace_back(tok,
6808
0
                                                     "case " + tok->strAt(1) + ": " + vartok->str() + " is " +
6809
0
                                                     tok->strAt(1) + " here.");
6810
0
                bool known = false;
6811
0
                if ((match4(tok->previous()) || match121(tok->tokAt(-2))) &&
6812
0
                    !match122(tok->tokAt(3)))
6813
0
                    known = true;
6814
0
                while (match123(tok->tokAt(3))) {
6815
0
                    known = false;
6816
0
                    tok = tok->tokAt(3);
6817
0
                    if (!tok->isName())
6818
0
                        tok = tok->next();
6819
0
                    values.emplace_back(MathLib::toBigNumber(tok->tokAt(1)));
6820
0
                    values.back().condition = tok;
6821
0
                    values.back().errorPath.emplace_back(tok,
6822
0
                                                         "case " + tok->strAt(1) + ": " + vartok->str() + " is " +
6823
0
                                                         tok->strAt(1) + " here.");
6824
0
                }
6825
0
                for (auto val = values.cbegin(); val != values.cend(); ++val) {
6826
0
                    valueFlowReverse(tokenlist, const_cast<Token*>(scope.classDef), vartok, *val, errorLogger, settings);
6827
0
                }
6828
0
                if (vartok->variable()->scope()) {
6829
0
                    if (known)
6830
0
                        values.back().setKnown();
6831
6832
                    // FIXME We must check if there is a return. See #9276
6833
                    /*
6834
                       valueFlowForwardVariable(tok->tokAt(3),
6835
                                             vartok->variable()->scope()->bodyEnd,
6836
                                             vartok->variable(),
6837
                                             vartok->varId(),
6838
                                             values,
6839
                                             values.back().isKnown(),
6840
                                             false,
6841
                                             tokenlist,
6842
                                             errorLogger,
6843
                                             settings);
6844
                     */
6845
0
                }
6846
0
            }
6847
0
        }
6848
0
    }
6849
1.17k
}
6850
6851
static std::list<ValueFlow::Value> getFunctionArgumentValues(const Token* argtok)
6852
0
{
6853
0
    std::list<ValueFlow::Value> argvalues(argtok->values());
6854
0
    removeImpossible(argvalues);
6855
0
    if (argvalues.empty() && match124(argtok)) {
6856
0
        argvalues.emplace_back(0);
6857
0
        argvalues.emplace_back(1);
6858
0
    }
6859
0
    return argvalues;
6860
0
}
6861
6862
static void valueFlowLibraryFunction(Token* tok, const std::string& returnValue, const Settings& settings)
6863
0
{
6864
0
    std::unordered_map<nonneg int, std::list<ValueFlow::Value>> argValues;
6865
0
    int argn = 1;
6866
0
    for (const Token* argtok : getArguments(tok->previous())) {
6867
0
        argValues[argn] = getFunctionArgumentValues(argtok);
6868
0
        argn++;
6869
0
    }
6870
0
    if (returnValue.find("arg") != std::string::npos && argValues.empty())
6871
0
        return;
6872
0
    productParams(settings, argValues, [&](const std::unordered_map<nonneg int, ValueFlow::Value>& arg) {
6873
0
        ValueFlow::Value value = evaluateLibraryFunction(arg, returnValue, settings, tok->isCpp());
6874
0
        if (value.isUninitValue())
6875
0
            return;
6876
0
        ValueFlow::Value::ValueKind kind = ValueFlow::Value::ValueKind::Known;
6877
0
        for (auto&& p : arg) {
6878
0
            if (p.second.isPossible())
6879
0
                kind = p.second.valueKind;
6880
0
            if (p.second.isInconclusive()) {
6881
0
                kind = p.second.valueKind;
6882
0
                break;
6883
0
            }
6884
0
        }
6885
0
        if (value.isImpossible() && kind != ValueFlow::Value::ValueKind::Known)
6886
0
            return;
6887
0
        if (!value.isImpossible())
6888
0
            value.valueKind = kind;
6889
0
        setTokenValue(tok, std::move(value), settings);
6890
0
    });
6891
0
}
6892
6893
static void valueFlowSubFunction(const TokenList& tokenlist,
6894
                                 const SymbolDatabase& symboldatabase,
6895
                                 ErrorLogger& errorLogger,
6896
                                 const Settings& settings)
6897
1.17k
{
6898
1.17k
    int id = 0;
6899
2.85k
    for (auto it = symboldatabase.functionScopes.crbegin(); it != symboldatabase.functionScopes.crend(); ++it) {
6900
1.67k
        const Scope* scope = *it;
6901
1.67k
        const Function* function = scope->function;
6902
1.67k
        if (!function)
6903
0
            continue;
6904
41.3k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
6905
39.6k
            if (tok->isKeyword() || !match38(tok))
6906
39.6k
                continue;
6907
6908
0
            const Function* const calledFunction = tok->function();
6909
0
            if (!calledFunction) {
6910
                // library function?
6911
0
                const std::string& returnValue(settings.library.returnValue(tok));
6912
0
                if (!returnValue.empty())
6913
0
                    valueFlowLibraryFunction(tok->next(), returnValue, settings);
6914
0
                continue;
6915
0
            }
6916
6917
0
            const Scope* const calledFunctionScope = calledFunction->functionScope;
6918
0
            if (!calledFunctionScope)
6919
0
                continue;
6920
6921
0
            id++;
6922
0
            std::unordered_map<const Variable*, std::list<ValueFlow::Value>> argvars;
6923
            // TODO: Rewrite this. It does not work well to inject 1 argument at a time.
6924
0
            const std::vector<const Token*>& callArguments = getArguments(tok);
6925
0
            for (int argnr = 0U; argnr < callArguments.size(); ++argnr) {
6926
0
                const Token* argtok = callArguments[argnr];
6927
                // Get function argument
6928
0
                const Variable* const argvar = calledFunction->getArgumentVar(argnr);
6929
0
                if (!argvar)
6930
0
                    break;
6931
6932
                // passing value(s) to function
6933
0
                std::list<ValueFlow::Value> argvalues(getFunctionArgumentValues(argtok));
6934
6935
                // Remove non-local lifetimes
6936
0
                argvalues.remove_if([](const ValueFlow::Value& v) {
6937
0
                    if (v.isLifetimeValue())
6938
0
                        return !v.isLocalLifetimeValue() && !v.isSubFunctionLifetimeValue();
6939
0
                    return false;
6940
0
                });
6941
                // Remove uninit values if argument is passed by value
6942
0
                if (argtok->variable() && !argtok->variable()->isPointer() && argvalues.size() == 1 &&
6943
0
                    argvalues.front().isUninitValue()) {
6944
0
                    if (CheckUninitVar::isVariableUsage(argtok, settings.library, false, CheckUninitVar::Alloc::NO_ALLOC, 0))
6945
0
                        continue;
6946
0
                }
6947
6948
0
                if (argvalues.empty())
6949
0
                    continue;
6950
6951
                // Error path..
6952
0
                for (ValueFlow::Value& v : argvalues) {
6953
0
                    const std::string nr = std::to_string(argnr + 1) + getOrdinalText(argnr + 1);
6954
6955
0
                    v.errorPath.emplace_back(argtok,
6956
0
                                             "Calling function '" + calledFunction->name() + "', " + nr + " argument '" +
6957
0
                                             argtok->expressionString() + "' value is " + v.infoString());
6958
0
                    v.path = 256 * v.path + id % 256;
6959
                    // Change scope of lifetime values
6960
0
                    if (v.isLifetimeValue())
6961
0
                        v.lifetimeScope = ValueFlow::Value::LifetimeScope::SubFunction;
6962
0
                }
6963
6964
                // passed values are not "known"..
6965
0
                lowerToPossible(argvalues);
6966
6967
0
                argvars[argvar] = std::move(argvalues);
6968
0
            }
6969
0
            valueFlowInjectParameter(tokenlist, errorLogger, settings, calledFunctionScope, argvars);
6970
0
        }
6971
1.67k
    }
6972
1.17k
}
6973
6974
static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings)
6975
1.17k
{
6976
1.17k
    if (!tokenlist.isCPP())
6977
0
        return;
6978
6979
1.67k
    for (const Scope* scope : symboldatabase.functionScopes) {
6980
1.67k
        const Function* function = scope->function;
6981
1.67k
        if (!function)
6982
0
            continue;
6983
1.67k
        for (nonneg int arg = function->minArgCount(); arg < function->argCount(); arg++) {
6984
0
            const Variable* var = function->getArgumentVar(arg);
6985
0
            if (var && var->hasDefault() && match125(var->nameToken())) {
6986
0
                const std::list<ValueFlow::Value> &values = var->nameToken()->tokAt(2)->values();
6987
0
                std::list<ValueFlow::Value> argvalues;
6988
0
                for (const ValueFlow::Value &value : values) {
6989
0
                    ValueFlow::Value v(value);
6990
0
                    v.defaultArg = true;
6991
0
                    v.changeKnownToPossible();
6992
0
                    if (v.isPossible())
6993
0
                        argvalues.push_back(std::move(v));
6994
0
                }
6995
0
                if (!argvalues.empty())
6996
0
                    valueFlowInjectParameter(tokenlist, errorLogger, settings, var, scope, argvalues);
6997
0
            }
6998
0
        }
6999
1.67k
    }
7000
1.17k
}
7001
7002
static const ValueFlow::Value* getKnownValueFromToken(const Token* tok)
7003
0
{
7004
0
    if (!tok)
7005
0
        return nullptr;
7006
0
    auto it = std::find_if(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) {
7007
0
        return (v.isIntValue() || v.isContainerSizeValue() || v.isFloatValue()) && v.isKnown();
7008
0
    });
7009
0
    if (it == tok->values().end())
7010
0
        return nullptr;
7011
0
    return std::addressof(*it);
7012
0
}
7013
7014
static const ValueFlow::Value* getKnownValueFromTokens(const std::vector<const Token*>& toks)
7015
0
{
7016
0
    if (toks.empty())
7017
0
        return nullptr;
7018
0
    const ValueFlow::Value* result = getKnownValueFromToken(toks.front());
7019
0
    if (!result)
7020
0
        return nullptr;
7021
0
    if (!std::all_of(std::next(toks.begin()), toks.end(), [&](const Token* tok) {
7022
0
        return std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) {
7023
0
            return v.equalValue(*result) && v.valueKind == result->valueKind;
7024
0
        });
7025
0
    }))
7026
0
        return nullptr;
7027
0
    return result;
7028
0
}
7029
7030
static void setFunctionReturnValue(const Function* f, Token* tok, ValueFlow::Value v, const Settings& settings)
7031
0
{
7032
0
    if (f->hasVirtualSpecifier()) {
7033
0
        if (v.isImpossible())
7034
0
            return;
7035
0
        v.setPossible();
7036
0
    } else if (!v.isImpossible()) {
7037
0
        v.setKnown();
7038
0
    }
7039
0
    v.errorPath.emplace_back(tok, "Calling function '" + f->name() + "' returns " + v.toString());
7040
0
    setTokenValue(tok, std::move(v), settings);
7041
0
}
7042
7043
static void valueFlowFunctionReturn(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings)
7044
1.17k
{
7045
90.3k
    for (Token* tok = tokenlist.back(); tok; tok = tok->previous()) {
7046
89.1k
        if (tok->str() != MatchCompiler::makeConstString("(") || !tok->astOperand1() || tok->isCast())
7047
87.9k
            continue;
7048
7049
1.23k
        const Function* function = nullptr;
7050
1.23k
        if (match38(tok->previous()))
7051
1.23k
            function = tok->previous()->function();
7052
0
        else
7053
0
            function = tok->astOperand1()->function();
7054
1.23k
        if (!function)
7055
1.23k
            continue;
7056
        // TODO: Check if member variable is a pointer or reference
7057
0
        if (function->isImplicitlyVirtual() && !function->hasFinalSpecifier())
7058
0
            continue;
7059
7060
0
        if (tok->hasKnownValue())
7061
0
            continue;
7062
7063
0
        std::vector<const Token*> returns = Function::findReturns(function);
7064
0
        if (returns.empty())
7065
0
            continue;
7066
7067
0
        if (const ValueFlow::Value* v = getKnownValueFromTokens(returns)) {
7068
0
            setFunctionReturnValue(function, tok, *v, settings);
7069
0
            continue;
7070
0
        }
7071
7072
        // Arguments..
7073
0
        std::vector<const Token*> arguments = getArguments(tok);
7074
7075
0
        ProgramMemory programMemory;
7076
0
        for (std::size_t i = 0; i < arguments.size(); ++i) {
7077
0
            const Variable* const arg = function->getArgumentVar(i);
7078
0
            if (!arg) {
7079
0
                if (settings.debugwarnings)
7080
0
                    bailout(tokenlist, errorLogger, tok, "function return; unhandled argument type");
7081
0
                programMemory.clear();
7082
0
                break;
7083
0
            }
7084
0
            const ValueFlow::Value* v = getKnownValueFromToken(arguments[i]);
7085
0
            if (!v)
7086
0
                continue;
7087
0
            programMemory.setValue(arg->nameToken(), *v);
7088
0
        }
7089
0
        if (programMemory.empty() && !arguments.empty())
7090
0
            continue;
7091
0
        std::vector<ValueFlow::Value> values = execute(function->functionScope, programMemory, settings);
7092
0
        for (const ValueFlow::Value& v : values) {
7093
0
            if (v.isUninitValue())
7094
0
                continue;
7095
0
            setFunctionReturnValue(function, tok, v, settings);
7096
0
        }
7097
0
    }
7098
1.17k
}
7099
7100
static bool needsInitialization(const Variable* var)
7101
0
{
7102
0
    if (!var)
7103
0
        return false;
7104
0
    if (var->hasDefault())
7105
0
        return false;
7106
0
    if (var->isPointer())
7107
0
        return true;
7108
0
    if (var->type() && var->type()->isUnionType())
7109
0
        return false;
7110
0
    if (!var->nameToken()->isCpp())
7111
0
        return true;
7112
0
    if (var->type() && var->type()->needInitialization == Type::NeedInitialization::True)
7113
0
        return true;
7114
0
    if (var->valueType()) {
7115
0
        if (var->valueType()->isPrimitive())
7116
0
            return true;
7117
0
        if (var->valueType()->type == ValueType::Type::POD)
7118
0
            return true;
7119
0
        if (var->valueType()->type == ValueType::Type::ITERATOR)
7120
0
            return true;
7121
0
        if (var->isStlType() && var->isArray()) {
7122
0
            if (const Token* ctt = var->valueType()->containerTypeToken) {
7123
0
                if (ctt->isStandardType())
7124
0
                    return true;
7125
0
                const Type* ct = ctt->type();
7126
0
                if (ct && ct->needInitialization == Type::NeedInitialization::True)
7127
0
                    return true;
7128
0
            }
7129
0
        }
7130
0
    }
7131
0
    return false;
7132
0
}
7133
7134
static void addToErrorPath(ValueFlow::Value& value, const ValueFlow::Value& from)
7135
0
{
7136
0
    std::unordered_set<const Token*> locations;
7137
0
    std::transform(value.errorPath.cbegin(),
7138
0
                   value.errorPath.cend(),
7139
0
                   std::inserter(locations, locations.begin()),
7140
0
                   [](const ErrorPathItem& e) {
7141
0
        return e.first;
7142
0
    });
7143
0
    if (from.condition && !value.condition)
7144
0
        value.condition = from.condition;
7145
0
    std::copy_if(from.errorPath.cbegin(),
7146
0
                 from.errorPath.cend(),
7147
0
                 std::back_inserter(value.errorPath),
7148
0
                 [&](const ErrorPathItem& e) {
7149
0
        return locations.insert(e.first).second;
7150
0
    });
7151
0
}
7152
7153
static std::vector<Token*> findAllUsages(const Variable* var,
7154
                                         Token* start, // cppcheck-suppress constParameterPointer // FP
7155
                                         const Library& library)
7156
0
{
7157
    // std::vector<Token*> result;
7158
0
    const Scope* scope = var->scope();
7159
0
    if (!scope)
7160
0
        return {};
7161
0
    return findTokensSkipDeadCode(library, start, scope->bodyEnd, [&](const Token* tok) {
7162
0
        return tok->varId() == var->declarationId();
7163
0
    });
7164
0
}
7165
7166
static Token* findStartToken(const Variable* var, Token* start, const Library& library)
7167
0
{
7168
0
    std::vector<Token*> uses = findAllUsages(var, start, library);
7169
0
    if (uses.empty())
7170
0
        return start;
7171
0
    Token* first = uses.front();
7172
0
    if (findmatch126(start, first) )
7173
0
        return start;
7174
0
    if (first != var->nameToken()) {
7175
        // if this is lhs in assignment then set first to the first token in LHS expression
7176
0
        Token* temp = first;
7177
0
        while (match127(temp->astParent()) && precedes(temp->astParent(), temp))
7178
0
            temp = temp->astParent();
7179
0
        if (match9(temp->astParent()) && precedes(temp, temp->astParent()))
7180
0
            first = temp;
7181
0
    }
7182
    // If there is only one usage
7183
0
    if (uses.size() == 1)
7184
0
        return first->previous();
7185
0
    const Scope* scope = first->scope();
7186
    // If first usage is in variable scope
7187
0
    if (scope == var->scope()) {
7188
0
        bool isLoopExpression = false;
7189
0
        for (const Token* parent = first; parent; parent = parent->astParent()) {
7190
0
            if (match33(parent->astParent()) &&
7191
0
                match33(parent->astParent()->astParent()) &&
7192
0
                match48(parent->astParent()->astParent()->astParent()) &&
7193
0
                match37(parent->astParent()->astParent()->astParent()->astOperand1()) &&
7194
0
                parent == parent->astParent()->astParent()->astParent()->astOperand2()->astOperand2()->astOperand2()) {
7195
0
                isLoopExpression = true;
7196
0
            }
7197
0
        }
7198
0
        return isLoopExpression ? start : first->previous();
7199
0
    }
7200
    // If all uses are in the same scope
7201
0
    if (std::all_of(uses.begin() + 1, uses.end(), [&](const Token* tok) {
7202
0
        return tok->scope() == scope;
7203
0
    }))
7204
0
        return first->previous();
7205
    // Compute the outer scope
7206
0
    while (scope && scope->nestedIn != var->scope())
7207
0
        scope = scope->nestedIn;
7208
0
    if (!scope)
7209
0
        return start;
7210
0
    auto* tok = const_cast<Token*>(scope->bodyStart);
7211
0
    if (!tok)
7212
0
        return start;
7213
0
    if (match46(tok->tokAt(-2)))
7214
0
        tok = tok->linkAt(-2);
7215
0
    if (match44(tok->previous()))
7216
0
        return tok->linkAt(-1)->previous();
7217
0
    return tok;
7218
0
}
7219
7220
static void valueFlowUninit(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings)
7221
1.17k
{
7222
90.3k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
7223
89.1k
        if (!tok->scope()->isExecutable())
7224
47.8k
            continue;
7225
41.3k
        if (!match128(tok))
7226
37.8k
            continue;
7227
3.51k
        const Variable* var = tok->variable();
7228
3.51k
        if (!var)
7229
0
            continue;
7230
3.51k
        if (var->nameToken() != tok || var->isInit())
7231
3.51k
            continue;
7232
0
        if (!needsInitialization(var))
7233
0
            continue;
7234
0
        if (!var->isLocal() || var->isStatic() || var->isExtern() || var->isReference() || var->isThrow())
7235
0
            continue;
7236
7237
0
        ValueFlow::Value uninitValue;
7238
0
        uninitValue.setKnown();
7239
0
        uninitValue.valueType = ValueFlow::Value::ValueType::UNINIT;
7240
0
        uninitValue.tokvalue = tok;
7241
0
        if (var->isArray())
7242
0
            uninitValue.indirect = var->dimensions().size();
7243
7244
0
        bool partial = false;
7245
7246
0
        Token* start = findStartToken(var, tok->next(), settings.library);
7247
7248
0
        std::map<Token*, ValueFlow::Value> partialReads;
7249
0
        if (const Scope* scope = var->typeScope()) {
7250
0
            if (findmatch129(scope->bodyStart, scope->bodyEnd) )
7251
0
                continue;
7252
0
            for (const Variable& memVar : scope->varlist) {
7253
0
                if (!memVar.isPublic())
7254
0
                    continue;
7255
                // Skip array since we can't track partial initialization from nested subexpressions
7256
0
                if (memVar.isArray())
7257
0
                    continue;
7258
0
                if (!needsInitialization(&memVar)) {
7259
0
                    if (!var->isPointer())
7260
0
                        partial = true;
7261
0
                    continue;
7262
0
                }
7263
0
                auto partialReadsAnalyzer = std::make_shared<PartialReadContainer>();
7264
0
                auto analyzer = makeMemberExpressionAnalyzer(memVar.nameToken()->str(), tok, uninitValue, partialReadsAnalyzer, settings);
7265
0
                valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, tokenlist, errorLogger, settings);
7266
7267
0
                for (auto&& p : *partialReadsAnalyzer) {
7268
0
                    Token* tok2 = p.first;
7269
0
                    const ValueFlow::Value& v = p.second;
7270
                    // Try to insert into map
7271
0
                    auto pp = partialReads.emplace(tok2, v);
7272
0
                    ValueFlow::Value& v2 = pp.first->second;
7273
0
                    const bool inserted = pp.second;
7274
                    // Merge the two values if it is already in map
7275
0
                    if (!inserted) {
7276
0
                        if (v.valueType != v2.valueType)
7277
0
                            continue;
7278
0
                        addToErrorPath(v2, v);
7279
0
                    }
7280
0
                    v2.subexpressions.push_back(memVar.nameToken()->str());
7281
0
                }
7282
0
            }
7283
0
        }
7284
7285
0
        for (auto&& p : partialReads) {
7286
0
            Token* tok2 = p.first;
7287
0
            ValueFlow::Value& v = p.second;
7288
7289
0
            setTokenValue(tok2, std::move(v), settings);
7290
0
        }
7291
7292
0
        if (partial)
7293
0
            continue;
7294
7295
0
        valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), std::move(uninitValue), tokenlist, errorLogger, settings);
7296
0
    }
7297
1.17k
}
7298
7299
static bool isContainerSizeChanged(const Token* expr,
7300
                                   const Token* start,
7301
                                   const Token* end,
7302
                                   int indirect,
7303
                                   const Settings& settings,
7304
                                   int depth = 20);
7305
7306
static bool isContainerSizeChangedByFunction(const Token* tok,
7307
                                             int indirect,
7308
                                             const Settings& settings,
7309
                                             int depth = 20)
7310
0
{
7311
0
    if (!tok->valueType())
7312
0
        return false;
7313
0
    if (!astIsContainer(tok))
7314
0
        return false;
7315
    // If we are accessing an element then we are not changing the container size
7316
0
    if (match130(tok)) {
7317
0
        const Library::Container::Yield yield = getLibraryContainer(tok)->getYield(tok->strAt(2));
7318
0
        if (yield != Library::Container::Yield::NO_YIELD)
7319
0
            return false;
7320
0
    }
7321
0
    if (match15(tok->astParent()))
7322
0
        return false;
7323
7324
    // address of variable
7325
0
    const bool addressOf = tok->valueType()->pointer || (tok->astParent() && tok->astParent()->isUnaryOp("&"));
7326
7327
0
    int narg;
7328
0
    const Token * ftok = getTokenArgumentFunction(tok, narg);
7329
0
    if (!ftok)
7330
0
        return false; // not a function => variable not changed
7331
0
    const Function * fun = ftok->function();
7332
0
    if (fun && !fun->isImplicitlyVirtual()) {
7333
0
        const Variable *arg = fun->getArgumentVar(narg);
7334
0
        if (arg) {
7335
0
            const bool isPointer = addressOf || indirect > 0;
7336
0
            if (!arg->isReference() && !isPointer)
7337
0
                return false;
7338
0
            if (!isPointer && arg->isConst())
7339
0
                return false;
7340
0
            if (arg->valueType() && arg->valueType()->constness == 1)
7341
0
                return false;
7342
0
            const Scope * scope = fun->functionScope;
7343
0
            if (scope) {
7344
                // Argument not used
7345
0
                if (!arg->nameToken())
7346
0
                    return false;
7347
0
                if (depth > 0)
7348
0
                    return isContainerSizeChanged(arg->nameToken(),
7349
0
                                                  scope->bodyStart,
7350
0
                                                  scope->bodyEnd,
7351
0
                                                  addressOf ? indirect + 1 : indirect,
7352
0
                                                  settings,
7353
0
                                                  depth - 1);
7354
0
            }
7355
            // Don't know => Safe guess
7356
0
            return true;
7357
0
        }
7358
0
    }
7359
7360
0
    bool inconclusive = false;
7361
0
    const bool isChanged = isVariableChangedByFunctionCall(tok, indirect, settings, &inconclusive);
7362
0
    return (isChanged || inconclusive);
7363
0
}
7364
7365
static const Token* parseBinaryIntOp(const Token* expr,
7366
                                     const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
7367
                                     MathLib::bigint& known)
7368
3.79k
{
7369
3.79k
    if (!expr)
7370
0
        return nullptr;
7371
3.79k
    if (!expr->astOperand1() || !expr->astOperand2())
7372
3.31k
        return nullptr;
7373
484
    if (expr->astOperand1()->exprId() == 0 && expr->astOperand2()->exprId() == 0)
7374
0
        return nullptr;
7375
484
    std::vector<MathLib::bigint> x1 = eval(expr->astOperand1());
7376
484
    if (expr->astOperand1()->exprId() == 0 && x1.empty())
7377
0
        return nullptr;
7378
484
    std::vector<MathLib::bigint> x2 = eval(expr->astOperand2());
7379
484
    if (expr->astOperand2()->exprId() == 0 && x2.empty())
7380
0
        return nullptr;
7381
484
    const Token* varTok = nullptr;
7382
484
    if (!x1.empty() && x2.empty()) {
7383
56
        varTok = expr->astOperand2();
7384
56
        known = x1.front();
7385
428
    } else if (x1.empty() && !x2.empty()) {
7386
61
        varTok = expr->astOperand1();
7387
61
        known = x2.front();
7388
61
    }
7389
484
    return varTok;
7390
484
}
7391
7392
const Token* ValueFlow::solveExprValue(const Token* expr,
7393
                                       const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
7394
                                       ValueFlow::Value& value)
7395
8.34k
{
7396
8.34k
    if (!value.isIntValue() && !value.isIteratorValue() && !value.isSymbolicValue())
7397
208
        return expr;
7398
8.13k
    if (value.isSymbolicValue() && !match131(expr))
7399
4.34k
        return expr;
7400
3.79k
    MathLib::bigint intval = 0;
7401
3.79k
    const Token* binaryTok = parseBinaryIntOp(expr, eval, intval);
7402
3.79k
    const bool rhs = astIsRHS(binaryTok);
7403
    // If its on the rhs, then -1 multiplication is needed, which is not possible with simple delta analysis used currently for symbolic values
7404
3.79k
    if (value.isSymbolicValue() && rhs && match132(expr))
7405
0
        return expr;
7406
3.79k
    if (binaryTok && expr->str().size() == 1) {
7407
93
        switch (expr->str()[0]) {
7408
0
        case '+': {
7409
0
            value.intvalue -= intval;
7410
0
            return ValueFlow::solveExprValue(binaryTok, eval, value);
7411
0
        }
7412
4
        case '-': {
7413
4
            if (rhs)
7414
0
                value.intvalue = intval - value.intvalue;
7415
4
            else
7416
4
                value.intvalue += intval;
7417
4
            return ValueFlow::solveExprValue(binaryTok, eval, value);
7418
0
        }
7419
0
        case '*': {
7420
0
            if (intval == 0)
7421
0
                break;
7422
0
            value.intvalue /= intval;
7423
0
            return ValueFlow::solveExprValue(binaryTok, eval, value);
7424
0
        }
7425
29
        case '^': {
7426
29
            value.intvalue ^= intval;
7427
29
            return ValueFlow::solveExprValue(binaryTok, eval, value);
7428
0
        }
7429
93
        }
7430
93
    }
7431
3.76k
    return expr;
7432
3.79k
}
7433
7434
bool ValueFlow::isContainerSizeChanged(const Token* tok, int indirect, const Settings& settings, int depth)
7435
0
{
7436
0
    if (!tok)
7437
0
        return false;
7438
0
    if (!tok->valueType() || !tok->valueType()->container)
7439
0
        return true;
7440
0
    if (astIsLHS(tok) && match133(tok->astParent()))
7441
0
        return true;
7442
0
    if (astIsLHS(tok) && match15(tok->astParent()))
7443
0
        return tok->valueType()->container->stdAssociativeLike;
7444
0
    const Library::Container::Action action = astContainerAction(tok);
7445
0
    switch (action) {
7446
0
    case Library::Container::Action::RESIZE:
7447
0
    case Library::Container::Action::CLEAR:
7448
0
    case Library::Container::Action::PUSH:
7449
0
    case Library::Container::Action::POP:
7450
0
    case Library::Container::Action::CHANGE:
7451
0
    case Library::Container::Action::INSERT:
7452
0
    case Library::Container::Action::ERASE:
7453
0
    case Library::Container::Action::APPEND:
7454
0
        return true;
7455
0
    case Library::Container::Action::NO_ACTION:
7456
        // Is this an unknown member function call?
7457
0
        if (astIsLHS(tok) && match16(tok->astParent())) {
7458
0
            const Library::Container::Yield yield = astContainerYield(tok);
7459
0
            return yield == Library::Container::Yield::NO_YIELD;
7460
0
        }
7461
0
        break;
7462
0
    case Library::Container::Action::FIND:
7463
0
    case Library::Container::Action::FIND_CONST:
7464
0
    case Library::Container::Action::CHANGE_CONTENT:
7465
0
    case Library::Container::Action::CHANGE_INTERNAL:
7466
0
        break;
7467
0
    }
7468
0
    return isContainerSizeChangedByFunction(tok, indirect, settings, depth);
7469
0
}
7470
7471
static bool isContainerSizeChanged(const Token* expr,
7472
                                   const Token* start,
7473
                                   const Token* end,
7474
                                   int indirect,
7475
                                   const Settings& settings,
7476
                                   int depth)
7477
0
{
7478
0
    for (const Token *tok = start; tok != end; tok = tok->next()) {
7479
0
        if (tok->exprId() != expr->exprId() && !isAliasOf(tok, expr))
7480
0
            continue;
7481
0
        if (ValueFlow::isContainerSizeChanged(tok, indirect, settings, depth))
7482
0
            return true;
7483
0
    }
7484
0
    return false;
7485
0
}
7486
7487
static void valueFlowSmartPointer(TokenList &tokenlist, ErrorLogger & errorLogger, const Settings &settings)
7488
1.17k
{
7489
90.3k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
7490
89.1k
        if (!tok->scope())
7491
0
            continue;
7492
89.1k
        if (!tok->scope()->isExecutable())
7493
47.8k
            continue;
7494
41.3k
        if (!astIsSmartPointer(tok))
7495
41.3k
            continue;
7496
0
        if (tok->variable() && match134(tok)) {
7497
0
            const Variable* var = tok->variable();
7498
0
            if (!var->isSmartPointer())
7499
0
                continue;
7500
0
            if (var->nameToken() == tok) {
7501
0
                if (match86(tok) && tok->next()->astOperand2() &&
7502
0
                    tok->next()->astOperand2()->str() != MatchCompiler::makeConstString(",")) {
7503
0
                    Token* inTok = tok->next()->astOperand2();
7504
0
                    const std::list<ValueFlow::Value>& values = inTok->values();
7505
0
                    const bool constValue = inTok->isNumber();
7506
0
                    valueFlowForwardAssign(inTok, var, values, constValue, true, tokenlist, errorLogger, settings);
7507
7508
0
                } else if (match135(tok)) {
7509
0
                    ValueFlow::Value v(0);
7510
0
                    v.setKnown();
7511
0
                    valueFlowForwardAssign(tok, var, {std::move(v)}, false, true, tokenlist, errorLogger, settings);
7512
0
                }
7513
0
            }
7514
0
        } else if (astIsLHS(tok) && match16(tok->astParent()) &&
7515
0
                   tok->astParent()->originalName() != MatchCompiler::makeConstString("->")) {
7516
0
            std::vector<const Variable*> vars = getVariables(tok);
7517
0
            Token* ftok = tok->astParent()->tokAt(2);
7518
0
            if (match136(tok->astParent())) {
7519
0
                if (match137(ftok)) {
7520
0
                    ValueFlow::Value v(0);
7521
0
                    v.setKnown();
7522
0
                    valueFlowForwardAssign(ftok, tok, std::move(vars), {std::move(v)}, false, tokenlist, errorLogger, settings);
7523
0
                } else {
7524
0
                    tok->removeValues(std::mem_fn(&ValueFlow::Value::isIntValue));
7525
0
                    Token* inTok = ftok->astOperand2();
7526
0
                    if (!inTok)
7527
0
                        continue;
7528
0
                    const std::list<ValueFlow::Value>& values = inTok->values();
7529
0
                    valueFlowForwardAssign(inTok, tok, std::move(vars), values, false, tokenlist, errorLogger, settings);
7530
0
                }
7531
0
            } else if (match138(tok->astParent())) {
7532
0
                const Token* parent = ftok->astParent();
7533
0
                bool hasParentReset = false;
7534
0
                while (parent) {
7535
0
                    if (match139(parent->tokAt(-2)) &&
7536
0
                        parent->tokAt(-2)->astOperand1()->exprId() == tok->exprId()) {
7537
0
                        hasParentReset = true;
7538
0
                        break;
7539
0
                    }
7540
0
                    parent = parent->astParent();
7541
0
                }
7542
0
                if (hasParentReset)
7543
0
                    continue;
7544
0
                ValueFlow::Value v(0);
7545
0
                v.setKnown();
7546
0
                valueFlowForwardAssign(ftok, tok, std::move(vars), {std::move(v)}, false, tokenlist, errorLogger, settings);
7547
0
            } else if (match65(tok->astParent())) {
7548
0
                ValueFlow::Value v = makeSymbolic(tok);
7549
0
                setTokenValue(tok->astParent()->tokAt(2), std::move(v), settings);
7550
0
            }
7551
0
        } else if (match140(tok->previous()) && astIsSmartPointer(tok) &&
7552
0
                   astIsSmartPointer(tok->astOperand1())) {
7553
0
            std::vector<const Token*> args = getArguments(tok);
7554
0
            if (args.empty())
7555
0
                continue;
7556
0
            for (const ValueFlow::Value& v : args.front()->values())
7557
0
                setTokenValue(tok, v, settings);
7558
0
        }
7559
0
    }
7560
1.17k
}
7561
7562
static Library::Container::Yield findIteratorYield(Token* tok, const Token*& ftok, const Settings& settings)
7563
0
{
7564
0
    auto yield = astContainerYield(tok, &ftok);
7565
0
    if (ftok)
7566
0
        return yield;
7567
7568
0
    if (!tok->astParent())
7569
0
        return yield;
7570
7571
    // begin/end free functions
7572
0
    return astFunctionYield(tok->astParent()->previous(), settings, &ftok);
7573
0
}
7574
7575
static void valueFlowIterators(TokenList& tokenlist, const Settings& settings)
7576
1.17k
{
7577
90.3k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
7578
89.1k
        if (!tok->scope())
7579
0
            continue;
7580
89.1k
        if (!tok->scope()->isExecutable())
7581
47.8k
            continue;
7582
41.3k
        if (!astIsContainer(tok))
7583
41.3k
            continue;
7584
0
        const Token* ftok = nullptr;
7585
0
        const Library::Container::Yield yield = findIteratorYield(tok, ftok, settings);
7586
0
        if (!ftok)
7587
0
            continue;
7588
0
        if (yield == Library::Container::Yield::START_ITERATOR) {
7589
0
            ValueFlow::Value v(0);
7590
0
            v.setKnown();
7591
0
            v.valueType = ValueFlow::Value::ValueType::ITERATOR_START;
7592
0
            setTokenValue(const_cast<Token*>(ftok)->next(), std::move(v), settings);
7593
0
        } else if (yield == Library::Container::Yield::END_ITERATOR) {
7594
0
            ValueFlow::Value v(0);
7595
0
            v.setKnown();
7596
0
            v.valueType = ValueFlow::Value::ValueType::ITERATOR_END;
7597
0
            setTokenValue(const_cast<Token*>(ftok)->next(), std::move(v), settings);
7598
0
        }
7599
0
    }
7600
1.17k
}
7601
7602
static std::list<ValueFlow::Value> getIteratorValues(std::list<ValueFlow::Value> values,
7603
                                                     const ValueFlow::Value::ValueKind* kind = nullptr)
7604
43.6k
{
7605
43.6k
    values.remove_if([&](const ValueFlow::Value& v) {
7606
6.73k
        if (kind && v.valueKind != *kind)
7607
366
            return true;
7608
6.36k
        return !v.isIteratorValue();
7609
6.73k
    });
7610
43.6k
    return values;
7611
43.6k
}
7612
7613
struct IteratorConditionHandler : SimpleConditionHandler {
7614
15.6k
    std::vector<Condition> parse(const Token* tok, const Settings& /*settings*/) const override {
7615
15.6k
        Condition cond;
7616
7617
15.6k
        if (match100(tok)) {
7618
1.12k
            if (!tok->astOperand1() || !tok->astOperand2())
7619
0
                return {};
7620
7621
1.12k
            constexpr ValueFlow::Value::ValueKind kind = ValueFlow::Value::ValueKind::Known;
7622
1.12k
            std::list<ValueFlow::Value> values = getIteratorValues(tok->astOperand1()->values(), &kind);
7623
1.12k
            if (!values.empty()) {
7624
0
                cond.vartok = tok->astOperand2();
7625
1.12k
            } else {
7626
1.12k
                values = getIteratorValues(tok->astOperand2()->values(), &kind);
7627
1.12k
                if (!values.empty())
7628
0
                    cond.vartok = tok->astOperand1();
7629
1.12k
            }
7630
1.12k
            for (ValueFlow::Value& v:values) {
7631
0
                v.setPossible();
7632
0
                v.assumeCondition(tok);
7633
0
            }
7634
1.12k
            cond.true_values = values;
7635
1.12k
            cond.false_values = std::move(values);
7636
1.12k
        }
7637
7638
15.6k
        return {std::move(cond)};
7639
15.6k
    }
7640
};
7641
7642
static void valueFlowIteratorInfer(TokenList& tokenlist, const Settings& settings)
7643
1.17k
{
7644
90.3k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
7645
89.1k
        if (!tok->scope())
7646
0
            continue;
7647
89.1k
        if (!tok->scope()->isExecutable())
7648
47.8k
            continue;
7649
41.3k
        std::list<ValueFlow::Value> values = getIteratorValues(tok->values());
7650
41.3k
        values.remove_if([&](const ValueFlow::Value& v) {
7651
0
            if (!v.isImpossible())
7652
0
                return true;
7653
0
            if (!v.condition)
7654
0
                return true;
7655
0
            if (v.bound != ValueFlow::Value::Bound::Point)
7656
0
                return true;
7657
0
            if (v.isIteratorEndValue() && v.intvalue <= 0)
7658
0
                return true;
7659
0
            if (v.isIteratorStartValue() && v.intvalue >= 0)
7660
0
                return true;
7661
0
            return false;
7662
0
        });
7663
41.3k
        for (ValueFlow::Value& v : values) {
7664
0
            v.setPossible();
7665
0
            if (v.isIteratorStartValue())
7666
0
                v.intvalue++;
7667
0
            if (v.isIteratorEndValue())
7668
0
                v.intvalue--;
7669
0
            setTokenValue(tok, std::move(v), settings);
7670
0
        }
7671
41.3k
    }
7672
1.17k
}
7673
7674
static std::vector<ValueFlow::Value> getContainerValues(const Token* tok)
7675
0
{
7676
0
    std::vector<ValueFlow::Value> values;
7677
0
    if (tok) {
7678
0
        std::copy_if(tok->values().cbegin(),
7679
0
                     tok->values().cend(),
7680
0
                     std::back_inserter(values),
7681
0
                     std::mem_fn(&ValueFlow::Value::isContainerSizeValue));
7682
0
    }
7683
0
    return values;
7684
0
}
7685
7686
static ValueFlow::Value makeContainerSizeValue(MathLib::bigint s, bool known = true)
7687
0
{
7688
0
    ValueFlow::Value value(s);
7689
0
    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7690
0
    if (known)
7691
0
        value.setKnown();
7692
0
    return value;
7693
0
}
7694
7695
static std::vector<ValueFlow::Value> makeContainerSizeValue(const Token* tok, bool known = true)
7696
0
{
7697
0
    if (tok->hasKnownIntValue())
7698
0
        return {makeContainerSizeValue(tok->values().front().intvalue, known)};
7699
0
    return {};
7700
0
}
7701
7702
static std::vector<ValueFlow::Value> getContainerSizeFromConstructorArgs(const std::vector<const Token*>& args,
7703
                                                                         const Library::Container* container,
7704
                                                                         bool known)
7705
0
{
7706
0
    if (astIsIntegral(args[0], false)) { // { count, i } or { count }
7707
0
        if (args.size() == 1 || (args.size() > 1 && !astIsIntegral(args[1], false)))
7708
0
            return {makeContainerSizeValue(args[0], known)};
7709
0
    } else if (astIsContainer(args[0]) && args.size() == 1) { // copy constructor
7710
0
        return getContainerValues(args[0]);
7711
0
    } else if (isIteratorPair(args)) {
7712
0
        std::vector<ValueFlow::Value> result = getContainerValues(args[0]);
7713
0
        if (!result.empty())
7714
0
            return result;
7715
        // (ptr, ptr + size)
7716
0
        if (astIsPointer(args[0]) && args[0]->exprId() != 0) {
7717
            // (ptr, ptr) is empty
7718
            // TODO: Use lifetime values to check if it points to the same address
7719
0
            if (args[0]->exprId() == args[1]->exprId())
7720
0
                return {makeContainerSizeValue(MathLib::bigint{0}, known)};
7721
            // TODO: Insert iterator positions for pointers
7722
0
            if (match141(args[1])) {
7723
0
                nonneg int const eid = args[0]->exprId();
7724
0
                const Token* vartok = args[1]->astOperand1();
7725
0
                const Token* sizetok = args[1]->astOperand2();
7726
0
                if (sizetok->exprId() == eid)
7727
0
                    std::swap(vartok, sizetok);
7728
0
                if (vartok->exprId() == eid && sizetok->hasKnownIntValue())
7729
0
                    return {makeContainerSizeValue(sizetok, known)};
7730
0
            }
7731
0
        }
7732
0
    } else if (container->stdStringLike) {
7733
0
        if (astIsPointer(args[0])) {
7734
0
            if (args.size() == 1 && args[0]->tokType() == Token::Type::eString)
7735
0
                return {makeContainerSizeValue(Token::getStrLength(args[0]), known)};
7736
0
            if (args.size() == 2 && astIsIntegral(args[1], false)) // { char*, count }
7737
0
                return {makeContainerSizeValue(args[1], known)};
7738
0
        } else if (astIsContainer(args[0])) {
7739
0
            if (args.size() == 1) // copy constructor { str }
7740
0
                return getContainerValues(args[0]);
7741
0
            if (args.size() == 3) // { str, pos, count }
7742
0
                return {makeContainerSizeValue(args[2], known)};
7743
            // TODO: { str, pos }, { ..., alloc }
7744
0
        }
7745
0
    }
7746
0
    return {};
7747
0
}
7748
7749
static bool valueFlowIsSameContainerType(const ValueType& contType, const Token* tok, const Settings& settings)
7750
0
{
7751
0
    if (!tok || !tok->valueType() || !tok->valueType()->containerTypeToken)
7752
0
        return true;
7753
7754
0
    const ValueType tokType = ValueType::parseDecl(tok->valueType()->containerTypeToken, settings);
7755
0
    return contType.isTypeEqual(&tokType) || tokType.type == ValueType::Type::UNKNOWN_TYPE;
7756
0
}
7757
7758
static std::vector<ValueFlow::Value> getInitListSize(const Token* tok,
7759
                                                     const ValueType* valueType,
7760
                                                     const Settings& settings,
7761
                                                     bool known = true)
7762
0
{
7763
0
    std::vector<const Token*> args = getArguments(tok);
7764
0
    if (args.empty())
7765
0
        return {makeContainerSizeValue(MathLib::bigint{0}, known)};
7766
0
    bool initList = tok->str() == MatchCompiler::makeConstString("{");
7767
    // Try to disambiguate init list from constructor
7768
0
    if (initList && args.size() < 4) {
7769
0
        initList = !isIteratorPair(args);
7770
0
        const Token* containerTypeToken = valueType->containerTypeToken;
7771
0
        if (valueType->container->stdStringLike) {
7772
0
            initList = astIsGenericChar(args[0]) && !astIsPointer(args[0]);
7773
0
        } else if (containerTypeToken) {
7774
0
            ValueType vt = ValueType::parseDecl(containerTypeToken, settings);
7775
0
            if (vt.pointer > 0 && astIsPointer(args[0]))
7776
0
                initList = true;
7777
0
            else if (vt.type == ValueType::ITERATOR && astIsIterator(args[0]))
7778
0
                initList = true;
7779
0
            else if (vt.isIntegral() && astIsIntegral(args[0], false))
7780
0
                initList = true;
7781
0
            else if (args.size() == 1 && valueFlowIsSameContainerType(vt, tok->astOperand2(), settings))
7782
0
                initList = false; // copy ctor
7783
0
            else if (args.size() == 2 && (!args[0]->valueType() || !args[1]->valueType())) // might be unknown iterators
7784
0
                initList = false;
7785
0
        }
7786
0
    }
7787
0
    if (!initList)
7788
0
        return getContainerSizeFromConstructorArgs(args, valueType->container, known);
7789
0
    return {makeContainerSizeValue(args.size(), known)};
7790
0
}
7791
7792
static std::vector<ValueFlow::Value> getContainerSizeFromConstructor(const Token* tok,
7793
                                                                     const ValueType* valueType,
7794
                                                                     const Settings& settings,
7795
                                                                     bool known = true)
7796
0
{
7797
0
    std::vector<const Token*> args = getArguments(tok);
7798
0
    if (args.empty())
7799
0
        return {makeContainerSizeValue(MathLib::bigint{0}, known)};
7800
    // Init list in constructor
7801
0
    if (args.size() == 1 && match4(args[0]))
7802
0
        return getInitListSize(args[0], valueType, settings, known);
7803
0
    return getContainerSizeFromConstructorArgs(args, valueType->container, known);
7804
0
}
7805
7806
static void valueFlowContainerSetTokValue(const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, const Token* tok, Token* initList)
7807
0
{
7808
0
    ValueFlow::Value value;
7809
0
    value.valueType = ValueFlow::Value::ValueType::TOK;
7810
0
    value.tokvalue = initList;
7811
0
    if (astIsContainerString(tok) && match4(initList) && match142(initList->astOperand2())) {
7812
0
        value.tokvalue = initList->astOperand2();
7813
0
    }
7814
0
    value.setKnown();
7815
0
    Token* start = initList->link() ? initList->link() : initList->next();
7816
0
    if (tok->variable() && tok->variable()->isConst()) {
7817
0
        valueFlowForwardConst(start, tok->variable()->scope()->bodyEnd, tok->variable(), {std::move(value)}, settings);
7818
0
    } else {
7819
0
        valueFlowForward(start, tok, std::move(value), tokenlist, errorLogger, settings);
7820
0
    }
7821
0
}
7822
7823
0
static const Scope* getFunctionScope(const Scope* scope) {
7824
0
    while (scope && scope->type != Scope::ScopeType::eFunction)
7825
0
        scope = scope->nestedIn;
7826
0
    return scope;
7827
0
}
7828
7829
static void valueFlowContainerSize(const TokenList& tokenlist,
7830
                                   const SymbolDatabase& symboldatabase,
7831
                                   ErrorLogger& errorLogger,
7832
                                   const Settings& settings,
7833
                                   const std::set<const Scope*>& skippedFunctions)
7834
1.17k
{
7835
    // declaration
7836
7.04k
    for (const Variable *var : symboldatabase.variableList()) {
7837
7.04k
        if (!var)
7838
1.17k
            continue;
7839
5.87k
        if (!var->scope() || !var->scope()->bodyEnd || !var->scope()->bodyStart)
7840
5.87k
            continue;
7841
0
        if (!var->valueType() || !var->valueType()->container)
7842
0
            continue;
7843
0
        if (!astIsContainer(var->nameToken()))
7844
0
            continue;
7845
0
        if (skippedFunctions.count(getFunctionScope(var->scope())))
7846
0
            continue;
7847
7848
0
        bool known = true;
7849
0
        MathLib::bigint size = 0;
7850
0
        const bool nonLocal = !var->isLocal() || var->isPointer() || var->isReference() || var->isStatic();
7851
0
        bool constSize = var->isConst() && !nonLocal;
7852
0
        bool staticSize = false;
7853
0
        if (var->valueType()->container->size_templateArgNo >= 0) {
7854
0
            staticSize = true;
7855
0
            constSize = true;
7856
0
            size = -1;
7857
0
            if (var->dimensions().size() == 1) {
7858
0
                const Dimension& dim = var->dimensions().front();
7859
0
                if (dim.known) {
7860
0
                    size = dim.num;
7861
0
                } else if (dim.tok && dim.tok->hasKnownIntValue()) {
7862
0
                    size = dim.tok->values().front().intvalue;
7863
0
                }
7864
0
            }
7865
0
            if (size < 0)
7866
0
                continue;
7867
0
        }
7868
0
        if (!staticSize && nonLocal)
7869
0
            continue;
7870
0
        auto* nameToken = const_cast<Token*>(var->nameToken());
7871
0
        if (nameToken->hasKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE))
7872
0
            continue;
7873
0
        if (!staticSize) {
7874
0
            if (!match143(nameToken) &&
7875
0
                !(match144(nameToken) && match145(nameToken->linkAt(1))) &&
7876
0
                !match38(nameToken))
7877
0
                continue;
7878
0
        }
7879
0
        if (match146(nameToken->astTop()->previous()))
7880
0
            known = !isVariableChanged(var, settings);
7881
0
        std::vector<ValueFlow::Value> values{ValueFlow::Value{size}};
7882
0
        values.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7883
0
        if (known)
7884
0
            values.back().setKnown();
7885
0
        if (!staticSize) {
7886
0
            if (match4(nameToken->next())) {
7887
0
                Token* initList = nameToken->next();
7888
0
                valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, nameToken, initList);
7889
0
                values = getInitListSize(initList, var->valueType(), settings, known);
7890
0
            } else if (match48(nameToken->next())) {
7891
0
                const Token* constructorArgs = nameToken->next();
7892
0
                values = getContainerSizeFromConstructor(constructorArgs, var->valueType(), settings, known);
7893
0
            }
7894
0
        }
7895
7896
0
        if (constSize) {
7897
0
            valueFlowForwardConst(nameToken->next(), var->scope()->bodyEnd, var, values, settings);
7898
0
            continue;
7899
0
        }
7900
7901
0
        for (const ValueFlow::Value& value : values) {
7902
0
            valueFlowForward(nameToken->next(), var->nameToken(), value, tokenlist, errorLogger, settings);
7903
0
        }
7904
0
    }
7905
7906
1.17k
    auto forwardMinimumContainerSize = [&](MathLib::bigint size, Token* opTok, const Token* exprTok) -> void {
7907
0
        if (size == 0)
7908
0
            return;
7909
7910
0
        ValueFlow::Value value(size - 1);
7911
0
        value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7912
0
        value.bound = ValueFlow::Value::Bound::Upper;
7913
0
        value.setImpossible();
7914
0
        Token* next = nextAfterAstRightmostLeaf(opTok);
7915
0
        if (!next)
7916
0
            next = opTok->next();
7917
0
        valueFlowForward(next, exprTok, std::move(value), tokenlist, errorLogger, settings);
7918
0
    };
7919
7920
    // after assignment
7921
1.67k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
7922
41.3k
        for (auto* tok = const_cast<Token*>(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) {
7923
39.6k
            if (match147(tok)) {
7924
0
                Token* containerTok = tok->next();
7925
0
                if (containerTok->exprId() == 0)
7926
0
                    continue;
7927
0
                if (containerTok->valueType() && containerTok->valueType()->container &&
7928
0
                    containerTok->valueType()->container->stdStringLike) {
7929
0
                    valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, containerTok, containerTok->tokAt(2));
7930
0
                    ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2)));
7931
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7932
0
                    value.setKnown();
7933
0
                    valueFlowForward(containerTok->next(), containerTok, std::move(value), tokenlist, errorLogger, settings);
7934
0
                }
7935
39.6k
            } else if (match148(tok->previous()) && astIsContainer(tok) && getLibraryContainer(tok)->size_templateArgNo < 0) {
7936
0
                std::vector<ValueFlow::Value> values;
7937
0
                if (match4(tok)) {
7938
0
                    values = getInitListSize(tok, tok->valueType(), settings, true);
7939
0
                    ValueFlow::Value value;
7940
0
                    value.valueType = ValueFlow::Value::ValueType::TOK;
7941
0
                    value.tokvalue = tok;
7942
0
                    value.setKnown();
7943
0
                    values.push_back(value);
7944
0
                } else if (match48(tok)) {
7945
0
                    const Token* constructorArgs = tok;
7946
0
                    values = getContainerSizeFromConstructor(constructorArgs, tok->valueType(), settings, true);
7947
0
                }
7948
0
                for (const ValueFlow::Value& value : values)
7949
0
                    setTokenValue(tok, value, settings);
7950
39.6k
            } else if (match149(tok) && match70(tok->tokAt(2)->astOperand2()) &&
7951
                       // init list
7952
39.6k
                       ((tok->tokAt(2) == tok->tokAt(2)->astOperand2()->astParent() && !tok->tokAt(2)->astOperand2()->astOperand2() && tok->tokAt(2)->astOperand2()->str() == MatchCompiler::makeConstString("{")) ||
7953
                        // constructor
7954
0
                        (!match40(tok->tokAt(2)->astOperand2()->astOperand1()) && settings.library.detectContainer(tok->tokAt(3))))) {
7955
0
                Token* containerTok = tok->next();
7956
0
                if (containerTok->exprId() == 0)
7957
0
                    continue;
7958
0
                if (astIsContainer(containerTok) && containerTok->valueType()->container->size_templateArgNo < 0) {
7959
0
                    Token* rhs = tok->tokAt(2)->astOperand2();
7960
0
                    std::vector<ValueFlow::Value> values = getInitListSize(rhs, containerTok->valueType(), settings);
7961
0
                    valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, containerTok, rhs);
7962
0
                    for (const ValueFlow::Value& value : values)
7963
0
                        valueFlowForward(containerTok->next(), containerTok, value, tokenlist, errorLogger, settings);
7964
0
                }
7965
39.6k
            } else if (match16(tok) && tok->astOperand1() && tok->astOperand1()->valueType() &&
7966
39.6k
                       tok->astOperand1()->valueType()->container) {
7967
0
                const Token* containerTok = tok->astOperand1();
7968
0
                if (containerTok->exprId() == 0)
7969
0
                    continue;
7970
0
                if (containerTok->variable() && containerTok->variable()->isArray())
7971
0
                    continue;
7972
0
                const Library::Container::Action action = containerTok->valueType()->container->getAction(tok->strAt(1));
7973
0
                if (action == Library::Container::Action::CLEAR) {
7974
0
                    ValueFlow::Value value(0);
7975
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7976
0
                    value.setKnown();
7977
0
                    valueFlowForward(tok->next(), containerTok, std::move(value), tokenlist, errorLogger, settings);
7978
0
                } else if (action == Library::Container::Action::RESIZE && tok->tokAt(2)->astOperand2() &&
7979
0
                           tok->tokAt(2)->astOperand2()->hasKnownIntValue()) {
7980
0
                    ValueFlow::Value value(tok->tokAt(2)->astOperand2()->values().front());
7981
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7982
0
                    value.setKnown();
7983
0
                    valueFlowForward(tok->linkAt(2), containerTok, std::move(value), tokenlist, errorLogger, settings);
7984
0
                } else if (action == Library::Container::Action::PUSH && !isIteratorPair(getArguments(tok->tokAt(2)))) {
7985
0
                    ValueFlow::Value value(0);
7986
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7987
0
                    value.setImpossible();
7988
0
                    valueFlowForward(tok->linkAt(2), containerTok, std::move(value), tokenlist, errorLogger, settings);
7989
0
                }
7990
                // TODO: handle more actions?
7991
7992
39.6k
            } else if (tok->str() == MatchCompiler::makeConstString("+=") && astIsContainer(tok->astOperand1())) {
7993
0
                const Token* containerTok = tok->astOperand1();
7994
0
                const Token* valueTok = tok->astOperand2();
7995
0
                const MathLib::bigint size = ValueFlow::valueFlowGetStrLength(valueTok);
7996
0
                forwardMinimumContainerSize(size, tok, containerTok);
7997
7998
39.6k
            } else if (tok->str() == MatchCompiler::makeConstString("=") && match141(tok->astOperand2()) && astIsContainerString(tok)) {
7999
0
                const Token* tok2 = tok->astOperand2();
8000
0
                MathLib::bigint size = 0;
8001
0
                while (match141(tok2) && tok2->astOperand2()) {
8002
0
                    size += ValueFlow::valueFlowGetStrLength(tok2->astOperand2());
8003
0
                    tok2 = tok2->astOperand1();
8004
0
                }
8005
0
                size += ValueFlow::valueFlowGetStrLength(tok2);
8006
0
                forwardMinimumContainerSize(size, tok, tok->astOperand1());
8007
0
            }
8008
39.6k
        }
8009
1.67k
    }
8010
1.17k
}
8011
8012
struct ContainerConditionHandler : ConditionHandler {
8013
    std::vector<Condition> parse(const Token* tok, const Settings& settings) const override
8014
15.6k
    {
8015
15.6k
        std::vector<Condition> conds;
8016
15.6k
        parseCompareEachInt(tok, [&](const Token* vartok, ValueFlow::Value true_value, ValueFlow::Value false_value) {
8017
248
            vartok = settings.library.getContainerFromYield(vartok, Library::Container::Yield::SIZE);
8018
248
            if (!vartok)
8019
248
                return;
8020
0
            true_value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8021
0
            false_value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8022
0
            Condition cond;
8023
0
            cond.true_values.push_back(std::move(true_value));
8024
0
            cond.false_values.push_back(std::move(false_value));
8025
0
            cond.vartok = vartok;
8026
0
            conds.push_back(std::move(cond));
8027
0
        });
8028
15.6k
        if (!conds.empty())
8029
0
            return conds;
8030
8031
15.6k
        const Token* vartok = nullptr;
8032
8033
        // Empty check
8034
15.6k
        if (tok->str() == MatchCompiler::makeConstString("(")) {
8035
2.46k
            vartok = settings.library.getContainerFromYield(tok, Library::Container::Yield::EMPTY);
8036
            // TODO: Handle .size()
8037
2.46k
            if (!vartok)
8038
2.46k
                return {};
8039
0
            const Token *parent = tok->astParent();
8040
0
            while (parent) {
8041
0
                if (match12(parent))
8042
0
                    return {};
8043
0
                parent = parent->astParent();
8044
0
            }
8045
0
            ValueFlow::Value value(tok, 0LL);
8046
0
            value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8047
0
            Condition cond;
8048
0
            cond.true_values.emplace_back(value);
8049
0
            cond.false_values.emplace_back(std::move(value));
8050
0
            cond.vartok = vartok;
8051
0
            cond.inverted = true;
8052
0
            return {std::move(cond)};
8053
0
        }
8054
        // String compare
8055
13.1k
        if (match100(tok)) {
8056
1.12k
            const Token *strtok = nullptr;
8057
1.12k
            if (match142(tok->astOperand1())) {
8058
0
                strtok = tok->astOperand1();
8059
0
                vartok = tok->astOperand2();
8060
1.12k
            } else if (match142(tok->astOperand2())) {
8061
0
                strtok = tok->astOperand2();
8062
0
                vartok = tok->astOperand1();
8063
0
            }
8064
1.12k
            if (!strtok)
8065
1.12k
                return {};
8066
0
            if (!astIsContainer(vartok))
8067
0
                return {};
8068
0
            ValueFlow::Value value(tok, Token::getStrLength(strtok));
8069
0
            value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8070
0
            Condition cond;
8071
0
            cond.false_values.emplace_back(value);
8072
0
            cond.true_values.emplace_back(std::move(value));
8073
0
            cond.vartok = vartok;
8074
0
            cond.impossible = false;
8075
0
            return {std::move(cond)};
8076
0
        }
8077
12.0k
        return {};
8078
13.1k
    }
8079
};
8080
8081
static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings)
8082
764
{
8083
764
    auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint {
8084
0
        MathLib::bigint sizeValue = -1;
8085
0
        const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(funcTok);
8086
0
        if (!allocFunc)
8087
0
            allocFunc = settings.library.getReallocFuncInfo(funcTok);
8088
0
        if (!allocFunc || allocFunc->bufferSize == Library::AllocFunc::BufferSize::none)
8089
0
            return sizeValue;
8090
8091
0
        const std::vector<const Token*> args = getArguments(funcTok);
8092
8093
0
        const Token* const arg1 = (args.size() >= allocFunc->bufferSizeArg1) ? args[allocFunc->bufferSizeArg1 - 1] : nullptr;
8094
0
        const Token* const arg2 = (args.size() >= allocFunc->bufferSizeArg2) ? args[allocFunc->bufferSizeArg2 - 1] : nullptr;
8095
8096
0
        switch (allocFunc->bufferSize) {
8097
0
        case Library::AllocFunc::BufferSize::none:
8098
0
            break;
8099
0
        case Library::AllocFunc::BufferSize::malloc:
8100
0
            if (arg1 && arg1->hasKnownIntValue())
8101
0
                sizeValue = arg1->getKnownIntValue();
8102
0
            break;
8103
0
        case Library::AllocFunc::BufferSize::calloc:
8104
0
            if (arg1 && arg2 && arg1->hasKnownIntValue() && arg2->hasKnownIntValue())
8105
0
                sizeValue = arg1->getKnownIntValue() * arg2->getKnownIntValue();
8106
0
            break;
8107
0
        case Library::AllocFunc::BufferSize::strdup:
8108
0
            if (arg1 && arg1->hasKnownValue()) {
8109
0
                const ValueFlow::Value& value = arg1->values().back();
8110
0
                if (value.isTokValue() && value.tokvalue->tokType() == Token::eString)
8111
0
                    sizeValue = Token::getStrLength(value.tokvalue) + 1; // Add one for the null terminator
8112
0
            }
8113
0
            break;
8114
0
        }
8115
0
        return sizeValue;
8116
0
    };
8117
8118
764
    auto getBufferSizeFromNew = [&](const Token* newTok) -> MathLib::bigint {
8119
0
        MathLib::bigint sizeValue = -1, numElem = -1;
8120
8121
0
        if (newTok && newTok->astOperand1()) { // number of elements
8122
0
            const Token* bracTok = nullptr, *typeTok = nullptr;
8123
0
            if (newTok->astOperand1()->str() == MatchCompiler::makeConstString("["))
8124
0
                bracTok = newTok->astOperand1();
8125
0
            else if (match52(newTok->astOperand1())) {
8126
0
                if (newTok->astOperand1()->astOperand1() && newTok->astOperand1()->astOperand1()->str() == MatchCompiler::makeConstString("["))
8127
0
                    bracTok = newTok->astOperand1()->astOperand1();
8128
0
                else
8129
0
                    typeTok = newTok->astOperand1()->astOperand1();
8130
0
            }
8131
0
            else
8132
0
                typeTok = newTok->astOperand1();
8133
0
            if (bracTok && bracTok->astOperand2() && bracTok->astOperand2()->hasKnownIntValue())
8134
0
                numElem = bracTok->astOperand2()->getKnownIntValue();
8135
0
            else if (match150(typeTok))
8136
0
                numElem = 1;
8137
0
        }
8138
8139
0
        if (numElem >= 0 && newTok->astParent() && newTok->astParent()->isAssignmentOp()) { // size of the allocated type
8140
0
            const Token* typeTok = newTok->astParent()->astOperand1(); // TODO: implement fallback for e.g. "auto p = new Type;"
8141
0
            if (!typeTok || !typeTok->varId())
8142
0
                typeTok = newTok->astParent()->previous(); // hack for "int** z = ..."
8143
0
            if (typeTok && typeTok->valueType()) {
8144
0
                const MathLib::bigint typeSize = typeTok->valueType()->typeSize(settings.platform, typeTok->valueType()->pointer > 1);
8145
0
                if (typeSize >= 0)
8146
0
                    sizeValue = numElem * typeSize;
8147
0
            }
8148
0
        }
8149
0
        return sizeValue;
8150
0
    };
8151
8152
1.10k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
8153
23.7k
        for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) {
8154
22.6k
            if (!match151(tok))
8155
22.6k
                continue;
8156
8157
14
            if (!tok->next()->variable())
8158
0
                continue;
8159
8160
14
            const Token *rhs = tok->tokAt(2)->astOperand2();
8161
14
            while (rhs && rhs->isCast())
8162
0
                rhs = rhs->astOperand2() ? rhs->astOperand2() : rhs->astOperand1();
8163
14
            if (!rhs)
8164
0
                continue;
8165
8166
14
            const bool isNew = rhs->isCpp() && rhs->str() == MatchCompiler::makeConstString("new");
8167
14
            if (!isNew && !match38(rhs->previous()))
8168
14
                continue;
8169
8170
0
            const MathLib::bigint sizeValue = isNew ? getBufferSizeFromNew(rhs) : getBufferSizeFromAllocFunc(rhs->previous());
8171
0
            if (sizeValue < 0)
8172
0
                continue;
8173
8174
0
            ValueFlow::Value value(sizeValue);
8175
0
            value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + MathLib::toString(sizeValue));
8176
0
            value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
8177
0
            value.setKnown();
8178
0
            valueFlowForward(const_cast<Token*>(rhs), functionScope->bodyEnd, tok->next(), std::move(value), tokenlist, errorLogger, settings);
8179
0
        }
8180
1.10k
    }
8181
764
}
8182
8183
static bool getMinMaxValues(const std::string& typestr,
8184
                            const Settings& settings,
8185
                            bool cpp,
8186
                            MathLib::bigint& minvalue,
8187
                            MathLib::bigint& maxvalue)
8188
0
{
8189
0
    TokenList typeTokens(&settings);
8190
0
    std::istringstream istr(typestr + ";");
8191
0
    if (!typeTokens.createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C))
8192
0
        return false;
8193
0
    typeTokens.simplifyPlatformTypes();
8194
0
    typeTokens.simplifyStdType();
8195
0
    const ValueType& vt = ValueType::parseDecl(typeTokens.front(), settings);
8196
0
    return ValueFlow::getMinMaxValues(&vt, settings.platform, minvalue, maxvalue);
8197
0
}
8198
8199
static void valueFlowSafeFunctions(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings)
8200
1.17k
{
8201
1.67k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
8202
1.67k
        if (!functionScope->bodyStart)
8203
0
            continue;
8204
1.67k
        const Function *function = functionScope->function;
8205
1.67k
        if (!function)
8206
0
            continue;
8207
8208
1.67k
        const bool safe = function->isSafe(settings);
8209
1.67k
        const bool all = safe && settings.platform.type != Platform::Type::Unspecified;
8210
8211
1.67k
        for (const Variable &arg : function->argumentList) {
8212
0
            if (!arg.nameToken() || !arg.valueType())
8213
0
                continue;
8214
8215
0
            if (arg.valueType()->type == ValueType::Type::CONTAINER) {
8216
0
                if (!safe)
8217
0
                    continue;
8218
0
                std::list<ValueFlow::Value> argValues;
8219
0
                argValues.emplace_back(0);
8220
0
                argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8221
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " is empty");
8222
0
                argValues.back().safe = true;
8223
0
                argValues.emplace_back(1000000);
8224
0
                argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8225
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000");
8226
0
                argValues.back().safe = true;
8227
0
                for (const ValueFlow::Value &value : argValues)
8228
0
                    valueFlowForward(const_cast<Token*>(functionScope->bodyStart), arg.nameToken(), value, tokenlist, errorLogger, settings);
8229
0
                continue;
8230
0
            }
8231
8232
0
            MathLib::bigint low, high;
8233
0
            bool isLow = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, low);
8234
0
            bool isHigh = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, high);
8235
8236
0
            if (!isLow && !isHigh && !all)
8237
0
                continue;
8238
8239
0
            const bool safeLow = !isLow;
8240
0
            const bool safeHigh = !isHigh;
8241
8242
0
            if ((!isLow || !isHigh) && all) {
8243
0
                MathLib::bigint minValue, maxValue;
8244
0
                if (ValueFlow::getMinMaxValues(arg.valueType(), settings.platform, minValue, maxValue)) {
8245
0
                    if (!isLow)
8246
0
                        low = minValue;
8247
0
                    if (!isHigh)
8248
0
                        high = maxValue;
8249
0
                    isLow = isHigh = true;
8250
0
                } else if (arg.valueType()->type == ValueType::Type::FLOAT || arg.valueType()->type == ValueType::Type::DOUBLE || arg.valueType()->type == ValueType::Type::LONGDOUBLE) {
8251
0
                    std::list<ValueFlow::Value> argValues;
8252
0
                    argValues.emplace_back(0);
8253
0
                    argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
8254
0
                    argValues.back().floatValue = isLow ? static_cast<double>(low) : -1E25;
8255
0
                    argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
8256
0
                    argValues.back().safe = true;
8257
0
                    argValues.emplace_back(0);
8258
0
                    argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
8259
0
                    argValues.back().floatValue = isHigh ? static_cast<double>(high) : 1E25;
8260
0
                    argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
8261
0
                    argValues.back().safe = true;
8262
0
                    valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
8263
0
                                     functionScope->bodyEnd,
8264
0
                                     arg.nameToken(),
8265
0
                                     std::move(argValues),
8266
0
                                     tokenlist,
8267
0
                                     errorLogger,
8268
0
                                     settings);
8269
0
                    continue;
8270
0
                }
8271
0
            }
8272
8273
0
            std::list<ValueFlow::Value> argValues;
8274
0
            if (isLow) {
8275
0
                argValues.emplace_back(low);
8276
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeLow ? "Safe checks: " : "") + "Assuming argument has value " + MathLib::toString(low));
8277
0
                argValues.back().safe = safeLow;
8278
0
            }
8279
0
            if (isHigh) {
8280
0
                argValues.emplace_back(high);
8281
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeHigh ? "Safe checks: " : "") + "Assuming argument has value " + MathLib::toString(high));
8282
0
                argValues.back().safe = safeHigh;
8283
0
            }
8284
8285
0
            if (!argValues.empty())
8286
0
                valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
8287
0
                                 functionScope->bodyEnd,
8288
0
                                 arg.nameToken(),
8289
0
                                 std::move(argValues),
8290
0
                                 tokenlist,
8291
0
                                 errorLogger,
8292
0
                                 settings);
8293
0
        }
8294
1.67k
    }
8295
1.17k
}
8296
8297
static void valueFlowUnknownFunctionReturn(TokenList& tokenlist, const Settings& settings)
8298
764
{
8299
764
    if (!tokenlist.front())
8300
0
        return;
8301
54.9k
    for (Token* tok = tokenlist.front()->next(); tok; tok = tok->next()) {
8302
54.1k
        if (!tok->astParent() || tok->str() != MatchCompiler::makeConstString("(") || !tok->previous()->isName())
8303
54.1k
            continue;
8304
8305
0
        if (const auto* f = settings.library.getAllocFuncInfo(tok->astOperand1())) {
8306
0
            if (settings.library.returnValueType(tok->astOperand1()).find('*') != std::string::npos) {
8307
                // Allocation function that returns a pointer
8308
0
                ValueFlow::Value value(0);
8309
0
                value.setPossible();
8310
0
                value.errorPath.emplace_back(tok, "Assuming allocation function fails");
8311
0
                if (Library::ismemory(f->groupId))
8312
0
                    value.unknownFunctionReturn = ValueFlow::Value::UnknownFunctionReturn::outOfMemory;
8313
0
                else
8314
0
                    value.unknownFunctionReturn = ValueFlow::Value::UnknownFunctionReturn::outOfResources;
8315
0
                setTokenValue(tok, std::move(value), settings);
8316
0
                continue;
8317
0
            }
8318
0
        }
8319
8320
0
        if (settings.checkUnknownFunctionReturn.find(tok->strAt(-1)) == settings.checkUnknownFunctionReturn.end())
8321
0
            continue;
8322
0
        std::vector<MathLib::bigint> unknownValues = settings.library.unknownReturnValues(tok->astOperand1());
8323
0
        if (unknownValues.empty())
8324
0
            continue;
8325
8326
        // Get min/max values for return type
8327
0
        const std::string& typestr = settings.library.returnValueType(tok->previous());
8328
0
        MathLib::bigint minvalue, maxvalue;
8329
0
        if (!getMinMaxValues(typestr, settings, tok->isCpp(), minvalue, maxvalue))
8330
0
            continue;
8331
8332
0
        for (MathLib::bigint value : unknownValues) {
8333
0
            if (value < minvalue)
8334
0
                value = minvalue;
8335
0
            else if (value > maxvalue)
8336
0
                value = maxvalue;
8337
0
            setTokenValue(tok, ValueFlow::Value(value), settings);
8338
0
        }
8339
0
    }
8340
764
}
8341
8342
static void valueFlowDebug(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings)
8343
764
{
8344
764
    if (!settings.debugnormal && !settings.debugwarnings)
8345
764
        return;
8346
0
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
8347
0
        if (tok->getTokenDebug() != TokenDebug::ValueFlow)
8348
0
            continue;
8349
0
        if (tok->astParent() && tok->astParent()->getTokenDebug() == TokenDebug::ValueFlow)
8350
0
            continue;
8351
0
        for (const ValueFlow::Value& v : tok->values()) {
8352
0
            std::string msg = "The value is " + debugString(v);
8353
0
            ErrorPath errorPath = v.errorPath;
8354
0
            errorPath.insert(errorPath.end(), v.debugPath.cbegin(), v.debugPath.cend());
8355
0
            errorPath.emplace_back(tok, "");
8356
0
            errorLogger.reportErr({errorPath, &tokenlist, Severity::debug, "valueFlow", msg, CWE{0}, Certainty::normal});
8357
0
        }
8358
0
    }
8359
0
}
8360
8361
const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(Token *expr, const Settings &settings)
8362
0
{
8363
0
    if (expr && expr->values().empty()) {
8364
0
        valueFlowConstantFoldAST(expr->astOperand1(), settings);
8365
0
        valueFlowConstantFoldAST(expr->astOperand2(), settings);
8366
0
        valueFlowSetConstantValue(expr, settings);
8367
0
    }
8368
0
    return expr && expr->hasKnownValue() ? &expr->values().front() : nullptr;
8369
0
}
8370
8371
struct ValueFlowState {
8372
    explicit ValueFlowState(TokenList& tokenlist,
8373
                            SymbolDatabase& symboldatabase,
8374
                            ErrorLogger& errorLogger,
8375
                            const Settings& settings)
8376
764
        : tokenlist(tokenlist), symboldatabase(symboldatabase), errorLogger(errorLogger), settings(settings)
8377
764
    {}
8378
8379
    TokenList& tokenlist;
8380
    SymbolDatabase& symboldatabase;
8381
    ErrorLogger& errorLogger;
8382
    const Settings& settings;
8383
    std::set<const Scope*> skippedFunctions;
8384
};
8385
8386
struct ValueFlowPass {
8387
32.0k
    ValueFlowPass() = default;
8388
32.0k
    ValueFlowPass(const ValueFlowPass&) = default;
8389
    // Name of pass
8390
    virtual const char* name() const = 0;
8391
    // Run the pass
8392
    virtual void run(const ValueFlowState& state) const = 0;
8393
    // Returns true if pass needs C++
8394
    virtual bool cpp() const = 0;
8395
64.1k
    virtual ~ValueFlowPass() noexcept = default;
8396
};
8397
8398
struct ValueFlowPassRunner {
8399
    using Clock = std::chrono::steady_clock;
8400
    using TimePoint = std::chrono::time_point<Clock>;
8401
    explicit ValueFlowPassRunner(ValueFlowState state, TimerResultsIntf* timerResults = nullptr)
8402
764
        : state(std::move(state)), stop(TimePoint::max()), timerResults(timerResults)
8403
764
    {
8404
764
        setSkippedFunctions();
8405
764
        setStopTime();
8406
764
    }
8407
8408
    bool run_once(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
8409
1.52k
    {
8410
12.2k
        return std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
8411
12.2k
            return run(pass);
8412
12.2k
        });
8413
1.52k
    }
8414
8415
    bool run(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
8416
764
    {
8417
764
        std::size_t values = 0;
8418
764
        std::size_t n = state.settings.vfOptions.maxIterations;
8419
1.93k
        while (n > 0 && values != getTotalValues()) {
8420
1.17k
            values = getTotalValues();
8421
30.5k
            if (std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
8422
30.5k
                return run(pass);
8423
30.5k
            }))
8424
0
                return true;
8425
1.17k
            --n;
8426
1.17k
        }
8427
764
        if (state.settings.debugwarnings) {
8428
0
            if (n == 0 && values != getTotalValues()) {
8429
0
                ErrorMessage::FileLocation loc(state.tokenlist.getFiles()[0], 0, 0);
8430
0
                ErrorMessage errmsg({std::move(loc)},
8431
0
                                    "",
8432
0
                                    Severity::debug,
8433
0
                                    "ValueFlow maximum iterations exceeded",
8434
0
                                    "valueFlowMaxIterations",
8435
0
                                    Certainty::normal);
8436
0
                state.errorLogger.reportErr(errmsg);
8437
0
            }
8438
0
        }
8439
764
        return false;
8440
764
    }
8441
8442
    bool run(const ValuePtr<ValueFlowPass>& pass) const
8443
42.7k
    {
8444
42.7k
        auto start = Clock::now();
8445
42.7k
        if (start > stop) {
8446
            // TODO: add bailout message
8447
0
            return true;
8448
0
        }
8449
42.7k
        if (!state.tokenlist.isCPP() && pass->cpp())
8450
0
            return false;
8451
42.7k
        if (timerResults) {
8452
0
            Timer t(pass->name(), state.settings.showtime, timerResults);
8453
0
            pass->run(state);
8454
42.7k
        } else {
8455
42.7k
            pass->run(state);
8456
42.7k
        }
8457
42.7k
        return false;
8458
42.7k
    }
8459
8460
    std::size_t getTotalValues() const
8461
3.11k
    {
8462
3.11k
        std::size_t n = 1;
8463
236k
        for (Token* tok = state.tokenlist.front(); tok; tok = tok->next())
8464
233k
            n += tok->values().size();
8465
3.11k
        return n;
8466
3.11k
    }
8467
8468
    void setSkippedFunctions()
8469
764
    {
8470
764
        if (state.settings.vfOptions.maxIfCount > 0) {
8471
0
            for (const Scope* functionScope : state.symboldatabase.functionScopes) {
8472
0
                int countIfScopes = 0;
8473
0
                std::vector<const Scope*> scopes{functionScope};
8474
0
                while (!scopes.empty()) {
8475
0
                    const Scope* s = scopes.back();
8476
0
                    scopes.pop_back();
8477
0
                    for (const Scope* s2 : s->nestedList) {
8478
0
                        scopes.emplace_back(s2);
8479
0
                        if (s2->type == Scope::ScopeType::eIf)
8480
0
                            ++countIfScopes;
8481
0
                    }
8482
0
                }
8483
0
                if (countIfScopes > state.settings.vfOptions.maxIfCount) {
8484
0
                    state.skippedFunctions.emplace(functionScope);
8485
8486
0
                    if (state.settings.severity.isEnabled(Severity::information)) {
8487
0
                        const std::string& functionName = functionScope->className;
8488
0
                        const std::list<ErrorMessage::FileLocation> callstack(
8489
0
                            1,
8490
0
                            ErrorMessage::FileLocation(functionScope->bodyStart, &state.tokenlist));
8491
0
                        const ErrorMessage errmsg(callstack,
8492
0
                                                  state.tokenlist.getSourceFilePath(),
8493
0
                                                  Severity::information,
8494
0
                                                  "Limiting ValueFlow analysis in function '" + functionName + "' since it is too complex. "
8495
0
                                                  "Please specify --check-level=exhaustive to perform full analysis.",
8496
0
                                                  "checkLevelNormal", // TODO: use more specific ID
8497
0
                                                  Certainty::normal);
8498
0
                        state.errorLogger.reportErr(errmsg);
8499
0
                    }
8500
0
                }
8501
0
            }
8502
0
        }
8503
764
    }
8504
8505
    void setStopTime()
8506
764
    {
8507
764
        if (state.settings.vfOptions.maxTime >= 0)
8508
0
            stop = Clock::now() + std::chrono::seconds{state.settings.vfOptions.maxTime};
8509
764
    }
8510
8511
    ValueFlowState state;
8512
    TimePoint stop;
8513
    TimerResultsIntf* timerResults;
8514
};
8515
8516
template<class F>
8517
struct ValueFlowPassAdaptor : ValueFlowPass {
8518
    const char* mName = nullptr;
8519
    bool mCPP = false;
8520
    F mRun;
8521
32.0k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41)
Line
Count
Source
8521
764
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
8522
0
    const char* name() const override {
8523
0
        return mName;
8524
0
    }
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41>::name() const
8525
    void run(const ValueFlowState& state) const override
8526
42.7k
    {
8527
42.7k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
42.7k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39>::run(ValueFlowState const&) const
Line
Count
Source
8526
1.17k
    {
8527
1.17k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
1.17k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41>::run(ValueFlowState const&) const
Line
Count
Source
8526
764
    {
8527
764
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
8528
764
    }
8529
0
    bool cpp() const override {
8530
0
        return mCPP;
8531
0
    }
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41>::cpp() const
8532
};
8533
8534
template<class F>
8535
static ValueFlowPassAdaptor<F> makeValueFlowPassAdaptor(const char* name, bool cpp, F run)
8536
32.0k
{
8537
32.0k
    return {name, cpp, run};
8538
32.0k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41)
Line
Count
Source
8536
764
{
8537
764
    return {name, cpp, run};
8538
764
}
8539
8540
#define VALUEFLOW_ADAPTOR(cpp, ...)                                                                                    \
8541
32.0k
    makeValueFlowPassAdaptor(#__VA_ARGS__,                                                                             \
8542
32.0k
                             (cpp),                                                                                      \
8543
32.0k
                             [](TokenList& tokenlist,                                                                  \
8544
32.0k
                                SymbolDatabase& symboldatabase,                                                        \
8545
32.0k
                                ErrorLogger& errorLogger,                                                              \
8546
32.0k
                                const Settings& settings,                                                              \
8547
42.7k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
42.7k
        (void)tokenlist;                                                                      \
8549
42.7k
        (void)symboldatabase;                                                                 \
8550
42.7k
        (void)errorLogger;                                                                    \
8551
42.7k
        (void)settings;                                                                       \
8552
42.7k
        (void)skippedFunctions;                                                               \
8553
42.7k
        __VA_ARGS__;                                                                          \
8554
42.7k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_0::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_1::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_2::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_3::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_4::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_5::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_6::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_7::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_8::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_9::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_10::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_11::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_12::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_13::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_14::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_15::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_16::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_17::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_18::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_19::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_20::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_21::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_22::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_23::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_24::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_25::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_26::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_27::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_28::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_29::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_30::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_31::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_32::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_33::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_34::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_35::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_36::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_37::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_38::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_39::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
1.17k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
1.17k
        (void)tokenlist;                                                                      \
8549
1.17k
        (void)symboldatabase;                                                                 \
8550
1.17k
        (void)errorLogger;                                                                    \
8551
1.17k
        (void)settings;                                                                       \
8552
1.17k
        (void)skippedFunctions;                                                               \
8553
1.17k
        __VA_ARGS__;                                                                          \
8554
1.17k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_40::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, TimerResultsIntf*)::$_41::operator()(TokenList&, SymbolDatabase&, ErrorLogger&, Settings const&, std::__1::set<Scope const*, std::__1::less<Scope const*>, std::__1::allocator<Scope const*> > const&) const
Line
Count
Source
8547
764
                                const std::set<const Scope*>& skippedFunctions) {                                      \
8548
764
        (void)tokenlist;                                                                      \
8549
764
        (void)symboldatabase;                                                                 \
8550
764
        (void)errorLogger;                                                                    \
8551
764
        (void)settings;                                                                       \
8552
764
        (void)skippedFunctions;                                                               \
8553
764
        __VA_ARGS__;                                                                          \
8554
764
    })
8555
8556
25.9k
#define VFA(...) VALUEFLOW_ADAPTOR(false, __VA_ARGS__)
8557
6.11k
#define VFA_CPP(...) VALUEFLOW_ADAPTOR(true, __VA_ARGS__)
8558
8559
void ValueFlow::setValues(TokenList& tokenlist,
8560
                          SymbolDatabase& symboldatabase,
8561
                          ErrorLogger& errorLogger,
8562
                          const Settings& settings,
8563
                          TimerResultsIntf* timerResults)
8564
764
{
8565
55.6k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next())
8566
54.9k
        tok->clearValueFlow();
8567
8568
    // commas in init..
8569
55.6k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
8570
54.9k
        if (tok->str() != MatchCompiler::makeConstString("{") || !tok->astOperand1())
8571
54.9k
            continue;
8572
0
        for (Token* tok2 = tok->next(); tok2 != tok->link(); tok2 = tok2->next()) {
8573
0
            if (tok2->link() && match152(tok2))
8574
0
                tok2 = tok2->link();
8575
0
            else if (tok2->str() == MatchCompiler::makeConstString(","))
8576
0
                tok2->isInitComma(true);
8577
0
        }
8578
0
    }
8579
8580
764
    ValueFlowPassRunner runner{ValueFlowState{tokenlist, symboldatabase, errorLogger, settings}, timerResults};
8581
764
    runner.run_once({
8582
764
        VFA(valueFlowEnumValue(symboldatabase, settings)),
8583
764
        VFA(valueFlowNumber(tokenlist, settings)),
8584
764
        VFA(valueFlowString(tokenlist, settings)),
8585
764
        VFA(valueFlowArray(tokenlist, settings)),
8586
764
        VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)),
8587
764
        VFA(valueFlowGlobalConstVar(tokenlist, settings)),
8588
764
        VFA(valueFlowEnumValue(symboldatabase, settings)),
8589
764
        VFA(valueFlowGlobalStaticVar(tokenlist, settings)),
8590
764
        VFA(valueFlowPointerAlias(tokenlist, settings)),
8591
764
        VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
8592
764
        VFA(valueFlowSymbolic(tokenlist, symboldatabase, errorLogger, settings)),
8593
764
        VFA(valueFlowBitAnd(tokenlist, settings)),
8594
764
        VFA(valueFlowSameExpressions(tokenlist, settings)),
8595
764
        VFA(valueFlowConditionExpressions(tokenlist, symboldatabase, errorLogger, settings)),
8596
764
    });
8597
8598
764
    runner.run({
8599
764
        VFA(valueFlowImpossibleValues(tokenlist, settings)),
8600
764
        VFA(valueFlowSymbolicOperators(symboldatabase, settings)),
8601
764
        VFA(valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
8602
764
        VFA(valueFlowSymbolicInfer(symboldatabase, settings)),
8603
764
        VFA(valueFlowArrayBool(tokenlist, settings)),
8604
764
        VFA(valueFlowArrayElement(tokenlist, settings)),
8605
764
        VFA(valueFlowRightShift(tokenlist, settings)),
8606
764
        VFA_CPP(
8607
764
            valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
8608
764
        VFA(valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
8609
764
        VFA_CPP(valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings)),
8610
764
        VFA(valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
8611
764
        VFA(valueFlowInferCondition(tokenlist, settings)),
8612
764
        VFA(valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings)),
8613
764
        VFA(valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings)),
8614
764
        VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings)),
8615
764
        VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)),
8616
764
        VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
8617
764
        VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings)),
8618
764
        VFA(valueFlowUninit(tokenlist, errorLogger, settings)),
8619
764
        VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, errorLogger, settings)),
8620
764
        VFA_CPP(valueFlowSmartPointer(tokenlist, errorLogger, settings)),
8621
764
        VFA_CPP(valueFlowIterators(tokenlist, settings)),
8622
764
        VFA_CPP(
8623
764
            valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
8624
764
        VFA_CPP(valueFlowIteratorInfer(tokenlist, settings)),
8625
764
        VFA_CPP(valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
8626
764
        VFA(valueFlowSafeFunctions(tokenlist, symboldatabase, errorLogger, settings)),
8627
764
    });
8628
8629
764
    runner.run_once({
8630
764
        VFA(valueFlowDynamicBufferSize(tokenlist, symboldatabase, errorLogger, settings)),
8631
764
        VFA(valueFlowDebug(tokenlist, errorLogger, settings)), // TODO: add option to print it after each step/iteration
8632
764
    });
8633
764
}
8634
8635
std::string ValueFlow::eitherTheConditionIsRedundant(const Token *condition)
8636
0
{
8637
0
    if (!condition)
8638
0
        return "Either the condition is redundant";
8639
0
    if (condition->str() == MatchCompiler::makeConstString("case")) {
8640
0
        std::string expr;
8641
0
        for (const Token *tok = condition; tok && tok->str() != MatchCompiler::makeConstString(":"); tok = tok->next()) {
8642
0
            expr += tok->str();
8643
0
            if (match153(tok))
8644
0
                expr += ' ';
8645
0
        }
8646
0
        return "Either the switch case '" + expr + "' is redundant";
8647
0
    }
8648
0
    return "Either the condition '" + condition->expressionString() + "' is redundant";
8649
0
}
8650
8651
const ValueFlow::Value* ValueFlow::findValue(const std::list<ValueFlow::Value>& values,
8652
                                             const Settings& settings,
8653
                                             const std::function<bool(const ValueFlow::Value&)> &pred)
8654
122
{
8655
122
    const ValueFlow::Value* ret = nullptr;
8656
126
    for (const ValueFlow::Value& v : values) {
8657
126
        if (pred(v)) {
8658
3
            if (!ret || ret->isInconclusive() || (ret->condition && !v.isInconclusive()))
8659
3
                ret = &v;
8660
3
            if (!ret->isInconclusive() && !ret->condition)
8661
3
                break;
8662
3
        }
8663
126
    }
8664
122
    if (ret) {
8665
3
        if (ret->isInconclusive() && !settings.certainty.isEnabled(Certainty::inconclusive))
8666
0
            return nullptr;
8667
3
        if (ret->condition && !settings.severity.isEnabled(Severity::warning))
8668
0
            return nullptr;
8669
3
    }
8670
122
    return ret;
8671
122
}
8672
8673
// TODO: returns a single value at most - no need for std::vector
8674
static std::vector<ValueFlow::Value> isOutOfBoundsImpl(const ValueFlow::Value& size,
8675
                                                       const Token* indexTok,
8676
                                                       bool condition)
8677
0
{
8678
0
    if (!indexTok)
8679
0
        return {};
8680
0
    const ValueFlow::Value* indexValue = indexTok->getMaxValue(condition, size.path);
8681
0
    if (!indexValue)
8682
0
        return {};
8683
0
    if (indexValue->intvalue >= size.intvalue)
8684
0
        return {*indexValue};
8685
0
    if (!condition)
8686
0
        return {};
8687
    // TODO: Use a better way to decide if the variable in unconstrained
8688
0
    if (!indexTok->variable() || !indexTok->variable()->isArgument())
8689
0
        return {};
8690
0
    if (std::any_of(indexTok->values().cbegin(), indexTok->values().cend(), [&](const ValueFlow::Value& v) {
8691
0
        return v.isSymbolicValue() && v.isPossible() && v.bound == ValueFlow::Value::Bound::Upper;
8692
0
    }))
8693
0
        return {};
8694
0
    if (indexValue->bound != ValueFlow::Value::Bound::Lower)
8695
0
        return {};
8696
0
    if (size.bound == ValueFlow::Value::Bound::Lower)
8697
0
        return {};
8698
    // Checking for underflow doesn't mean it could be out of bounds
8699
0
    if (indexValue->intvalue == 0)
8700
0
        return {};
8701
0
    ValueFlow::Value value = inferCondition(">=", indexTok, indexValue->intvalue);
8702
0
    if (!value.isKnown())
8703
0
        return {};
8704
0
    if (value.intvalue == 0)
8705
0
        return {};
8706
0
    value.intvalue = size.intvalue;
8707
0
    value.bound = ValueFlow::Value::Bound::Lower;
8708
0
    return {std::move(value)};
8709
0
}
8710
8711
// TODO: return single value at most - no need for std::vector
8712
std::vector<ValueFlow::Value> ValueFlow::isOutOfBounds(const Value& size, const Token* indexTok, bool possible)
8713
0
{
8714
0
    ValueFlow::Value inBoundsValue = inferCondition("<", indexTok, size.intvalue);
8715
0
    if (inBoundsValue.isKnown() && inBoundsValue.intvalue != 0)
8716
0
        return {};
8717
0
    std::vector<ValueFlow::Value> result = isOutOfBoundsImpl(size, indexTok, false);
8718
0
    if (!result.empty())
8719
0
        return result;
8720
0
    if (!possible)
8721
0
        return result;
8722
0
    return isOutOfBoundsImpl(size, indexTok, true);
8723
0
}