Coverage Report

Created: 2023-09-25 06:15

/src/cppcheck/lib/valueflow.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Cppcheck - A tool for static C/C++ code analysis
3
 * Copyright (C) 2007-2023 Cppcheck team.
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
/**
20
 * @brief This is the ValueFlow component in Cppcheck.
21
 *
22
 * Each @sa Token in the token list has a list of values. These are
23
 * the "possible" values for the Token at runtime.
24
 *
25
 * In the --debug and --debug-normal output you can see the ValueFlow data. For example:
26
 *
27
 *     int f()
28
 *     {
29
 *         int x = 10;
30
 *         return 4 * x + 2;
31
 *     }
32
 *
33
 * The --debug-normal output says:
34
 *
35
 *     ##Value flow
36
 *     Line 3
37
 *       10 always 10
38
 *     Line 4
39
 *       4 always 4
40
 *       * always 40
41
 *       x always 10
42
 *       + always 42
43
 *       2 always 2
44
 *
45
 * All value flow analysis is executed in the ValueFlow::setValues() function. The ValueFlow analysis is executed after
46
 * the tokenizer/ast/symboldatabase/etc.. The ValueFlow analysis is done in a series of valueFlow* function calls, where
47
 * each such function call can only use results from previous function calls. The function calls should be arranged so
48
 * that valueFlow* that do not require previous ValueFlow information should be first.
49
 *
50
 * Type of analysis
51
 * ================
52
 *
53
 * This is "flow sensitive" value flow analysis. We _usually_ track the value for 1 variable at a time.
54
 *
55
 * How are calculations handled
56
 * ============================
57
 *
58
 * Here is an example code:
59
 *
60
 *   x = 3 + 4;
61
 *
62
 * The valueFlowNumber set the values for the "3" and "4" tokens by calling setTokenValue().
63
 * The setTokenValue() handle the calculations automatically. When both "3" and "4" have values, the "+" can be
64
 * calculated. setTokenValue() recursively calls itself when parents in calculations can be calculated.
65
 *
66
 * Forward / Reverse flow analysis
67
 * ===============================
68
 *
69
 * In forward value flow analysis we know a value and see what happens when we are stepping the program forward. Like
70
 * normal execution. The valueFlowForward is used in this analysis.
71
 *
72
 * In reverse value flow analysis we know the value of a variable at line X. And try to "execute backwards" to determine
73
 * possible values before line X. The valueFlowReverse is used in this analysis.
74
 *
75
 *
76
 */
77
78
#include "valueflow.h"
79
80
#include "analyzer.h"
81
#include "astutils.h"
82
#include "calculate.h"
83
#include "checkuninitvar.h"
84
#include "config.h"
85
#include "errorlogger.h"
86
#include "errortypes.h"
87
#include "findtoken.h"
88
#include "forwardanalyzer.h"
89
#include "infer.h"
90
#include "library.h"
91
#include "mathlib.h"
92
#include "path.h"
93
#include "platform.h"
94
#include "programmemory.h"
95
#include "reverseanalyzer.h"
96
#include "settings.h"
97
#include "smallvector.h"
98
#include "sourcelocation.h"
99
#include "standards.h"
100
#include "symboldatabase.h"
101
#include "timer.h"
102
#include "token.h"
103
#include "tokenlist.h"
104
#include "utils.h"
105
#include "valueptr.h"
106
#include "vfvalue.h"
107
108
#include <algorithm>
109
#include <array>
110
#include <cassert>
111
#include <chrono>
112
#include <climits>
113
#include <cstdlib>
114
#include <cstring>
115
#include <exception>
116
#include <functional>
117
#include <initializer_list>
118
#include <iterator>
119
#include <limits>
120
#include <map>
121
#include <memory>
122
#include <set>
123
#include <sstream> // IWYU pragma: keep
124
#include <string>
125
#include <type_traits>
126
#include <unordered_map>
127
#include <unordered_set>
128
#include <vector>
129
130
static void bailoutInternal(const std::string& type, TokenList &tokenlist, ErrorLogger *errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function)
131
0
{
132
0
    if (function.find("operator") != std::string::npos)
133
0
        function = "(valueFlow)";
134
0
    std::list<ErrorMessage::FileLocation> callstack(1, ErrorMessage::FileLocation(tok, &tokenlist));
135
0
    ErrorMessage errmsg(callstack, tokenlist.getSourceFilePath(), Severity::debug,
136
0
                        Path::stripDirectoryPart(file) + ":" + std::to_string(line) + ":" + function + " bailout: " + what, type, Certainty::normal);
137
0
    errorLogger->reportErr(errmsg);
138
0
}
139
140
0
#define bailout2(type, tokenlist, errorLogger, tok, what) bailoutInternal(type, tokenlist, errorLogger, tok, what, __FILE__, __LINE__, __func__)
141
142
0
#define bailout(tokenlist, errorLogger, tok, what) bailout2("valueFlowBailout", tokenlist, errorLogger, tok, what)
143
144
0
#define bailoutIncompleteVar(tokenlist, errorLogger, tok, what) bailout2("valueFlowBailoutIncompleteVar", tokenlist, errorLogger, tok, what)
145
146
static std::string debugString(const ValueFlow::Value& v)
147
0
{
148
0
    std::string kind;
149
0
    switch (v.valueKind) {
150
151
0
    case ValueFlow::Value::ValueKind::Impossible:
152
0
    case ValueFlow::Value::ValueKind::Known:
153
0
        kind = "always";
154
0
        break;
155
0
    case ValueFlow::Value::ValueKind::Inconclusive:
156
0
        kind = "inconclusive";
157
0
        break;
158
0
    case ValueFlow::Value::ValueKind::Possible:
159
0
        kind = "possible";
160
0
        break;
161
0
    }
162
0
    return kind + " " + v.toString();
163
0
}
164
165
static void setSourceLocation(ValueFlow::Value& v,
166
                              SourceLocation ctx,
167
                              const Token* tok,
168
                              SourceLocation local = SourceLocation::current())
169
0
{
170
0
    std::string file = ctx.file_name();
171
0
    if (file.empty())
172
0
        return;
173
0
    std::string s = Path::stripDirectoryPart(file) + ":" + std::to_string(ctx.line()) + ": " + ctx.function_name() +
174
0
                    " => " + local.function_name() + ": " + debugString(v);
175
0
    v.debugPath.emplace_back(tok, std::move(s));
176
0
}
177
178
static void changeKnownToPossible(std::list<ValueFlow::Value> &values, int indirect=-1)
179
2.30k
{
180
3.68k
    for (ValueFlow::Value& v: values) {
181
3.68k
        if (indirect >= 0 && v.indirect != indirect)
182
0
            continue;
183
3.68k
        v.changeKnownToPossible();
184
3.68k
    }
185
2.30k
}
186
187
static void removeImpossible(std::list<ValueFlow::Value>& values, int indirect = -1)
188
0
{
189
0
    values.remove_if([&](const ValueFlow::Value& v) {
190
0
        if (indirect >= 0 && v.indirect != indirect)
191
0
            return false;
192
0
        return v.isImpossible();
193
0
    });
194
0
}
195
196
static void lowerToPossible(std::list<ValueFlow::Value>& values, int indirect = -1)
197
0
{
198
0
    changeKnownToPossible(values, indirect);
199
0
    removeImpossible(values, indirect);
200
0
}
201
202
static void changePossibleToKnown(std::list<ValueFlow::Value>& values, int indirect = -1)
203
304
{
204
304
    for (ValueFlow::Value& v : values) {
205
304
        if (indirect >= 0 && v.indirect != indirect)
206
0
            continue;
207
304
        if (!v.isPossible())
208
39
            continue;
209
265
        if (v.bound != ValueFlow::Value::Bound::Point)
210
0
            continue;
211
265
        v.setKnown();
212
265
    }
213
304
}
214
215
static bool isNonConditionalPossibleIntValue(const ValueFlow::Value& v)
216
0
{
217
0
    if (v.conditional)
218
0
        return false;
219
0
    if (v.condition)
220
0
        return false;
221
0
    if (!v.isPossible())
222
0
        return false;
223
0
    if (!v.isIntValue())
224
0
        return false;
225
0
    return true;
226
0
}
227
228
static void setValueUpperBound(ValueFlow::Value& value, bool upper)
229
11.2k
{
230
11.2k
    if (upper)
231
5.61k
        value.bound = ValueFlow::Value::Bound::Upper;
232
5.61k
    else
233
5.61k
        value.bound = ValueFlow::Value::Bound::Lower;
234
11.2k
}
235
236
static void setValueBound(ValueFlow::Value& value, const Token* tok, bool invert)
237
14.8k
{
238
14.8k
    if (Token::Match(tok, "<|<=")) {
239
6.13k
        setValueUpperBound(value, !invert);
240
8.67k
    } else if (Token::Match(tok, ">|>=")) {
241
5.08k
        setValueUpperBound(value, invert);
242
5.08k
    }
243
14.8k
}
244
245
static void setConditionalValue(ValueFlow::Value& value, const Token* tok, MathLib::bigint i)
246
14.8k
{
247
14.8k
    assert(value.isIntValue());
248
0
    value.intvalue = i;
249
14.8k
    value.assumeCondition(tok);
250
14.8k
    value.setPossible();
251
14.8k
}
252
253
static void setConditionalValues(const Token* tok,
254
                                 bool lhs,
255
                                 MathLib::bigint value,
256
                                 ValueFlow::Value& true_value,
257
                                 ValueFlow::Value& false_value)
258
7.40k
{
259
7.40k
    if (Token::Match(tok, "==|!=|>=|<=")) {
260
3.97k
        setConditionalValue(true_value, tok, value);
261
3.97k
        const char* greaterThan = ">=";
262
3.97k
        const char* lessThan = "<=";
263
3.97k
        if (lhs)
264
2.17k
            std::swap(greaterThan, lessThan);
265
3.97k
        if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
266
1.07k
            setConditionalValue(false_value, tok, value - 1);
267
2.89k
        } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) {
268
1.10k
            setConditionalValue(false_value, tok, value + 1);
269
1.79k
        } else {
270
1.79k
            setConditionalValue(false_value, tok, value);
271
1.79k
        }
272
3.97k
    } else {
273
3.43k
        const char* greaterThan = ">";
274
3.43k
        const char* lessThan = "<";
275
3.43k
        if (lhs)
276
1.64k
            std::swap(greaterThan, lessThan);
277
3.43k
        if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
278
1.72k
            setConditionalValue(true_value, tok, value + 1);
279
1.72k
            setConditionalValue(false_value, tok, value);
280
1.72k
        } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) {
281
1.70k
            setConditionalValue(true_value, tok, value - 1);
282
1.70k
            setConditionalValue(false_value, tok, value);
283
1.70k
        }
284
3.43k
    }
285
7.40k
    setValueBound(true_value, tok, lhs);
286
7.40k
    setValueBound(false_value, tok, !lhs);
287
7.40k
}
288
289
static bool isSaturated(MathLib::bigint value)
290
3.66k
{
291
3.66k
    return value == std::numeric_limits<MathLib::bigint>::max() || value == std::numeric_limits<MathLib::bigint>::min();
292
3.66k
}
293
294
static void parseCompareEachInt(
295
    const Token* tok,
296
    const std::function<void(const Token* varTok, ValueFlow::Value true_value, ValueFlow::Value false_value)>& each,
297
    const std::function<std::vector<ValueFlow::Value>(const Token*)>& evaluate)
298
80.5k
{
299
80.5k
    if (!tok->astOperand1() || !tok->astOperand2())
300
44.3k
        return;
301
36.1k
    if (tok->isComparisonOp()) {
302
14.7k
        std::vector<ValueFlow::Value> value1 = evaluate(tok->astOperand1());
303
14.7k
        std::vector<ValueFlow::Value> value2 = evaluate(tok->astOperand2());
304
14.7k
        if (!value1.empty() && !value2.empty()) {
305
321
            if (tok->astOperand1()->hasKnownIntValue())
306
311
                value2.clear();
307
321
            if (tok->astOperand2()->hasKnownIntValue())
308
304
                value1.clear();
309
321
        }
310
14.7k
        for (const ValueFlow::Value& v1 : value1) {
311
1.95k
            ValueFlow::Value true_value = v1;
312
1.95k
            ValueFlow::Value false_value = v1;
313
1.95k
            if (isSaturated(v1.intvalue) || astIsFloat(tok->astOperand2(), /*unknown*/ false))
314
0
                continue;
315
1.95k
            setConditionalValues(tok, true, v1.intvalue, true_value, false_value);
316
1.95k
            each(tok->astOperand2(), std::move(true_value), std::move(false_value));
317
1.95k
        }
318
14.7k
        for (const ValueFlow::Value& v2 : value2) {
319
1.71k
            ValueFlow::Value true_value = v2;
320
1.71k
            ValueFlow::Value false_value = v2;
321
1.71k
            if (isSaturated(v2.intvalue) || astIsFloat(tok->astOperand1(), /*unknown*/ false))
322
0
                continue;
323
1.71k
            setConditionalValues(tok, false, v2.intvalue, true_value, false_value);
324
1.71k
            each(tok->astOperand1(), std::move(true_value), std::move(false_value));
325
1.71k
        }
326
14.7k
    }
327
36.1k
}
328
329
static void parseCompareEachInt(
330
    const Token* tok,
331
    const std::function<void(const Token* varTok, ValueFlow::Value true_value, ValueFlow::Value false_value)>& each)
332
79.3k
{
333
79.3k
    parseCompareEachInt(tok, each, [](const Token* t) -> std::vector<ValueFlow::Value> {
334
27.2k
        if (t->hasKnownIntValue())
335
4.01k
            return {t->values().front()};
336
23.2k
        std::vector<ValueFlow::Value> result;
337
23.2k
        std::copy_if(t->values().cbegin(), t->values().cend(), std::back_inserter(result), [&](const ValueFlow::Value& v) {
338
4.83k
            if (v.path < 1)
339
4.83k
                return false;
340
0
            if (!isNonConditionalPossibleIntValue(v))
341
0
                return false;
342
0
            return true;
343
0
        });
344
23.2k
        return result;
345
27.2k
    });
346
79.3k
}
347
348
const Token* ValueFlow::parseCompareInt(const Token* tok,
349
                                        ValueFlow::Value& true_value,
350
                                        ValueFlow::Value& false_value,
351
                                        const std::function<std::vector<MathLib::bigint>(const Token*)>& evaluate)
352
1.13k
{
353
1.13k
    const Token* result = nullptr;
354
1.13k
    parseCompareEachInt(
355
1.13k
        tok,
356
1.13k
        [&](const Token* vartok, ValueFlow::Value true_value2, ValueFlow::Value false_value2) {
357
247
        if (result)
358
2
            return;
359
245
        result = vartok;
360
245
        true_value = std::move(true_value2);
361
245
        false_value = std::move(false_value2);
362
245
    },
363
2.27k
        [&](const Token* t) -> std::vector<ValueFlow::Value> {
364
2.27k
        std::vector<ValueFlow::Value> r;
365
2.27k
        std::vector<MathLib::bigint> v = evaluate(t);
366
367
2.27k
        std::transform(v.cbegin(), v.cend(), std::back_inserter(r), [&](MathLib::bigint i) {
368
274
            return ValueFlow::Value{i};
369
274
        });
370
2.27k
        return r;
371
2.27k
    });
372
1.13k
    return result;
373
1.13k
}
374
375
const Token *ValueFlow::parseCompareInt(const Token *tok, ValueFlow::Value &true_value, ValueFlow::Value &false_value)
376
0
{
377
0
    return parseCompareInt(tok, true_value, false_value, [](const Token* t) -> std::vector<MathLib::bigint> {
378
0
        if (t->hasKnownIntValue())
379
0
            return {t->values().front().intvalue};
380
0
        return std::vector<MathLib::bigint>{};
381
0
    });
382
0
}
383
384
static bool isEscapeScope(const Token* tok, const Settings* settings, bool unknown = false)
385
90
{
386
90
    if (!Token::simpleMatch(tok, "{"))
387
0
        return false;
388
    // TODO this search for termTok in all subscopes. It should check the end of the scope.
389
90
    const Token * termTok = Token::findmatch(tok, "return|continue|break|throw|goto", tok->link());
390
90
    if (termTok && termTok->scope() == tok->scope())
391
1
        return true;
392
89
    std::string unknownFunction;
393
89
    if (settings->library.isScopeNoReturn(tok->link(), &unknownFunction))
394
0
        return unknownFunction.empty() || unknown;
395
89
    return false;
396
89
}
397
398
static ValueFlow::Value castValue(ValueFlow::Value value, const ValueType::Sign sign, nonneg int bit)
399
335
{
400
335
    if (value.isFloatValue()) {
401
0
        value.valueType = ValueFlow::Value::ValueType::INT;
402
0
        if (value.floatValue >= std::numeric_limits<int>::min() && value.floatValue <= std::numeric_limits<int>::max()) {
403
0
            value.intvalue = value.floatValue;
404
0
        } else { // don't perform UB
405
0
            value.intvalue = 0;
406
0
        }
407
0
    }
408
335
    if (bit < MathLib::bigint_bits) {
409
335
        const MathLib::biguint one = 1;
410
335
        value.intvalue &= (one << bit) - 1;
411
335
        if (sign == ValueType::Sign::SIGNED && value.intvalue & (one << (bit - 1))) {
412
29
            value.intvalue |= ~((one << bit) - 1ULL);
413
29
        }
414
335
    }
415
335
    return value;
416
335
}
417
418
0
static bool isNumeric(const ValueFlow::Value& value) {
419
0
    return value.isIntValue() || value.isFloatValue();
420
0
}
421
422
void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value &result)
423
3.86k
{
424
3.86k
    if (value1.isKnown() && value2.isKnown())
425
469
        result.setKnown();
426
3.40k
    else if (value1.isImpossible() || value2.isImpossible())
427
935
        result.setImpossible();
428
2.46k
    else if (value1.isInconclusive() || value2.isInconclusive())
429
0
        result.setInconclusive();
430
2.46k
    else
431
2.46k
        result.setPossible();
432
3.86k
    if (value1.tokvalue)
433
1.21k
        result.tokvalue = value1.tokvalue;
434
2.65k
    else if (value2.tokvalue)
435
849
        result.tokvalue = value2.tokvalue;
436
3.86k
    if (value1.isSymbolicValue()) {
437
912
        result.valueType = value1.valueType;
438
912
        result.tokvalue = value1.tokvalue;
439
912
    }
440
3.86k
    if (value2.isSymbolicValue()) {
441
1.44k
        result.valueType = value2.valueType;
442
1.44k
        result.tokvalue = value2.tokvalue;
443
1.44k
    }
444
3.86k
    if (value1.isIteratorValue())
445
0
        result.valueType = value1.valueType;
446
3.86k
    if (value2.isIteratorValue())
447
0
        result.valueType = value2.valueType;
448
3.86k
    result.condition = value1.condition ? value1.condition : value2.condition;
449
3.86k
    result.varId = (value1.varId != 0) ? value1.varId : value2.varId;
450
3.86k
    result.varvalue = (result.varId == value1.varId) ? value1.varvalue : value2.varvalue;
451
3.86k
    result.errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath;
452
3.86k
    result.safe = value1.safe || value2.safe;
453
3.86k
    if (value1.bound == ValueFlow::Value::Bound::Point || value2.bound == ValueFlow::Value::Bound::Point) {
454
2.90k
        if (value1.bound == ValueFlow::Value::Bound::Upper || value2.bound == ValueFlow::Value::Bound::Upper)
455
953
            result.bound = ValueFlow::Value::Bound::Upper;
456
2.90k
        if (value1.bound == ValueFlow::Value::Bound::Lower || value2.bound == ValueFlow::Value::Bound::Lower)
457
784
            result.bound = ValueFlow::Value::Bound::Lower;
458
2.90k
    }
459
3.86k
    if (value1.path != value2.path)
460
0
        result.path = -1;
461
3.86k
    else
462
3.86k
        result.path = value1.path;
463
3.86k
}
464
465
static const Token *getCastTypeStartToken(const Token *parent, const Settings* settings)
466
10.2k
{
467
    // TODO: This might be a generic utility function?
468
10.2k
    if (!Token::Match(parent, "{|("))
469
8.04k
        return nullptr;
470
    // Functional cast
471
2.19k
    if (parent->isBinaryOp() && Token::Match(parent->astOperand1(), "%type% (|{") &&
472
2.19k
        parent->astOperand1()->tokType() == Token::eType && astIsPrimitive(parent))
473
0
        return parent->astOperand1();
474
2.19k
    if (parent->str() != "(")
475
0
        return nullptr;
476
2.19k
    if (!parent->astOperand2() && Token::Match(parent, "( %name%|::")) {
477
0
        const Token* ftok = parent->next();
478
0
        if (ftok->isStandardType())
479
0
            return ftok;
480
0
        if (Token::simpleMatch(ftok, "::"))
481
0
            ftok = ftok->next();
482
0
        while (Token::Match(ftok, "%name% ::"))
483
0
            ftok = ftok->tokAt(2);
484
0
        if (settings->library.isNotLibraryFunction(ftok))
485
0
            return parent->next();
486
0
    }
487
2.19k
    if (parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
488
0
        return parent->astOperand1()->tokAt(2);
489
2.19k
    return nullptr;
490
2.19k
}
491
492
// does the operation cause a loss of information?
493
static bool isNonInvertibleOperation(const Token* tok)
494
6.76k
{
495
6.76k
    return !Token::Match(tok, "+|-");
496
6.76k
}
497
498
static bool isComputableValue(const Token* parent, const ValueFlow::Value& value)
499
2.35k
{
500
2.35k
    const bool noninvertible = isNonInvertibleOperation(parent);
501
2.35k
    if (noninvertible && value.isImpossible())
502
59
        return false;
503
2.29k
    if (!value.isIntValue() && !value.isFloatValue() && !value.isTokValue() && !value.isIteratorValue())
504
73
        return false;
505
2.22k
    if (value.isIteratorValue() && !Token::Match(parent, "+|-"))
506
0
        return false;
507
2.22k
    if (value.isTokValue() && (!parent->isComparisonOp() || !Token::Match(value.tokvalue, "{|%str%")))
508
0
        return false;
509
2.22k
    return true;
510
2.22k
}
511
512
static Library::Container::Yield getContainerYield(Token* tok, const Settings* settings, Token** parent = nullptr)
513
0
{
514
0
    if (Token::Match(tok, ". %name% (") && tok->astParent() == tok->tokAt(2) && tok->astOperand1() &&
515
0
        tok->astOperand1()->valueType()) {
516
0
        const Library::Container* c = getLibraryContainer(tok->astOperand1());
517
0
        if (parent)
518
0
            *parent = tok->astParent();
519
0
        return c ? c->getYield(tok->strAt(1)) : Library::Container::Yield::NO_YIELD;
520
0
    }
521
0
    if (Token::Match(tok->previous(), "%name% (")) {
522
0
        if (parent)
523
0
            *parent = tok;
524
0
        if (const Library::Function* f = settings->library.getFunction(tok->previous())) {
525
0
            return f->containerYield;
526
0
        }
527
0
    }
528
0
    return Library::Container::Yield::NO_YIELD;
529
0
}
530
531
/** Set token value for cast */
532
static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings *settings);
533
534
static bool isCompatibleValueTypes(ValueFlow::Value::ValueType x, ValueFlow::Value::ValueType y)
535
452
{
536
452
    static const std::unordered_map<ValueFlow::Value::ValueType,
537
452
                                    std::unordered_set<ValueFlow::Value::ValueType, EnumClassHash>,
538
452
                                    EnumClassHash>
539
452
    compatibleTypes = {
540
452
        {ValueFlow::Value::ValueType::INT,
541
452
         {ValueFlow::Value::ValueType::FLOAT,
542
452
          ValueFlow::Value::ValueType::SYMBOLIC,
543
452
          ValueFlow::Value::ValueType::TOK}},
544
452
        {ValueFlow::Value::ValueType::FLOAT, {ValueFlow::Value::ValueType::INT}},
545
452
        {ValueFlow::Value::ValueType::TOK, {ValueFlow::Value::ValueType::INT}},
546
452
        {ValueFlow::Value::ValueType::ITERATOR_START, {ValueFlow::Value::ValueType::INT}},
547
452
        {ValueFlow::Value::ValueType::ITERATOR_END, {ValueFlow::Value::ValueType::INT}},
548
452
    };
549
452
    if (x == y)
550
452
        return true;
551
0
    auto it = compatibleTypes.find(x);
552
0
    if (it == compatibleTypes.end())
553
0
        return false;
554
0
    return it->second.count(y) > 0;
555
0
}
556
557
static bool isCompatibleValues(const ValueFlow::Value& value1, const ValueFlow::Value& value2)
558
452
{
559
452
    if (value1.isSymbolicValue() && value2.isSymbolicValue() && value1.tokvalue->exprId() != value2.tokvalue->exprId())
560
0
        return false;
561
452
    if (!isCompatibleValueTypes(value1.valueType, value2.valueType))
562
0
        return false;
563
452
    if (value1.isKnown() || value2.isKnown())
564
432
        return true;
565
20
    if (value1.isImpossible() || value2.isImpossible())
566
12
        return false;
567
8
    if (value1.varId == 0 || value2.varId == 0)
568
0
        return true;
569
8
    if (value1.varId == value2.varId && value1.varvalue == value2.varvalue && value1.isIntValue() && value2.isIntValue())
570
8
        return true;
571
0
    return false;
572
8
}
573
574
static ValueFlow::Value truncateImplicitConversion(Token* parent, const ValueFlow::Value& value, const Settings* settings)
575
35.1k
{
576
35.1k
    if (!value.isIntValue() && !value.isFloatValue())
577
0
        return value;
578
35.1k
    if (!parent)
579
14.1k
        return value;
580
20.9k
    if (!parent->isBinaryOp())
581
3.42k
        return value;
582
17.5k
    if (!parent->isConstOp())
583
14.5k
        return value;
584
2.96k
    if (!astIsIntegral(parent->astOperand1(), false))
585
432
        return value;
586
2.53k
    if (!astIsIntegral(parent->astOperand2(), false))
587
301
        return value;
588
2.22k
    const ValueType* vt1 = parent->astOperand1()->valueType();
589
2.22k
    const ValueType* vt2 = parent->astOperand2()->valueType();
590
    // If the sign is the same there is no truncation
591
2.22k
    if (vt1->sign == vt2->sign)
592
1.89k
        return value;
593
335
    const size_t n1 = ValueFlow::getSizeOf(*vt1, settings);
594
335
    const size_t n2 = ValueFlow::getSizeOf(*vt2, settings);
595
335
    ValueType::Sign sign = ValueType::Sign::UNSIGNED;
596
335
    if (n1 < n2)
597
183
        sign = vt2->sign;
598
152
    else if (n1 > n2)
599
152
        sign = vt1->sign;
600
335
    ValueFlow::Value v = castValue(value, sign, std::max(n1, n2) * 8);
601
335
    v.wideintvalue = value.intvalue;
602
335
    return v;
603
2.22k
}
604
605
/** set ValueFlow value and perform calculations if possible */
606
static void setTokenValue(Token* tok,
607
                          ValueFlow::Value value,
608
                          const Settings* settings,
609
                          SourceLocation loc = SourceLocation::current())
610
43.1k
{
611
    // Skip setting values that are too big since its ambiguous
612
43.1k
    if (!value.isImpossible() && value.isIntValue() && value.intvalue < 0 && astIsUnsigned(tok) &&
613
43.1k
        ValueFlow::getSizeOf(*tok->valueType(), settings) >= sizeof(MathLib::bigint))
614
0
        return;
615
616
43.1k
    if (!value.isImpossible() && value.isIntValue())
617
35.1k
        value = truncateImplicitConversion(tok->astParent(), value, settings);
618
619
43.1k
    if (settings->debugnormal)
620
0
        setSourceLocation(value, loc, tok);
621
622
43.1k
    if (!tok->addValue(value))
623
3.86k
        return;
624
625
39.2k
    if (value.path < 0)
626
0
        return;
627
628
39.2k
    Token *parent = tok->astParent();
629
39.2k
    if (!parent)
630
14.4k
        return;
631
632
24.8k
    if (Token::simpleMatch(parent, ",") && !parent->isInitComma() && astIsRHS(tok)) {
633
0
        const Token* callParent = findParent(parent, [](const Token* p) {
634
0
            return !Token::simpleMatch(p, ",");
635
0
        });
636
        // Ensure that the comma isn't a function call
637
0
        if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{") &&
638
0
                            (!Token::Match(callParent, "( %name%") || settings->library.isNotLibraryFunction(callParent->next())) &&
639
0
                            !(callParent->str() == "(" && (Token::simpleMatch(callParent->astOperand1(), "*") || Token::Match(callParent->astOperand1(), "%name%|("))))) {
640
0
            setTokenValue(parent, std::move(value), settings);
641
0
            return;
642
0
        }
643
0
    }
644
645
24.8k
    if (Token::simpleMatch(parent, "=") && astIsRHS(tok)) {
646
14.6k
        setTokenValue(parent, value, settings);
647
14.6k
        if (!value.isUninitValue())
648
14.6k
            return;
649
14.6k
    }
650
651
10.2k
    if (value.isContainerSizeValue() && astIsContainer(tok)) {
652
        // .empty, .size, +"abc", +'a'
653
0
        if (Token::Match(parent, "+|==|!=") && parent->astOperand1() && parent->astOperand2()) {
654
0
            for (const ValueFlow::Value &value1 : parent->astOperand1()->values()) {
655
0
                if (value1.isImpossible())
656
0
                    continue;
657
0
                for (const ValueFlow::Value &value2 : parent->astOperand2()->values()) {
658
0
                    if (value2.isImpossible())
659
0
                        continue;
660
0
                    if (value1.path != value2.path)
661
0
                        continue;
662
0
                    ValueFlow::Value result;
663
0
                    if (Token::Match(parent, "%comp%"))
664
0
                        result.valueType = ValueFlow::Value::ValueType::INT;
665
0
                    else
666
0
                        result.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
667
668
0
                    if (value1.isContainerSizeValue() && value2.isContainerSizeValue())
669
0
                        result.intvalue = calculate(parent->str(), value1.intvalue, value2.intvalue);
670
0
                    else if (value1.isContainerSizeValue() && value2.isTokValue() && value2.tokvalue->tokType() == Token::eString)
671
0
                        result.intvalue = calculate(parent->str(), value1.intvalue, MathLib::bigint(Token::getStrLength(value2.tokvalue)));
672
0
                    else if (value2.isContainerSizeValue() && value1.isTokValue() && value1.tokvalue->tokType() == Token::eString)
673
0
                        result.intvalue = calculate(parent->str(), MathLib::bigint(Token::getStrLength(value1.tokvalue)), value2.intvalue);
674
0
                    else
675
0
                        continue;
676
677
0
                    combineValueProperties(value1, value2, result);
678
679
0
                    if (Token::simpleMatch(parent, "==") && result.intvalue)
680
0
                        continue;
681
0
                    if (Token::simpleMatch(parent, "!=") && !result.intvalue)
682
0
                        continue;
683
684
0
                    setTokenValue(parent, std::move(result), settings);
685
0
                }
686
0
            }
687
0
        }
688
0
        Token* next = nullptr;
689
0
        const Library::Container::Yield yields = getContainerYield(parent, settings, &next);
690
0
        if (yields == Library::Container::Yield::SIZE) {
691
0
            ValueFlow::Value v(value);
692
0
            v.valueType = ValueFlow::Value::ValueType::INT;
693
0
            setTokenValue(next, std::move(v), settings);
694
0
        } else if (yields == Library::Container::Yield::EMPTY) {
695
0
            ValueFlow::Value v(value);
696
0
            v.valueType = ValueFlow::Value::ValueType::INT;
697
0
            v.bound = ValueFlow::Value::Bound::Point;
698
0
            if (value.isImpossible()) {
699
0
                if (value.intvalue == 0)
700
0
                    v.setKnown();
701
0
                else if ((value.bound == ValueFlow::Value::Bound::Upper && value.intvalue > 0) ||
702
0
                         (value.bound == ValueFlow::Value::Bound::Lower && value.intvalue < 0)) {
703
0
                    v.intvalue = 0;
704
0
                    v.setKnown();
705
0
                } else
706
0
                    v.setPossible();
707
0
            } else {
708
0
                v.intvalue = !v.intvalue;
709
0
            }
710
0
            setTokenValue(next, std::move(v), settings);
711
0
        }
712
0
        return;
713
0
    }
714
715
10.2k
    if (value.isLifetimeValue()) {
716
0
        if (!ValueFlow::isLifetimeBorrowed(parent, settings))
717
0
            return;
718
0
        if (value.lifetimeKind == ValueFlow::Value::LifetimeKind::Iterator && astIsIterator(parent)) {
719
0
            setTokenValue(parent,std::move(value),settings);
720
0
        } else if (astIsPointer(tok) && astIsPointer(parent) && !parent->isUnaryOp("*") &&
721
0
                   (parent->isArithmeticalOp() || parent->isCast())) {
722
0
            setTokenValue(parent,std::move(value),settings);
723
0
        }
724
0
        return;
725
0
    }
726
727
10.2k
    if (value.isUninitValue()) {
728
0
        if (Token::Match(tok, ". %var%"))
729
0
            setTokenValue(tok->next(), value, settings);
730
0
        if (parent->isCast()) {
731
0
            setTokenValue(parent, std::move(value), settings);
732
0
            return;
733
0
        }
734
0
        ValueFlow::Value pvalue = value;
735
0
        if (!value.subexpressions.empty() && Token::Match(parent, ". %var%")) {
736
0
            if (contains(value.subexpressions, parent->next()->str()))
737
0
                pvalue.subexpressions.clear();
738
0
            else
739
0
                return;
740
0
        }
741
0
        if (parent->isUnaryOp("&")) {
742
0
            pvalue.indirect++;
743
0
            setTokenValue(parent, std::move(pvalue), settings);
744
0
        } else if (Token::Match(parent, ". %var%") && parent->astOperand1() == tok && parent->astOperand2()) {
745
0
            if (parent->originalName() == "->" && pvalue.indirect > 0)
746
0
                pvalue.indirect--;
747
0
            setTokenValue(parent->astOperand2(), std::move(pvalue), settings);
748
0
        } else if (Token::Match(parent->astParent(), ". %var%") && parent->astParent()->astOperand1() == parent) {
749
0
            if (parent->astParent()->originalName() == "->" && pvalue.indirect > 0)
750
0
                pvalue.indirect--;
751
0
            setTokenValue(parent->astParent()->astOperand2(), std::move(pvalue), settings);
752
0
        } else if (parent->isUnaryOp("*") && pvalue.indirect > 0) {
753
0
            pvalue.indirect--;
754
0
            setTokenValue(parent, std::move(pvalue), settings);
755
0
        }
756
0
        return;
757
0
    }
758
759
    // cast..
760
10.2k
    if (const Token *castType = getCastTypeStartToken(parent, settings)) {
761
0
        if (contains({ValueFlow::Value::ValueType::INT, ValueFlow::Value::ValueType::SYMBOLIC}, value.valueType) &&
762
0
            Token::simpleMatch(parent->astOperand1(), "dynamic_cast"))
763
0
            return;
764
0
        const ValueType &valueType = ValueType::parseDecl(castType, *settings);
765
0
        if (value.isImpossible() && value.isIntValue() && value.intvalue < 0 && astIsUnsigned(tok) &&
766
0
            valueType.sign == ValueType::SIGNED && tok->valueType() &&
767
0
            ValueFlow::getSizeOf(*tok->valueType(), settings) >= ValueFlow::getSizeOf(valueType, settings))
768
0
            return;
769
0
        setTokenValueCast(parent, valueType, value, settings);
770
0
    }
771
772
10.2k
    else if (parent->str() == ":") {
773
0
        setTokenValue(parent,value,settings);
774
0
    }
775
776
10.2k
    else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2() && parent->astOperand1()) {
777
        // is condition always true/false?
778
0
        if (parent->astOperand1()->hasKnownValue()) {
779
0
            const ValueFlow::Value &condvalue = parent->astOperand1()->values().front();
780
0
            const bool cond(condvalue.isTokValue() || (condvalue.isIntValue() && condvalue.intvalue != 0));
781
0
            if (cond && !tok->astOperand1()) { // true condition, no second operator
782
0
                setTokenValue(parent, condvalue, settings);
783
0
            } else {
784
0
                const Token *op = cond ? tok->astOperand1() : tok->astOperand2();
785
0
                if (!op) // #7769 segmentation fault at setTokenValue()
786
0
                    return;
787
0
                const std::list<ValueFlow::Value> &values = op->values();
788
0
                if (std::find(values.cbegin(), values.cend(), value) != values.cend())
789
0
                    setTokenValue(parent, value, settings);
790
0
            }
791
0
        } else if (!value.isImpossible()) {
792
            // is condition only depending on 1 variable?
793
            // cppcheck-suppress[variableScope] #8541
794
0
            nonneg int varId = 0;
795
0
            bool ret = false;
796
0
            visitAstNodes(parent->astOperand1(),
797
0
                          [&](const Token *t) {
798
0
                if (t->varId()) {
799
0
                    if (varId > 0 || value.varId != 0)
800
0
                        ret = true;
801
0
                    varId = t->varId();
802
0
                } else if (t->str() == "(" && Token::Match(t->previous(), "%name%"))
803
0
                    ret = true; // function call
804
0
                return ret ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
805
0
            });
806
0
            if (ret)
807
0
                return;
808
809
0
            ValueFlow::Value v(value);
810
0
            v.conditional = true;
811
0
            v.changeKnownToPossible();
812
813
0
            setTokenValue(parent, v, settings);
814
0
        }
815
0
    }
816
817
10.2k
    else if (parent->str() == "?" && value.isIntValue() && tok == parent->astOperand1() && value.isKnown() &&
818
10.2k
             parent->astOperand2() && parent->astOperand2()->astOperand1() && parent->astOperand2()->astOperand2()) {
819
0
        const std::list<ValueFlow::Value> &values = (value.intvalue == 0
820
0
                ? parent->astOperand2()->astOperand2()->values()
821
0
                : parent->astOperand2()->astOperand1()->values());
822
823
0
        for (const ValueFlow::Value &v : values)
824
0
            setTokenValue(parent, v, settings);
825
0
    }
826
827
    // Calculations..
828
10.2k
    else if ((parent->isArithmeticalOp() || parent->isComparisonOp() || (parent->tokType() == Token::eBitOp) || (parent->tokType() == Token::eLogicalOp)) &&
829
10.2k
             parent->astOperand1() &&
830
10.2k
             parent->astOperand2()) {
831
832
4.41k
        const bool noninvertible = isNonInvertibleOperation(parent);
833
834
        // Skip operators with impossible values that are not invertible
835
4.41k
        if (noninvertible && value.isImpossible())
836
1.37k
            return;
837
838
        // known result when a operand is 0.
839
3.03k
        if (Token::Match(parent, "[&*]") && astIsIntegral(parent, true) && value.isKnown() && value.isIntValue() &&
840
3.03k
            value.intvalue == 0) {
841
36
            setTokenValue(parent, std::move(value), settings);
842
36
            return;
843
36
        }
844
845
        // known result when a operand is true.
846
2.99k
        if (Token::simpleMatch(parent, "&&") && value.isKnown() && value.isIntValue() && value.intvalue==0) {
847
0
            setTokenValue(parent, std::move(value), settings);
848
0
            return;
849
0
        }
850
851
        // known result when a operand is false.
852
2.99k
        if (Token::simpleMatch(parent, "||") && value.isKnown() && value.isIntValue() && value.intvalue!=0) {
853
0
            setTokenValue(parent, std::move(value), settings);
854
0
            return;
855
0
        }
856
857
2.99k
        for (const ValueFlow::Value &value1 : parent->astOperand1()->values()) {
858
1.87k
            if (!isComputableValue(parent, value1))
859
107
                continue;
860
1.77k
            for (const ValueFlow::Value &value2 : parent->astOperand2()->values()) {
861
477
                if (value1.path != value2.path)
862
0
                    continue;
863
477
                if (!isComputableValue(parent, value2))
864
25
                    continue;
865
452
                if (value1.isIteratorValue() && value2.isIteratorValue())
866
0
                    continue;
867
452
                if (!isCompatibleValues(value1, value2))
868
12
                    continue;
869
440
                ValueFlow::Value result(0);
870
440
                combineValueProperties(value1, value2, result);
871
440
                if (astIsFloat(parent, false)) {
872
0
                    if (!result.isIntValue() && !result.isFloatValue())
873
0
                        continue;
874
0
                    result.valueType = ValueFlow::Value::ValueType::FLOAT;
875
0
                }
876
440
                const double floatValue1 = value1.isFloatValue() ? value1.floatValue : value1.intvalue;
877
440
                const double floatValue2 = value2.isFloatValue() ? value2.floatValue : value2.intvalue;
878
440
                const auto intValue1 = [&]() -> MathLib::bigint {
879
440
                    return value1.isFloatValue() ? static_cast<MathLib::bigint>(value1.floatValue) : value1.intvalue;
880
440
                };
881
440
                const auto intValue2 = [&]() -> MathLib::bigint {
882
440
                    return value2.isFloatValue() ? static_cast<MathLib::bigint>(value2.floatValue) : value2.intvalue;
883
440
                };
884
440
                if ((value1.isFloatValue() || value2.isFloatValue()) && Token::Match(parent, "&|^|%|<<|>>|==|!=|%or%"))
885
0
                    continue;
886
440
                if (Token::Match(parent, "==|!=")) {
887
61
                    if ((value1.isIntValue() && value2.isTokValue()) || (value1.isTokValue() && value2.isIntValue())) {
888
0
                        if (parent->str() == "==")
889
0
                            result.intvalue = 0;
890
0
                        else if (parent->str() == "!=")
891
0
                            result.intvalue = 1;
892
61
                    } else if (value1.isIntValue() && value2.isIntValue()) {
893
61
                        bool error = false;
894
61
                        result.intvalue = calculate(parent->str(), intValue1(), intValue2(), &error);
895
61
                        if (error)
896
0
                            continue;
897
61
                    } else if (value1.isTokValue() && value2.isTokValue() &&
898
0
                               (astIsContainer(parent->astOperand1()) || astIsContainer(parent->astOperand2()))) {
899
0
                        const Token* tok1 = value1.tokvalue;
900
0
                        const Token* tok2 = value2.tokvalue;
901
0
                        bool equal = false;
902
0
                        if (Token::Match(tok1, "%str%") && Token::Match(tok2, "%str%")) {
903
0
                            equal = tok1->str() == tok2->str();
904
0
                        } else if (Token::simpleMatch(tok1, "{") && Token::simpleMatch(tok2, "{")) {
905
0
                            std::vector<const Token*> args1 = getArguments(tok1);
906
0
                            std::vector<const Token*> args2 = getArguments(tok2);
907
0
                            if (args1.size() == args2.size()) {
908
0
                                if (!std::all_of(args1.begin(), args1.end(), std::mem_fn(&Token::hasKnownIntValue)))
909
0
                                    continue;
910
0
                                if (!std::all_of(args2.begin(), args2.end(), std::mem_fn(&Token::hasKnownIntValue)))
911
0
                                    continue;
912
0
                                equal = std::equal(args1.begin(),
913
0
                                                   args1.end(),
914
0
                                                   args2.begin(),
915
0
                                                   [&](const Token* atok, const Token* btok) {
916
0
                                    return atok->values().front().intvalue ==
917
0
                                    btok->values().front().intvalue;
918
0
                                });
919
0
                            } else {
920
0
                                equal = false;
921
0
                            }
922
0
                        } else {
923
0
                            continue;
924
0
                        }
925
0
                        result.intvalue = parent->str() == "==" ? equal : !equal;
926
0
                    } else {
927
0
                        continue;
928
0
                    }
929
61
                    setTokenValue(parent, result, settings);
930
379
                } else if (Token::Match(parent, "%op%")) {
931
379
                    if (Token::Match(parent, "%comp%")) {
932
81
                        if (!result.isFloatValue() && !value1.isIntValue() && !value2.isIntValue())
933
0
                            continue;
934
298
                    } else {
935
298
                        if (value1.isTokValue() || value2.isTokValue())
936
0
                            break;
937
298
                    }
938
379
                    bool error = false;
939
379
                    if (result.isFloatValue()) {
940
0
                        result.floatValue = calculate(parent->str(), floatValue1, floatValue2, &error);
941
379
                    } else {
942
379
                        result.intvalue = calculate(parent->str(), intValue1(), intValue2(), &error);
943
379
                    }
944
379
                    if (error)
945
6
                        continue;
946
                    // If the bound comes from the second value then invert the bound when subtracting
947
373
                    if (Token::simpleMatch(parent, "-") && value2.bound == result.bound &&
948
373
                        value2.bound != ValueFlow::Value::Bound::Point)
949
3
                        result.invertBound();
950
373
                    setTokenValue(parent, result, settings);
951
373
                }
952
440
            }
953
1.77k
        }
954
2.99k
    }
955
956
    // !
957
5.82k
    else if (parent->str() == "!") {
958
0
        for (const ValueFlow::Value &val : tok->values()) {
959
0
            if (!val.isIntValue())
960
0
                continue;
961
0
            if (val.isImpossible() && val.intvalue != 0)
962
0
                continue;
963
0
            ValueFlow::Value v(val);
964
0
            if (val.isImpossible())
965
0
                v.setKnown();
966
0
            else
967
0
                v.intvalue = !v.intvalue;
968
0
            setTokenValue(parent, std::move(v), settings);
969
0
        }
970
0
    }
971
972
    // ~
973
5.82k
    else if (parent->str() == "~") {
974
484
        for (const ValueFlow::Value &val : tok->values()) {
975
484
            if (!val.isIntValue())
976
12
                continue;
977
472
            ValueFlow::Value v(val);
978
472
            v.intvalue = ~v.intvalue;
979
472
            int bits = 0;
980
472
            if (tok->valueType() &&
981
472
                tok->valueType()->sign == ValueType::Sign::UNSIGNED &&
982
472
                tok->valueType()->pointer == 0) {
983
0
                if (tok->valueType()->type == ValueType::Type::INT)
984
0
                    bits = settings->platform.int_bit;
985
0
                else if (tok->valueType()->type == ValueType::Type::LONG)
986
0
                    bits = settings->platform.long_bit;
987
0
            }
988
472
            if (bits > 0 && bits < MathLib::bigint_bits)
989
0
                v.intvalue &= (((MathLib::biguint)1)<<bits) - 1;
990
472
            setTokenValue(parent, std::move(v), settings);
991
472
        }
992
469
    }
993
994
    // unary minus
995
5.35k
    else if (parent->isUnaryOp("-")) {
996
0
        for (const ValueFlow::Value &val : tok->values()) {
997
0
            if (!val.isIntValue() && !val.isFloatValue())
998
0
                continue;
999
0
            ValueFlow::Value v(val);
1000
0
            if (v.isIntValue()) {
1001
0
                if (v.intvalue == LLONG_MIN)
1002
                    // Value can't be inverted
1003
0
                    continue;
1004
0
                v.intvalue = -v.intvalue;
1005
0
            } else
1006
0
                v.floatValue = -v.floatValue;
1007
0
            v.invertBound();
1008
0
            setTokenValue(parent, std::move(v), settings);
1009
0
        }
1010
0
    }
1011
1012
    // increment
1013
5.35k
    else if (parent->str() == "++") {
1014
69
        for (const ValueFlow::Value &val : tok->values()) {
1015
69
            if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue())
1016
0
                continue;
1017
69
            ValueFlow::Value v(val);
1018
69
            if (parent == tok->previous()) {
1019
65
                if (v.isIntValue() || v.isSymbolicValue())
1020
65
                    v.intvalue = v.intvalue + 1;
1021
0
                else
1022
0
                    v.floatValue = v.floatValue + 1.0;
1023
65
            }
1024
69
            setTokenValue(parent, std::move(v), settings);
1025
69
        }
1026
58
    }
1027
1028
    // decrement
1029
5.29k
    else if (parent->str() == "--") {
1030
77
        for (const ValueFlow::Value &val : tok->values()) {
1031
77
            if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue())
1032
0
                continue;
1033
77
            ValueFlow::Value v(val);
1034
77
            if (parent == tok->previous()) {
1035
75
                if (v.isIntValue() || v.isSymbolicValue())
1036
75
                    v.intvalue = v.intvalue - 1;
1037
0
                else
1038
0
                    v.floatValue = v.floatValue - 1.0;
1039
75
            }
1040
77
            setTokenValue(parent, std::move(v), settings);
1041
77
        }
1042
63
    }
1043
1044
5.23k
    else if (Token::Match(parent, ":: %name%") && parent->astOperand2() == tok) {
1045
0
        setTokenValue(parent, value, settings);
1046
0
    }
1047
    // Calling std::size or std::empty on an array
1048
5.23k
    else if (value.isTokValue() && Token::simpleMatch(value.tokvalue, "{") && tok->variable() &&
1049
5.23k
             tok->variable()->isArray() && Token::Match(parent->previous(), "%name% (") && astIsRHS(tok)) {
1050
0
        std::vector<const Token*> args = getArguments(value.tokvalue);
1051
0
        if (const Library::Function* f = settings->library.getFunction(parent->previous())) {
1052
0
            if (f->containerYield == Library::Container::Yield::SIZE) {
1053
0
                ValueFlow::Value v(value);
1054
0
                v.valueType = ValueFlow::Value::ValueType::INT;
1055
0
                v.intvalue = args.size();
1056
0
                setTokenValue(parent, std::move(v), settings);
1057
0
            } else if (f->containerYield == Library::Container::Yield::EMPTY) {
1058
0
                ValueFlow::Value v(value);
1059
0
                v.intvalue = args.empty();
1060
0
                v.valueType = ValueFlow::Value::ValueType::INT;
1061
0
                setTokenValue(parent, std::move(v), settings);
1062
0
            }
1063
0
        }
1064
0
    }
1065
10.2k
}
1066
1067
static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings *settings)
1068
0
{
1069
0
    if (valueType.pointer || value.isImpossible())
1070
0
        setTokenValue(parent,value,settings);
1071
0
    else if (valueType.type == ValueType::Type::CHAR)
1072
0
        setTokenValue(parent, castValue(value, valueType.sign, settings->platform.char_bit), settings);
1073
0
    else if (valueType.type == ValueType::Type::SHORT)
1074
0
        setTokenValue(parent, castValue(value, valueType.sign, settings->platform.short_bit), settings);
1075
0
    else if (valueType.type == ValueType::Type::INT)
1076
0
        setTokenValue(parent, castValue(value, valueType.sign, settings->platform.int_bit), settings);
1077
0
    else if (valueType.type == ValueType::Type::LONG)
1078
0
        setTokenValue(parent, castValue(value, valueType.sign, settings->platform.long_bit), settings);
1079
0
    else if (valueType.type == ValueType::Type::LONGLONG)
1080
0
        setTokenValue(parent, castValue(value, valueType.sign, settings->platform.long_long_bit), settings);
1081
0
    else if (valueType.isFloat() && isNumeric(value)) {
1082
0
        ValueFlow::Value floatValue = value;
1083
0
        floatValue.valueType = ValueFlow::Value::ValueType::FLOAT;
1084
0
        if (value.isIntValue())
1085
0
            floatValue.floatValue = value.intvalue;
1086
0
        setTokenValue(parent, std::move(floatValue), settings);
1087
0
    } else if (value.isIntValue()) {
1088
0
        const long long charMax = settings->platform.signedCharMax();
1089
0
        const long long charMin = settings->platform.signedCharMin();
1090
0
        if (charMin <= value.intvalue && value.intvalue <= charMax) {
1091
            // unknown type, but value is small so there should be no truncation etc
1092
0
            setTokenValue(parent,value,settings);
1093
0
        }
1094
0
    }
1095
0
}
1096
1097
static nonneg int getSizeOfType(const Token *typeTok, const Settings *settings)
1098
0
{
1099
0
    const ValueType &valueType = ValueType::parseDecl(typeTok, *settings);
1100
1101
0
    return ValueFlow::getSizeOf(valueType, settings);
1102
0
}
1103
1104
size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings *settings)
1105
2.62k
{
1106
2.62k
    if (vt.pointer)
1107
0
        return settings->platform.sizeof_pointer;
1108
2.62k
    if (vt.type == ValueType::Type::BOOL || vt.type == ValueType::Type::CHAR)
1109
547
        return 1;
1110
2.07k
    if (vt.type == ValueType::Type::SHORT)
1111
0
        return settings->platform.sizeof_short;
1112
2.07k
    if (vt.type == ValueType::Type::WCHAR_T)
1113
0
        return settings->platform.sizeof_wchar_t;
1114
2.07k
    if (vt.type == ValueType::Type::INT)
1115
2.07k
        return settings->platform.sizeof_int;
1116
0
    if (vt.type == ValueType::Type::LONG)
1117
0
        return settings->platform.sizeof_long;
1118
0
    if (vt.type == ValueType::Type::LONGLONG)
1119
0
        return settings->platform.sizeof_long_long;
1120
0
    if (vt.type == ValueType::Type::FLOAT)
1121
0
        return settings->platform.sizeof_float;
1122
0
    if (vt.type == ValueType::Type::DOUBLE)
1123
0
        return settings->platform.sizeof_double;
1124
0
    if (vt.type == ValueType::Type::LONGDOUBLE)
1125
0
        return settings->platform.sizeof_long_double;
1126
1127
0
    return 0;
1128
0
}
1129
1130
1131
static bool getMinMaxValues(const ValueType* vt, const cppcheck::Platform& platform, MathLib::bigint& minValue, MathLib::bigint& maxValue);
1132
1133
// Handle various constants..
1134
static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp)
1135
184k
{
1136
184k
    if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
1137
19.1k
        try {
1138
19.1k
            MathLib::bigint signedValue = MathLib::toLongNumber(tok->str());
1139
19.1k
            const ValueType* vt = tok->valueType();
1140
19.1k
            if (vt && vt->sign == ValueType::UNSIGNED && signedValue < 0 && ValueFlow::getSizeOf(*vt, settings) < sizeof(MathLib::bigint)) {
1141
0
                MathLib::bigint minValue{}, maxValue{};
1142
0
                if (getMinMaxValues(tok->valueType(), settings->platform, minValue, maxValue))
1143
0
                    signedValue += maxValue + 1;
1144
0
            }
1145
19.1k
            ValueFlow::Value value(signedValue);
1146
19.1k
            if (!tok->isTemplateArg())
1147
19.1k
                value.setKnown();
1148
19.1k
            setTokenValue(tok, std::move(value), settings);
1149
19.1k
        } catch (const std::exception & /*e*/) {
1150
            // Bad character literal
1151
0
        }
1152
165k
    } else if (tok->isNumber() && MathLib::isFloat(tok->str())) {
1153
0
        ValueFlow::Value value;
1154
0
        value.valueType = ValueFlow::Value::ValueType::FLOAT;
1155
0
        value.floatValue = MathLib::toDoubleNumber(tok->str());
1156
0
        if (!tok->isTemplateArg())
1157
0
            value.setKnown();
1158
0
        setTokenValue(tok, std::move(value), settings);
1159
165k
    } else if (tok->enumerator() && tok->enumerator()->value_known) {
1160
0
        ValueFlow::Value value(tok->enumerator()->value);
1161
0
        if (!tok->isTemplateArg())
1162
0
            value.setKnown();
1163
0
        setTokenValue(tok, std::move(value), settings);
1164
165k
    } else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
1165
0
        ValueFlow::Value value(0);
1166
0
        if (!tok->isTemplateArg())
1167
0
            value.setKnown();
1168
0
        setTokenValue(tok, std::move(value), settings);
1169
165k
    } else if (Token::simpleMatch(tok, "sizeof (")) {
1170
0
        if (tok->next()->astOperand2() && !tok->next()->astOperand2()->isLiteral() && tok->next()->astOperand2()->valueType() &&
1171
0
            (tok->next()->astOperand2()->valueType()->pointer == 0 || // <- TODO this is a bailout, abort when there are array->pointer conversions
1172
0
             (tok->next()->astOperand2()->variable() && !tok->next()->astOperand2()->variable()->isArray())) &&
1173
0
            !tok->next()->astOperand2()->valueType()->isEnum()) { // <- TODO this is a bailout, handle enum with non-int types
1174
0
            const size_t sz = ValueFlow::getSizeOf(*tok->next()->astOperand2()->valueType(), settings);
1175
0
            if (sz) {
1176
0
                ValueFlow::Value value(sz);
1177
0
                value.setKnown();
1178
0
                setTokenValue(tok->next(), std::move(value), settings);
1179
0
                return tok->linkAt(1);
1180
0
            }
1181
0
        }
1182
1183
0
        const Token *tok2 = tok->tokAt(2);
1184
        // skip over tokens to find variable or type
1185
0
        while (tok2 && !tok2->isStandardType() && Token::Match(tok2, "%name% ::|.|[")) {
1186
0
            if (tok2->next()->str() == "[")
1187
0
                tok2 = tok2->linkAt(1)->next();
1188
0
            else
1189
0
                tok2 = tok2->tokAt(2);
1190
0
        }
1191
0
        if (Token::simpleMatch(tok, "sizeof ( *")) {
1192
0
            const ValueType *vt = tok->tokAt(2)->valueType();
1193
0
            const size_t sz = vt ? ValueFlow::getSizeOf(*vt, settings) : 0;
1194
0
            if (sz > 0) {
1195
0
                ValueFlow::Value value(sz);
1196
0
                if (!tok2->isTemplateArg() && settings->platform.type != cppcheck::Platform::Type::Unspecified)
1197
0
                    value.setKnown();
1198
0
                setTokenValue(tok->next(), std::move(value), settings);
1199
0
            }
1200
0
        } else if (tok2->enumerator() && tok2->enumerator()->scope) {
1201
0
            long long size = settings->platform.sizeof_int;
1202
0
            const Token * type = tok2->enumerator()->scope->enumType;
1203
0
            if (type) {
1204
0
                size = getSizeOfType(type, settings);
1205
0
                if (size == 0)
1206
0
                    tok->linkAt(1);
1207
0
            }
1208
0
            ValueFlow::Value value(size);
1209
0
            if (!tok2->isTemplateArg() && settings->platform.type != cppcheck::Platform::Type::Unspecified)
1210
0
                value.setKnown();
1211
0
            setTokenValue(tok, value, settings);
1212
0
            setTokenValue(tok->next(), std::move(value), settings);
1213
0
        } else if (tok2->type() && tok2->type()->isEnumType()) {
1214
0
            long long size = settings->platform.sizeof_int;
1215
0
            if (tok2->type()->classScope) {
1216
0
                const Token * type = tok2->type()->classScope->enumType;
1217
0
                if (type) {
1218
0
                    size = getSizeOfType(type, settings);
1219
0
                }
1220
0
            }
1221
0
            ValueFlow::Value value(size);
1222
0
            if (!tok2->isTemplateArg() && settings->platform.type != cppcheck::Platform::Type::Unspecified)
1223
0
                value.setKnown();
1224
0
            setTokenValue(tok, value, settings);
1225
0
            setTokenValue(tok->next(), std::move(value), settings);
1226
0
        } else if (Token::Match(tok, "sizeof ( %var% ) /") && tok->next()->astParent() == tok->tokAt(4) &&
1227
0
                   tok->tokAt(4)->astOperand2() && Token::simpleMatch(tok->tokAt(4)->astOperand2()->previous(), "sizeof (")) {
1228
            // Get number of elements in array
1229
0
            const Token *sz1 = tok->tokAt(2);
1230
0
            const Token *sz2 = tok->tokAt(4)->astOperand2(); // left parenthesis of sizeof on rhs
1231
0
            const nonneg int varid1 = sz1->varId();
1232
0
            if (varid1 &&
1233
0
                sz1->variable() &&
1234
0
                sz1->variable()->isArray() &&
1235
0
                !sz1->variable()->dimensions().empty() &&
1236
0
                sz1->variable()->dimensionKnown(0) &&
1237
0
                Token::Match(sz2->astOperand2(), "*|[") && Token::Match(sz2->astOperand2()->astOperand1(), "%varid%", varid1)) {
1238
0
                ValueFlow::Value value(sz1->variable()->dimension(0));
1239
0
                if (!tok2->isTemplateArg() && settings->platform.type != cppcheck::Platform::Type::Unspecified)
1240
0
                    value.setKnown();
1241
0
                setTokenValue(tok->tokAt(4), std::move(value), settings);
1242
0
            }
1243
0
        } else if (Token::Match(tok2, "%var% )")) {
1244
0
            const Variable *var = tok2->variable();
1245
            // only look for single token types (no pointers or references yet)
1246
0
            if (var && var->typeStartToken() == var->typeEndToken()) {
1247
                // find the size of the type
1248
0
                size_t size = 0;
1249
0
                if (var->isEnumType()) {
1250
0
                    size = settings->platform.sizeof_int;
1251
0
                    if (var->type()->classScope && var->type()->classScope->enumType)
1252
0
                        size = getSizeOfType(var->type()->classScope->enumType, settings);
1253
0
                } else if (var->valueType()) {
1254
0
                    size = ValueFlow::getSizeOf(*var->valueType(), settings);
1255
0
                } else if (!var->type()) {
1256
0
                    size = getSizeOfType(var->typeStartToken(), settings);
1257
0
                }
1258
                // find the number of elements
1259
0
                size_t count = 1;
1260
0
                for (size_t i = 0; i < var->dimensions().size(); ++i) {
1261
0
                    if (var->dimensionKnown(i))
1262
0
                        count *= var->dimension(i);
1263
0
                    else
1264
0
                        count = 0;
1265
0
                }
1266
0
                if (size && count > 0) {
1267
0
                    ValueFlow::Value value(count * size);
1268
0
                    if (settings->platform.type != cppcheck::Platform::Type::Unspecified)
1269
0
                        value.setKnown();
1270
0
                    setTokenValue(tok, value, settings);
1271
0
                    setTokenValue(tok->next(), std::move(value), settings);
1272
0
                }
1273
0
            }
1274
0
        } else if (tok2->tokType() == Token::eString) {
1275
0
            const size_t sz = Token::getStrSize(tok2, settings);
1276
0
            if (sz > 0) {
1277
0
                ValueFlow::Value value(sz);
1278
0
                value.setKnown();
1279
0
                setTokenValue(const_cast<Token *>(tok->next()), std::move(value), settings);
1280
0
            }
1281
0
        } else if (tok2->tokType() == Token::eChar) {
1282
0
            nonneg int sz = 0;
1283
0
            if (cpp && settings->standards.cpp >= Standards::CPP20 && tok2->isUtf8())
1284
0
                sz = 1;
1285
0
            else if (tok2->isUtf16())
1286
0
                sz = 2;
1287
0
            else if (tok2->isUtf32())
1288
0
                sz = 4;
1289
0
            else if (tok2->isLong())
1290
0
                sz = settings->platform.sizeof_wchar_t;
1291
0
            else if ((tok2->isCChar() && !cpp) || (tok2->isCMultiChar()))
1292
0
                sz = settings->platform.sizeof_int;
1293
0
            else
1294
0
                sz = 1;
1295
1296
0
            if (sz > 0) {
1297
0
                ValueFlow::Value value(sz);
1298
0
                value.setKnown();
1299
0
                setTokenValue(tok->next(), std::move(value), settings);
1300
0
            }
1301
0
        } else if (!tok2->type()) {
1302
0
            const ValueType& vt = ValueType::parseDecl(tok2, *settings);
1303
0
            size_t sz = ValueFlow::getSizeOf(vt, settings);
1304
0
            const Token* brac = tok2->astParent();
1305
0
            while (Token::simpleMatch(brac, "[")) {
1306
0
                const Token* num = brac->astOperand2();
1307
0
                if (num && ((num->isNumber() && MathLib::isInt(num->str())) || num->tokType() == Token::eChar)) {
1308
0
                    try {
1309
0
                        const MathLib::biguint dim = MathLib::toULongNumber(num->str());
1310
0
                        sz *= dim;
1311
0
                        brac = brac->astParent();
1312
0
                        continue;
1313
0
                    }
1314
0
                    catch (const std::exception& /*e*/) {
1315
                        // Bad integer literal
1316
0
                    }
1317
0
                }
1318
0
                sz = 0;
1319
0
                break;
1320
0
            }
1321
0
            if (sz > 0) {
1322
0
                ValueFlow::Value value(sz);
1323
0
                if (!tok2->isTemplateArg() && settings->platform.type != cppcheck::Platform::Type::Unspecified)
1324
0
                    value.setKnown();
1325
0
                setTokenValue(tok->next(), std::move(value), settings);
1326
0
            }
1327
0
        }
1328
        // skip over enum
1329
0
        tok = tok->linkAt(1);
1330
165k
    } else if (Token::Match(tok, "%name% [{(] [)}]") && (tok->isStandardType() ||
1331
4.32k
                                                         (tok->variable() && tok->variable()->nameToken() == tok &&
1332
4.32k
                                                          (tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))))) {
1333
0
        ValueFlow::Value value(0);
1334
0
        if (!tok->isTemplateArg())
1335
0
            value.setKnown();
1336
0
        setTokenValue(tok->next(), std::move(value), settings);
1337
165k
    } else if (Token::Match(tok, "%name% = {") && tok->variable() &&
1338
165k
               (tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))) {
1339
0
        if (Token::simpleMatch(tok->tokAt(3), "}")) {
1340
0
            ValueFlow::Value value(0);
1341
0
            value.setKnown();
1342
0
            setTokenValue(tok->tokAt(2), std::move(value), settings);
1343
0
        } else if (tok->tokAt(2)->astOperand1() && tok->tokAt(2)->astOperand1()->hasKnownIntValue()) {
1344
0
            ValueFlow::Value value(tok->tokAt(2)->astOperand1()->getKnownIntValue());
1345
0
            value.setKnown();
1346
0
            setTokenValue(tok->tokAt(2), std::move(value), settings);
1347
0
        }
1348
0
    }
1349
184k
    return tok->next();
1350
184k
}
1351
1352
static void valueFlowNumber(TokenList &tokenlist, const Settings* settings)
1353
2.72k
{
1354
187k
    for (Token *tok = tokenlist.front(); tok;) {
1355
184k
        tok = valueFlowSetConstantValue(tok, settings, tokenlist.isCPP());
1356
184k
    }
1357
1358
2.72k
    if (tokenlist.isCPP()) {
1359
187k
        for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1360
184k
            if (tok->isName() && !tok->varId() && Token::Match(tok, "false|true")) {
1361
0
                ValueFlow::Value value(tok->str() == "true");
1362
0
                if (!tok->isTemplateArg())
1363
0
                    value.setKnown();
1364
0
                setTokenValue(tok, std::move(value), settings);
1365
184k
            } else if (Token::Match(tok, "[(,] NULL [,)]")) {
1366
                // NULL function parameters are not simplified in the
1367
                // normal tokenlist
1368
0
                ValueFlow::Value value(0);
1369
0
                if (!tok->isTemplateArg())
1370
0
                    value.setKnown();
1371
0
                setTokenValue(tok->next(), std::move(value), settings);
1372
0
            }
1373
184k
        }
1374
2.72k
    }
1375
2.72k
}
1376
1377
static void valueFlowString(TokenList &tokenlist, const Settings* settings)
1378
1.36k
{
1379
93.5k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1380
92.2k
        if (tok->tokType() == Token::eString) {
1381
0
            ValueFlow::Value strvalue;
1382
0
            strvalue.valueType = ValueFlow::Value::ValueType::TOK;
1383
0
            strvalue.tokvalue = tok;
1384
0
            strvalue.setKnown();
1385
0
            setTokenValue(tok, std::move(strvalue), settings);
1386
0
        }
1387
92.2k
    }
1388
1.36k
}
1389
1390
static void valueFlowArray(TokenList &tokenlist, const Settings *settings)
1391
1.36k
{
1392
1.36k
    std::map<nonneg int, const Token *> constantArrays;
1393
1394
93.5k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1395
92.2k
        if (tok->varId() > 0) {
1396
            // array
1397
19.8k
            const std::map<nonneg int, const Token *>::const_iterator it = constantArrays.find(tok->varId());
1398
19.8k
            if (it != constantArrays.end()) {
1399
0
                ValueFlow::Value value;
1400
0
                value.valueType = ValueFlow::Value::ValueType::TOK;
1401
0
                value.tokvalue = it->second;
1402
0
                value.setKnown();
1403
0
                setTokenValue(tok, std::move(value), settings);
1404
0
            }
1405
1406
            // const array decl
1407
19.8k
            else if (tok->variable() && tok->variable()->isArray() && tok->variable()->isConst() &&
1408
19.8k
                     tok->variable()->nameToken() == tok && Token::Match(tok, "%var% [ %num%| ] = {")) {
1409
0
                Token* rhstok = tok->next()->link()->tokAt(2);
1410
0
                constantArrays[tok->varId()] = rhstok;
1411
0
                tok = rhstok->link();
1412
0
            }
1413
1414
            // pointer = array
1415
19.8k
            else if (tok->variable() && tok->variable()->isArray() && Token::simpleMatch(tok->astParent(), "=") &&
1416
19.8k
                     astIsRHS(tok) && tok->astParent()->astOperand1() &&
1417
19.8k
                     tok->astParent()->astOperand1()->variable() &&
1418
19.8k
                     tok->astParent()->astOperand1()->variable()->isPointer()) {
1419
0
                ValueFlow::Value value;
1420
0
                value.valueType = ValueFlow::Value::ValueType::TOK;
1421
0
                value.tokvalue = tok;
1422
0
                value.setKnown();
1423
0
                setTokenValue(tok, std::move(value), settings);
1424
0
            }
1425
19.8k
            continue;
1426
19.8k
        }
1427
1428
72.4k
        if (Token::Match(tok, "const %type% %var% [ %num%| ] = {")) {
1429
0
            Token *vartok = tok->tokAt(2);
1430
0
            Token *rhstok = vartok->next()->link()->tokAt(2);
1431
0
            constantArrays[vartok->varId()] = rhstok;
1432
0
            tok = rhstok->link();
1433
0
            continue;
1434
0
        }
1435
1436
72.4k
        if (Token::Match(tok, "const char %var% [ %num%| ] = %str% ;")) {
1437
0
            Token *vartok = tok->tokAt(2);
1438
0
            Token *strtok = vartok->next()->link()->tokAt(2);
1439
0
            constantArrays[vartok->varId()] = strtok;
1440
0
            tok = strtok->next();
1441
0
            continue;
1442
0
        }
1443
72.4k
    }
1444
1.36k
}
1445
1446
static bool isNonZero(const Token *tok)
1447
0
{
1448
0
    return tok && (!tok->hasKnownIntValue() || tok->values().front().intvalue != 0);
1449
0
}
1450
1451
static const Token *getOtherOperand(const Token *tok)
1452
0
{
1453
0
    if (!tok)
1454
0
        return nullptr;
1455
0
    if (!tok->astParent())
1456
0
        return nullptr;
1457
0
    if (tok->astParent()->astOperand1() != tok)
1458
0
        return tok->astParent()->astOperand1();
1459
0
    if (tok->astParent()->astOperand2() != tok)
1460
0
        return tok->astParent()->astOperand2();
1461
0
    return nullptr;
1462
0
}
1463
1464
static void valueFlowArrayBool(TokenList &tokenlist, const Settings *settings)
1465
2.27k
{
1466
163k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1467
160k
        if (tok->hasKnownIntValue())
1468
29.6k
            continue;
1469
131k
        const Variable *var = nullptr;
1470
131k
        bool known = false;
1471
131k
        const std::list<ValueFlow::Value>::const_iterator val =
1472
131k
            std::find_if(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isTokValue));
1473
131k
        if (val == tok->values().end()) {
1474
131k
            var = tok->variable();
1475
131k
            known = true;
1476
131k
        } else {
1477
0
            var = val->tokvalue->variable();
1478
0
            known = val->isKnown();
1479
0
        }
1480
131k
        if (!var)
1481
96.9k
            continue;
1482
34.2k
        if (!var->isArray() || var->isArgument() || var->isStlType())
1483
34.2k
            continue;
1484
0
        if (isNonZero(getOtherOperand(tok)) && Token::Match(tok->astParent(), "%comp%"))
1485
0
            continue;
1486
        // TODO: Check for function argument
1487
0
        if ((astIsBool(tok->astParent()) && !Token::Match(tok->astParent(), "(|%name%")) ||
1488
0
            (tok->astParent() && Token::Match(tok->astParent()->previous(), "if|while|for ("))) {
1489
0
            ValueFlow::Value value{1};
1490
0
            if (known)
1491
0
                value.setKnown();
1492
0
            setTokenValue(tok, std::move(value), settings);
1493
0
        }
1494
0
    }
1495
2.27k
}
1496
1497
static void valueFlowArrayElement(TokenList& tokenlist, const Settings* settings)
1498
2.27k
{
1499
163k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
1500
160k
        if (tok->hasKnownIntValue())
1501
29.6k
            continue;
1502
131k
        const Token* indexTok = nullptr;
1503
131k
        const Token* arrayTok = nullptr;
1504
131k
        if (Token::simpleMatch(tok, "[") && tok->isBinaryOp()) {
1505
0
            indexTok = tok->astOperand2();
1506
0
            arrayTok = tok->astOperand1();
1507
131k
        } else if (Token::Match(tok->tokAt(-2), ". %name% (") && astIsContainer(tok->tokAt(-2)->astOperand1())) {
1508
0
            arrayTok = tok->tokAt(-2)->astOperand1();
1509
0
            const Library::Container* container = getLibraryContainer(arrayTok);
1510
0
            if (!container || container->stdAssociativeLike)
1511
0
                continue;
1512
0
            const Library::Container::Yield yield = container->getYield(tok->strAt(-1));
1513
0
            if (yield != Library::Container::Yield::AT_INDEX)
1514
0
                continue;
1515
0
            indexTok = tok->astOperand2();
1516
0
        }
1517
1518
131k
        if (!indexTok || !arrayTok)
1519
131k
            continue;
1520
1521
0
        for (const ValueFlow::Value& arrayValue : arrayTok->values()) {
1522
0
            if (!arrayValue.isTokValue())
1523
0
                continue;
1524
0
            if (arrayValue.isImpossible())
1525
0
                continue;
1526
0
            for (const ValueFlow::Value& indexValue : indexTok->values()) {
1527
0
                if (!indexValue.isIntValue())
1528
0
                    continue;
1529
0
                if (indexValue.isImpossible())
1530
0
                    continue;
1531
0
                if (!arrayValue.isKnown() && !indexValue.isKnown() && arrayValue.varId != 0 && indexValue.varId != 0 &&
1532
0
                    !(arrayValue.varId == indexValue.varId && arrayValue.varvalue == indexValue.varvalue))
1533
0
                    continue;
1534
1535
0
                ValueFlow::Value result(0);
1536
0
                result.condition = arrayValue.condition ? arrayValue.condition : indexValue.condition;
1537
0
                result.setInconclusive(arrayValue.isInconclusive() || indexValue.isInconclusive());
1538
0
                result.varId = (arrayValue.varId != 0) ? arrayValue.varId : indexValue.varId;
1539
0
                result.varvalue = (result.varId == arrayValue.varId) ? arrayValue.intvalue : indexValue.intvalue;
1540
0
                if (arrayValue.valueKind == indexValue.valueKind)
1541
0
                    result.valueKind = arrayValue.valueKind;
1542
1543
0
                result.errorPath.insert(result.errorPath.end(), arrayValue.errorPath.cbegin(), arrayValue.errorPath.cend());
1544
0
                result.errorPath.insert(result.errorPath.end(), indexValue.errorPath.cbegin(), indexValue.errorPath.cend());
1545
1546
0
                const MathLib::bigint index = indexValue.intvalue;
1547
1548
0
                if (arrayValue.tokvalue->tokType() == Token::eString) {
1549
0
                    const std::string s = arrayValue.tokvalue->strValue();
1550
0
                    if (index == s.size()) {
1551
0
                        result.intvalue = 0;
1552
0
                        setTokenValue(tok, result, settings);
1553
0
                    } else if (index >= 0 && index < s.size()) {
1554
0
                        result.intvalue = s[index];
1555
0
                        setTokenValue(tok, result, settings);
1556
0
                    }
1557
0
                } else if (Token::simpleMatch(arrayValue.tokvalue, "{")) {
1558
0
                    std::vector<const Token*> args = getArguments(arrayValue.tokvalue);
1559
0
                    if (index < 0 || index >= args.size())
1560
0
                        continue;
1561
0
                    const Token* arg = args[index];
1562
0
                    if (!arg->hasKnownIntValue())
1563
0
                        continue;
1564
0
                    const ValueFlow::Value& v = arg->values().front();
1565
0
                    result.intvalue = v.intvalue;
1566
0
                    result.errorPath.insert(result.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
1567
0
                    setTokenValue(tok, result, settings);
1568
0
                }
1569
0
            }
1570
0
        }
1571
0
    }
1572
2.27k
}
1573
1574
static void valueFlowPointerAlias(TokenList &tokenlist, const Settings* settings)
1575
1.36k
{
1576
93.5k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1577
        // not address of
1578
92.2k
        if (!tok->isUnaryOp("&"))
1579
92.2k
            continue;
1580
1581
        // parent should be a '='
1582
0
        if (!Token::simpleMatch(tok->astParent(), "="))
1583
0
            continue;
1584
1585
        // child should be some buffer or variable
1586
0
        const Token *vartok = tok->astOperand1();
1587
0
        while (vartok) {
1588
0
            if (vartok->str() == "[")
1589
0
                vartok = vartok->astOperand1();
1590
0
            else if (vartok->str() == "." || vartok->str() == "::")
1591
0
                vartok = vartok->astOperand2();
1592
0
            else
1593
0
                break;
1594
0
        }
1595
0
        if (!(vartok && vartok->variable() && !vartok->variable()->isPointer()))
1596
0
            continue;
1597
1598
0
        ValueFlow::Value value;
1599
0
        value.valueType = ValueFlow::Value::ValueType::TOK;
1600
0
        value.tokvalue = tok;
1601
0
        setTokenValue(tok, std::move(value), settings);
1602
0
    }
1603
1.36k
}
1604
1605
static void valueFlowBitAnd(TokenList &tokenlist, const Settings* settings)
1606
1.36k
{
1607
93.5k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1608
92.2k
        if (tok->str() != "&")
1609
91.9k
            continue;
1610
1611
253
        if (tok->hasKnownValue())
1612
4
            continue;
1613
1614
249
        if (!tok->astOperand1() || !tok->astOperand2())
1615
1
            continue;
1616
1617
248
        MathLib::bigint number;
1618
248
        if (MathLib::isInt(tok->astOperand1()->str()))
1619
25
            number = MathLib::toLongNumber(tok->astOperand1()->str());
1620
223
        else if (MathLib::isInt(tok->astOperand2()->str()))
1621
15
            number = MathLib::toLongNumber(tok->astOperand2()->str());
1622
208
        else
1623
208
            continue;
1624
1625
40
        int bit = 0;
1626
540
        while (bit <= (MathLib::bigint_bits - 2) && ((((MathLib::bigint)1) << bit) < number))
1627
500
            ++bit;
1628
1629
40
        if ((((MathLib::bigint)1) << bit) == number) {
1630
3
            setTokenValue(tok, ValueFlow::Value(0), settings);
1631
3
            setTokenValue(tok, ValueFlow::Value(number), settings);
1632
3
        }
1633
40
    }
1634
1.36k
}
1635
1636
static void valueFlowSameExpressions(TokenList &tokenlist, const Settings* settings)
1637
1.36k
{
1638
93.5k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1639
92.2k
        if (tok->hasKnownIntValue())
1640
16.9k
            continue;
1641
1642
75.2k
        if (!tok->astOperand1() || !tok->astOperand2())
1643
68.2k
            continue;
1644
1645
7.04k
        if (tok->astOperand1()->isLiteral() || tok->astOperand2()->isLiteral())
1646
798
            continue;
1647
1648
6.24k
        if (!astIsIntegral(tok->astOperand1(), false) && !astIsIntegral(tok->astOperand2(), false))
1649
347
            continue;
1650
1651
5.89k
        ValueFlow::Value val;
1652
1653
5.89k
        if (Token::Match(tok, "==|>=|<=|/")) {
1654
759
            val = ValueFlow::Value(1);
1655
759
            val.setKnown();
1656
759
        }
1657
1658
5.89k
        if (Token::Match(tok, "!=|>|<|%|-")) {
1659
1.29k
            val = ValueFlow::Value(0);
1660
1.29k
            val.setKnown();
1661
1.29k
        }
1662
1663
5.89k
        if (!val.isKnown())
1664
3.83k
            continue;
1665
1666
2.05k
        if (isSameExpression(tokenlist.isCPP(), false, tok->astOperand1(), tok->astOperand2(), settings->library, true, true, &val.errorPath)) {
1667
318
            setTokenValue(tok, std::move(val), settings);
1668
318
        }
1669
2.05k
    }
1670
1.36k
}
1671
1672
static bool getExpressionRange(const Token *expr, MathLib::bigint *minvalue, MathLib::bigint *maxvalue)
1673
0
{
1674
0
    if (expr->hasKnownIntValue()) {
1675
0
        if (minvalue)
1676
0
            *minvalue = expr->values().front().intvalue;
1677
0
        if (maxvalue)
1678
0
            *maxvalue = expr->values().front().intvalue;
1679
0
        return true;
1680
0
    }
1681
1682
0
    if (expr->str() == "&" && expr->astOperand1() && expr->astOperand2()) {
1683
0
        MathLib::bigint vals[4];
1684
0
        const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]);
1685
0
        const bool rhsHasKnownRange = getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]);
1686
0
        if (!lhsHasKnownRange && !rhsHasKnownRange)
1687
0
            return false;
1688
0
        if (!lhsHasKnownRange || !rhsHasKnownRange) {
1689
0
            if (minvalue)
1690
0
                *minvalue = lhsHasKnownRange ? vals[0] : vals[2];
1691
0
            if (maxvalue)
1692
0
                *maxvalue = lhsHasKnownRange ? vals[1] : vals[3];
1693
0
        } else {
1694
0
            if (minvalue)
1695
0
                *minvalue = vals[0] & vals[2];
1696
0
            if (maxvalue)
1697
0
                *maxvalue = vals[1] & vals[3];
1698
0
        }
1699
0
        return true;
1700
0
    }
1701
1702
0
    if (expr->str() == "%" && expr->astOperand1() && expr->astOperand2()) {
1703
0
        MathLib::bigint vals[4];
1704
0
        if (!getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]))
1705
0
            return false;
1706
0
        if (vals[2] <= 0)
1707
0
            return false;
1708
0
        const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]);
1709
0
        if (lhsHasKnownRange && vals[0] < 0)
1710
0
            return false;
1711
        // If lhs has unknown value, it must be unsigned
1712
0
        if (!lhsHasKnownRange && (!expr->astOperand1()->valueType() || expr->astOperand1()->valueType()->sign != ValueType::Sign::UNSIGNED))
1713
0
            return false;
1714
0
        if (minvalue)
1715
0
            *minvalue = 0;
1716
0
        if (maxvalue)
1717
0
            *maxvalue = vals[3] - 1;
1718
0
        return true;
1719
0
    }
1720
1721
0
    return false;
1722
0
}
1723
1724
static void valueFlowRightShift(TokenList &tokenList, const Settings* settings)
1725
2.27k
{
1726
163k
    for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
1727
160k
        if (tok->str() != ">>")
1728
160k
            continue;
1729
1730
0
        if (tok->hasKnownValue())
1731
0
            continue;
1732
1733
0
        if (!tok->astOperand1() || !tok->astOperand2())
1734
0
            continue;
1735
1736
0
        if (!tok->astOperand2()->hasKnownValue())
1737
0
            continue;
1738
1739
0
        const MathLib::bigint rhsvalue = tok->astOperand2()->values().front().intvalue;
1740
0
        if (rhsvalue < 0)
1741
0
            continue;
1742
1743
0
        if (!tok->astOperand1()->valueType() || !tok->astOperand1()->valueType()->isIntegral())
1744
0
            continue;
1745
1746
0
        if (!tok->astOperand2()->valueType() || !tok->astOperand2()->valueType()->isIntegral())
1747
0
            continue;
1748
1749
0
        MathLib::bigint lhsmax=0;
1750
0
        if (!getExpressionRange(tok->astOperand1(), nullptr, &lhsmax))
1751
0
            continue;
1752
0
        if (lhsmax < 0)
1753
0
            continue;
1754
0
        int lhsbits;
1755
0
        if ((tok->astOperand1()->valueType()->type == ValueType::Type::CHAR) ||
1756
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::SHORT) ||
1757
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::WCHAR_T) ||
1758
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::BOOL) ||
1759
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::INT))
1760
0
            lhsbits = settings->platform.int_bit;
1761
0
        else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONG)
1762
0
            lhsbits = settings->platform.long_bit;
1763
0
        else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONGLONG)
1764
0
            lhsbits = settings->platform.long_long_bit;
1765
0
        else
1766
0
            continue;
1767
0
        if (rhsvalue >= lhsbits || rhsvalue >= MathLib::bigint_bits || (1ULL << rhsvalue) <= lhsmax)
1768
0
            continue;
1769
1770
0
        ValueFlow::Value val(0);
1771
0
        val.setKnown();
1772
0
        setTokenValue(tok, std::move(val), settings);
1773
0
    }
1774
2.27k
}
1775
1776
static std::vector<MathLib::bigint> minUnsignedValue(const Token* tok, int depth = 8)
1777
0
{
1778
0
    std::vector<MathLib::bigint> result = {};
1779
0
    if (!tok)
1780
0
        return result;
1781
0
    if (depth < 0)
1782
0
        return result;
1783
0
    if (tok->hasKnownIntValue()) {
1784
0
        result = {tok->values().front().intvalue};
1785
0
    } else if (!Token::Match(tok, "-|%|&|^") && tok->isConstOp() && tok->astOperand1() && tok->astOperand2()) {
1786
0
        std::vector<MathLib::bigint> op1 = minUnsignedValue(tok->astOperand1(), depth - 1);
1787
0
        std::vector<MathLib::bigint> op2 = minUnsignedValue(tok->astOperand2(), depth - 1);
1788
0
        if (!op1.empty() && !op2.empty()) {
1789
0
            result = calculate<std::vector<MathLib::bigint>>(tok->str(), op1.front(), op2.front());
1790
0
        }
1791
0
    }
1792
0
    if (result.empty() && astIsUnsigned(tok))
1793
0
        result = {0};
1794
0
    return result;
1795
0
}
1796
1797
static bool isConvertedToIntegral(const Token* tok, const Settings* settings)
1798
0
{
1799
0
    if (!tok)
1800
0
        return false;
1801
0
    std::vector<ValueType> parentTypes = getParentValueTypes(tok, settings);
1802
0
    if (parentTypes.empty())
1803
0
        return false;
1804
0
    const ValueType& vt = parentTypes.front();
1805
0
    return vt.type != ValueType::UNKNOWN_INT && vt.isIntegral();
1806
0
}
1807
1808
static bool isSameToken(const Token* tok1, const Token* tok2)
1809
0
{
1810
0
    if (!tok1 || !tok2)
1811
0
        return false;
1812
0
    if (tok1->exprId() != 0 && tok1->exprId() == tok2->exprId())
1813
0
        return true;
1814
0
    if (tok1->hasKnownIntValue() && tok2->hasKnownIntValue())
1815
0
        return tok1->values().front().intvalue == tok2->values().front().intvalue;
1816
0
    return false;
1817
0
}
1818
1819
static void valueFlowImpossibleValues(TokenList& tokenList, const Settings* settings)
1820
2.27k
{
1821
163k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
1822
160k
        if (tok->hasKnownIntValue())
1823
29.6k
            continue;
1824
131k
        if (Token::Match(tok, "true|false"))
1825
0
            continue;
1826
131k
        if (astIsBool(tok) || Token::Match(tok, "%comp%")) {
1827
3.44k
            ValueFlow::Value lower{-1};
1828
3.44k
            lower.bound = ValueFlow::Value::Bound::Upper;
1829
3.44k
            lower.setImpossible();
1830
3.44k
            setTokenValue(tok, std::move(lower), settings);
1831
1832
3.44k
            ValueFlow::Value upper{2};
1833
3.44k
            upper.bound = ValueFlow::Value::Bound::Lower;
1834
3.44k
            upper.setImpossible();
1835
3.44k
            setTokenValue(tok, std::move(upper), settings);
1836
127k
        } else if (astIsUnsigned(tok) && !astIsPointer(tok)) {
1837
0
            std::vector<MathLib::bigint> minvalue = minUnsignedValue(tok);
1838
0
            if (minvalue.empty())
1839
0
                continue;
1840
0
            ValueFlow::Value value{std::max<MathLib::bigint>(0, minvalue.front()) - 1};
1841
0
            value.bound = ValueFlow::Value::Bound::Upper;
1842
0
            value.setImpossible();
1843
0
            setTokenValue(tok, std::move(value), settings);
1844
0
        }
1845
131k
        if (Token::simpleMatch(tok, "?") && Token::Match(tok->astOperand1(), "<|<=|>|>=")) {
1846
0
            const Token* condTok = tok->astOperand1();
1847
0
            const Token* branchesTok = tok->astOperand2();
1848
1849
0
            auto tokens = makeArray(condTok->astOperand1(), condTok->astOperand2());
1850
0
            auto branches = makeArray(branchesTok->astOperand1(), branchesTok->astOperand2());
1851
0
            bool flipped = false;
1852
0
            if (std::equal(tokens.cbegin(), tokens.cend(), branches.crbegin(), &isSameToken))
1853
0
                flipped = true;
1854
0
            else if (!std::equal(tokens.cbegin(), tokens.cend(), branches.cbegin(), &isSameToken))
1855
0
                continue;
1856
0
            const bool isMin = Token::Match(condTok, "<|<=") ^ flipped;
1857
0
            std::vector<ValueFlow::Value> values;
1858
0
            for (const Token* tok2 : tokens) {
1859
0
                if (tok2->hasKnownIntValue()) {
1860
0
                    values.emplace_back();
1861
0
                } else {
1862
0
                    ValueFlow::Value symValue{};
1863
0
                    symValue.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
1864
0
                    symValue.tokvalue = tok2;
1865
0
                    values.push_back(symValue);
1866
0
                    std::copy_if(tok2->values().cbegin(),
1867
0
                                 tok2->values().cend(),
1868
0
                                 std::back_inserter(values),
1869
0
                                 [](const ValueFlow::Value& v) {
1870
0
                        if (!v.isKnown())
1871
0
                            return false;
1872
0
                        return v.isSymbolicValue();
1873
0
                    });
1874
0
                }
1875
0
            }
1876
0
            for (ValueFlow::Value& value : values) {
1877
0
                value.setImpossible();
1878
0
                if (isMin) {
1879
0
                    value.intvalue++;
1880
0
                    value.bound = ValueFlow::Value::Bound::Lower;
1881
0
                } else {
1882
0
                    value.intvalue--;
1883
0
                    value.bound = ValueFlow::Value::Bound::Upper;
1884
0
                }
1885
0
                setTokenValue(tok, std::move(value), settings);
1886
0
            }
1887
1888
131k
        } else if (Token::simpleMatch(tok, "%") && tok->astOperand2() && tok->astOperand2()->hasKnownIntValue()) {
1889
123
            ValueFlow::Value value{tok->astOperand2()->values().front()};
1890
123
            value.bound = ValueFlow::Value::Bound::Lower;
1891
123
            value.setImpossible();
1892
123
            setTokenValue(tok, std::move(value), settings);
1893
131k
        } else if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) {
1894
0
            ValueFlow::Value value{-1};
1895
0
            value.bound = ValueFlow::Value::Bound::Upper;
1896
0
            value.setImpossible();
1897
0
            setTokenValue(tok->next(), std::move(value), settings);
1898
131k
        } else if (Token::Match(tok, ". data|c_str (") && astIsContainerOwned(tok->astOperand1())) {
1899
0
            const Library::Container* container = getLibraryContainer(tok->astOperand1());
1900
0
            if (!container)
1901
0
                continue;
1902
0
            if (!container->stdStringLike)
1903
0
                continue;
1904
0
            if (container->view)
1905
0
                continue;
1906
0
            ValueFlow::Value value{0};
1907
0
            value.setImpossible();
1908
0
            setTokenValue(tok->tokAt(2), std::move(value), settings);
1909
131k
        } else if (Token::Match(tok, "make_shared|make_unique <") && Token::simpleMatch(tok->linkAt(1), "> (")) {
1910
0
            ValueFlow::Value value{0};
1911
0
            value.setImpossible();
1912
0
            setTokenValue(tok->linkAt(1)->next(), std::move(value), settings);
1913
131k
        } else if ((tokenList.isCPP() && Token::simpleMatch(tok, "this")) || tok->isUnaryOp("&")) {
1914
0
            ValueFlow::Value value{0};
1915
0
            value.setImpossible();
1916
0
            setTokenValue(tok, std::move(value), settings);
1917
131k
        } else if (tok->isIncompleteVar() && tok->astParent() && tok->astParent()->isUnaryOp("-") &&
1918
131k
                   isConvertedToIntegral(tok->astParent(), settings)) {
1919
0
            ValueFlow::Value value{0};
1920
0
            value.setImpossible();
1921
0
            setTokenValue(tok, std::move(value), settings);
1922
0
        }
1923
131k
    }
1924
2.27k
}
1925
1926
static void valueFlowEnumValue(SymbolDatabase & symboldatabase, const Settings * settings)
1927
2.72k
{
1928
9.88k
    for (Scope & scope : symboldatabase.scopeList) {
1929
9.88k
        if (scope.type != Scope::eEnum)
1930
9.88k
            continue;
1931
0
        MathLib::bigint value = 0;
1932
0
        bool prev_enum_is_known = true;
1933
1934
0
        for (Enumerator & enumerator : scope.enumeratorList) {
1935
0
            if (enumerator.start) {
1936
0
                Token* rhs = const_cast<Token*>(enumerator.start->previous()->astOperand2());
1937
0
                ValueFlow::valueFlowConstantFoldAST(rhs, settings);
1938
0
                if (rhs && rhs->hasKnownIntValue()) {
1939
0
                    enumerator.value = rhs->values().front().intvalue;
1940
0
                    enumerator.value_known = true;
1941
0
                    value = enumerator.value + 1;
1942
0
                    prev_enum_is_known = true;
1943
0
                } else
1944
0
                    prev_enum_is_known = false;
1945
0
            } else if (prev_enum_is_known) {
1946
0
                enumerator.value = value++;
1947
0
                enumerator.value_known = true;
1948
0
            }
1949
0
        }
1950
0
    }
1951
2.72k
}
1952
1953
static void valueFlowGlobalConstVar(TokenList& tokenList, const Settings *settings)
1954
1.36k
{
1955
    // Get variable values...
1956
1.36k
    std::map<const Variable*, ValueFlow::Value> vars;
1957
93.5k
    for (const Token* tok = tokenList.front(); tok; tok = tok->next()) {
1958
92.2k
        if (!tok->variable())
1959
72.4k
            continue;
1960
        // Initialization...
1961
19.8k
        if (tok == tok->variable()->nameToken() &&
1962
19.8k
            !tok->variable()->isVolatile() &&
1963
19.8k
            !tok->variable()->isArgument() &&
1964
19.8k
            tok->variable()->isConst() &&
1965
19.8k
            tok->valueType() &&
1966
19.8k
            tok->valueType()->isIntegral() &&
1967
19.8k
            tok->valueType()->pointer == 0 &&
1968
19.8k
            tok->valueType()->constness == 1 &&
1969
19.8k
            Token::Match(tok, "%name% =") &&
1970
19.8k
            tok->next()->astOperand2() &&
1971
19.8k
            tok->next()->astOperand2()->hasKnownIntValue()) {
1972
0
            vars[tok->variable()] = tok->next()->astOperand2()->values().front();
1973
0
        }
1974
19.8k
    }
1975
1976
    // Set values..
1977
93.5k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
1978
92.2k
        if (!tok->variable())
1979
72.4k
            continue;
1980
19.8k
        const std::map<const Variable*, ValueFlow::Value>::const_iterator var = vars.find(tok->variable());
1981
19.8k
        if (var == vars.end())
1982
19.8k
            continue;
1983
0
        setTokenValue(tok, var->second, settings);
1984
0
    }
1985
1.36k
}
1986
1987
static void valueFlowGlobalStaticVar(TokenList &tokenList, const Settings *settings)
1988
1.36k
{
1989
    // Get variable values...
1990
1.36k
    std::map<const Variable *, ValueFlow::Value> vars;
1991
93.5k
    for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
1992
92.2k
        if (!tok->variable())
1993
72.4k
            continue;
1994
        // Initialization...
1995
19.8k
        if (tok == tok->variable()->nameToken() &&
1996
19.8k
            tok->variable()->isStatic() &&
1997
19.8k
            !tok->variable()->isConst() &&
1998
19.8k
            tok->valueType() &&
1999
19.8k
            tok->valueType()->isIntegral() &&
2000
19.8k
            tok->valueType()->pointer == 0 &&
2001
19.8k
            tok->valueType()->constness == 0 &&
2002
19.8k
            Token::Match(tok, "%name% =") &&
2003
19.8k
            tok->next()->astOperand2() &&
2004
19.8k
            tok->next()->astOperand2()->hasKnownIntValue()) {
2005
0
            vars[tok->variable()] = tok->next()->astOperand2()->values().front();
2006
19.8k
        } else {
2007
            // If variable is written anywhere in TU then remove it from vars
2008
19.8k
            if (!tok->astParent())
2009
6.81k
                continue;
2010
13.0k
            if (Token::Match(tok->astParent(), "++|--|&") && !tok->astParent()->astOperand2())
2011
1.42k
                vars.erase(tok->variable());
2012
11.6k
            else if (tok->astParent()->isAssignmentOp()) {
2013
8.79k
                if (tok == tok->astParent()->astOperand1())
2014
8.26k
                    vars.erase(tok->variable());
2015
523
                else if (tokenList.isCPP() && Token::Match(tok->astParent()->tokAt(-2), "& %name% ="))
2016
0
                    vars.erase(tok->variable());
2017
8.79k
            } else if (isLikelyStreamRead(tokenList.isCPP(), tok->astParent())) {
2018
0
                vars.erase(tok->variable());
2019
2.81k
            } else if (Token::Match(tok->astParent(), "[(,]"))
2020
2
                vars.erase(tok->variable());
2021
13.0k
        }
2022
19.8k
    }
2023
2024
    // Set values..
2025
93.5k
    for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
2026
92.2k
        if (!tok->variable())
2027
72.4k
            continue;
2028
19.8k
        const std::map<const Variable *, ValueFlow::Value>::const_iterator var = vars.find(tok->variable());
2029
19.8k
        if (var == vars.end())
2030
19.8k
            continue;
2031
0
        setTokenValue(tok, var->second, settings);
2032
0
    }
2033
1.36k
}
2034
2035
static ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings* settings);
2036
static ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings* settings);
2037
2038
static Analyzer::Result valueFlowForward(Token* startToken,
2039
                                         const Token* endToken,
2040
                                         const Token* exprTok,
2041
                                         ValueFlow::Value value,
2042
                                         const TokenList& tokenlist,
2043
                                         const Settings* settings,
2044
                                         SourceLocation loc = SourceLocation::current())
2045
5.51k
{
2046
5.51k
    if (settings->debugnormal)
2047
0
        setSourceLocation(value, loc, startToken);
2048
5.51k
    return valueFlowGenericForward(startToken,
2049
5.51k
                                   endToken,
2050
5.51k
                                   makeAnalyzer(exprTok, std::move(value), tokenlist, settings),
2051
5.51k
                                   *settings);
2052
5.51k
}
2053
2054
static Analyzer::Result valueFlowForward(Token* startToken,
2055
                                         const Token* endToken,
2056
                                         const Token* exprTok,
2057
                                         std::list<ValueFlow::Value> values,
2058
                                         const TokenList& tokenlist,
2059
                                         const Settings* settings,
2060
                                         SourceLocation loc = SourceLocation::current())
2061
3.58k
{
2062
3.58k
    Analyzer::Result result{};
2063
5.46k
    for (ValueFlow::Value& v : values) {
2064
5.46k
        result.update(valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, settings, loc));
2065
5.46k
    }
2066
3.58k
    return result;
2067
3.58k
}
2068
2069
template<class ValueOrValues>
2070
static Analyzer::Result valueFlowForward(Token* startToken,
2071
                                         const Token* exprTok,
2072
                                         ValueOrValues v,
2073
                                         TokenList& tokenlist,
2074
                                         const Settings* settings,
2075
                                         SourceLocation loc = SourceLocation::current())
2076
0
{
2077
0
    const Token* endToken = nullptr;
2078
0
    const Function* f = Scope::nestedInFunction(startToken->scope());
2079
0
    if (f && f->functionScope)
2080
0
        endToken = f->functionScope->bodyEnd;
2081
0
    return valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, settings, loc);
2082
0
}
2083
2084
static Analyzer::Result valueFlowForwardRecursive(Token* top,
2085
                                                  const Token* exprTok,
2086
                                                  std::list<ValueFlow::Value> values,
2087
                                                  const TokenList& tokenlist,
2088
                                                  const Settings* settings,
2089
                                                  SourceLocation loc = SourceLocation::current())
2090
0
{
2091
0
    Analyzer::Result result{};
2092
0
    for (ValueFlow::Value& v : values) {
2093
0
        if (settings->debugnormal)
2094
0
            setSourceLocation(v, loc, top);
2095
0
        result.update(
2096
0
            valueFlowGenericForward(top, makeAnalyzer(exprTok, std::move(v), tokenlist, settings), *settings));
2097
0
    }
2098
0
    return result;
2099
0
}
2100
2101
static void valueFlowReverse(Token* tok,
2102
                             const Token* const endToken,
2103
                             const Token* const varToken,
2104
                             std::list<ValueFlow::Value> values,
2105
                             const TokenList& tokenlist,
2106
                             const Settings* settings,
2107
                             SourceLocation loc = SourceLocation::current())
2108
1.79k
{
2109
2.84k
    for (ValueFlow::Value& v : values) {
2110
2.84k
        if (settings->debugnormal)
2111
0
            setSourceLocation(v, loc, tok);
2112
2.84k
        valueFlowGenericReverse(tok, endToken, makeReverseAnalyzer(varToken, std::move(v), tokenlist, settings), *settings);
2113
2.84k
    }
2114
1.79k
}
2115
2116
// Deprecated
2117
static void valueFlowReverse(const TokenList& tokenlist,
2118
                             Token* tok,
2119
                             const Token* const varToken,
2120
                             ValueFlow::Value val,
2121
                             const ValueFlow::Value& val2,
2122
                             ErrorLogger* /*errorLogger*/,
2123
                             const Settings* settings = nullptr,
2124
                             SourceLocation loc = SourceLocation::current())
2125
0
{
2126
0
    std::list<ValueFlow::Value> values = {std::move(val)};
2127
0
    if (val2.varId != 0)
2128
0
        values.push_back(val2);
2129
0
    valueFlowReverse(tok, nullptr, varToken, std::move(values), tokenlist, settings, loc);
2130
0
}
2131
2132
static bool isConditionKnown(const Token* tok, bool then)
2133
5.13k
{
2134
5.13k
    const char* op = "||";
2135
5.13k
    if (then)
2136
2.80k
        op = "&&";
2137
5.13k
    const Token* parent = tok->astParent();
2138
5.13k
    while (parent && (parent->str() == op || parent->str() == "!" || parent->isCast()))
2139
0
        parent = parent->astParent();
2140
5.13k
    const Token* top = tok->astTop();
2141
5.13k
    if (top && Token::Match(top->previous(), "if|while|for ("))
2142
5.13k
        return parent == top || Token::simpleMatch(parent, ";");
2143
0
    return parent && parent->str() != op;
2144
5.13k
}
2145
2146
static const std::string& invertAssign(const std::string& assign)
2147
91
{
2148
91
    static std::unordered_map<std::string, std::string> lookup = {{"=", "="},
2149
91
        {"+=", "-="},
2150
91
        {"-=", "+="},
2151
91
        {"*=", "/="},
2152
91
        {"/=", "*="},
2153
91
        {"<<=", ">>="},
2154
91
        {">>=", "<<="},
2155
91
        {"^=", "^="}};
2156
91
    auto it = lookup.find(assign);
2157
91
    if (it == lookup.end()) {
2158
0
        return emptyString;
2159
0
    }
2160
91
    return it->second;
2161
91
}
2162
2163
0
static std::string removeAssign(const std::string& assign) {
2164
0
    return std::string{assign.cbegin(), assign.cend() - 1};
2165
0
}
2166
2167
template<class T, class U>
2168
static T calculateAssign(const std::string& assign, const T& x, const U& y, bool* error = nullptr)
2169
219
{
2170
219
    if (assign.empty() || assign.back() != '=') {
2171
0
        if (error)
2172
0
            *error = true;
2173
0
        return T{};
2174
0
    }
2175
219
    if (assign == "=")
2176
219
        return y;
2177
0
    return calculate<T, T>(removeAssign(assign), x, y, error);
2178
219
}
valueflow.cpp:long long calculateAssign<long long, long long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, long long const&, long long const&, bool*)
Line
Count
Source
2169
219
{
2170
219
    if (assign.empty() || assign.back() != '=') {
2171
0
        if (error)
2172
0
            *error = true;
2173
0
        return T{};
2174
0
    }
2175
219
    if (assign == "=")
2176
219
        return y;
2177
0
    return calculate<T, T>(removeAssign(assign), x, y, error);
2178
219
}
Unexecuted instantiation: valueflow.cpp:double calculateAssign<double, long long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double const&, long long const&, bool*)
2179
2180
template<class T, class U>
2181
static void assignValueIfMutable(T& x, const U& y)
2182
37
{
2183
37
    x = y;
2184
37
}
valueflow.cpp:void assignValueIfMutable<long long, long long>(long long&, long long const&)
Line
Count
Source
2182
37
{
2183
37
    x = y;
2184
37
}
Unexecuted instantiation: valueflow.cpp:void assignValueIfMutable<double, double>(double&, double const&)
2185
2186
template<class T, class U>
2187
static void assignValueIfMutable(const T& /*unused*/, const U& /*unused*/)
2188
182
{}
valueflow.cpp:void assignValueIfMutable<long long, long long>(long long const&, long long const&)
Line
Count
Source
2188
182
{}
Unexecuted instantiation: valueflow.cpp:void assignValueIfMutable<double, double>(double const&, double const&)
2189
2190
template<class Value, REQUIRES("Value must ValueFlow::Value", std::is_convertible<Value&, const ValueFlow::Value&> )>
2191
static bool evalAssignment(Value& lhsValue, const std::string& assign, const ValueFlow::Value& rhsValue)
2192
227
{
2193
227
    bool error = false;
2194
227
    if (lhsValue.isSymbolicValue() && rhsValue.isIntValue()) {
2195
8
        if (assign != "+=" && assign != "-=")
2196
8
            return false;
2197
0
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2198
219
    } else if (lhsValue.isIntValue() && rhsValue.isIntValue()) {
2199
219
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2200
219
    } else if (lhsValue.isFloatValue() && rhsValue.isIntValue()) {
2201
0
        assignValueIfMutable(lhsValue.floatValue,
2202
0
                             calculateAssign(assign, lhsValue.floatValue, rhsValue.intvalue, &error));
2203
0
    } else {
2204
0
        return false;
2205
0
    }
2206
219
    return !error;
2207
227
}
valueflow.cpp:bool evalAssignment<ValueFlow::Value const, void>(ValueFlow::Value const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value const&)
Line
Count
Source
2192
190
{
2193
190
    bool error = false;
2194
190
    if (lhsValue.isSymbolicValue() && rhsValue.isIntValue()) {
2195
8
        if (assign != "+=" && assign != "-=")
2196
8
            return false;
2197
0
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2198
182
    } else if (lhsValue.isIntValue() && rhsValue.isIntValue()) {
2199
182
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2200
182
    } else if (lhsValue.isFloatValue() && rhsValue.isIntValue()) {
2201
0
        assignValueIfMutable(lhsValue.floatValue,
2202
0
                             calculateAssign(assign, lhsValue.floatValue, rhsValue.intvalue, &error));
2203
0
    } else {
2204
0
        return false;
2205
0
    }
2206
182
    return !error;
2207
190
}
valueflow.cpp:bool evalAssignment<ValueFlow::Value, void>(ValueFlow::Value&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueFlow::Value const&)
Line
Count
Source
2192
37
{
2193
37
    bool error = false;
2194
37
    if (lhsValue.isSymbolicValue() && rhsValue.isIntValue()) {
2195
0
        if (assign != "+=" && assign != "-=")
2196
0
            return false;
2197
0
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2198
37
    } else if (lhsValue.isIntValue() && rhsValue.isIntValue()) {
2199
37
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2200
37
    } else if (lhsValue.isFloatValue() && rhsValue.isIntValue()) {
2201
0
        assignValueIfMutable(lhsValue.floatValue,
2202
0
                             calculateAssign(assign, lhsValue.floatValue, rhsValue.intvalue, &error));
2203
0
    } else {
2204
0
        return false;
2205
0
    }
2206
37
    return !error;
2207
37
}
2208
2209
static ValueFlow::Value::MoveKind isMoveOrForward(const Token* tok)
2210
0
{
2211
0
    if (!tok)
2212
0
        return ValueFlow::Value::MoveKind::NonMovedVariable;
2213
0
    const Token* parent = tok->astParent();
2214
0
    if (!Token::simpleMatch(parent, "("))
2215
0
        return ValueFlow::Value::MoveKind::NonMovedVariable;
2216
0
    const Token* ftok = parent->astOperand1();
2217
0
    if (!ftok)
2218
0
        return ValueFlow::Value::MoveKind::NonMovedVariable;
2219
0
    if (Token::simpleMatch(ftok->astOperand1(), "std :: move"))
2220
0
        return ValueFlow::Value::MoveKind::MovedVariable;
2221
0
    if (Token::simpleMatch(ftok->astOperand1(), "std :: forward"))
2222
0
        return ValueFlow::Value::MoveKind::ForwardedVariable;
2223
    // TODO: Check for cast
2224
0
    return ValueFlow::Value::MoveKind::NonMovedVariable;
2225
0
}
2226
2227
template<class T>
2228
struct SingleRange {
2229
    T* x;
2230
0
    T* begin() const {
2231
0
        return x;
2232
0
    }
2233
0
    T* end() const {
2234
0
        return x+1;
2235
0
    }
2236
};
2237
2238
template<class T>
2239
SingleRange<T> MakeSingleRange(T& x)
2240
33.0k
{
2241
33.0k
    return {&x};
2242
33.0k
}
2243
2244
class SelectValueFromVarIdMapRange {
2245
    using M = std::unordered_map<nonneg int, ValueFlow::Value>;
2246
2247
    struct Iterator {
2248
        using iterator_category = std::forward_iterator_tag;
2249
        using value_type = const ValueFlow::Value;
2250
        using pointer = value_type *;
2251
        using reference = value_type &;
2252
        using difference_type = std::ptrdiff_t;
2253
2254
        explicit Iterator(const M::const_iterator & it)
2255
0
            : mIt(it) {}
2256
2257
0
        reference operator*() const {
2258
0
            return mIt->second;
2259
0
        }
2260
2261
0
        pointer operator->() const {
2262
0
            return &mIt->second;
2263
0
        }
2264
2265
0
        Iterator &operator++() {
2266
            // cppcheck-suppress postfixOperator - forward iterator needs to perform post-increment
2267
0
            mIt++;
2268
0
            return *this;
2269
0
        }
2270
2271
0
        friend bool operator==(const Iterator &a, const Iterator &b) {
2272
0
            return a.mIt == b.mIt;
2273
0
        }
2274
2275
0
        friend bool operator!=(const Iterator &a, const Iterator &b) {
2276
0
            return a.mIt != b.mIt;
2277
0
        }
2278
2279
    private:
2280
        M::const_iterator mIt;
2281
    };
2282
2283
public:
2284
    explicit SelectValueFromVarIdMapRange(const M *m)
2285
0
        : mMap(m) {}
2286
2287
0
    Iterator begin() const {
2288
0
        return Iterator(mMap->begin());
2289
0
    }
2290
0
    Iterator end() const {
2291
0
        return Iterator(mMap->end());
2292
0
    }
2293
2294
private:
2295
    const M *mMap;
2296
};
2297
2298
// Check if its an alias of the variable or is being aliased to this variable
2299
template<typename V>
2300
static bool isAliasOf(const Variable * var, const Token *tok, nonneg int varid, const V& values, bool* inconclusive = nullptr)
2301
33.0k
{
2302
33.0k
    if (tok->varId() == varid)
2303
0
        return false;
2304
33.0k
    if (tok->varId() == 0)
2305
26.9k
        return false;
2306
6.16k
    if (isAliasOf(tok, varid, inconclusive))
2307
0
        return true;
2308
6.16k
    if (var && !var->isPointer())
2309
6.16k
        return false;
2310
    // Search through non value aliases
2311
0
    return std::any_of(values.begin(), values.end(), [&](const ValueFlow::Value& val) {
2312
0
        if (!val.isNonValue())
2313
0
            return false;
2314
0
        if (val.isInconclusive())
2315
0
            return false;
2316
0
        if (val.isLifetimeValue() && !val.isLocalLifetimeValue())
2317
0
            return false;
2318
0
        if (val.isLifetimeValue() && val.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
2319
0
            return false;
2320
0
        if (!Token::Match(val.tokvalue, ".|&|*|%var%"))
2321
0
            return false;
2322
0
        return astHasVar(val.tokvalue, tok->varId());
2323
0
    });
Unexecuted instantiation: valueflow.cpp:isAliasOf<SingleRange<ValueFlow::Value const> >(Variable const*, Token const*, int, SingleRange<ValueFlow::Value const> const&, bool*)::{lambda(ValueFlow::Value const&)#1}::operator()(ValueFlow::Value const&) const
Unexecuted instantiation: valueflow.cpp:isAliasOf<SelectValueFromVarIdMapRange>(Variable const*, Token const*, int, SelectValueFromVarIdMapRange const&, bool*)::{lambda(ValueFlow::Value const&)#1}::operator()(ValueFlow::Value const&) const
2324
6.16k
}
valueflow.cpp:bool isAliasOf<SingleRange<ValueFlow::Value const> >(Variable const*, Token const*, int, SingleRange<ValueFlow::Value const> const&, bool*)
Line
Count
Source
2301
33.0k
{
2302
33.0k
    if (tok->varId() == varid)
2303
0
        return false;
2304
33.0k
    if (tok->varId() == 0)
2305
26.9k
        return false;
2306
6.16k
    if (isAliasOf(tok, varid, inconclusive))
2307
0
        return true;
2308
6.16k
    if (var && !var->isPointer())
2309
6.16k
        return false;
2310
    // Search through non value aliases
2311
0
    return std::any_of(values.begin(), values.end(), [&](const ValueFlow::Value& val) {
2312
0
        if (!val.isNonValue())
2313
0
            return false;
2314
0
        if (val.isInconclusive())
2315
0
            return false;
2316
0
        if (val.isLifetimeValue() && !val.isLocalLifetimeValue())
2317
0
            return false;
2318
0
        if (val.isLifetimeValue() && val.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
2319
0
            return false;
2320
0
        if (!Token::Match(val.tokvalue, ".|&|*|%var%"))
2321
0
            return false;
2322
0
        return astHasVar(val.tokvalue, tok->varId());
2323
0
    });
2324
6.16k
}
Unexecuted instantiation: valueflow.cpp:bool isAliasOf<SelectValueFromVarIdMapRange>(Variable const*, Token const*, int, SelectValueFromVarIdMapRange const&, bool*)
2325
2326
static bool bifurcate(const Token* tok, const std::set<nonneg int>& varids, const Settings* settings, int depth = 20);
2327
2328
static bool bifurcateVariableChanged(const Variable* var,
2329
                                     const std::set<nonneg int>& varids,
2330
                                     const Token* start,
2331
                                     const Token* end,
2332
                                     const Settings* settings,
2333
                                     int depth = 20)
2334
6
{
2335
6
    bool result = false;
2336
6
    const Token* tok = start;
2337
42
    while ((tok = findVariableChanged(
2338
42
                tok->next(), end, var->isPointer(), var->declarationId(), var->isGlobal(), settings, true))) {
2339
36
        if (Token::Match(tok->astParent(), "%assign%")) {
2340
28
            if (!bifurcate(tok->astParent()->astOperand2(), varids, settings, depth - 1))
2341
0
                return true;
2342
28
        } else {
2343
8
            result = true;
2344
8
        }
2345
36
    }
2346
6
    return result;
2347
6
}
2348
2349
static bool bifurcate(const Token* tok, const std::set<nonneg int>& varids, const Settings* settings, int depth)
2350
69
{
2351
69
    if (depth < 0)
2352
0
        return false;
2353
69
    if (!tok)
2354
0
        return true;
2355
69
    if (tok->hasKnownIntValue())
2356
33
        return true;
2357
36
    if (tok->isConstOp())
2358
21
        return bifurcate(tok->astOperand1(), varids, settings, depth) && bifurcate(tok->astOperand2(), varids, settings, depth);
2359
15
    if (tok->varId() != 0) {
2360
6
        if (varids.count(tok->varId()) > 0)
2361
0
            return true;
2362
6
        const Variable* var = tok->variable();
2363
6
        if (!var)
2364
0
            return false;
2365
6
        const Token* start = var->declEndToken();
2366
6
        if (!start)
2367
0
            return false;
2368
6
        if (start->strAt(-1) == ")" || start->strAt(-1) == "}")
2369
0
            return false;
2370
6
        if (Token::Match(start, "; %varid% =", var->declarationId()))
2371
6
            start = start->tokAt(2);
2372
6
        if (var->isConst() || !bifurcateVariableChanged(var, varids, start, tok, settings, depth))
2373
0
            return var->isArgument() || bifurcate(start->astOperand2(), varids, settings, depth - 1);
2374
6
        return false;
2375
6
    }
2376
9
    return false;
2377
15
}
2378
2379
struct ValueFlowAnalyzer : Analyzer {
2380
    const TokenList& tokenlist;
2381
    const Settings* settings;
2382
    ProgramMemoryState pms;
2383
2384
8.63k
    explicit ValueFlowAnalyzer(const TokenList& t, const Settings* s = nullptr) : tokenlist(t), settings(s), pms(settings) {}
2385
2386
    virtual const ValueFlow::Value* getValue(const Token* tok) const = 0;
2387
    virtual ValueFlow::Value* getValue(const Token* tok) = 0;
2388
2389
    virtual void makeConditional() = 0;
2390
2391
    virtual void addErrorPath(const Token* tok, const std::string& s) = 0;
2392
2393
    virtual bool match(const Token* tok) const = 0;
2394
2395
28.5k
    virtual bool internalMatch(const Token* /*tok*/) const {
2396
28.5k
        return false;
2397
28.5k
    }
2398
2399
    virtual bool isAlias(const Token* tok, bool& inconclusive) const = 0;
2400
2401
    using ProgramState = ProgramMemory::Map;
2402
2403
    virtual ProgramState getProgramState() const = 0;
2404
2405
3.01k
    virtual int getIndirect(const Token* tok) const {
2406
3.01k
        const ValueFlow::Value* value = getValue(tok);
2407
3.01k
        if (value)
2408
3.01k
            return value->indirect;
2409
0
        return 0;
2410
3.01k
    }
2411
2412
0
    virtual bool isGlobal() const {
2413
0
        return false;
2414
0
    }
2415
0
    virtual bool dependsOnThis() const {
2416
0
        return false;
2417
0
    }
2418
0
    virtual bool isVariable() const {
2419
0
        return false;
2420
0
    }
2421
2422
3.08k
    bool isCPP() const {
2423
3.08k
        return tokenlist.isCPP();
2424
3.08k
    }
2425
2426
6.22k
    const Settings* getSettings() const {
2427
6.22k
        return settings;
2428
6.22k
    }
2429
2430
    // Returns Action::Match if its an exact match, return Action::Read if it partially matches the lifetime
2431
    Action analyzeLifetime(const Token* tok) const
2432
0
    {
2433
0
        if (!tok)
2434
0
            return Action::None;
2435
0
        if (match(tok))
2436
0
            return Action::Match;
2437
0
        if (Token::simpleMatch(tok, ".") && analyzeLifetime(tok->astOperand1()) != Action::None)
2438
0
            return Action::Read;
2439
0
        if (astIsRHS(tok) && Token::simpleMatch(tok->astParent(), "."))
2440
0
            return analyzeLifetime(tok->astParent());
2441
0
        return Action::None;
2442
0
    }
2443
2444
    struct ConditionState {
2445
        bool dependent = true;
2446
        bool unknown = true;
2447
2448
1.10k
        bool isUnknownDependent() const {
2449
1.10k
            return unknown && dependent;
2450
1.10k
        }
2451
    };
2452
2453
    std::unordered_map<nonneg int, const Token*> getSymbols(const Token* tok) const
2454
444
    {
2455
444
        std::unordered_map<nonneg int, const Token*> result;
2456
444
        if (!tok)
2457
0
            return result;
2458
444
        for (const ValueFlow::Value& v : tok->values()) {
2459
50
            if (!v.isSymbolicValue())
2460
33
                continue;
2461
17
            if (v.isImpossible())
2462
0
                continue;
2463
17
            if (!v.tokvalue)
2464
0
                continue;
2465
17
            if (v.tokvalue->exprId() == 0)
2466
0
                continue;
2467
17
            if (match(v.tokvalue))
2468
0
                continue;
2469
17
            result[v.tokvalue->exprId()] = v.tokvalue;
2470
17
        }
2471
444
        return result;
2472
444
    }
2473
2474
    ConditionState analyzeCondition(const Token* tok, int depth = 20) const
2475
1.11k
    {
2476
1.11k
        ConditionState result;
2477
1.11k
        if (!tok)
2478
55
            return result;
2479
1.06k
        if (depth < 0)
2480
0
            return result;
2481
1.06k
        depth--;
2482
1.06k
        if (analyze(tok, Direction::Forward).isRead()) {
2483
20
            result.dependent = true;
2484
20
            result.unknown = false;
2485
20
            return result;
2486
20
        }
2487
1.04k
        if (tok->hasKnownIntValue() || tok->isLiteral()) {
2488
120
            result.dependent = false;
2489
120
            result.unknown = false;
2490
120
            return result;
2491
120
        }
2492
922
        if (Token::Match(tok, "%cop%")) {
2493
478
            if (isLikelyStream(isCPP(), tok->astOperand1())) {
2494
0
                result.dependent = false;
2495
0
                return result;
2496
0
            }
2497
478
            ConditionState lhs = analyzeCondition(tok->astOperand1(), depth - 1);
2498
478
            if (lhs.isUnknownDependent())
2499
73
                return lhs;
2500
405
            ConditionState rhs = analyzeCondition(tok->astOperand2(), depth - 1);
2501
405
            if (rhs.isUnknownDependent())
2502
108
                return rhs;
2503
297
            if (Token::Match(tok, "%comp%"))
2504
166
                result.dependent = lhs.dependent && rhs.dependent;
2505
131
            else
2506
131
                result.dependent = lhs.dependent || rhs.dependent;
2507
297
            result.unknown = lhs.unknown || rhs.unknown;
2508
297
            return result;
2509
405
        }
2510
444
        if (Token::Match(tok->previous(), "%name% (")) {
2511
0
            std::vector<const Token*> args = getArguments(tok->previous());
2512
0
            if (Token::Match(tok->tokAt(-2), ". %name% (")) {
2513
0
                args.push_back(tok->tokAt(-2)->astOperand1());
2514
0
            }
2515
0
            result.dependent = std::any_of(args.cbegin(), args.cend(), [&](const Token* arg) {
2516
0
                ConditionState cs = analyzeCondition(arg, depth - 1);
2517
0
                return cs.dependent;
2518
0
            });
2519
0
            if (result.dependent) {
2520
                // Check if we can evaluate the function
2521
0
                if (!evaluate(Evaluate::Integral, tok).empty())
2522
0
                    result.unknown = false;
2523
0
            }
2524
0
            return result;
2525
0
        }
2526
2527
444
        std::unordered_map<nonneg int, const Token*> symbols = getSymbols(tok);
2528
444
        result.dependent = false;
2529
444
        for (auto&& p : symbols) {
2530
15
            const Token* arg = p.second;
2531
15
            ConditionState cs = analyzeCondition(arg, depth - 1);
2532
15
            result.dependent = cs.dependent;
2533
15
            if (result.dependent)
2534
5
                break;
2535
15
        }
2536
444
        if (result.dependent) {
2537
            // Check if we can evaluate the token
2538
5
            if (!evaluate(Evaluate::Integral, tok).empty())
2539
0
                result.unknown = false;
2540
5
        }
2541
444
        return result;
2542
444
    }
2543
2544
1.50k
    virtual Action isModified(const Token* tok) const {
2545
1.50k
        const Action read = Action::Read;
2546
1.50k
        const ValueFlow::Value* value = getValue(tok);
2547
1.50k
        if (value) {
2548
            // Moving a moved value won't change the moved value
2549
1.50k
            if (value->isMovedValue() && isMoveOrForward(tok) != ValueFlow::Value::MoveKind::NonMovedVariable)
2550
0
                return read;
2551
            // Inserting elements to container won't change the lifetime
2552
1.50k
            if (astIsContainer(tok) && value->isLifetimeValue() &&
2553
1.50k
                contains({Library::Container::Action::PUSH,
2554
0
                          Library::Container::Action::INSERT,
2555
0
                          Library::Container::Action::CHANGE_INTERNAL},
2556
0
                         astContainerAction(tok)))
2557
0
                return read;
2558
1.50k
        }
2559
1.50k
        bool inconclusive = false;
2560
1.50k
        if (isVariableChangedByFunctionCall(tok, getIndirect(tok), getSettings(), &inconclusive))
2561
0
            return read | Action::Invalid;
2562
1.50k
        if (inconclusive)
2563
0
            return read | Action::Inconclusive;
2564
1.50k
        if (isVariableChanged(tok, getIndirect(tok), getSettings(), isCPP())) {
2565
361
            if (Token::Match(tok->astParent(), "*|[|.|++|--"))
2566
0
                return read | Action::Invalid;
2567
            // Check if its assigned to the same value
2568
361
            if (value && !value->isImpossible() && Token::simpleMatch(tok->astParent(), "=") && astIsLHS(tok) &&
2569
361
                astIsIntegral(tok->astParent()->astOperand2(), false)) {
2570
198
                std::vector<MathLib::bigint> result = evaluateInt(tok->astParent()->astOperand2());
2571
198
                if (!result.empty() && value->equalTo(result.front()))
2572
0
                    return Action::Idempotent;
2573
198
            }
2574
361
            return Action::Invalid;
2575
361
        }
2576
1.14k
        return read;
2577
1.50k
    }
2578
2579
475
    virtual Action isAliasModified(const Token* tok, int indirect = -1) const {
2580
        // Lambda function call
2581
475
        if (Token::Match(tok, "%var% ("))
2582
            // TODO: Check if modified in the lambda function
2583
0
            return Action::Invalid;
2584
475
        if (indirect == -1) {
2585
238
            indirect = 0;
2586
238
            if (const ValueType* vt = tok->valueType()) {
2587
238
                indirect = vt->pointer;
2588
238
                if (vt->type == ValueType::ITERATOR)
2589
0
                    ++indirect;
2590
238
            }
2591
238
        }
2592
785
        for (int i = 0; i <= indirect; ++i)
2593
475
            if (isVariableChanged(tok, i, getSettings(), isCPP()))
2594
165
                return Action::Invalid;
2595
310
        return Action::None;
2596
475
    }
2597
2598
0
    virtual Action isThisModified(const Token* tok) const {
2599
0
        if (isThisChanged(tok, 0, getSettings(), isCPP()))
2600
0
            return Action::Invalid;
2601
0
        return Action::None;
2602
0
    }
2603
2604
    Action isGlobalModified(const Token* tok) const
2605
4
    {
2606
4
        if (tok->function()) {
2607
0
            if (!tok->function()->isConstexpr() && !isConstFunctionCall(tok, getSettings()->library))
2608
0
                return Action::Invalid;
2609
4
        } else if (getSettings()->library.getFunction(tok)) {
2610
            // Assume library function doesn't modify user-global variables
2611
0
            return Action::None;
2612
4
        } else if (Token::simpleMatch(tok->astParent(), ".") && astIsContainer(tok->astParent()->astOperand1())) {
2613
            // Assume container member function doesn't modify user-global variables
2614
0
            return Action::None;
2615
4
        } else if (tok->tokType() == Token::eType && astIsPrimitive(tok->next())) {
2616
            // Function cast does not modify global variables
2617
0
            return Action::None;
2618
4
        } else if (!tok->isKeyword() && Token::Match(tok, "%name% (")) {
2619
0
            return Action::Invalid;
2620
0
        }
2621
4
        return Action::None;
2622
4
    }
2623
2624
    static const std::string& getAssign(const Token* tok, Direction d)
2625
227
    {
2626
227
        if (d == Direction::Forward)
2627
136
            return tok->str();
2628
91
        return invertAssign(tok->str());
2629
227
    }
2630
2631
1.99k
    virtual Action isWritable(const Token* tok, Direction d) const {
2632
1.99k
        const ValueFlow::Value* value = getValue(tok);
2633
1.99k
        if (!value)
2634
0
            return Action::None;
2635
1.99k
        if (!(value->isIntValue() || value->isFloatValue() || value->isSymbolicValue() || value->isLifetimeValue()))
2636
0
            return Action::None;
2637
1.99k
        const Token* parent = tok->astParent();
2638
        // Only if its invertible
2639
1.99k
        if (value->isImpossible() && !Token::Match(parent, "+=|-=|*=|++|--"))
2640
361
            return Action::None;
2641
1.63k
        if (value->isLifetimeValue()) {
2642
0
            if (value->lifetimeKind != ValueFlow::Value::LifetimeKind::Iterator)
2643
0
                return Action::None;
2644
0
            if (!Token::Match(parent, "++|--|+="))
2645
0
                return Action::None;
2646
0
            return Action::Read | Action::Write;
2647
0
        }
2648
1.63k
        if (parent && parent->isAssignmentOp() && astIsLHS(tok)) {
2649
451
            const Token* rhs = parent->astOperand2();
2650
451
            std::vector<MathLib::bigint> result = evaluateInt(rhs);
2651
451
            if (!result.empty()) {
2652
190
                ValueFlow::Value rhsValue{result.front()};
2653
190
                Action a;
2654
190
                if (!evalAssignment(*value, getAssign(parent, d), rhsValue))
2655
8
                    a = Action::Invalid;
2656
182
                else
2657
182
                    a = Action::Write;
2658
190
                if (parent->str() != "=") {
2659
0
                    a |= Action::Read | Action::Incremental;
2660
190
                } else {
2661
190
                    if (!value->isImpossible() && value->equalValue(rhsValue))
2662
120
                        a = Action::Idempotent;
2663
190
                    if (tok->exprId() != 0 &&
2664
296
                        findAstNode(rhs, [&](const Token* child) {
2665
296
                        return tok->exprId() == child->exprId();
2666
296
                    }))
2667
58
                        a |= Action::Incremental;
2668
190
                }
2669
190
                return a;
2670
190
            }
2671
451
        }
2672
2673
        // increment/decrement
2674
1.44k
        if (Token::Match(tok->astParent(), "++|--")) {
2675
297
            return Action::Read | Action::Write | Action::Incremental;
2676
297
        }
2677
1.14k
        return Action::None;
2678
1.44k
    }
2679
2680
244
    virtual void writeValue(ValueFlow::Value* value, const Token* tok, Direction d) const {
2681
244
        if (!value)
2682
0
            return;
2683
244
        if (!tok->astParent())
2684
0
            return;
2685
        // Lifetime value doesn't change
2686
244
        if (value->isLifetimeValue())
2687
0
            return;
2688
244
        if (tok->astParent()->isAssignmentOp()) {
2689
37
            const Token* rhs = tok->astParent()->astOperand2();
2690
37
            std::vector<MathLib::bigint> result = evaluateInt(rhs);
2691
37
            assert(!result.empty());
2692
0
            ValueFlow::Value rhsValue{result.front()};
2693
37
            if (evalAssignment(*value, getAssign(tok->astParent(), d), rhsValue)) {
2694
37
                std::string info("Compound assignment '" + tok->astParent()->str() + "', assigned value is " +
2695
37
                                 value->infoString());
2696
37
                if (tok->astParent()->str() == "=")
2697
37
                    value->errorPath.clear();
2698
37
                value->errorPath.emplace_back(tok, std::move(info));
2699
37
            } else {
2700
0
                assert(false && "Writable value cannot be evaluated");
2701
                // TODO: Don't set to zero
2702
0
                value->intvalue = 0;
2703
0
            }
2704
207
        } else if (tok->astParent()->tokType() == Token::eIncDecOp) {
2705
207
            bool inc = tok->astParent()->str() == "++";
2706
207
            const std::string opName(inc ? "incremented" : "decremented");
2707
207
            if (d == Direction::Reverse)
2708
29
                inc = !inc;
2709
207
            value->intvalue += (inc ? 1 : -1);
2710
207
            value->errorPath.emplace_back(tok, tok->str() + " is " + opName + "', new value is " + value->infoString());
2711
207
        }
2712
244
    }
2713
2714
0
    virtual bool useSymbolicValues() const {
2715
0
        return true;
2716
0
    }
2717
2718
    const Token* findMatch(const Token* tok) const
2719
42
    {
2720
182
        return findAstNode(tok, [&](const Token* child) {
2721
182
            return match(child);
2722
182
        });
2723
42
    }
2724
2725
    bool isSameSymbolicValue(const Token* tok, ValueFlow::Value* value = nullptr) const
2726
26.0k
    {
2727
26.0k
        if (!useSymbolicValues())
2728
0
            return false;
2729
26.0k
        if (Token::Match(tok, "%assign%"))
2730
1.28k
            return false;
2731
24.7k
        const ValueFlow::Value* currValue = getValue(tok);
2732
24.7k
        if (!currValue)
2733
0
            return false;
2734
        // If the same symbolic value is already there then skip
2735
24.7k
        if (currValue->isSymbolicValue() &&
2736
24.7k
            std::any_of(tok->values().cbegin(), tok->values().cend(), [&](const ValueFlow::Value& v) {
2737
3.25k
            return v.isSymbolicValue() && currValue->equalValue(v);
2738
3.25k
        }))
2739
22
            return false;
2740
24.7k
        const bool isPoint = currValue->bound == ValueFlow::Value::Bound::Point && currValue->isIntValue();
2741
24.7k
        const bool exact = !currValue->isIntValue() || currValue->isImpossible();
2742
24.7k
        for (const ValueFlow::Value& v : tok->values()) {
2743
9.49k
            if (!v.isSymbolicValue())
2744
9.13k
                continue;
2745
356
            if (currValue->equalValue(v))
2746
0
                continue;
2747
356
            const bool toImpossible = v.isImpossible() && currValue->isKnown();
2748
356
            if (!v.isKnown() && !toImpossible)
2749
275
                continue;
2750
81
            if (exact && v.intvalue != 0 && !isPoint)
2751
3
                continue;
2752
78
            std::vector<MathLib::bigint> r;
2753
78
            ValueFlow::Value::Bound bound = currValue->bound;
2754
78
            if (match(v.tokvalue)) {
2755
14
                r = {currValue->intvalue};
2756
64
            } else if (!exact && findMatch(v.tokvalue)) {
2757
4
                r = evaluate(Evaluate::Integral, v.tokvalue, tok);
2758
4
                if (bound == ValueFlow::Value::Bound::Point)
2759
4
                    bound = v.bound;
2760
4
            }
2761
78
            if (!r.empty()) {
2762
14
                if (value) {
2763
5
                    value->errorPath.insert(value->errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
2764
5
                    value->intvalue = r.front() + v.intvalue;
2765
5
                    if (toImpossible)
2766
0
                        value->setImpossible();
2767
5
                    value->bound = bound;
2768
5
                }
2769
14
                return true;
2770
14
            }
2771
78
        }
2772
24.7k
        return false;
2773
24.7k
    }
2774
2775
1.99k
    Action analyzeMatch(const Token* tok, Direction d) const {
2776
1.99k
        const Token* parent = tok->astParent();
2777
1.99k
        if (d == Direction::Reverse && isGlobal() && !dependsOnThis() && Token::Match(parent, ". %name% (")) {
2778
0
            Action a = isGlobalModified(parent->next());
2779
0
            if (a != Action::None)
2780
0
                return a;
2781
0
        }
2782
1.99k
        if ((astIsPointer(tok) || astIsSmartPointer(tok)) &&
2783
1.99k
            (Token::Match(parent, "*|[") || (parent && parent->originalName() == "->")) && getIndirect(tok) <= 0)
2784
0
            return Action::Read;
2785
2786
1.99k
        Action w = isWritable(tok, d);
2787
1.99k
        if (w != Action::None)
2788
487
            return w;
2789
2790
        // Check for modifications by function calls
2791
1.50k
        return isModified(tok);
2792
1.99k
    }
2793
2794
28.5k
    Action analyzeToken(const Token* ref, const Token* tok, Direction d, bool inconclusiveRef) const {
2795
28.5k
        if (!ref)
2796
0
            return Action::None;
2797
        // If its an inconclusiveRef then ref != tok
2798
28.5k
        assert(!inconclusiveRef || ref != tok);
2799
0
        bool inconclusive = false;
2800
28.5k
        if (match(ref)) {
2801
1.99k
            if (inconclusiveRef) {
2802
0
                Action a = isModified(tok);
2803
0
                if (a.isModified() || a.isInconclusive())
2804
0
                    return Action::Inconclusive;
2805
1.99k
            } else {
2806
1.99k
                return analyzeMatch(tok, d) | Action::Match;
2807
1.99k
            }
2808
26.5k
        } else if (ref->isUnaryOp("*") && !match(ref->astOperand1())) {
2809
0
            const Token* lifeTok = nullptr;
2810
0
            for (const ValueFlow::Value& v:ref->astOperand1()->values()) {
2811
0
                if (!v.isLocalLifetimeValue())
2812
0
                    continue;
2813
0
                if (lifeTok)
2814
0
                    return Action::None;
2815
0
                lifeTok = v.tokvalue;
2816
0
            }
2817
0
            if (!lifeTok)
2818
0
                return Action::None;
2819
0
            Action la = analyzeLifetime(lifeTok);
2820
0
            if (la.matches()) {
2821
0
                Action a = Action::Read;
2822
0
                if (isModified(tok).isModified())
2823
0
                    a = Action::Invalid;
2824
0
                if (Token::Match(tok->astParent(), "%assign%") && astIsLHS(tok))
2825
0
                    a |= Action::Invalid;
2826
0
                if (inconclusiveRef && a.isModified())
2827
0
                    return Action::Inconclusive;
2828
0
                return a;
2829
0
            }
2830
0
            if (la.isRead()) {
2831
0
                return isAliasModified(tok);
2832
0
            }
2833
0
            return Action::None;
2834
2835
26.5k
        } else if (isAlias(ref, inconclusive)) {
2836
475
            inconclusive |= inconclusiveRef;
2837
475
            Action a = isAliasModified(tok);
2838
475
            if (inconclusive && a.isModified())
2839
0
                return Action::Inconclusive;
2840
475
            return a;
2841
475
        }
2842
26.0k
        if (isSameSymbolicValue(ref))
2843
9
            return Action::Read | Action::SymbolicMatch;
2844
2845
26.0k
        return Action::None;
2846
26.0k
    }
2847
2848
28.5k
    Action analyze(const Token* tok, Direction d) const override {
2849
28.5k
        if (invalid())
2850
0
            return Action::Invalid;
2851
        // Follow references
2852
28.5k
        auto refs = followAllReferences(tok);
2853
28.5k
        const bool inconclusiveRefs = refs.size() != 1;
2854
28.5k
        if (std::none_of(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
2855
28.5k
            return tok == ref.token;
2856
28.5k
        }))
2857
0
            refs.emplace_back(ReferenceToken{tok, {}});
2858
28.5k
        for (const ReferenceToken& ref:refs) {
2859
28.5k
            Action a = analyzeToken(ref.token, tok, d, inconclusiveRefs && ref.token != tok);
2860
28.5k
            if (internalMatch(ref.token))
2861
0
                a |= Action::Internal;
2862
28.5k
            if (a != Action::None)
2863
2.16k
                return a;
2864
28.5k
        }
2865
26.3k
        if (dependsOnThis() && exprDependsOnThis(tok, !isVariable()))
2866
0
            return isThisModified(tok);
2867
2868
        // bailout: global non-const variables
2869
26.3k
        if (isGlobal() && !dependsOnThis() && Token::Match(tok, "%name% (") &&
2870
26.3k
            !Token::simpleMatch(tok->linkAt(1), ") {")) {
2871
4
            return isGlobalModified(tok);
2872
4
        }
2873
26.3k
        return Action::None;
2874
26.3k
    }
2875
2876
    template<class F>
2877
    std::vector<MathLib::bigint> evaluateInt(const Token* tok, F getProgramMemory) const
2878
1.64k
    {
2879
1.64k
        if (tok->hasKnownIntValue())
2880
296
            return {static_cast<int>(tok->values().front().intvalue)};
2881
1.35k
        std::vector<MathLib::bigint> result;
2882
1.35k
        ProgramMemory pm = getProgramMemory();
2883
1.35k
        if (Token::Match(tok, "&&|%oror%")) {
2884
0
            if (conditionIsTrue(tok, pm, getSettings()))
2885
0
                result.push_back(1);
2886
0
            if (conditionIsFalse(tok, pm, getSettings()))
2887
0
                result.push_back(0);
2888
1.35k
        } else {
2889
1.35k
            MathLib::bigint out = 0;
2890
1.35k
            bool error = false;
2891
1.35k
            execute(tok, pm, &out, &error, getSettings());
2892
1.35k
            if (!error)
2893
134
                result.push_back(out);
2894
1.35k
        }
2895
1.35k
        return result;
2896
1.64k
    }
std::__1::vector<long long, ValueFlowAnalyzer::evaluateInt(Token const*) const::{lambda()#1}::allocator<long long> > ValueFlowAnalyzer::evaluateInt<ValueFlowAnalyzer::evaluateInt(Token const*) const::{lambda()#1}>(Token const*, ValueFlowAnalyzer::evaluateInt(Token const*) const::{lambda()#1}) const
Line
Count
Source
2878
686
    {
2879
686
        if (tok->hasKnownIntValue())
2880
166
            return {static_cast<int>(tok->values().front().intvalue)};
2881
520
        std::vector<MathLib::bigint> result;
2882
520
        ProgramMemory pm = getProgramMemory();
2883
520
        if (Token::Match(tok, "&&|%oror%")) {
2884
0
            if (conditionIsTrue(tok, pm, getSettings()))
2885
0
                result.push_back(1);
2886
0
            if (conditionIsFalse(tok, pm, getSettings()))
2887
0
                result.push_back(0);
2888
520
        } else {
2889
520
            MathLib::bigint out = 0;
2890
520
            bool error = false;
2891
520
            execute(tok, pm, &out, &error, getSettings());
2892
520
            if (!error)
2893
61
                result.push_back(out);
2894
520
        }
2895
520
        return result;
2896
686
    }
std::__1::vector<long long, ValueFlowAnalyzer::evaluate(Analyzer::Evaluate, Token const*, Token const*) const::{lambda()#1}::allocator<long long> > ValueFlowAnalyzer::evaluateInt<ValueFlowAnalyzer::evaluate(Analyzer::Evaluate, Token const*, Token const*) const::{lambda()#1}>(Token const*, ValueFlowAnalyzer::evaluate(Analyzer::Evaluate, Token const*, Token const*) const::{lambda()#1}) const
Line
Count
Source
2878
961
    {
2879
961
        if (tok->hasKnownIntValue())
2880
130
            return {static_cast<int>(tok->values().front().intvalue)};
2881
831
        std::vector<MathLib::bigint> result;
2882
831
        ProgramMemory pm = getProgramMemory();
2883
831
        if (Token::Match(tok, "&&|%oror%")) {
2884
0
            if (conditionIsTrue(tok, pm, getSettings()))
2885
0
                result.push_back(1);
2886
0
            if (conditionIsFalse(tok, pm, getSettings()))
2887
0
                result.push_back(0);
2888
831
        } else {
2889
831
            MathLib::bigint out = 0;
2890
831
            bool error = false;
2891
831
            execute(tok, pm, &out, &error, getSettings());
2892
831
            if (!error)
2893
73
                result.push_back(out);
2894
831
        }
2895
831
        return result;
2896
961
    }
2897
    std::vector<MathLib::bigint> evaluateInt(const Token* tok) const
2898
686
    {
2899
686
        return evaluateInt(tok, [&] {
2900
520
            return ProgramMemory{getProgramState()};
2901
520
        });
2902
686
    }
2903
2904
    std::vector<MathLib::bigint> evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const override
2905
961
    {
2906
961
        if (e == Evaluate::Integral) {
2907
961
            return evaluateInt(tok, [&] {
2908
831
                return pms.get(tok, ctx, getProgramState());
2909
831
            });
2910
961
        }
2911
0
        if (e == Evaluate::ContainerEmpty) {
2912
0
            const ValueFlow::Value* value = ValueFlow::findValue(tok->values(), nullptr, [](const ValueFlow::Value& v) {
2913
0
                return v.isKnown() && v.isContainerSizeValue();
2914
0
            });
2915
0
            if (value)
2916
0
                return {value->intvalue == 0};
2917
0
            ProgramMemory pm = pms.get(tok, ctx, getProgramState());
2918
0
            MathLib::bigint out = 0;
2919
0
            if (pm.getContainerEmptyValue(tok->exprId(), out))
2920
0
                return {static_cast<int>(out)};
2921
0
            return {};
2922
0
        }
2923
0
        return {};
2924
0
    }
2925
2926
408
    void assume(const Token* tok, bool state, unsigned int flags) override {
2927
        // Update program state
2928
408
        pms.removeModifiedVars(tok);
2929
408
        pms.addState(tok, getProgramState());
2930
408
        pms.assume(tok, state, flags & Assume::ContainerEmpty);
2931
2932
408
        bool isCondBlock = false;
2933
408
        const Token* parent = tok->astParent();
2934
408
        if (parent) {
2935
408
            isCondBlock = Token::Match(parent->previous(), "if|while (");
2936
408
        }
2937
2938
408
        if (isCondBlock) {
2939
408
            const Token* startBlock = parent->link()->next();
2940
408
            if (Token::simpleMatch(startBlock, ";") && Token::simpleMatch(parent->tokAt(-2), "} while ("))
2941
0
                startBlock = parent->linkAt(-2);
2942
408
            const Token* endBlock = startBlock->link();
2943
408
            if (state) {
2944
316
                pms.removeModifiedVars(endBlock);
2945
316
                pms.addState(endBlock->previous(), getProgramState());
2946
316
            } else {
2947
92
                if (Token::simpleMatch(endBlock, "} else {"))
2948
36
                    pms.addState(endBlock->linkAt(2)->previous(), getProgramState());
2949
92
            }
2950
408
        }
2951
2952
408
        if (!(flags & Assume::Quiet)) {
2953
88
            if (flags & Assume::ContainerEmpty) {
2954
0
                std::string s = state ? "empty" : "not empty";
2955
0
                addErrorPath(tok, "Assuming container is " + s);
2956
88
            } else {
2957
88
                std::string s = bool_to_string(state);
2958
88
                addErrorPath(tok, "Assuming condition is " + s);
2959
88
            }
2960
88
        }
2961
408
        if (!(flags & Assume::Absolute))
2962
400
            makeConditional();
2963
408
    }
2964
2965
    virtual void internalUpdate(Token* /*tok*/, const ValueFlow::Value& /*v*/, Direction /*d*/)
2966
0
    {
2967
0
        assert(false && "Internal update unimplemented.");
2968
0
    }
2969
2970
1.01k
    void update(Token* tok, Action a, Direction d) override {
2971
1.01k
        ValueFlow::Value* value = getValue(tok);
2972
1.01k
        if (!value)
2973
0
            return;
2974
1.01k
        ValueFlow::Value localValue;
2975
1.01k
        if (a.isSymbolicMatch()) {
2976
            // Make a copy of the value to modify it
2977
5
            localValue = *value;
2978
5
            value = &localValue;
2979
5
            isSameSymbolicValue(tok, &localValue);
2980
5
        }
2981
1.01k
        if (a.isInternal())
2982
0
            internalUpdate(tok, *value, d);
2983
        // Read first when moving forward
2984
1.01k
        if (d == Direction::Forward && a.isRead())
2985
676
            setTokenValue(tok, *value, getSettings());
2986
1.01k
        if (a.isInconclusive())
2987
0
            lowerToInconclusive();
2988
1.01k
        if (a.isWrite() && tok->astParent()) {
2989
244
            writeValue(value, tok, d);
2990
244
        }
2991
        // Read last when moving in reverse
2992
1.01k
        if (d == Direction::Reverse && a.isRead())
2993
71
            setTokenValue(tok, *value, getSettings());
2994
1.01k
    }
2995
2996
0
    ValuePtr<Analyzer> reanalyze(Token* /*tok*/, const std::string& /*msg*/) const override {
2997
0
        return {};
2998
0
    }
2999
};
3000
3001
struct SingleValueFlowAnalyzer : ValueFlowAnalyzer {
3002
    std::unordered_map<nonneg int, const Variable*> varids;
3003
    std::unordered_map<nonneg int, const Variable*> aliases;
3004
    ValueFlow::Value value;
3005
3006
8.63k
    SingleValueFlowAnalyzer(ValueFlow::Value v, const TokenList& t, const Settings* s) : ValueFlowAnalyzer(t, s), value(std::move(v)) {}
3007
3008
26.5k
    const std::unordered_map<nonneg int, const Variable*>& getVars() const {
3009
26.5k
        return varids;
3010
26.5k
    }
3011
3012
26.5k
    const std::unordered_map<nonneg int, const Variable*>& getAliasedVars() const {
3013
26.5k
        return aliases;
3014
26.5k
    }
3015
3016
31.2k
    const ValueFlow::Value* getValue(const Token* /*tok*/) const override {
3017
31.2k
        return &value;
3018
31.2k
    }
3019
1.01k
    ValueFlow::Value* getValue(const Token* /*tok*/) override {
3020
1.01k
        return &value;
3021
1.01k
    }
3022
3023
400
    void makeConditional() override {
3024
400
        value.conditional = true;
3025
400
    }
3026
3027
    bool useSymbolicValues() const override
3028
26.0k
    {
3029
26.0k
        if (value.isUninitValue())
3030
0
            return false;
3031
26.0k
        if (value.isLifetimeValue())
3032
0
            return false;
3033
26.0k
        return true;
3034
26.0k
    }
3035
3036
88
    void addErrorPath(const Token* tok, const std::string& s) override {
3037
88
        value.errorPath.emplace_back(tok, s);
3038
88
    }
3039
3040
26.5k
    bool isAlias(const Token* tok, bool& inconclusive) const override {
3041
26.5k
        if (value.isLifetimeValue())
3042
0
            return false;
3043
26.5k
        for (const auto& m: {
3044
26.5k
            std::ref(getVars()), std::ref(getAliasedVars())
3045
52.5k
        }) {
3046
52.5k
            for (const auto& p:m.get()) {
3047
33.5k
                nonneg int const varid = p.first;
3048
33.5k
                const Variable* var = p.second;
3049
33.5k
                if (tok->varId() == varid)
3050
475
                    return true;
3051
33.0k
                if (isAliasOf(var, tok, varid, MakeSingleRange(value), &inconclusive))
3052
0
                    return true;
3053
33.0k
            }
3054
52.5k
        }
3055
26.0k
        return false;
3056
26.5k
    }
3057
3058
0
    bool isGlobal() const override {
3059
0
        const auto& vars = getVars();
3060
0
        return std::any_of(vars.cbegin(), vars.cend(), [] (const std::pair<nonneg int, const Variable*>& p) {
3061
0
            const Variable* var = p.second;
3062
0
            return !var->isLocal() && !var->isArgument() && !var->isConst();
3063
0
        });
3064
0
    }
3065
3066
689
    bool lowerToPossible() override {
3067
689
        if (value.isImpossible())
3068
172
            return false;
3069
517
        value.changeKnownToPossible();
3070
517
        return true;
3071
689
    }
3072
0
    bool lowerToInconclusive() override {
3073
0
        if (value.isImpossible())
3074
0
            return false;
3075
0
        value.setInconclusive();
3076
0
        return true;
3077
0
    }
3078
3079
638
    bool isConditional() const override {
3080
638
        if (value.conditional)
3081
66
            return true;
3082
572
        if (value.condition)
3083
316
            return !value.isKnown() && !value.isImpossible();
3084
256
        return false;
3085
572
    }
3086
3087
    bool stopOnCondition(const Token* condTok) const override
3088
592
    {
3089
592
        if (value.isNonValue())
3090
0
            return false;
3091
592
        if (value.isImpossible())
3092
161
            return false;
3093
431
        if (isConditional() && !value.isKnown() && !value.isImpossible())
3094
212
            return true;
3095
219
        if (value.isSymbolicValue())
3096
0
            return false;
3097
219
        ConditionState cs = analyzeCondition(condTok);
3098
219
        return cs.isUnknownDependent();
3099
219
    }
3100
3101
497
    bool updateScope(const Token* endBlock, bool /*modified*/) const override {
3102
497
        const Scope* scope = endBlock->scope();
3103
497
        if (!scope)
3104
0
            return false;
3105
497
        if (scope->type == Scope::eLambda)
3106
0
            return value.isLifetimeValue();
3107
497
        if (scope->type == Scope::eIf || scope->type == Scope::eElse || scope->type == Scope::eWhile ||
3108
497
            scope->type == Scope::eFor) {
3109
497
            if (value.isKnown() || value.isImpossible())
3110
362
                return true;
3111
135
            if (value.isLifetimeValue())
3112
0
                return true;
3113
135
            if (isConditional())
3114
120
                return false;
3115
15
            const Token* condTok = getCondTokFromEnd(endBlock);
3116
15
            std::set<nonneg int> varids2;
3117
15
            std::transform(getVars().cbegin(), getVars().cend(), std::inserter(varids2, varids2.begin()), SelectMapKeys{});
3118
15
            return bifurcate(condTok, varids2, getSettings());
3119
135
        }
3120
3121
0
        return false;
3122
497
    }
3123
3124
37
    ValuePtr<Analyzer> reanalyze(Token* tok, const std::string& msg) const override {
3125
37
        ValueFlow::Value newValue = value;
3126
37
        newValue.errorPath.emplace_back(tok, msg);
3127
37
        return makeAnalyzer(tok, std::move(newValue), tokenlist, settings);
3128
37
    }
3129
};
3130
3131
struct ExpressionAnalyzer : SingleValueFlowAnalyzer {
3132
    const Token* expr;
3133
    bool local = true;
3134
    bool unknown{};
3135
    bool dependOnThis{};
3136
    bool uniqueExprId{};
3137
3138
    ExpressionAnalyzer(const Token* e, ValueFlow::Value val, const TokenList& t, const Settings* s)
3139
        : SingleValueFlowAnalyzer(std::move(val), t, s),
3140
        expr(e)
3141
8.63k
    {
3142
3143
8.63k
        assert(e && e->exprId() != 0 && "Not a valid expression");
3144
0
        dependOnThis = exprDependsOnThis(expr);
3145
8.63k
        setupExprVarIds(expr);
3146
8.63k
        if (value.isSymbolicValue()) {
3147
5.16k
            dependOnThis |= exprDependsOnThis(value.tokvalue);
3148
5.16k
            setupExprVarIds(value.tokvalue);
3149
5.16k
        }
3150
8.63k
        uniqueExprId =
3151
8.63k
            expr->isUniqueExprId() && (Token::Match(expr, "%cop%") || !isVariableChanged(expr, 0, s, t.isCPP()));
3152
8.63k
    }
3153
3154
12.7k
    static bool nonLocal(const Variable* var, bool deref) {
3155
12.7k
        return !var || (!var->isLocal() && !var->isArgument()) || (deref && var->isArgument() && var->isPointer()) ||
3156
12.7k
               var->isStatic() || var->isReference() || var->isExtern();
3157
12.7k
    }
3158
3159
13.7k
    void setupExprVarIds(const Token* start, int depth = 0) {
3160
13.7k
        const int maxDepth = 4;
3161
13.7k
        if (depth > maxDepth)
3162
0
            return;
3163
29.0k
        visitAstNodes(start, [&](const Token* tok) {
3164
29.0k
            const bool top = depth == 0 && tok == start;
3165
29.0k
            const bool ispointer = astIsPointer(tok) || astIsSmartPointer(tok) || astIsIterator(tok);
3166
29.0k
            if (!top || !ispointer || value.indirect != 0) {
3167
29.0k
                for (const ValueFlow::Value& v : tok->values()) {
3168
7.90k
                    if (!(v.isLocalLifetimeValue() || (ispointer && v.isSymbolicValue() && v.isKnown())))
3169
7.90k
                        continue;
3170
0
                    if (!v.tokvalue)
3171
0
                        continue;
3172
0
                    if (v.tokvalue == tok)
3173
0
                        continue;
3174
0
                    setupExprVarIds(v.tokvalue, depth + 1);
3175
0
                }
3176
29.0k
            }
3177
29.0k
            if (depth == 0 && tok->isIncompleteVar()) {
3178
                // TODO: Treat incomplete var as global, but we need to update
3179
                // the alias variables to just expr ids instead of requiring
3180
                // Variable
3181
5.16k
                unknown = true;
3182
5.16k
                return ChildrenToVisit::none;
3183
5.16k
            }
3184
23.8k
            if (tok->varId() > 0) {
3185
12.7k
                varids[tok->varId()] = tok->variable();
3186
12.7k
                if (!Token::simpleMatch(tok->previous(), ".")) {
3187
12.7k
                    const Variable* var = tok->variable();
3188
12.7k
                    if (var && var->isReference() && var->isLocal() && Token::Match(var->nameToken(), "%var% [=(]") &&
3189
12.7k
                        !isGlobalData(var->nameToken()->next()->astOperand2(), isCPP()))
3190
0
                        return ChildrenToVisit::none;
3191
12.7k
                    const bool deref = tok->astParent() &&
3192
12.7k
                                       (tok->astParent()->isUnaryOp("*") ||
3193
12.7k
                                        (tok->astParent()->str() == "[" && tok == tok->astParent()->astOperand1()));
3194
12.7k
                    local &= !nonLocal(tok->variable(), deref);
3195
12.7k
                }
3196
12.7k
            }
3197
23.8k
            return ChildrenToVisit::op1_and_op2;
3198
23.8k
        });
3199
13.7k
    }
3200
3201
36.5k
    virtual bool skipUniqueExprIds() const {
3202
36.5k
        return true;
3203
36.5k
    }
3204
3205
37.3k
    bool invalid() const override {
3206
37.3k
        if (skipUniqueExprIds() && uniqueExprId)
3207
2.69k
            return true;
3208
34.6k
        return unknown;
3209
37.3k
    }
3210
3211
2.11k
    ProgramState getProgramState() const override {
3212
2.11k
        ProgramState ps;
3213
2.11k
        ps[expr] = value;
3214
2.11k
        return ps;
3215
2.11k
    }
3216
3217
28.1k
    bool match(const Token* tok) const override {
3218
28.1k
        return tok->exprId() == expr->exprId();
3219
28.1k
    }
3220
3221
53.0k
    bool dependsOnThis() const override {
3222
53.0k
        return dependOnThis;
3223
53.0k
    }
3224
3225
26.7k
    bool isGlobal() const override {
3226
26.7k
        return !local;
3227
26.7k
    }
3228
3229
0
    bool isVariable() const override {
3230
0
        return expr->varId() > 0;
3231
0
    }
3232
3233
475
    Action isAliasModified(const Token* tok, int indirect) const override {
3234
475
        if (value.isSymbolicValue() && tok->exprId() == value.tokvalue->exprId())
3235
237
            indirect = 0;
3236
475
        return SingleValueFlowAnalyzer::isAliasModified(tok, indirect);
3237
475
    }
3238
};
3239
3240
struct SameExpressionAnalyzer : ExpressionAnalyzer {
3241
    SameExpressionAnalyzer(const Token* e, ValueFlow::Value val, const TokenList& t, const Settings* s)
3242
        : ExpressionAnalyzer(e, std::move(val), t, s)
3243
112
    {}
3244
3245
397
    bool skipUniqueExprIds() const override {
3246
397
        return false;
3247
397
    }
3248
3249
    bool match(const Token* tok) const override
3250
285
    {
3251
285
        return isSameExpression(isCPP(), true, expr, tok, getSettings()->library, true, true);
3252
285
    }
3253
};
3254
3255
struct OppositeExpressionAnalyzer : ExpressionAnalyzer {
3256
    bool isNot{};
3257
3258
    OppositeExpressionAnalyzer(bool pIsNot, const Token* e, ValueFlow::Value val, const TokenList& t, const Settings* s)
3259
        : ExpressionAnalyzer(e, std::move(val), t, s), isNot(pIsNot)
3260
124
    {}
3261
3262
459
    bool skipUniqueExprIds() const override {
3263
459
        return false;
3264
459
    }
3265
3266
335
    bool match(const Token* tok) const override {
3267
335
        return isOppositeCond(isNot, isCPP(), expr, tok, getSettings()->library, true, true);
3268
335
    }
3269
};
3270
3271
struct SubExpressionAnalyzer : ExpressionAnalyzer {
3272
    using PartialReadContainer = std::vector<std::pair<Token *, ValueFlow::Value>>;
3273
    // A shared_ptr is used so partial reads can be captured even after forking
3274
    std::shared_ptr<PartialReadContainer> partialReads;
3275
3276
    SubExpressionAnalyzer(const Token* e, ValueFlow::Value val, const TokenList& t, const Settings* s)
3277
        : ExpressionAnalyzer(e, std::move(val), t, s), partialReads(std::make_shared<PartialReadContainer>())
3278
0
    {}
3279
3280
    virtual bool submatch(const Token* tok, bool exact = true) const = 0;
3281
3282
    bool isAlias(const Token* tok, bool& inconclusive) const override
3283
0
    {
3284
0
        if (tok->exprId() == expr->exprId() && tok->astParent() && submatch(tok->astParent(), false))
3285
0
            return false;
3286
0
        return ExpressionAnalyzer::isAlias(tok, inconclusive);
3287
0
    }
3288
3289
    bool match(const Token* tok) const override
3290
0
    {
3291
0
        return tok->astOperand1() && tok->astOperand1()->exprId() == expr->exprId() && submatch(tok);
3292
0
    }
3293
    bool internalMatch(const Token* tok) const override
3294
0
    {
3295
0
        return tok->exprId() == expr->exprId() && !(astIsLHS(tok) && submatch(tok->astParent(), false));
3296
0
    }
3297
    void internalUpdate(Token* tok, const ValueFlow::Value& v, Direction /*d*/) override
3298
0
    {
3299
0
        partialReads->emplace_back(tok, v);
3300
0
    }
3301
3302
    // No reanalysis for subexression
3303
0
    ValuePtr<Analyzer> reanalyze(Token* /*tok*/, const std::string& /*msg*/) const override {
3304
0
        return {};
3305
0
    }
3306
};
3307
3308
struct MemberExpressionAnalyzer : SubExpressionAnalyzer {
3309
    std::string varname;
3310
3311
    MemberExpressionAnalyzer(std::string varname, const Token* e, ValueFlow::Value val, const TokenList& t, const Settings* s)
3312
        : SubExpressionAnalyzer(e, std::move(val), t, s), varname(std::move(varname))
3313
0
    {}
3314
3315
    bool submatch(const Token* tok, bool exact) const override
3316
0
    {
3317
0
        if (!Token::Match(tok, ". %var%"))
3318
0
            return false;
3319
0
        if (!exact)
3320
0
            return true;
3321
0
        return tok->next()->str() == varname;
3322
0
    }
3323
};
3324
3325
enum class LifetimeCapture { Undefined, ByValue, ByReference };
3326
3327
static std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
3328
0
{
3329
0
    std::string result;
3330
0
    if (!val)
3331
0
        return "object";
3332
0
    switch (val->lifetimeKind) {
3333
0
    case ValueFlow::Value::LifetimeKind::Lambda:
3334
0
        result = "lambda";
3335
0
        break;
3336
0
    case ValueFlow::Value::LifetimeKind::Iterator:
3337
0
        result = "iterator";
3338
0
        break;
3339
0
    case ValueFlow::Value::LifetimeKind::Object:
3340
0
    case ValueFlow::Value::LifetimeKind::SubObject:
3341
0
    case ValueFlow::Value::LifetimeKind::Address:
3342
0
        if (astIsPointer(tok))
3343
0
            result = "pointer";
3344
0
        else if (Token::simpleMatch(tok, "=") && astIsPointer(tok->astOperand2()))
3345
0
            result = "pointer";
3346
0
        else
3347
0
            result = "object";
3348
0
        break;
3349
0
    }
3350
0
    return result;
3351
0
}
3352
3353
std::string ValueFlow::lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ErrorPath &errorPath)
3354
0
{
3355
0
    const Token *tokvalue = val ? val->tokvalue : nullptr;
3356
0
    const Variable *tokvar = tokvalue ? tokvalue->variable() : nullptr;
3357
0
    const Token *vartok = tokvar ? tokvar->nameToken() : nullptr;
3358
0
    const bool classVar = tokvar ? (!tokvar->isLocal() && !tokvar->isArgument() && !tokvar->isGlobal()) : false;
3359
0
    std::string type = lifetimeType(tok, val);
3360
0
    std::string msg = type;
3361
0
    if (vartok) {
3362
0
        if (!classVar)
3363
0
            errorPath.emplace_back(vartok, "Variable created here.");
3364
0
        const Variable * var = vartok->variable();
3365
0
        if (var) {
3366
0
            std::string submessage;
3367
0
            switch (val->lifetimeKind) {
3368
0
            case ValueFlow::Value::LifetimeKind::SubObject:
3369
0
            case ValueFlow::Value::LifetimeKind::Object:
3370
0
            case ValueFlow::Value::LifetimeKind::Address:
3371
0
                if (type == "pointer")
3372
0
                    submessage = " to local variable";
3373
0
                else
3374
0
                    submessage = " that points to local variable";
3375
0
                break;
3376
0
            case ValueFlow::Value::LifetimeKind::Lambda:
3377
0
                submessage = " that captures local variable";
3378
0
                break;
3379
0
            case ValueFlow::Value::LifetimeKind::Iterator:
3380
0
                submessage = " to local container";
3381
0
                break;
3382
0
            }
3383
0
            if (classVar)
3384
0
                submessage.replace(submessage.find("local"), 5, "member");
3385
0
            msg += submessage + " '" + var->name() + "'";
3386
0
        }
3387
0
    }
3388
0
    return msg;
3389
0
}
3390
3391
std::vector<ValueFlow::Value> ValueFlow::getLifetimeObjValues(const Token* tok, bool inconclusive, MathLib::bigint path)
3392
4.78k
{
3393
4.78k
    std::vector<ValueFlow::Value> result;
3394
4.78k
    auto pred = [&](const ValueFlow::Value& v) {
3395
1.67k
        if (!v.isLocalLifetimeValue() && !(path != 0 && v.isSubFunctionLifetimeValue()))
3396
1.67k
            return false;
3397
0
        if (!inconclusive && v.isInconclusive())
3398
0
            return false;
3399
0
        if (!v.tokvalue)
3400
0
            return false;
3401
0
        if (path >= 0 && v.path != 0 && v.path != path)
3402
0
            return false;
3403
0
        return true;
3404
0
    };
3405
4.78k
    std::copy_if(tok->values().cbegin(), tok->values().cend(), std::back_inserter(result), pred);
3406
4.78k
    return result;
3407
4.78k
}
3408
3409
static bool hasUniqueOwnership(const Token* tok)
3410
0
{
3411
0
    if (!tok)
3412
0
        return false;
3413
0
    const Variable* var = tok->variable();
3414
0
    if (var && var->isArray() && !var->isArgument())
3415
0
        return true;
3416
0
    if (astIsPointer(tok))
3417
0
        return false;
3418
0
    if (astIsUniqueSmartPointer(tok))
3419
0
        return true;
3420
0
    if (astIsContainerOwned(tok))
3421
0
        return true;
3422
0
    return false;
3423
0
}
3424
3425
// Check if dereferencing an object that doesn't have unique ownership
3426
static bool derefShared(const Token* tok)
3427
0
{
3428
0
    if (!tok)
3429
0
        return false;
3430
0
    if (!tok->isUnaryOp("*") && tok->str() != "[" && tok->str() != ".")
3431
0
        return false;
3432
0
    if (tok->str() == "." && tok->originalName() != "->")
3433
0
        return false;
3434
0
    const Token* ptrTok = tok->astOperand1();
3435
0
    return !hasUniqueOwnership(ptrTok);
3436
0
}
3437
3438
ValueFlow::Value ValueFlow::getLifetimeObjValue(const Token *tok, bool inconclusive)
3439
303
{
3440
303
    std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(tok, inconclusive);
3441
    // There should only be one lifetime
3442
303
    if (values.size() != 1)
3443
303
        return ValueFlow::Value{};
3444
0
    return values.front();
3445
303
}
3446
3447
template<class Predicate>
3448
static std::vector<ValueFlow::LifetimeToken> getLifetimeTokens(const Token* tok,
3449
                                                               bool escape,
3450
                                                               ValueFlow::Value::ErrorPath errorPath,
3451
                                                               Predicate pred,
3452
                                                               int depth = 20)
3453
17.8k
{
3454
17.8k
    if (!tok)
3455
0
        return std::vector<ValueFlow::LifetimeToken> {};
3456
17.8k
    if (Token::simpleMatch(tok, "..."))
3457
0
        return std::vector<ValueFlow::LifetimeToken>{};
3458
17.8k
    const Variable *var = tok->variable();
3459
17.8k
    if (pred(tok))
3460
0
        return {{tok, std::move(errorPath)}};
3461
17.8k
    if (depth < 0)
3462
0
        return {{tok, std::move(errorPath)}};
3463
17.8k
    if (var && var->declarationId() == tok->varId()) {
3464
17.8k
        if (var->isReference() || var->isRValueReference()) {
3465
0
            const Token * const varDeclEndToken = var->declEndToken();
3466
0
            if (!varDeclEndToken)
3467
0
                return {{tok, true, std::move(errorPath)}};
3468
0
            if (var->isArgument()) {
3469
0
                errorPath.emplace_back(varDeclEndToken, "Passed to reference.");
3470
0
                return {{tok, true, std::move(errorPath)}};
3471
0
            }
3472
0
            if (Token::simpleMatch(varDeclEndToken, "=")) {
3473
0
                errorPath.emplace_back(varDeclEndToken, "Assigned to reference.");
3474
0
                const Token *vartok = varDeclEndToken->astOperand2();
3475
0
                const bool temporary = isTemporary(true, vartok, nullptr, true);
3476
0
                const bool nonlocal = var->isStatic() || var->isGlobal();
3477
0
                if (vartok == tok || (nonlocal && temporary) ||
3478
0
                    (!escape && (var->isConst() || var->isRValueReference()) && temporary))
3479
0
                    return {{tok, true, std::move(errorPath)}};
3480
0
                if (vartok)
3481
0
                    return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3482
0
            } else if (Token::simpleMatch(var->nameToken()->astParent(), ":") &&
3483
0
                       var->nameToken()->astParent()->astParent() &&
3484
0
                       Token::simpleMatch(var->nameToken()->astParent()->astParent()->previous(), "for (")) {
3485
0
                errorPath.emplace_back(var->nameToken(), "Assigned to reference.");
3486
0
                const Token* vartok = var->nameToken();
3487
0
                if (vartok == tok)
3488
0
                    return {{tok, true, std::move(errorPath)}};
3489
0
                const Token* contok = var->nameToken()->astParent()->astOperand2();
3490
0
                if (astIsContainer(contok))
3491
0
                    return getLifetimeTokens(contok, escape, std::move(errorPath), pred, depth - 1);
3492
0
                return std::vector<ValueFlow::LifetimeToken>{};
3493
0
            } else {
3494
0
                return std::vector<ValueFlow::LifetimeToken> {};
3495
0
            }
3496
0
        }
3497
17.8k
    } else if (Token::Match(tok->previous(), "%name% (")) {
3498
0
        const Function *f = tok->previous()->function();
3499
0
        if (f) {
3500
0
            if (!Function::returnsReference(f))
3501
0
                return {{tok, std::move(errorPath)}};
3502
0
            std::vector<ValueFlow::LifetimeToken> result;
3503
0
            std::vector<const Token*> returns = Function::findReturns(f);
3504
0
            for (const Token* returnTok : returns) {
3505
0
                if (returnTok == tok)
3506
0
                    continue;
3507
0
                for (ValueFlow::LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, depth - returns.size())) {
3508
0
                    const Token* argvarTok = lt.token;
3509
0
                    const Variable* argvar = argvarTok->variable();
3510
0
                    if (!argvar)
3511
0
                        continue;
3512
0
                    const Token* argTok = nullptr;
3513
0
                    if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
3514
0
                        const int n = getArgumentPos(argvar, f);
3515
0
                        if (n < 0)
3516
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3517
0
                        std::vector<const Token*> args = getArguments(tok->previous());
3518
                        // TODO: Track lifetimes of default parameters
3519
0
                        if (n >= args.size())
3520
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3521
0
                        argTok = args[n];
3522
0
                        lt.errorPath.emplace_back(returnTok, "Return reference.");
3523
0
                        lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
3524
0
                    } else if (Token::Match(tok->tokAt(-2), ". %name% (") && !derefShared(tok->tokAt(-2)) &&
3525
0
                               exprDependsOnThis(argvarTok)) {
3526
0
                        argTok = tok->tokAt(-2)->astOperand1();
3527
0
                        lt.errorPath.emplace_back(returnTok, "Return reference that depends on 'this'.");
3528
0
                        lt.errorPath.emplace_back(tok->previous(),
3529
0
                                                  "Calling member function on '" + argTok->expressionString() + "'.");
3530
0
                    }
3531
0
                    if (argTok) {
3532
0
                        std::vector<ValueFlow::LifetimeToken> arglts = ValueFlow::LifetimeToken::setInconclusive(
3533
0
                            getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, depth - returns.size()),
3534
0
                            returns.size() > 1);
3535
0
                        result.insert(result.end(), arglts.cbegin(), arglts.cend());
3536
0
                    }
3537
0
                }
3538
0
            }
3539
0
            return result;
3540
0
        }
3541
0
        if (Token::Match(tok->tokAt(-2), ". %name% (") && tok->tokAt(-2)->originalName() != "->" && astIsContainer(tok->tokAt(-2)->astOperand1())) {
3542
0
            const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1());
3543
0
            const Library::Container::Yield y = library->getYield(tok->previous()->str());
3544
0
            if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {
3545
0
                errorPath.emplace_back(tok->previous(), "Accessing container.");
3546
0
                return ValueFlow::LifetimeToken::setAddressOf(
3547
0
                    getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, depth - 1),
3548
0
                    false);
3549
0
            }
3550
0
        }
3551
0
    } else if (Token::Match(tok, ".|::|[") || tok->isUnaryOp("*")) {
3552
3553
0
        const Token *vartok = tok;
3554
0
        while (vartok) {
3555
0
            if (vartok->str() == "[" || vartok->originalName() == "->" || vartok->isUnaryOp("*"))
3556
0
                vartok = vartok->astOperand1();
3557
0
            else if (vartok->str() == "." || vartok->str() == "::")
3558
0
                vartok = vartok->astOperand2();
3559
0
            else
3560
0
                break;
3561
0
        }
3562
3563
0
        if (!vartok)
3564
0
            return {{tok, std::move(errorPath)}};
3565
0
        if (derefShared(vartok->astParent())) {
3566
0
            for (const ValueFlow::Value &v : vartok->values()) {
3567
0
                if (!v.isLocalLifetimeValue())
3568
0
                    continue;
3569
0
                if (v.tokvalue == tok)
3570
0
                    continue;
3571
0
                errorPath.insert(errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
3572
0
                return getLifetimeTokens(v.tokvalue, escape, std::move(errorPath), pred, depth - 1);
3573
0
            }
3574
0
        } else {
3575
0
            return ValueFlow::LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1),
3576
0
                                                          !(astIsContainer(vartok) && Token::simpleMatch(vartok->astParent(), "[")));
3577
0
        }
3578
0
    } else if (Token::simpleMatch(tok, "{") && getArgumentStart(tok) &&
3579
0
               !Token::simpleMatch(getArgumentStart(tok), ",") && getArgumentStart(tok)->valueType()) {
3580
0
        const Token* vartok = getArgumentStart(tok);
3581
0
        auto vts = getParentValueTypes(tok);
3582
0
        auto it = std::find_if(vts.cbegin(), vts.cend(), [&](const ValueType& vt) {
3583
0
            return vt.isTypeEqual(vartok->valueType());
3584
0
        });
Unexecuted instantiation: valueflow.cpp:getLifetimeTokens<ValueFlow::getLifetimeTokens(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> > > > >)::$_4>(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*, 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> > > > >)::$_4, int)::{lambda(ValueType const&)#1}::operator()(ValueType const&) const
Unexecuted instantiation: valueflow.cpp:getLifetimeTokens<ValueFlow::hasLifetimeToken(Token const*, Token const*)::$_5>(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*)::$_5, int)::{lambda(ValueType const&)#1}::operator()(ValueType const&) const
3585
0
        if (it != vts.end())
3586
0
            return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3587
0
    }
3588
17.8k
    return {{tok, std::move(errorPath)}};
3589
17.8k
}
valueflow.cpp:std::__1::vector<ValueFlow::LifetimeToken, std::__1::allocator<ValueFlow::LifetimeToken> > getLifetimeTokens<ValueFlow::getLifetimeTokens(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> > > > >)::$_4>(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*, 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> > > > >)::$_4, int)
Line
Count
Source
3453
17.8k
{
3454
17.8k
    if (!tok)
3455
0
        return std::vector<ValueFlow::LifetimeToken> {};
3456
17.8k
    if (Token::simpleMatch(tok, "..."))
3457
0
        return std::vector<ValueFlow::LifetimeToken>{};
3458
17.8k
    const Variable *var = tok->variable();
3459
17.8k
    if (pred(tok))
3460
0
        return {{tok, std::move(errorPath)}};
3461
17.8k
    if (depth < 0)
3462
0
        return {{tok, std::move(errorPath)}};
3463
17.8k
    if (var && var->declarationId() == tok->varId()) {
3464
17.8k
        if (var->isReference() || var->isRValueReference()) {
3465
0
            const Token * const varDeclEndToken = var->declEndToken();
3466
0
            if (!varDeclEndToken)
3467
0
                return {{tok, true, std::move(errorPath)}};
3468
0
            if (var->isArgument()) {
3469
0
                errorPath.emplace_back(varDeclEndToken, "Passed to reference.");
3470
0
                return {{tok, true, std::move(errorPath)}};
3471
0
            }
3472
0
            if (Token::simpleMatch(varDeclEndToken, "=")) {
3473
0
                errorPath.emplace_back(varDeclEndToken, "Assigned to reference.");
3474
0
                const Token *vartok = varDeclEndToken->astOperand2();
3475
0
                const bool temporary = isTemporary(true, vartok, nullptr, true);
3476
0
                const bool nonlocal = var->isStatic() || var->isGlobal();
3477
0
                if (vartok == tok || (nonlocal && temporary) ||
3478
0
                    (!escape && (var->isConst() || var->isRValueReference()) && temporary))
3479
0
                    return {{tok, true, std::move(errorPath)}};
3480
0
                if (vartok)
3481
0
                    return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3482
0
            } else if (Token::simpleMatch(var->nameToken()->astParent(), ":") &&
3483
0
                       var->nameToken()->astParent()->astParent() &&
3484
0
                       Token::simpleMatch(var->nameToken()->astParent()->astParent()->previous(), "for (")) {
3485
0
                errorPath.emplace_back(var->nameToken(), "Assigned to reference.");
3486
0
                const Token* vartok = var->nameToken();
3487
0
                if (vartok == tok)
3488
0
                    return {{tok, true, std::move(errorPath)}};
3489
0
                const Token* contok = var->nameToken()->astParent()->astOperand2();
3490
0
                if (astIsContainer(contok))
3491
0
                    return getLifetimeTokens(contok, escape, std::move(errorPath), pred, depth - 1);
3492
0
                return std::vector<ValueFlow::LifetimeToken>{};
3493
0
            } else {
3494
0
                return std::vector<ValueFlow::LifetimeToken> {};
3495
0
            }
3496
0
        }
3497
17.8k
    } else if (Token::Match(tok->previous(), "%name% (")) {
3498
0
        const Function *f = tok->previous()->function();
3499
0
        if (f) {
3500
0
            if (!Function::returnsReference(f))
3501
0
                return {{tok, std::move(errorPath)}};
3502
0
            std::vector<ValueFlow::LifetimeToken> result;
3503
0
            std::vector<const Token*> returns = Function::findReturns(f);
3504
0
            for (const Token* returnTok : returns) {
3505
0
                if (returnTok == tok)
3506
0
                    continue;
3507
0
                for (ValueFlow::LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, depth - returns.size())) {
3508
0
                    const Token* argvarTok = lt.token;
3509
0
                    const Variable* argvar = argvarTok->variable();
3510
0
                    if (!argvar)
3511
0
                        continue;
3512
0
                    const Token* argTok = nullptr;
3513
0
                    if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
3514
0
                        const int n = getArgumentPos(argvar, f);
3515
0
                        if (n < 0)
3516
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3517
0
                        std::vector<const Token*> args = getArguments(tok->previous());
3518
                        // TODO: Track lifetimes of default parameters
3519
0
                        if (n >= args.size())
3520
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3521
0
                        argTok = args[n];
3522
0
                        lt.errorPath.emplace_back(returnTok, "Return reference.");
3523
0
                        lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
3524
0
                    } else if (Token::Match(tok->tokAt(-2), ". %name% (") && !derefShared(tok->tokAt(-2)) &&
3525
0
                               exprDependsOnThis(argvarTok)) {
3526
0
                        argTok = tok->tokAt(-2)->astOperand1();
3527
0
                        lt.errorPath.emplace_back(returnTok, "Return reference that depends on 'this'.");
3528
0
                        lt.errorPath.emplace_back(tok->previous(),
3529
0
                                                  "Calling member function on '" + argTok->expressionString() + "'.");
3530
0
                    }
3531
0
                    if (argTok) {
3532
0
                        std::vector<ValueFlow::LifetimeToken> arglts = ValueFlow::LifetimeToken::setInconclusive(
3533
0
                            getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, depth - returns.size()),
3534
0
                            returns.size() > 1);
3535
0
                        result.insert(result.end(), arglts.cbegin(), arglts.cend());
3536
0
                    }
3537
0
                }
3538
0
            }
3539
0
            return result;
3540
0
        }
3541
0
        if (Token::Match(tok->tokAt(-2), ". %name% (") && tok->tokAt(-2)->originalName() != "->" && astIsContainer(tok->tokAt(-2)->astOperand1())) {
3542
0
            const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1());
3543
0
            const Library::Container::Yield y = library->getYield(tok->previous()->str());
3544
0
            if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {
3545
0
                errorPath.emplace_back(tok->previous(), "Accessing container.");
3546
0
                return ValueFlow::LifetimeToken::setAddressOf(
3547
0
                    getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, depth - 1),
3548
0
                    false);
3549
0
            }
3550
0
        }
3551
0
    } else if (Token::Match(tok, ".|::|[") || tok->isUnaryOp("*")) {
3552
3553
0
        const Token *vartok = tok;
3554
0
        while (vartok) {
3555
0
            if (vartok->str() == "[" || vartok->originalName() == "->" || vartok->isUnaryOp("*"))
3556
0
                vartok = vartok->astOperand1();
3557
0
            else if (vartok->str() == "." || vartok->str() == "::")
3558
0
                vartok = vartok->astOperand2();
3559
0
            else
3560
0
                break;
3561
0
        }
3562
3563
0
        if (!vartok)
3564
0
            return {{tok, std::move(errorPath)}};
3565
0
        if (derefShared(vartok->astParent())) {
3566
0
            for (const ValueFlow::Value &v : vartok->values()) {
3567
0
                if (!v.isLocalLifetimeValue())
3568
0
                    continue;
3569
0
                if (v.tokvalue == tok)
3570
0
                    continue;
3571
0
                errorPath.insert(errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
3572
0
                return getLifetimeTokens(v.tokvalue, escape, std::move(errorPath), pred, depth - 1);
3573
0
            }
3574
0
        } else {
3575
0
            return ValueFlow::LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1),
3576
0
                                                          !(astIsContainer(vartok) && Token::simpleMatch(vartok->astParent(), "[")));
3577
0
        }
3578
0
    } else if (Token::simpleMatch(tok, "{") && getArgumentStart(tok) &&
3579
0
               !Token::simpleMatch(getArgumentStart(tok), ",") && getArgumentStart(tok)->valueType()) {
3580
0
        const Token* vartok = getArgumentStart(tok);
3581
0
        auto vts = getParentValueTypes(tok);
3582
0
        auto it = std::find_if(vts.cbegin(), vts.cend(), [&](const ValueType& vt) {
3583
0
            return vt.isTypeEqual(vartok->valueType());
3584
0
        });
3585
0
        if (it != vts.end())
3586
0
            return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3587
0
    }
3588
17.8k
    return {{tok, std::move(errorPath)}};
3589
17.8k
}
Unexecuted instantiation: valueflow.cpp:std::__1::vector<ValueFlow::LifetimeToken, std::__1::allocator<ValueFlow::LifetimeToken> > getLifetimeTokens<ValueFlow::hasLifetimeToken(Token const*, Token const*)::$_5>(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*)::$_5, int)
3590
3591
std::vector<ValueFlow::LifetimeToken> ValueFlow::getLifetimeTokens(const Token* tok, bool escape, ValueFlow::Value::ErrorPath errorPath)
3592
17.8k
{
3593
17.8k
    return getLifetimeTokens(tok, escape, std::move(errorPath), [](const Token*) {
3594
17.8k
        return false;
3595
17.8k
    });
3596
17.8k
}
3597
3598
bool ValueFlow::hasLifetimeToken(const Token* tok, const Token* lifetime)
3599
0
{
3600
0
    bool result = false;
3601
0
    getLifetimeTokens(tok, false, ValueFlow::Value::ErrorPath{}, [&](const Token* tok2) {
3602
0
        result = tok2->exprId() == lifetime->exprId();
3603
0
        return result;
3604
0
    });
3605
0
    return result;
3606
0
}
3607
3608
static const Token* getLifetimeToken(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf = nullptr)
3609
17.8k
{
3610
17.8k
    std::vector<ValueFlow::LifetimeToken> lts = ValueFlow::getLifetimeTokens(tok);
3611
17.8k
    if (lts.size() != 1)
3612
0
        return nullptr;
3613
17.8k
    if (lts.front().inconclusive)
3614
0
        return nullptr;
3615
17.8k
    if (addressOf)
3616
0
        *addressOf = lts.front().addressOf;
3617
17.8k
    errorPath.insert(errorPath.end(), lts.front().errorPath.cbegin(), lts.front().errorPath.cend());
3618
17.8k
    return lts.front().token;
3619
17.8k
}
3620
3621
const Variable* ValueFlow::getLifetimeVariable(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf)
3622
17.8k
{
3623
17.8k
    const Token* tok2 = getLifetimeToken(tok, errorPath, addressOf);
3624
17.8k
    if (tok2 && tok2->variable())
3625
17.8k
        return tok2->variable();
3626
0
    return nullptr;
3627
17.8k
}
3628
3629
const Variable* ValueFlow::getLifetimeVariable(const Token* tok)
3630
0
{
3631
0
    ValueFlow::Value::ErrorPath errorPath;
3632
0
    return getLifetimeVariable(tok, errorPath, nullptr);
3633
0
}
3634
3635
static bool isNotLifetimeValue(const ValueFlow::Value& val)
3636
0
{
3637
0
    return !val.isLifetimeValue();
3638
0
}
3639
3640
static bool isLifetimeOwned(const ValueType* vtParent)
3641
0
{
3642
0
    if (vtParent->container)
3643
0
        return !vtParent->container->view;
3644
0
    return vtParent->type == ValueType::CONTAINER;
3645
0
}
3646
3647
static bool isLifetimeOwned(const ValueType *vt, const ValueType *vtParent)
3648
0
{
3649
0
    if (!vtParent)
3650
0
        return false;
3651
0
    if (isLifetimeOwned(vtParent))
3652
0
        return true;
3653
0
    if (!vt)
3654
0
        return false;
3655
    // If converted from iterator to pointer then the iterator is most likely a pointer
3656
0
    if (vtParent->pointer == 1 && vt->pointer == 0 && vt->type == ValueType::ITERATOR)
3657
0
        return false;
3658
0
    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE) {
3659
0
        if (vt->pointer != vtParent->pointer)
3660
0
            return true;
3661
0
        if (vt->type != vtParent->type) {
3662
0
            if (vtParent->type == ValueType::RECORD)
3663
0
                return true;
3664
0
            if (isLifetimeOwned(vtParent))
3665
0
                return true;
3666
0
        }
3667
0
    }
3668
3669
0
    return false;
3670
0
}
3671
3672
static bool isLifetimeBorrowed(const ValueType *vt, const ValueType *vtParent)
3673
0
{
3674
0
    if (!vtParent)
3675
0
        return false;
3676
0
    if (!vt)
3677
0
        return false;
3678
0
    if (vt->pointer > 0 && vt->pointer == vtParent->pointer)
3679
0
        return true;
3680
0
    if (vtParent->container && vtParent->container->view)
3681
0
        return true;
3682
0
    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE && vtParent->container == vt->container) {
3683
0
        if (vtParent->pointer > vt->pointer)
3684
0
            return true;
3685
0
        if (vtParent->pointer < vt->pointer && vtParent->isIntegral())
3686
0
            return true;
3687
0
        if (vtParent->str() == vt->str())
3688
0
            return true;
3689
0
    }
3690
3691
0
    return false;
3692
0
}
3693
3694
static const Token* skipCVRefs(const Token* tok, const Token* endTok)
3695
0
{
3696
0
    while (tok != endTok && Token::Match(tok, "const|volatile|auto|&|&&"))
3697
0
        tok = tok->next();
3698
0
    return tok;
3699
0
}
3700
3701
static bool isNotEqual(std::pair<const Token*, const Token*> x, std::pair<const Token*, const Token*> y)
3702
482
{
3703
482
    const Token* start1 = x.first;
3704
482
    const Token* start2 = y.first;
3705
482
    if (start1 == nullptr || start2 == nullptr)
3706
482
        return false;
3707
0
    while (start1 != x.second && start2 != y.second) {
3708
0
        const Token* tok1 = skipCVRefs(start1, x.second);
3709
0
        if (tok1 != start1) {
3710
0
            start1 = tok1;
3711
0
            continue;
3712
0
        }
3713
0
        const Token* tok2 = skipCVRefs(start2, y.second);
3714
0
        if (tok2 != start2) {
3715
0
            start2 = tok2;
3716
0
            continue;
3717
0
        }
3718
0
        if (start1->str() != start2->str())
3719
0
            return true;
3720
0
        start1 = start1->next();
3721
0
        start2 = start2->next();
3722
0
    }
3723
0
    start1 = skipCVRefs(start1, x.second);
3724
0
    start2 = skipCVRefs(start2, y.second);
3725
0
    return !(start1 == x.second && start2 == y.second);
3726
0
}
3727
static bool isNotEqual(std::pair<const Token*, const Token*> x, const std::string& y)
3728
0
{
3729
0
    TokenList tokenList(nullptr);
3730
0
    std::istringstream istr(y);
3731
0
    tokenList.createTokens(istr);
3732
0
    return isNotEqual(x, std::make_pair(tokenList.front(), tokenList.back()));
3733
0
}
3734
static bool isNotEqual(std::pair<const Token*, const Token*> x, const ValueType* y)
3735
964
{
3736
964
    if (y == nullptr)
3737
529
        return false;
3738
435
    if (y->originalTypeName.empty())
3739
435
        return false;
3740
0
    return isNotEqual(x, y->originalTypeName);
3741
435
}
3742
3743
static bool isDifferentType(const Token* src, const Token* dst)
3744
482
{
3745
482
    const Type* t = Token::typeOf(src);
3746
482
    const Type* parentT = Token::typeOf(dst);
3747
482
    if (t && parentT) {
3748
0
        if (t->classDef && parentT->classDef && t->classDef != parentT->classDef)
3749
0
            return true;
3750
482
    } else {
3751
482
        std::pair<const Token*, const Token*> decl = Token::typeDecl(src);
3752
482
        std::pair<const Token*, const Token*> parentdecl = Token::typeDecl(dst);
3753
482
        if (isNotEqual(decl, parentdecl))
3754
0
            return true;
3755
482
        if (isNotEqual(decl, dst->valueType()))
3756
0
            return true;
3757
482
        if (isNotEqual(parentdecl, src->valueType()))
3758
0
            return true;
3759
482
    }
3760
482
    return false;
3761
482
}
3762
3763
bool ValueFlow::isLifetimeBorrowed(const Token *tok, const Settings *settings)
3764
0
{
3765
0
    if (!tok)
3766
0
        return true;
3767
0
    if (tok->str() == ",")
3768
0
        return true;
3769
0
    if (!tok->astParent())
3770
0
        return true;
3771
0
    const Token* parent = nullptr;
3772
0
    const ValueType* vt = tok->valueType();
3773
0
    std::vector<ValueType> vtParents = getParentValueTypes(tok, settings, &parent);
3774
0
    for (const ValueType& vtParent : vtParents) {
3775
0
        if (isLifetimeBorrowed(vt, &vtParent))
3776
0
            return true;
3777
0
        if (isLifetimeOwned(vt, &vtParent))
3778
0
            return false;
3779
0
    }
3780
0
    if (parent) {
3781
0
        if (isDifferentType(tok, parent))
3782
0
            return false;
3783
0
    }
3784
0
    return true;
3785
0
}
3786
3787
static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings *settings);
3788
3789
static void valueFlowLifetimeConstructor(Token *tok,
3790
                                         TokenList &tokenlist,
3791
                                         ErrorLogger *errorLogger,
3792
                                         const Settings *settings);
3793
3794
static bool isRangeForScope(const Scope* scope)
3795
0
{
3796
0
    if (!scope)
3797
0
        return false;
3798
0
    if (scope->type != Scope::eFor)
3799
0
        return false;
3800
0
    if (!scope->bodyStart)
3801
0
        return false;
3802
0
    if (!Token::simpleMatch(scope->bodyStart->previous(), ") {"))
3803
0
        return false;
3804
0
    return Token::simpleMatch(scope->bodyStart->linkAt(-1)->astOperand2(), ":");
3805
0
}
3806
3807
static const Token* getEndOfVarScope(const Variable* var)
3808
0
{
3809
0
    if (!var)
3810
0
        return nullptr;
3811
0
    const Scope* innerScope = var->scope();
3812
0
    const Scope* outerScope = innerScope;
3813
0
    if (var->typeStartToken() && var->typeStartToken()->scope())
3814
0
        outerScope = var->typeStartToken()->scope();
3815
0
    if (!innerScope && outerScope)
3816
0
        innerScope = outerScope;
3817
0
    if (!innerScope || !outerScope)
3818
0
        return nullptr;
3819
0
    if (!innerScope->isExecutable())
3820
0
        return nullptr;
3821
    // If the variable is defined in a for/while initializer then we want to
3822
    // pick one token after the end so forward analysis can analyze the exit
3823
    // conditions
3824
0
    if (innerScope != outerScope && outerScope->isExecutable() && innerScope->isLoopScope() &&
3825
0
        !isRangeForScope(innerScope))
3826
0
        return innerScope->bodyEnd->next();
3827
0
    return innerScope->bodyEnd;
3828
0
}
3829
3830
const Token* ValueFlow::getEndOfExprScope(const Token* tok, const Scope* defaultScope, bool smallest)
3831
2.94k
{
3832
2.94k
    const Token* end = nullptr;
3833
2.94k
    bool local = false;
3834
3.07k
    visitAstNodes(tok, [&](const Token* child) {
3835
3.07k
        if (const Variable* var = child->variable()) {
3836
2.46k
            local |= var->isLocal();
3837
2.46k
            if (var->isLocal() || var->isArgument()) {
3838
0
                const Token* varEnd = getEndOfVarScope(var);
3839
0
                if (!end || (smallest ? precedes(varEnd, end) : succeeds(varEnd, end)))
3840
0
                    end = varEnd;
3841
3842
0
                const Token* top = var->nameToken()->astTop();
3843
0
                if (top && Token::simpleMatch(top->tokAt(-1), "if (")) { // variable declared in if (...)
3844
0
                    const Token* elseTok = top->link()->linkAt(1);
3845
0
                    if (Token::simpleMatch(elseTok, "} else {") && tok->scope()->isNestedIn(elseTok->tokAt(2)->scope()))
3846
0
                        end = tok->scope()->bodyEnd;
3847
0
                }
3848
0
            }
3849
2.46k
        }
3850
3.07k
        return ChildrenToVisit::op1_and_op2;
3851
3.07k
    });
3852
2.94k
    if (!end && defaultScope)
3853
2.19k
        end = defaultScope->bodyEnd;
3854
2.94k
    if (!end) {
3855
749
        const Scope* scope = tok->scope();
3856
749
        if (scope)
3857
749
            end = scope->bodyEnd;
3858
        // If there is no local variables then pick the function scope
3859
749
        if (!local) {
3860
1.25k
            while (scope && scope->isLocal())
3861
509
                scope = scope->nestedIn;
3862
749
            if (scope && scope->isExecutable())
3863
749
                end = scope->bodyEnd;
3864
749
        }
3865
749
    }
3866
2.94k
    return end;
3867
2.94k
}
3868
3869
static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings *settings)
3870
206
{
3871
    // Forward lifetimes to constructed variable
3872
206
    if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) {
3873
0
        std::list<ValueFlow::Value> values = tok->values();
3874
0
        values.remove_if(&isNotLifetimeValue);
3875
0
        valueFlowForward(nextAfterAstRightmostLeaf(tok), ValueFlow::getEndOfExprScope(tok), tok->previous(), values, tokenlist, settings);
3876
0
        return;
3877
0
    }
3878
206
    Token *parent = tok->astParent();
3879
206
    while (parent && parent->str() == ",")
3880
0
        parent = parent->astParent();
3881
206
    if (!parent)
3882
206
        return;
3883
    // Assignment
3884
0
    if (parent->str() == "=" && (!parent->astParent() || Token::simpleMatch(parent->astParent(), ";"))) {
3885
        // Rhs values..
3886
0
        if (!parent->astOperand2() || parent->astOperand2()->values().empty())
3887
0
            return;
3888
3889
0
        if (!ValueFlow::isLifetimeBorrowed(parent->astOperand2(), settings))
3890
0
            return;
3891
3892
0
        const Token* expr = getLHSVariableToken(parent);
3893
0
        if (!expr)
3894
0
            return;
3895
3896
0
        if (expr->exprId() == 0)
3897
0
            return;
3898
3899
0
        const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
3900
3901
        // Only forward lifetime values
3902
0
        std::list<ValueFlow::Value> values = parent->astOperand2()->values();
3903
0
        values.remove_if(&isNotLifetimeValue);
3904
        // Dont forward lifetimes that overlap
3905
0
        values.remove_if([&](const ValueFlow::Value& value) {
3906
0
            return findAstNode(value.tokvalue, [&](const Token* child) {
3907
0
                return child->exprId() == expr->exprId();
3908
0
            });
3909
0
        });
3910
3911
        // Skip RHS
3912
0
        const Token *nextExpression = nextAfterAstRightmostLeaf(parent);
3913
3914
0
        if (expr->exprId() > 0) {
3915
0
            valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope->next(), expr, values, tokenlist, settings);
3916
3917
0
            for (ValueFlow::Value& val : values) {
3918
0
                if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address)
3919
0
                    val.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject;
3920
0
            }
3921
            // TODO: handle `[`
3922
0
            if (Token::simpleMatch(parent->astOperand1(), ".")) {
3923
0
                const Token* parentLifetime =
3924
0
                    getParentLifetime(tokenlist.isCPP(), parent->astOperand1()->astOperand2(), &settings->library);
3925
0
                if (parentLifetime && parentLifetime->exprId() > 0) {
3926
0
                    valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, parentLifetime, values, tokenlist, settings);
3927
0
                }
3928
0
            }
3929
0
        }
3930
        // Constructor
3931
0
    } else if (Token::simpleMatch(parent, "{") && !isScopeBracket(parent)) {
3932
0
        valueFlowLifetimeConstructor(parent, tokenlist, errorLogger, settings);
3933
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
3934
        // Function call
3935
0
    } else if (Token::Match(parent->previous(), "%name% (")) {
3936
0
        valueFlowLifetimeFunction(parent->previous(), tokenlist, errorLogger, settings);
3937
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
3938
        // Variable
3939
0
    } else if (tok->variable() && tok->variable()->scope()) {
3940
0
        const Variable *var = tok->variable();
3941
0
        const Token *endOfVarScope = var->scope()->bodyEnd;
3942
3943
0
        std::list<ValueFlow::Value> values = tok->values();
3944
0
        const Token *nextExpression = nextAfterAstRightmostLeaf(parent);
3945
        // Only forward lifetime values
3946
0
        values.remove_if(&isNotLifetimeValue);
3947
0
        valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, tok, values, tokenlist, settings);
3948
        // Cast
3949
0
    } else if (parent->isCast()) {
3950
0
        std::list<ValueFlow::Value> values = tok->values();
3951
        // Only forward lifetime values
3952
0
        values.remove_if(&isNotLifetimeValue);
3953
0
        for (ValueFlow::Value& value:values)
3954
0
            setTokenValue(parent, std::move(value), settings);
3955
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
3956
0
    }
3957
0
}
3958
3959
struct LifetimeStore {
3960
    const Token* argtok{};
3961
    std::string message;
3962
    ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object;
3963
    ErrorPath errorPath;
3964
    bool inconclusive{};
3965
    bool forward = true;
3966
3967
    struct Context {
3968
        Token* tok{};
3969
        TokenList* tokenlist{};
3970
        ErrorLogger* errorLogger{};
3971
        const Settings* settings{};
3972
    };
3973
3974
0
    LifetimeStore() = default;
3975
3976
    LifetimeStore(const Token* argtok,
3977
                  std::string message,
3978
                  ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object,
3979
                  bool inconclusive = false)
3980
        : argtok(argtok),
3981
        message(std::move(message)),
3982
        type(type),
3983
        inconclusive(inconclusive)
3984
0
    {}
3985
3986
    template<class F>
3987
    static void forEach(const std::vector<const Token*>& argtoks,
3988
                        const std::string& message,
3989
                        ValueFlow::Value::LifetimeKind type,
3990
0
                        F f) {
3991
0
        std::map<const Token*, Context> forwardToks;
3992
0
        for (const Token* arg : argtoks) {
3993
0
            LifetimeStore ls{arg, message, type};
3994
0
            Context c{};
3995
0
            ls.mContext = &c;
3996
0
            ls.forward = false;
3997
0
            f(ls);
3998
0
            if (c.tok)
3999
0
                forwardToks[c.tok] = c;
4000
0
        }
4001
0
        for (const auto& p : forwardToks) {
4002
0
            const Context& c = p.second;
4003
0
            valueFlowForwardLifetime(c.tok, *c.tokenlist, c.errorLogger, c.settings);
4004
0
        }
4005
0
    }
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeConstructor(Token*, TokenList&, ErrorLogger*, Settings const*)::$_62>(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&, ErrorLogger*, Settings const*)::$_62)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeConstructor(Token*, TokenList&, ErrorLogger*, Settings const*)::$_63>(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&, ErrorLogger*, Settings const*)::$_63)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeConstructor(Token*, TokenList&, ErrorLogger*, Settings const*)::$_64>(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&, ErrorLogger*, Settings const*)::$_64)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeClassConstructor(Token*, Type const*, TokenList&, ErrorLogger*, Settings const*)::$_60>(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&, ErrorLogger*, Settings const*)::$_60)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeClassConstructor(Token*, Type const*, TokenList&, ErrorLogger*, Settings const*)::$_61>(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&, ErrorLogger*, Settings const*)::$_61)
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*> >, TokenList&, ErrorLogger*, Settings const*)::$_58>(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*> >, TokenList&, ErrorLogger*, Settings const*)::$_58)
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*> >, TokenList&, ErrorLogger*, Settings const*)::$_59>(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*> >, TokenList&, ErrorLogger*, Settings const*)::$_59)
4006
4007
0
    static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, TokenList &tokenlist, const Settings* settings, ErrorLogger *errorLogger) {
4008
0
        if (!var)
4009
0
            return LifetimeStore{};
4010
0
        if (!var->isArgument())
4011
0
            return LifetimeStore{};
4012
0
        const int n = getArgumentPos(var, f);
4013
0
        if (n < 0)
4014
0
            return LifetimeStore{};
4015
0
        std::vector<const Token *> args = getArguments(tok);
4016
0
        if (n >= args.size()) {
4017
0
            if (settings->debugwarnings)
4018
0
                bailout(tokenlist,
4019
0
                        errorLogger,
4020
0
                        tok,
4021
0
                        "Argument mismatch: Function '" + tok->str() + "' returning lifetime from argument index " +
4022
0
                        std::to_string(n) + " but only " + std::to_string(args.size()) +
4023
0
                        " arguments are available.");
4024
0
            return LifetimeStore{};
4025
0
        }
4026
0
        const Token *argtok2 = args[n];
4027
0
        return LifetimeStore{argtok2, "Passed to '" + tok->expressionString() + "'.", ValueFlow::Value::LifetimeKind::Object};
4028
0
    }
4029
4030
    template<class Predicate>
4031
    bool byRef(Token* tok,
4032
               TokenList& tokenlist,
4033
               ErrorLogger* errorLogger,
4034
               const Settings* settings,
4035
               Predicate pred,
4036
               SourceLocation loc = SourceLocation::current()) const
4037
0
    {
4038
0
        if (!argtok)
4039
0
            return false;
4040
0
        bool update = false;
4041
0
        for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok)) {
4042
0
            if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4043
0
                continue;
4044
0
            ErrorPath er = errorPath;
4045
0
            er.insert(er.end(), lt.errorPath.cbegin(), lt.errorPath.cend());
4046
0
            if (!lt.token)
4047
0
                return false;
4048
0
            if (!pred(lt.token))
4049
0
                return false;
4050
0
            er.emplace_back(argtok, message);
4051
4052
0
            ValueFlow::Value value;
4053
0
            value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4054
0
            value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4055
0
            value.tokvalue = lt.token;
4056
0
            value.errorPath = std::move(er);
4057
0
            value.lifetimeKind = type;
4058
0
            value.setInconclusive(lt.inconclusive || inconclusive);
4059
            // Don't add the value a second time
4060
0
            if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4061
0
                return false;
4062
0
            if (settings->debugnormal)
4063
0
                setSourceLocation(value, loc, tok);
4064
0
            setTokenValue(tok, std::move(value), settings);
4065
0
            update = true;
4066
0
        }
4067
0
        if (update && forward)
4068
0
            forwardLifetime(tok, tokenlist, errorLogger, settings);
4069
0
        return update;
4070
0
    }
Unexecuted instantiation: bool LifetimeStore::byRef<std::__1::function<bool (Token const*)> >(Token*, TokenList&, ErrorLogger*, Settings const*, std::__1::function<bool (Token const*)>, SourceLocation) const
Unexecuted instantiation: bool LifetimeStore::byRef<LifetimeStore::byRef(Token*, TokenList&, ErrorLogger*, Settings const*, SourceLocation) const::{lambda(Token const*)#1}>(Token*, TokenList&, ErrorLogger*, Settings const*, LifetimeStore::byRef(Token*, TokenList&, ErrorLogger*, Settings const*, SourceLocation) const::{lambda(Token const*)#1}, SourceLocation) const
4071
4072
    bool byRef(Token* tok,
4073
               TokenList& tokenlist,
4074
               ErrorLogger* errorLogger,
4075
               const Settings* settings,
4076
               SourceLocation loc = SourceLocation::current()) const
4077
0
    {
4078
0
        return byRef(
4079
0
            tok,
4080
0
            tokenlist,
4081
0
            errorLogger,
4082
0
            settings,
4083
0
            [](const Token*) {
4084
0
            return true;
4085
0
        },
4086
0
            loc);
4087
0
    }
4088
4089
    template<class Predicate>
4090
    bool byVal(Token* tok,
4091
               TokenList& tokenlist,
4092
               ErrorLogger* errorLogger,
4093
               const Settings* settings,
4094
               Predicate pred,
4095
               SourceLocation loc = SourceLocation::current()) const
4096
0
    {
4097
0
        if (!argtok)
4098
0
            return false;
4099
0
        bool update = false;
4100
0
        if (argtok->values().empty()) {
4101
0
            ErrorPath er;
4102
0
            er.emplace_back(argtok, message);
4103
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok)) {
4104
0
                if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4105
0
                    continue;
4106
0
                ValueFlow::Value value;
4107
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4108
0
                value.tokvalue = lt.token;
4109
0
                value.capturetok = argtok;
4110
0
                value.errorPath = er;
4111
0
                value.lifetimeKind = type;
4112
0
                value.setInconclusive(inconclusive || lt.inconclusive);
4113
0
                const Variable* var = lt.token->variable();
4114
0
                if (var && var->isArgument()) {
4115
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::Argument;
4116
0
                } else {
4117
0
                    continue;
4118
0
                }
4119
                // Don't add the value a second time
4120
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4121
0
                    continue;
4122
0
                if (settings->debugnormal)
4123
0
                    setSourceLocation(value, loc, tok);
4124
0
                setTokenValue(tok, std::move(value), settings);
4125
0
                update = true;
4126
0
            }
4127
0
        }
4128
0
        for (const ValueFlow::Value &v : argtok->values()) {
4129
0
            if (!v.isLifetimeValue())
4130
0
                continue;
4131
0
            const Token *tok3 = v.tokvalue;
4132
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok3)) {
4133
0
                if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4134
0
                    continue;
4135
0
                ErrorPath er = v.errorPath;
4136
0
                er.insert(er.end(), lt.errorPath.cbegin(), lt.errorPath.cend());
4137
0
                if (!lt.token)
4138
0
                    return false;
4139
0
                if (!pred(lt.token))
4140
0
                    return false;
4141
0
                er.emplace_back(argtok, message);
4142
0
                er.insert(er.end(), errorPath.cbegin(), errorPath.cend());
4143
4144
0
                ValueFlow::Value value;
4145
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4146
0
                value.lifetimeScope = v.lifetimeScope;
4147
0
                value.path = v.path;
4148
0
                value.tokvalue = lt.token;
4149
0
                value.capturetok = argtok;
4150
0
                value.errorPath = std::move(er);
4151
0
                value.lifetimeKind = type;
4152
0
                value.setInconclusive(lt.inconclusive || v.isInconclusive() || inconclusive);
4153
                // Don't add the value a second time
4154
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4155
0
                    continue;
4156
0
                if (settings->debugnormal)
4157
0
                    setSourceLocation(value, loc, tok);
4158
0
                setTokenValue(tok, std::move(value), settings);
4159
0
                update = true;
4160
0
            }
4161
0
        }
4162
0
        if (update && forward)
4163
0
            forwardLifetime(tok, tokenlist, errorLogger, settings);
4164
0
        return update;
4165
0
    }
Unexecuted instantiation: bool LifetimeStore::byVal<std::__1::function<bool (Token const*)> >(Token*, TokenList&, ErrorLogger*, Settings const*, std::__1::function<bool (Token const*)>, SourceLocation) const
Unexecuted instantiation: bool LifetimeStore::byVal<LifetimeStore::byVal(Token*, TokenList&, ErrorLogger*, Settings const*, SourceLocation) const::{lambda(Token const*)#1}>(Token*, TokenList&, ErrorLogger*, Settings const*, LifetimeStore::byVal(Token*, TokenList&, ErrorLogger*, Settings const*, SourceLocation) const::{lambda(Token const*)#1}, SourceLocation) const
Unexecuted instantiation: bool LifetimeStore::byVal<LifetimeStore::byDerefCopy(Token*, TokenList&, ErrorLogger*, Settings const*, SourceLocation) const::{lambda(Token const*)#1}>(Token*, TokenList&, ErrorLogger*, Settings const*, LifetimeStore::byDerefCopy(Token*, TokenList&, ErrorLogger*, Settings const*, SourceLocation) const::{lambda(Token const*)#1}, SourceLocation) const
4166
4167
    bool byVal(Token* tok,
4168
               TokenList& tokenlist,
4169
               ErrorLogger* errorLogger,
4170
               const Settings* settings,
4171
               SourceLocation loc = SourceLocation::current()) const
4172
0
    {
4173
0
        return byVal(
4174
0
            tok,
4175
0
            tokenlist,
4176
0
            errorLogger,
4177
0
            settings,
4178
0
            [](const Token*) {
4179
0
            return true;
4180
0
        },
4181
0
            loc);
4182
0
    }
4183
4184
    template<class Predicate>
4185
    bool byDerefCopy(Token* tok,
4186
                     TokenList& tokenlist,
4187
                     ErrorLogger* errorLogger,
4188
                     const Settings* settings,
4189
                     Predicate pred,
4190
                     SourceLocation loc = SourceLocation::current()) const
4191
0
    {
4192
0
        bool update = false;
4193
0
        if (!settings->certainty.isEnabled(Certainty::inconclusive) && inconclusive)
4194
0
            return update;
4195
0
        if (!argtok)
4196
0
            return update;
4197
0
        if (!tok)
4198
0
            return update;
4199
0
        for (const ValueFlow::Value &v : argtok->values()) {
4200
0
            if (!v.isLifetimeValue())
4201
0
                continue;
4202
0
            const Token *tok2 = v.tokvalue;
4203
0
            ErrorPath er = v.errorPath;
4204
0
            const Variable *var = ValueFlow::getLifetimeVariable(tok2, er);
4205
            // TODO: the inserted data is never used
4206
0
            er.insert(er.end(), errorPath.cbegin(), errorPath.cend());
4207
0
            if (!var)
4208
0
                continue;
4209
0
            const Token * const varDeclEndToken = var->declEndToken();
4210
0
            for (const Token *tok3 = tok; tok3 && tok3 != varDeclEndToken; tok3 = tok3->previous()) {
4211
0
                if (tok3->varId() == var->declarationId()) {
4212
0
                    update |= LifetimeStore{tok3, message, type, inconclusive}
4213
0
                    .byVal(tok, tokenlist, errorLogger, settings, pred, loc);
4214
0
                    break;
4215
0
                }
4216
0
            }
4217
0
        }
4218
0
        return update;
4219
0
    }
4220
4221
    bool byDerefCopy(Token* tok,
4222
                     TokenList& tokenlist,
4223
                     ErrorLogger* errorLogger,
4224
                     const Settings* settings,
4225
                     SourceLocation loc = SourceLocation::current()) const
4226
0
    {
4227
0
        return byDerefCopy(
4228
0
            tok,
4229
0
            tokenlist,
4230
0
            errorLogger,
4231
0
            settings,
4232
0
            [](const Token*) {
4233
0
            return true;
4234
0
        },
4235
0
            loc);
4236
0
    }
4237
4238
private:
4239
    Context* mContext{};
4240
0
    void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings* settings) const {
4241
0
        if (mContext) {
4242
0
            mContext->tok = tok;
4243
0
            mContext->tokenlist = &tokenlist;
4244
0
            mContext->errorLogger = errorLogger;
4245
0
            mContext->settings = settings;
4246
0
        }
4247
0
        valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4248
0
    }
4249
};
4250
4251
static bool hasBorrowingVariables(const std::list<Variable>& vars, const std::vector<const Token*>& args, int depth = 10)
4252
0
{
4253
0
    if (depth < 0)
4254
0
        return true;
4255
0
    return std::any_of(vars.cbegin(), vars.cend(), [&](const Variable& var) {
4256
0
        if (const ValueType* vt = var.valueType()) {
4257
0
            if (vt->pointer > 0 &&
4258
0
                std::none_of(args.begin(), args.end(), [vt](const Token* arg) {
4259
0
                return arg->valueType() && arg->valueType()->type == vt->type;
4260
0
            }))
4261
0
                return false;
4262
0
            if (vt->pointer > 0)
4263
0
                return true;
4264
0
            if (vt->reference != Reference::None)
4265
0
                return true;
4266
0
            if (vt->isPrimitive())
4267
0
                return false;
4268
0
            if (vt->isEnum())
4269
0
                return false;
4270
            // TODO: Check container inner type
4271
0
            if (vt->type == ValueType::CONTAINER && vt->container)
4272
0
                return vt->container->view;
4273
0
            if (vt->typeScope)
4274
0
                return hasBorrowingVariables(vt->typeScope->varlist, args, depth - 1);
4275
0
        }
4276
0
        return true;
4277
0
    });
4278
0
}
4279
4280
static void valueFlowLifetimeUserConstructor(Token* tok,
4281
                                             const Function* constructor,
4282
                                             const std::string& name,
4283
                                             std::vector<const Token*> args,
4284
                                             TokenList& tokenlist,
4285
                                             ErrorLogger* errorLogger,
4286
                                             const Settings* settings)
4287
0
{
4288
0
    if (!constructor)
4289
0
        return;
4290
0
    std::unordered_map<const Token*, const Variable*> argToParam;
4291
0
    for (std::size_t i = 0; i < args.size(); i++)
4292
0
        argToParam[args[i]] = constructor->getArgumentVar(i);
4293
0
    if (const Token* initList = constructor->constructorMemberInitialization()) {
4294
0
        std::unordered_map<const Variable*, LifetimeCapture> paramCapture;
4295
0
        for (const Token* tok2 : astFlatten(initList->astOperand2(), ",")) {
4296
0
            if (!Token::simpleMatch(tok2, "("))
4297
0
                continue;
4298
0
            if (!tok2->astOperand1())
4299
0
                continue;
4300
0
            if (!tok2->astOperand2())
4301
0
                continue;
4302
0
            const Variable* var = tok2->astOperand1()->variable();
4303
0
            const Token* expr = tok2->astOperand2();
4304
0
            if (!var)
4305
0
                continue;
4306
0
            if (!ValueFlow::isLifetimeBorrowed(expr, settings))
4307
0
                continue;
4308
0
            const Variable* argvar = ValueFlow::getLifetimeVariable(expr);
4309
0
            if (var->isReference() || var->isRValueReference()) {
4310
0
                if (argvar && argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
4311
0
                    paramCapture[argvar] = LifetimeCapture::ByReference;
4312
0
                }
4313
0
            } else {
4314
0
                bool found = false;
4315
0
                for (const ValueFlow::Value& v : expr->values()) {
4316
0
                    if (!v.isLifetimeValue())
4317
0
                        continue;
4318
0
                    if (v.path > 0)
4319
0
                        continue;
4320
0
                    if (!v.tokvalue)
4321
0
                        continue;
4322
0
                    const Variable* lifeVar = v.tokvalue->variable();
4323
0
                    if (!lifeVar)
4324
0
                        continue;
4325
0
                    LifetimeCapture c = LifetimeCapture::Undefined;
4326
0
                    if (!v.isArgumentLifetimeValue() && (lifeVar->isReference() || lifeVar->isRValueReference()))
4327
0
                        c = LifetimeCapture::ByReference;
4328
0
                    else if (v.isArgumentLifetimeValue())
4329
0
                        c = LifetimeCapture::ByValue;
4330
0
                    if (c != LifetimeCapture::Undefined) {
4331
0
                        paramCapture[lifeVar] = c;
4332
0
                        found = true;
4333
0
                    }
4334
0
                }
4335
0
                if (!found && argvar && argvar->isArgument())
4336
0
                    paramCapture[argvar] = LifetimeCapture::ByValue;
4337
0
            }
4338
0
        }
4339
        // TODO: Use SubExpressionAnalyzer for members
4340
0
        LifetimeStore::forEach(args,
4341
0
                               "Passed to constructor of '" + name + "'.",
4342
0
                               ValueFlow::Value::LifetimeKind::SubObject,
4343
0
                               [&](const LifetimeStore& ls) {
4344
0
            const Variable* paramVar = argToParam.at(ls.argtok);
4345
0
            if (paramCapture.count(paramVar) == 0)
4346
0
                return;
4347
0
            const LifetimeCapture c = paramCapture.at(paramVar);
4348
0
            if (c == LifetimeCapture::ByReference)
4349
0
                ls.byRef(tok, tokenlist, errorLogger, settings);
4350
0
            else
4351
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
4352
0
        });
4353
0
    } else if (hasBorrowingVariables(constructor->nestedIn->varlist, args)) {
4354
0
        LifetimeStore::forEach(args,
4355
0
                               "Passed to constructor of '" + name + "'.",
4356
0
                               ValueFlow::Value::LifetimeKind::SubObject,
4357
0
                               [&](LifetimeStore& ls) {
4358
0
            ls.inconclusive = true;
4359
0
            const Variable* var = argToParam.at(ls.argtok);
4360
0
            if (var && !var->isConst() && var->isReference())
4361
0
                ls.byRef(tok, tokenlist, errorLogger, settings);
4362
0
            else
4363
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
4364
0
        });
4365
0
    }
4366
0
}
4367
4368
static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings *settings)
4369
206
{
4370
206
    if (!Token::Match(tok, "%name% ("))
4371
0
        return;
4372
206
    Token* memtok = nullptr;
4373
206
    if (Token::Match(tok->astParent(), ". %name% (") && astIsRHS(tok))
4374
0
        memtok = tok->astParent()->astOperand1();
4375
206
    const int returnContainer = settings->library.returnValueContainer(tok);
4376
206
    if (returnContainer >= 0) {
4377
0
        std::vector<const Token *> args = getArguments(tok);
4378
0
        for (int argnr = 1; argnr <= args.size(); ++argnr) {
4379
0
            const Library::ArgumentChecks::IteratorInfo *i = settings->library.getArgIteratorInfo(tok, argnr);
4380
0
            if (!i)
4381
0
                continue;
4382
0
            if (i->container != returnContainer)
4383
0
                continue;
4384
0
            const Token * const argTok = args[argnr - 1];
4385
0
            bool forward = false;
4386
0
            for (ValueFlow::Value val : argTok->values()) {
4387
0
                if (!val.isLifetimeValue())
4388
0
                    continue;
4389
0
                val.errorPath.emplace_back(argTok, "Passed to '" + tok->str() + "'.");
4390
0
                setTokenValue(tok->next(), std::move(val), settings);
4391
0
                forward = true;
4392
0
            }
4393
            // Check if lifetime is available to avoid adding the lifetime twice
4394
0
            if (forward) {
4395
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4396
0
                break;
4397
0
            }
4398
0
        }
4399
206
    } else if (Token::Match(tok->tokAt(-2), "std :: ref|cref|tie|front_inserter|back_inserter")) {
4400
0
        for (const Token *argtok : getArguments(tok)) {
4401
0
            LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byRef(
4402
0
                tok->next(), tokenlist, errorLogger, settings);
4403
0
        }
4404
206
    } else if (Token::Match(tok->tokAt(-2), "std :: make_tuple|tuple_cat|make_pair|make_reverse_iterator|next|prev|move|bind")) {
4405
0
        for (const Token *argtok : getArguments(tok)) {
4406
0
            LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byVal(
4407
0
                tok->next(), tokenlist, errorLogger, settings);
4408
0
        }
4409
206
    } else if (memtok && Token::Match(tok->astParent(), ". push_back|push_front|insert|push|assign") &&
4410
206
               astIsContainer(memtok)) {
4411
0
        std::vector<const Token *> args = getArguments(tok);
4412
0
        const std::size_t n = args.size();
4413
0
        if (n > 1 && Token::typeStr(args[n - 2]) == Token::typeStr(args[n - 1]) &&
4414
0
            (((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) ||
4415
0
              (astIsPointer(args[n - 2]) && astIsPointer(args[n - 1]))))) {
4416
0
            LifetimeStore{
4417
0
                args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
4418
0
            .byDerefCopy(memtok, tokenlist, errorLogger, settings);
4419
0
        } else if (!args.empty() && ValueFlow::isLifetimeBorrowed(args.back(), settings)) {
4420
0
            LifetimeStore{
4421
0
                args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
4422
0
            .byVal(memtok, tokenlist, errorLogger, settings);
4423
0
        }
4424
206
    } else if (tok->function()) {
4425
0
        const Function *f = tok->function();
4426
0
        if (f->isConstructor()) {
4427
0
            valueFlowLifetimeUserConstructor(tok->next(), f, tok->str(), getArguments(tok), tokenlist, errorLogger, settings);
4428
0
            return;
4429
0
        }
4430
0
        if (Function::returnsReference(f))
4431
0
            return;
4432
0
        std::vector<const Token*> returns = Function::findReturns(f);
4433
0
        const bool inconclusive = returns.size() > 1;
4434
0
        bool update = false;
4435
0
        for (const Token* returnTok : returns) {
4436
0
            if (returnTok == tok)
4437
0
                continue;
4438
0
            const Variable *returnVar = ValueFlow::getLifetimeVariable(returnTok);
4439
0
            if (returnVar && returnVar->isArgument() && (returnVar->isConst() || !isVariableChanged(returnVar, settings, tokenlist.isCPP()))) {
4440
0
                LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, tokenlist, settings, errorLogger);
4441
0
                ls.inconclusive = inconclusive;
4442
0
                ls.forward = false;
4443
0
                update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
4444
0
            }
4445
0
            for (const ValueFlow::Value &v : returnTok->values()) {
4446
0
                if (!v.isLifetimeValue())
4447
0
                    continue;
4448
0
                if (!v.tokvalue)
4449
0
                    continue;
4450
0
                if (memtok &&
4451
0
                    (contains({ValueFlow::Value::LifetimeScope::ThisPointer, ValueFlow::Value::LifetimeScope::ThisValue},
4452
0
                              v.lifetimeScope) ||
4453
0
                     exprDependsOnThis(v.tokvalue))) {
4454
0
                    LifetimeStore ls = LifetimeStore{memtok,
4455
0
                                                     "Passed to member function '" + tok->expressionString() + "'.",
4456
0
                                                     ValueFlow::Value::LifetimeKind::Object};
4457
0
                    ls.inconclusive = inconclusive;
4458
0
                    ls.forward = false;
4459
0
                    ls.errorPath = v.errorPath;
4460
0
                    ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
4461
0
                    int thisIndirect = v.lifetimeScope == ValueFlow::Value::LifetimeScope::ThisValue ? 0 : 1;
4462
0
                    if (derefShared(memtok->astParent()))
4463
0
                        thisIndirect--;
4464
0
                    if (thisIndirect == -1)
4465
0
                        update |= ls.byDerefCopy(tok->next(), tokenlist, errorLogger, settings);
4466
0
                    else if (thisIndirect == 0)
4467
0
                        update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
4468
0
                    else if (thisIndirect == 1)
4469
0
                        update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings);
4470
0
                    continue;
4471
0
                }
4472
0
                const Variable *var = v.tokvalue->variable();
4473
0
                LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, var, tokenlist, settings, errorLogger);
4474
0
                if (!ls.argtok)
4475
0
                    continue;
4476
0
                ls.forward = false;
4477
0
                ls.inconclusive = inconclusive;
4478
0
                ls.errorPath = v.errorPath;
4479
0
                ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
4480
0
                if (!v.isArgumentLifetimeValue() && (var->isReference() || var->isRValueReference())) {
4481
0
                    update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings);
4482
0
                } else if (v.isArgumentLifetimeValue()) {
4483
0
                    update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
4484
0
                }
4485
0
            }
4486
0
        }
4487
0
        if (update)
4488
0
            valueFlowForwardLifetime(tok->next(), tokenlist, errorLogger, settings);
4489
206
    } else if (tok->valueType()) {
4490
        // TODO: Propagate lifetimes with library functions
4491
206
        if (settings->library.getFunction(tok->previous()))
4492
0
            return;
4493
        // Assume constructing the valueType
4494
206
        valueFlowLifetimeConstructor(tok->next(), tokenlist, errorLogger, settings);
4495
206
        valueFlowForwardLifetime(tok->next(), tokenlist, errorLogger, settings);
4496
206
    } else {
4497
0
        const std::string& retVal = settings->library.returnValue(tok);
4498
0
        if (startsWith(retVal, "arg")) {
4499
0
            std::size_t iArg{};
4500
0
            try {
4501
0
                iArg = strToInt<std::size_t>(retVal.substr(3));
4502
0
            } catch (...) {
4503
0
                return;
4504
0
            }
4505
0
            std::vector<const Token*> args = getArguments(tok);
4506
0
            if (iArg > 0 && iArg <= args.size()) {
4507
0
                const Token* varTok = args[iArg - 1];
4508
0
                if (varTok->variable() && varTok->variable()->isLocal())
4509
0
                    LifetimeStore{ varTok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Address }.byRef(
4510
0
                    tok->next(), tokenlist, errorLogger, settings);
4511
0
            }
4512
0
        }
4513
0
    }
4514
206
}
4515
4516
static bool isScope(const Token* tok)
4517
1.55k
{
4518
1.55k
    if (!tok)
4519
0
        return false;
4520
1.55k
    if (!Token::simpleMatch(tok, "{"))
4521
206
        return false;
4522
1.34k
    const Scope* scope = tok->scope();
4523
1.34k
    if (!scope)
4524
0
        return false;
4525
1.34k
    if (!scope->bodyStart)
4526
0
        return false;
4527
1.34k
    return scope->bodyStart == tok;
4528
1.34k
}
4529
4530
static const Function* findConstructor(const Scope* scope, const Token* tok, const std::vector<const Token*>& args)
4531
0
{
4532
0
    if (!tok)
4533
0
        return nullptr;
4534
0
    const Function* f = tok->function();
4535
0
    if (!f && tok->astOperand1())
4536
0
        f = tok->astOperand1()->function();
4537
    // Search for a constructor
4538
0
    if (!f || !f->isConstructor()) {
4539
0
        f = nullptr;
4540
0
        std::vector<const Function*> candidates;
4541
0
        for (const Function& function : scope->functionList) {
4542
0
            if (function.minArgCount() > args.size())
4543
0
                continue;
4544
0
            if (!function.isConstructor())
4545
0
                continue;
4546
0
            candidates.push_back(&function);
4547
0
        }
4548
        // TODO: Narrow the candidates
4549
0
        if (candidates.size() == 1)
4550
0
            f = candidates.front();
4551
0
    }
4552
0
    if (!f)
4553
0
        return nullptr;
4554
0
    return f;
4555
0
}
4556
4557
static void valueFlowLifetimeClassConstructor(Token* tok,
4558
                                              const Type* t,
4559
                                              TokenList& tokenlist,
4560
                                              ErrorLogger* errorLogger,
4561
                                              const Settings* settings)
4562
0
{
4563
0
    if (!Token::Match(tok, "(|{"))
4564
0
        return;
4565
0
    if (isScope(tok))
4566
0
        return;
4567
0
    if (!t) {
4568
0
        if (tok->valueType() && tok->valueType()->type != ValueType::RECORD)
4569
0
            return;
4570
0
        if (tok->str() != "{" && !Token::Match(tok->previous(), "%var% (") && !isVariableDecl(tok->previous()))
4571
0
            return;
4572
        // If the type is unknown then assume it captures by value in the
4573
        // constructor, but make each lifetime inconclusive
4574
0
        std::vector<const Token*> args = getArguments(tok);
4575
0
        LifetimeStore::forEach(args,
4576
0
                               "Passed to initializer list.",
4577
0
                               ValueFlow::Value::LifetimeKind::SubObject,
4578
0
                               [&](LifetimeStore& ls) {
4579
0
            ls.inconclusive = true;
4580
0
            ls.byVal(tok, tokenlist, errorLogger, settings);
4581
0
        });
4582
0
        return;
4583
0
    }
4584
0
    const Scope* scope = t->classScope;
4585
0
    if (!scope)
4586
0
        return;
4587
    // Aggregate constructor
4588
0
    if (t->derivedFrom.empty() && (t->isClassType() || t->isStructType())) {
4589
0
        std::vector<const Token*> args = getArguments(tok);
4590
0
        if (scope->numConstructors == 0) {
4591
0
            auto it = scope->varlist.cbegin();
4592
0
            LifetimeStore::forEach(
4593
0
                args,
4594
0
                "Passed to constructor of '" + t->name() + "'.",
4595
0
                ValueFlow::Value::LifetimeKind::SubObject,
4596
0
                [&](const LifetimeStore& ls) {
4597
                // Skip static variable
4598
0
                it = std::find_if(it, scope->varlist.cend(), [](const Variable& var) {
4599
0
                    return !var.isStatic();
4600
0
                });
4601
0
                if (it == scope->varlist.cend())
4602
0
                    return;
4603
0
                const Variable& var = *it;
4604
0
                if (var.isReference() || var.isRValueReference()) {
4605
0
                    ls.byRef(tok, tokenlist, errorLogger, settings);
4606
0
                } else if (ValueFlow::isLifetimeBorrowed(ls.argtok, settings)) {
4607
0
                    ls.byVal(tok, tokenlist, errorLogger, settings);
4608
0
                }
4609
0
                it++;
4610
0
            });
4611
0
        } else {
4612
0
            const Function* constructor = findConstructor(scope, tok, args);
4613
0
            valueFlowLifetimeUserConstructor(tok, constructor, t->name(), args, tokenlist, errorLogger, settings);
4614
0
        }
4615
0
    }
4616
0
}
4617
4618
static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings* settings)
4619
206
{
4620
206
    if (!Token::Match(tok, "(|{"))
4621
0
        return;
4622
206
    if (isScope(tok))
4623
0
        return;
4624
206
    std::vector<ValueType> vts;
4625
206
    if (tok->valueType()) {
4626
0
        vts = {*tok->valueType()};
4627
206
    } else if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous()) &&
4628
206
               tok->previous()->valueType()) {
4629
0
        vts = {*tok->previous()->valueType()};
4630
206
    } else if (Token::simpleMatch(tok, "{") && !Token::Match(tok->previous(), "%name%")) {
4631
0
        vts = getParentValueTypes(tok, settings);
4632
0
    }
4633
4634
206
    for (const ValueType& vt : vts) {
4635
0
        if (vt.pointer > 0) {
4636
0
            std::vector<const Token*> args = getArguments(tok);
4637
0
            LifetimeStore::forEach(args,
4638
0
                                   "Passed to initializer list.",
4639
0
                                   ValueFlow::Value::LifetimeKind::SubObject,
4640
0
                                   [&](const LifetimeStore& ls) {
4641
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
4642
0
            });
4643
0
        } else if (vt.container && vt.type == ValueType::CONTAINER) {
4644
0
            std::vector<const Token*> args = getArguments(tok);
4645
0
            if (args.size() == 1 && vt.container->view && astIsContainerOwned(args.front())) {
4646
0
                LifetimeStore{args.front(), "Passed to container view.", ValueFlow::Value::LifetimeKind::SubObject}
4647
0
                .byRef(tok, tokenlist, errorLogger, settings);
4648
0
            } else if (args.size() == 2 && astIsIterator(args[0]) && astIsIterator(args[1])) {
4649
0
                LifetimeStore::forEach(
4650
0
                    args,
4651
0
                    "Passed to initializer list.",
4652
0
                    ValueFlow::Value::LifetimeKind::SubObject,
4653
0
                    [&](const LifetimeStore& ls) {
4654
0
                    ls.byDerefCopy(tok, tokenlist, errorLogger, settings);
4655
0
                });
4656
0
            } else if (vt.container->hasInitializerListConstructor) {
4657
0
                LifetimeStore::forEach(args,
4658
0
                                       "Passed to initializer list.",
4659
0
                                       ValueFlow::Value::LifetimeKind::SubObject,
4660
0
                                       [&](const LifetimeStore& ls) {
4661
0
                    ls.byVal(tok, tokenlist, errorLogger, settings);
4662
0
                });
4663
0
            }
4664
0
        } else {
4665
0
            const Type* t = nullptr;
4666
0
            if (vt.typeScope && vt.typeScope->definedType)
4667
0
                t = vt.typeScope->definedType;
4668
0
            else
4669
0
                t = Token::typeOf(tok->previous());
4670
0
            valueFlowLifetimeClassConstructor(tok, t, tokenlist, errorLogger, settings);
4671
0
        }
4672
0
    }
4673
206
}
4674
4675
struct Lambda {
4676
    explicit Lambda(const Token* tok)
4677
107k
    {
4678
107k
        if (!Token::simpleMatch(tok, "[") || !tok->link())
4679
107k
            return;
4680
0
        capture = tok;
4681
4682
0
        if (Token::simpleMatch(capture->link(), "] (")) {
4683
0
            arguments = capture->link()->next();
4684
0
        }
4685
0
        const Token * afterArguments = arguments ? arguments->link()->next() : capture->link()->next();
4686
0
        if (afterArguments && afterArguments->originalName() == "->") {
4687
0
            returnTok = afterArguments->next();
4688
0
            bodyTok = Token::findsimplematch(returnTok, "{");
4689
0
        } else if (Token::simpleMatch(afterArguments, "{")) {
4690
0
            bodyTok = afterArguments;
4691
0
        }
4692
0
        for (const Token* c:getCaptures()) {
4693
0
            if (Token::Match(c, "this !!.")) {
4694
0
                explicitCaptures[c->variable()] = std::make_pair(c, LifetimeCapture::ByReference);
4695
0
            } else if (Token::simpleMatch(c, "* this")) {
4696
0
                explicitCaptures[c->next()->variable()] = std::make_pair(c->next(), LifetimeCapture::ByValue);
4697
0
            } else if (c->variable()) {
4698
0
                explicitCaptures[c->variable()] = std::make_pair(c, LifetimeCapture::ByValue);
4699
0
            } else if (c->isUnaryOp("&") && Token::Match(c->astOperand1(), "%var%")) {
4700
0
                explicitCaptures[c->astOperand1()->variable()] =
4701
0
                    std::make_pair(c->astOperand1(), LifetimeCapture::ByReference);
4702
0
            } else {
4703
0
                const std::string& s = c->expressionString();
4704
0
                if (s == "=")
4705
0
                    implicitCapture = LifetimeCapture::ByValue;
4706
0
                else if (s == "&")
4707
0
                    implicitCapture = LifetimeCapture::ByReference;
4708
0
            }
4709
0
        }
4710
0
    }
4711
4712
    const Token* capture{};
4713
    const Token* arguments{};
4714
    const Token* returnTok{};
4715
    const Token* bodyTok{};
4716
    std::unordered_map<const Variable*, std::pair<const Token*, LifetimeCapture>> explicitCaptures;
4717
    LifetimeCapture implicitCapture = LifetimeCapture::Undefined;
4718
4719
0
    std::vector<const Token*> getCaptures() const {
4720
0
        return getArguments(capture);
4721
0
    }
4722
4723
107k
    bool isLambda() const {
4724
107k
        return capture && bodyTok;
4725
107k
    }
4726
};
4727
4728
static bool isDecayedPointer(const Token *tok)
4729
0
{
4730
0
    if (!tok)
4731
0
        return false;
4732
0
    if (!tok->astParent())
4733
0
        return false;
4734
0
    if (astIsPointer(tok->astParent()) && !Token::simpleMatch(tok->astParent(), "return"))
4735
0
        return true;
4736
0
    if (tok->astParent()->isConstOp())
4737
0
        return true;
4738
0
    if (!Token::simpleMatch(tok->astParent(), "return"))
4739
0
        return false;
4740
0
    return astIsPointer(tok->astParent());
4741
0
}
4742
4743
static bool isConvertedToView(const Token* tok, const Settings* settings)
4744
0
{
4745
0
    std::vector<ValueType> vtParents = getParentValueTypes(tok, settings);
4746
0
    return std::any_of(vtParents.cbegin(), vtParents.cend(), [&](const ValueType& vt) {
4747
0
        if (!vt.container)
4748
0
            return false;
4749
0
        return vt.container->view;
4750
0
    });
4751
0
}
4752
4753
static bool isContainerOfPointers(const Token* tok, const Settings* settings)
4754
0
{
4755
0
    if (!tok)
4756
0
    {
4757
0
        return true;
4758
0
    }
4759
4760
0
    ValueType vt = ValueType::parseDecl(tok, *settings);
4761
0
    return vt.pointer > 0;
4762
0
}
4763
4764
static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger *errorLogger, const Settings *settings)
4765
3.63k
{
4766
256k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
4767
253k
        if (!tok->scope())
4768
0
            continue;
4769
253k
        if (tok->scope()->type == Scope::eGlobal)
4770
145k
            continue;
4771
107k
        Lambda lam(tok);
4772
        // Lambdas
4773
107k
        if (lam.isLambda()) {
4774
0
            const Scope * bodyScope = lam.bodyTok->scope();
4775
4776
0
            std::set<const Scope *> scopes;
4777
            // Avoid capturing a variable twice
4778
0
            std::set<nonneg int> varids;
4779
0
            bool capturedThis = false;
4780
4781
0
            auto isImplicitCapturingVariable = [&](const Token *varTok) {
4782
0
                const Variable *var = varTok->variable();
4783
0
                if (!var)
4784
0
                    return false;
4785
0
                if (varids.count(var->declarationId()) > 0)
4786
0
                    return false;
4787
0
                if (!var->isLocal() && !var->isArgument())
4788
0
                    return false;
4789
0
                const Scope *scope = var->scope();
4790
0
                if (!scope)
4791
0
                    return false;
4792
0
                if (scopes.count(scope) > 0)
4793
0
                    return false;
4794
0
                if (scope->isNestedIn(bodyScope))
4795
0
                    return false;
4796
0
                scopes.insert(scope);
4797
0
                varids.insert(var->declarationId());
4798
0
                return true;
4799
0
            };
4800
4801
0
            bool update = false;
4802
0
            auto captureVariable = [&](const Token* tok2, LifetimeCapture c, const std::function<bool(const Token*)> &pred) {
4803
0
                if (varids.count(tok->varId()) > 0)
4804
0
                    return;
4805
0
                if (c == LifetimeCapture::ByReference) {
4806
0
                    LifetimeStore ls{
4807
0
                        tok2, "Lambda captures variable by reference here.", ValueFlow::Value::LifetimeKind::Lambda};
4808
0
                    ls.forward = false;
4809
0
                    update |= ls.byRef(tok, tokenlist, errorLogger, settings, pred);
4810
0
                } else if (c == LifetimeCapture::ByValue) {
4811
0
                    LifetimeStore ls{
4812
0
                        tok2, "Lambda captures variable by value here.", ValueFlow::Value::LifetimeKind::Lambda};
4813
0
                    ls.forward = false;
4814
0
                    update |= ls.byVal(tok, tokenlist, errorLogger, settings, pred);
4815
0
                    pred(tok2);
4816
0
                }
4817
0
            };
4818
4819
0
            auto captureThisVariable = [&](const Token* tok2, LifetimeCapture c) {
4820
0
                ValueFlow::Value value;
4821
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4822
0
                if (c == LifetimeCapture::ByReference)
4823
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::ThisPointer;
4824
0
                else if (c == LifetimeCapture::ByValue)
4825
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::ThisValue;
4826
0
                value.tokvalue = tok2;
4827
0
                value.errorPath.emplace_back(tok2, "Lambda captures the 'this' variable here.");
4828
0
                value.lifetimeKind = ValueFlow::Value::LifetimeKind::Lambda;
4829
0
                capturedThis = true;
4830
                // Don't add the value a second time
4831
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4832
0
                    return;
4833
0
                setTokenValue(tok, std::move(value), settings);
4834
0
                update |= true;
4835
0
            };
4836
4837
            // Handle explicit capture
4838
0
            for (const auto& p:lam.explicitCaptures) {
4839
0
                const Variable* var = p.first;
4840
0
                const Token* tok2 = p.second.first;
4841
0
                const LifetimeCapture c = p.second.second;
4842
0
                if (Token::Match(tok2, "this !!.")) {
4843
0
                    captureThisVariable(tok2, c);
4844
0
                } else if (var) {
4845
0
                    captureVariable(tok2, c, [](const Token*) {
4846
0
                        return true;
4847
0
                    });
4848
0
                    varids.insert(var->declarationId());
4849
0
                }
4850
0
            }
4851
4852
0
            auto isImplicitCapturingThis = [&](const Token* tok2) {
4853
0
                if (capturedThis)
4854
0
                    return false;
4855
0
                if (Token::simpleMatch(tok2, "this"))
4856
0
                    return true;
4857
0
                if (tok2->variable()) {
4858
0
                    if (Token::simpleMatch(tok2->previous(), "."))
4859
0
                        return false;
4860
0
                    const Variable* var = tok2->variable();
4861
0
                    if (var->isLocal())
4862
0
                        return false;
4863
0
                    if (var->isArgument())
4864
0
                        return false;
4865
0
                    return exprDependsOnThis(tok2);
4866
0
                }
4867
0
                if (Token::simpleMatch(tok2, "("))
4868
0
                    return exprDependsOnThis(tok2);
4869
0
                return false;
4870
0
            };
4871
4872
0
            for (const Token * tok2 = lam.bodyTok; tok2 != lam.bodyTok->link(); tok2 = tok2->next()) {
4873
0
                if (isImplicitCapturingThis(tok2)) {
4874
0
                    captureThisVariable(tok2, LifetimeCapture::ByReference);
4875
0
                } else if (tok2->variable()) {
4876
0
                    captureVariable(tok2, lam.implicitCapture, isImplicitCapturingVariable);
4877
0
                }
4878
0
            }
4879
0
            if (update)
4880
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4881
0
        }
4882
        // address of
4883
107k
        else if (tok->isUnaryOp("&")) {
4884
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1())) {
4885
0
                if (!settings->certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4886
0
                    continue;
4887
0
                ErrorPath errorPath = lt.errorPath;
4888
0
                errorPath.emplace_back(tok, "Address of variable taken here.");
4889
4890
0
                ValueFlow::Value value;
4891
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4892
0
                value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4893
0
                value.tokvalue = lt.token;
4894
0
                value.errorPath = std::move(errorPath);
4895
0
                if (lt.addressOf || astIsPointer(lt.token) || !Token::Match(lt.token->astParent(), ".|["))
4896
0
                    value.lifetimeKind = ValueFlow::Value::LifetimeKind::Address;
4897
0
                value.setInconclusive(lt.inconclusive);
4898
0
                setTokenValue(tok, std::move(value), settings);
4899
4900
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4901
0
            }
4902
0
        }
4903
        // Converting to container view
4904
107k
        else if (astIsContainerOwned(tok) && isConvertedToView(tok, settings)) {
4905
0
            LifetimeStore ls =
4906
0
                LifetimeStore{tok, "Converted to container view", ValueFlow::Value::LifetimeKind::SubObject};
4907
0
            ls.byRef(tok, tokenlist, errorLogger, settings);
4908
0
            valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4909
0
        }
4910
        // container lifetimes
4911
107k
        else if (astIsContainer(tok)) {
4912
0
            Token * parent = astParentSkipParens(tok);
4913
0
            if (!parent)
4914
0
                continue;
4915
0
            if (!Token::Match(parent, ". %name% (") && !Token::Match(parent->previous(), "%name% ("))
4916
0
                continue;
4917
4918
            // Skip if its a free function that doesnt yield an iterator to the container
4919
0
            if (Token::Match(parent->previous(), "%name% (") &&
4920
0
                !contains({Library::Container::Yield::START_ITERATOR, Library::Container::Yield::END_ITERATOR},
4921
0
                          astFunctionYield(parent->previous(), settings)))
4922
0
                continue;
4923
4924
0
            ValueFlow::Value master;
4925
0
            master.valueType = ValueFlow::Value::ValueType::LIFETIME;
4926
0
            master.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4927
4928
0
            if (astIsIterator(parent->tokAt(2))) {
4929
0
                master.errorPath.emplace_back(parent->tokAt(2), "Iterator to container is created here.");
4930
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator;
4931
0
            } else if (astIsIterator(parent) && Token::Match(parent->previous(), "%name% (") &&
4932
0
                       contains({Library::Container::Yield::START_ITERATOR, Library::Container::Yield::END_ITERATOR},
4933
0
                                astFunctionYield(parent->previous(), settings))) {
4934
0
                master.errorPath.emplace_back(parent, "Iterator to container is created here.");
4935
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator;
4936
0
            } else if ((astIsPointer(parent->tokAt(2)) &&
4937
0
                        !isContainerOfPointers(tok->valueType()->containerTypeToken, settings)) ||
4938
0
                       Token::Match(parent->next(), "data|c_str")) {
4939
0
                master.errorPath.emplace_back(parent->tokAt(2), "Pointer to container is created here.");
4940
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Object;
4941
0
            } else {
4942
0
                continue;
4943
0
            }
4944
4945
0
            std::vector<const Token*> toks = {};
4946
0
            if (tok->isUnaryOp("*") || parent->originalName() == "->") {
4947
0
                for (const ValueFlow::Value& v : tok->values()) {
4948
0
                    if (!v.isLocalLifetimeValue())
4949
0
                        continue;
4950
0
                    if (v.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
4951
0
                        continue;
4952
0
                    if (!v.tokvalue)
4953
0
                        continue;
4954
0
                    toks.push_back(v.tokvalue);
4955
0
                }
4956
0
            } else if (astIsContainerView(tok)) {
4957
0
                for (const ValueFlow::Value& v : tok->values()) {
4958
0
                    if (!v.isLocalLifetimeValue())
4959
0
                        continue;
4960
0
                    if (!v.tokvalue)
4961
0
                        continue;
4962
0
                    if (!astIsContainerOwned(v.tokvalue))
4963
0
                        continue;
4964
0
                    toks.push_back(v.tokvalue);
4965
0
                }
4966
0
            } else {
4967
0
                toks = {tok};
4968
0
            }
4969
4970
0
            for (const Token* tok2 : toks) {
4971
0
                for (const ReferenceToken& rt : followAllReferences(tok2, false)) {
4972
0
                    ValueFlow::Value value = master;
4973
0
                    value.tokvalue = rt.token;
4974
0
                    value.errorPath.insert(value.errorPath.begin(), rt.errors.cbegin(), rt.errors.cend());
4975
0
                    if (Token::simpleMatch(parent, "("))
4976
0
                        setTokenValue(parent, value, settings);
4977
0
                    else
4978
0
                        setTokenValue(parent->tokAt(2), value, settings);
4979
4980
0
                    if (!rt.token->variable()) {
4981
0
                        LifetimeStore ls = LifetimeStore{
4982
0
                            rt.token, master.errorPath.back().second, ValueFlow::Value::LifetimeKind::Object};
4983
0
                        ls.byRef(parent->tokAt(2), tokenlist, errorLogger, settings);
4984
0
                    }
4985
0
                }
4986
0
            }
4987
0
            valueFlowForwardLifetime(parent->tokAt(2), tokenlist, errorLogger, settings);
4988
0
        }
4989
        // Check constructors
4990
107k
        else if (Token::Match(tok, "=|return|%name%|{|,|> {") && !isScope(tok->next())) {
4991
0
            valueFlowLifetimeConstructor(tok->next(), tokenlist, errorLogger, settings);
4992
0
        }
4993
        // Check function calls
4994
107k
        else if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->next()->link(), ") {")) {
4995
206
            valueFlowLifetimeFunction(tok, tokenlist, errorLogger, settings);
4996
206
        }
4997
        // Unique pointer lifetimes
4998
107k
        else if (astIsUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
4999
0
            Token* ptok = tok->astParent()->tokAt(2);
5000
0
            ErrorPath errorPath = {{ptok, "Raw pointer to smart pointer created here."}};
5001
0
            ValueFlow::Value value;
5002
0
            value.valueType = ValueFlow::Value::ValueType::LIFETIME;
5003
0
            value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
5004
0
            value.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject;
5005
0
            value.tokvalue = tok;
5006
0
            value.errorPath = errorPath;
5007
0
            setTokenValue(ptok, std::move(value), settings);
5008
0
            valueFlowForwardLifetime(ptok, tokenlist, errorLogger, settings);
5009
0
        }
5010
        // Check variables
5011
107k
        else if (tok->variable()) {
5012
17.8k
            ErrorPath errorPath;
5013
17.8k
            const Variable * var = ValueFlow::getLifetimeVariable(tok, errorPath);
5014
17.8k
            if (!var)
5015
0
                continue;
5016
17.8k
            if (var->nameToken() == tok)
5017
0
                continue;
5018
17.8k
            if (var->isArray() && !var->isStlType() && !var->isArgument() && isDecayedPointer(tok)) {
5019
0
                errorPath.emplace_back(tok, "Array decayed to pointer here.");
5020
5021
0
                ValueFlow::Value value;
5022
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
5023
0
                value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
5024
0
                value.tokvalue = var->nameToken();
5025
0
                value.errorPath = errorPath;
5026
0
                setTokenValue(tok, std::move(value), settings);
5027
5028
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
5029
0
            }
5030
17.8k
        }
5031
        // Forward any lifetimes
5032
89.2k
        else if (std::any_of(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
5033
0
            valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
5034
0
        }
5035
107k
    }
5036
3.63k
}
5037
5038
static bool isStdMoveOrStdForwarded(Token * tok, ValueFlow::Value::MoveKind * moveKind, Token ** varTok = nullptr)
5039
66.7k
{
5040
66.7k
    if (tok->str() != "std")
5041
66.7k
        return false;
5042
0
    ValueFlow::Value::MoveKind kind = ValueFlow::Value::MoveKind::NonMovedVariable;
5043
0
    Token * variableToken = nullptr;
5044
0
    if (Token::Match(tok, "std :: move ( %var% )")) {
5045
0
        variableToken = tok->tokAt(4);
5046
0
        kind = ValueFlow::Value::MoveKind::MovedVariable;
5047
0
    } else if (Token::simpleMatch(tok, "std :: forward <")) {
5048
0
        Token * const leftAngle = tok->tokAt(3);
5049
0
        Token * rightAngle = leftAngle->link();
5050
0
        if (Token::Match(rightAngle, "> ( %var% )")) {
5051
0
            variableToken = rightAngle->tokAt(2);
5052
0
            kind = ValueFlow::Value::MoveKind::ForwardedVariable;
5053
0
        }
5054
0
    }
5055
0
    if (!variableToken)
5056
0
        return false;
5057
0
    if (variableToken->strAt(2) == ".") // Only partially moved
5058
0
        return false;
5059
0
    if (variableToken->valueType() && variableToken->valueType()->type >= ValueType::Type::VOID)
5060
0
        return false;
5061
0
    if (moveKind != nullptr)
5062
0
        *moveKind = kind;
5063
0
    if (varTok != nullptr)
5064
0
        *varTok = variableToken;
5065
0
    return true;
5066
0
}
5067
5068
static bool isOpenParenthesisMemberFunctionCallOfVarId(const Token * openParenthesisToken, nonneg int varId)
5069
0
{
5070
0
    const Token * varTok = openParenthesisToken->tokAt(-3);
5071
0
    return Token::Match(varTok, "%varid% . %name% (", varId) &&
5072
0
           varTok->next()->originalName().empty();
5073
0
}
5074
5075
static const Token * findOpenParentesisOfMove(const Token * moveVarTok)
5076
0
{
5077
0
    const Token * tok = moveVarTok;
5078
0
    while (tok && tok->str() != "(")
5079
0
        tok = tok->previous();
5080
0
    return tok;
5081
0
}
5082
5083
static const Token * findEndOfFunctionCallForParameter(const Token * parameterToken)
5084
0
{
5085
0
    if (!parameterToken)
5086
0
        return nullptr;
5087
0
    const Token * parent = parameterToken->astParent();
5088
0
    while (parent && !parent->isOp() && parent->str() != "(")
5089
0
        parent = parent->astParent();
5090
0
    if (!parent)
5091
0
        return nullptr;
5092
0
    return nextAfterAstRightmostLeaf(parent);
5093
0
}
5094
5095
static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings)
5096
2.27k
{
5097
2.27k
    if (!tokenlist.isCPP() || settings->standards.cpp < Standards::CPP11)
5098
0
        return;
5099
2.90k
    for (const Scope * scope : symboldatabase.functionScopes) {
5100
2.90k
        if (!scope)
5101
0
            continue;
5102
2.90k
        const Token * start = scope->bodyStart;
5103
2.90k
        if (scope->function) {
5104
2.90k
            const Token * memberInitializationTok = scope->function->constructorMemberInitialization();
5105
2.90k
            if (memberInitializationTok)
5106
0
                start = memberInitializationTok;
5107
2.90k
        }
5108
5109
69.6k
        for (Token* tok = const_cast<Token*>(start); tok != scope->bodyEnd; tok = tok->next()) {
5110
66.7k
            Token * varTok;
5111
66.7k
            if (Token::Match(tok, "%var% . reset|clear (") && tok->next()->originalName().empty()) {
5112
0
                varTok = tok;
5113
5114
0
                const Variable *var = tok->variable();
5115
0
                if (!var || (!var->isLocal() && !var->isArgument()))
5116
0
                    continue;
5117
5118
0
                ValueFlow::Value value;
5119
0
                value.valueType = ValueFlow::Value::ValueType::MOVED;
5120
0
                value.moveKind = ValueFlow::Value::MoveKind::NonMovedVariable;
5121
0
                value.errorPath.emplace_back(tok, "Calling " + tok->next()->expressionString() + " makes " + tok->str() + " 'non-moved'");
5122
0
                value.setKnown();
5123
5124
0
                setTokenValue(tok, value, settings);
5125
0
                if (var->scope()) {
5126
0
                    const Token* const endOfVarScope = var->scope()->bodyEnd;
5127
0
                    valueFlowForward(tok->next(), endOfVarScope, tok, std::move(value), tokenlist, settings);
5128
0
                }
5129
0
                continue;
5130
0
            }
5131
66.7k
            ValueFlow::Value::MoveKind moveKind;
5132
66.7k
            if (!isStdMoveOrStdForwarded(tok, &moveKind, &varTok))
5133
66.7k
                continue;
5134
0
            const nonneg int varId = varTok->varId();
5135
            // x is not MOVED after assignment if code is:  x = ... std::move(x) .. ;
5136
0
            const Token *parent = tok->astParent();
5137
0
            while (parent && parent->str() != "=" && parent->str() != "return" &&
5138
0
                   !(parent->str() == "(" && isOpenParenthesisMemberFunctionCallOfVarId(parent, varId)))
5139
0
                parent = parent->astParent();
5140
0
            if (parent &&
5141
0
                (parent->str() == "return" || // MOVED in return statement
5142
0
                 parent->str() == "(")) // MOVED in self assignment, isOpenParenthesisMemberFunctionCallOfVarId == true
5143
0
                continue;
5144
0
            if (parent && parent->astOperand1() && parent->astOperand1()->varId() == varId)
5145
0
                continue;
5146
0
            const Token* const endOfVarScope = ValueFlow::getEndOfExprScope(varTok);
5147
5148
0
            const Token * openParentesisOfMove = findOpenParentesisOfMove(varTok);
5149
0
            const Token * endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
5150
0
            if (endOfFunctionCall) {
5151
0
                ValueFlow::Value value;
5152
0
                value.valueType = ValueFlow::Value::ValueType::MOVED;
5153
0
                value.moveKind = moveKind;
5154
0
                if (moveKind == ValueFlow::Value::MoveKind::MovedVariable)
5155
0
                    value.errorPath.emplace_back(tok, "Calling std::move(" + varTok->str() + ")");
5156
0
                else // if (moveKind == ValueFlow::Value::ForwardedVariable)
5157
0
                    value.errorPath.emplace_back(tok, "Calling std::forward(" + varTok->str() + ")");
5158
0
                value.setKnown();
5159
5160
0
                valueFlowForward(const_cast<Token*>(endOfFunctionCall), endOfVarScope, varTok, std::move(value), tokenlist, settings);
5161
0
            }
5162
0
        }
5163
2.90k
    }
5164
2.27k
}
5165
5166
static const Token* findIncompleteVar(const Token* start, const Token* end)
5167
1.50k
{
5168
15.5k
    for (const Token* tok = start; tok != end; tok = tok->next()) {
5169
14.8k
        if (tok->isIncompleteVar())
5170
758
            return tok;
5171
14.8k
    }
5172
744
    return nullptr;
5173
1.50k
}
5174
5175
static ValueFlow::Value makeConditionValue(long long val,
5176
                                           const Token* condTok,
5177
                                           bool assume,
5178
                                           bool impossible = false,
5179
                                           const Settings* settings = nullptr,
5180
                                           SourceLocation loc = SourceLocation::current())
5181
236
{
5182
236
    ValueFlow::Value v(val);
5183
236
    v.setKnown();
5184
236
    if (impossible) {
5185
0
        v.intvalue = !v.intvalue;
5186
0
        v.setImpossible();
5187
0
    }
5188
236
    v.condition = condTok;
5189
236
    if (assume)
5190
161
        v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is true");
5191
75
    else
5192
75
        v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is false");
5193
236
    if (settings && settings->debugnormal)
5194
0
        setSourceLocation(v, loc, condTok);
5195
236
    return v;
5196
236
}
5197
5198
static std::vector<const Token*> getConditions(const Token* tok, const char* op)
5199
180
{
5200
180
    std::vector<const Token*> conds = {tok};
5201
180
    if (tok->str() == op) {
5202
0
        std::vector<const Token*> args = astFlatten(tok, op);
5203
0
        std::copy_if(args.cbegin(), args.cend(), std::back_inserter(conds), [&](const Token* tok2) {
5204
0
            if (tok2->exprId() == 0)
5205
0
                return false;
5206
0
            if (tok2->hasKnownIntValue())
5207
0
                return false;
5208
0
            if (Token::Match(tok2, "%var%|.") && !astIsBool(tok2))
5209
0
                return false;
5210
0
            return true;
5211
0
        });
5212
0
    }
5213
180
    return conds;
5214
180
}
5215
5216
static bool isBreakOrContinueScope(const Token* endToken)
5217
191
{
5218
191
    if (!Token::simpleMatch(endToken, "}"))
5219
0
        return false;
5220
191
    return Token::Match(endToken->tokAt(-2), "break|continue ;");
5221
191
}
5222
5223
static const Scope* getLoopScope(const Token* tok)
5224
0
{
5225
0
    if (!tok)
5226
0
        return nullptr;
5227
0
    const Scope* scope = tok->scope();
5228
0
    while (scope && scope->type != Scope::eWhile && scope->type != Scope::eFor && scope->type != Scope::eDo)
5229
0
        scope = scope->nestedIn;
5230
0
    return scope;
5231
0
}
5232
5233
//
5234
static void valueFlowConditionExpressions(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings)
5235
1.36k
{
5236
1.50k
    for (const Scope * scope : symboldatabase.functionScopes) {
5237
1.50k
        if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) {
5238
758
            if (settings.debugwarnings)
5239
758
                bailoutIncompleteVar(tokenlist, errorLogger, incompleteTok, "Skipping function due to incomplete variable " + incompleteTok->str());
5240
758
            break;
5241
758
        }
5242
5243
9.85k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5244
9.10k
            if (!Token::simpleMatch(tok, "if ("))
5245
8.86k
                continue;
5246
239
            Token* parenTok = tok->next();
5247
239
            if (!Token::simpleMatch(parenTok->link(), ") {"))
5248
0
                continue;
5249
239
            Token * blockTok = parenTok->link()->tokAt(1);
5250
239
            const Token* condTok = parenTok->astOperand2();
5251
239
            if (condTok->exprId() == 0)
5252
0
                continue;
5253
239
            if (condTok->hasKnownIntValue())
5254
58
                continue;
5255
181
            if (!isConstExpression(condTok, settings.library, tokenlist.isCPP()))
5256
91
                continue;
5257
90
            const bool is1 = (condTok->isComparisonOp() || condTok->tokType() == Token::eLogicalOp || astIsBool(condTok));
5258
5259
90
            Token* startTok = blockTok;
5260
            // Inner condition
5261
90
            {
5262
90
                for (const Token* condTok2 : getConditions(condTok, "&&")) {
5263
90
                    if (is1) {
5264
71
                        const bool isBool = astIsBool(condTok2) || Token::Match(condTok2, "%comp%|%oror%|&&");
5265
71
                        SameExpressionAnalyzer a1(condTok2, makeConditionValue(1, condTok2, /*assume*/ true, !isBool), tokenlist, &settings); // don't set '1' for non-boolean expressions
5266
71
                        valueFlowGenericForward(startTok, startTok->link(), a1, settings);
5267
71
                    }
5268
5269
90
                    OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(0, condTok2, true), tokenlist, &settings);
5270
90
                    valueFlowGenericForward(startTok, startTok->link(), a2, settings);
5271
90
                }
5272
90
            }
5273
5274
90
            std::vector<const Token*> conds = getConditions(condTok, "||");
5275
5276
            // Check else block
5277
90
            if (Token::simpleMatch(startTok->link(), "} else {")) {
5278
40
                startTok = startTok->link()->tokAt(2);
5279
40
                for (const Token* condTok2:conds) {
5280
40
                    SameExpressionAnalyzer a1(condTok2, makeConditionValue(0, condTok2, false), tokenlist, &settings);
5281
40
                    valueFlowGenericForward(startTok, startTok->link(), a1, settings);
5282
5283
40
                    if (is1) {
5284
33
                        OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(1, condTok2, false), tokenlist, &settings);
5285
33
                        valueFlowGenericForward(startTok, startTok->link(), a2, settings);
5286
33
                    }
5287
40
                }
5288
40
            }
5289
5290
            // Check if the block terminates early
5291
90
            if (isEscapeScope(blockTok, &settings)) {
5292
1
                const Scope* scope2 = scope;
5293
                // If escaping a loop then only use the loop scope
5294
1
                if (isBreakOrContinueScope(blockTok->link())) {
5295
0
                    scope2 = getLoopScope(blockTok->link());
5296
0
                    if (!scope2)
5297
0
                        continue;
5298
0
                }
5299
1
                for (const Token* condTok2:conds) {
5300
1
                    SameExpressionAnalyzer a1(condTok2, makeConditionValue(0, condTok2, false), tokenlist, &settings);
5301
1
                    valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a1, settings);
5302
5303
1
                    if (is1) {
5304
1
                        OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(1, condTok2, false), tokenlist, &settings);
5305
1
                        valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a2, settings);
5306
1
                    }
5307
1
                }
5308
1
            }
5309
90
        }
5310
744
    }
5311
1.36k
}
5312
5313
static bool isTruncated(const ValueType* src, const ValueType* dst, const Settings* settings)
5314
332
{
5315
332
    if (src->pointer > 0 || dst->pointer > 0)
5316
0
        return src->pointer != dst->pointer;
5317
332
    if (src->smartPointer && dst->smartPointer)
5318
0
        return false;
5319
332
    if ((src->isIntegral() && dst->isIntegral()) || (src->isFloat() && dst->isFloat())) {
5320
332
        const size_t srcSize = ValueFlow::getSizeOf(*src, settings);
5321
332
        const size_t dstSize = ValueFlow::getSizeOf(*dst, settings);
5322
332
        if (srcSize > dstSize)
5323
0
            return true;
5324
332
        if (srcSize == dstSize && src->sign != dst->sign)
5325
0
            return true;
5326
332
    } else if (src->type == dst->type) {
5327
0
        if (src->type == ValueType::Type::RECORD)
5328
0
            return src->typeScope != dst->typeScope;
5329
0
    } else {
5330
0
        return true;
5331
0
    }
5332
332
    return false;
5333
332
}
5334
5335
static void setSymbolic(ValueFlow::Value& value, const Token* tok)
5336
7.56k
{
5337
7.56k
    assert(tok && tok->exprId() > 0 && "Missing expr id for symbolic value");
5338
0
    value.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
5339
7.56k
    value.tokvalue = tok;
5340
7.56k
}
5341
5342
static ValueFlow::Value makeSymbolic(const Token* tok, MathLib::bigint delta = 0)
5343
92
{
5344
92
    ValueFlow::Value value;
5345
92
    value.setKnown();
5346
92
    setSymbolic(value, tok);
5347
92
    value.intvalue = delta;
5348
92
    return value;
5349
92
}
5350
5351
static std::set<nonneg int> getVarIds(const Token* tok)
5352
814
{
5353
814
    std::set<nonneg int> result;
5354
1.88k
    visitAstNodes(tok, [&](const Token* child) {
5355
1.88k
        if (child->varId() > 0)
5356
731
            result.insert(child->varId());
5357
1.88k
        return ChildrenToVisit::op1_and_op2;
5358
1.88k
    });
5359
814
    return result;
5360
814
}
5361
5362
static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings)
5363
1.36k
{
5364
1.73k
    for (const Scope* scope : symboldatabase.functionScopes) {
5365
37.6k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5366
35.9k
            if (!Token::simpleMatch(tok, "="))
5367
34.0k
                continue;
5368
1.90k
            if (tok->astParent())
5369
364
                continue;
5370
1.53k
            if (!tok->astOperand1())
5371
0
                continue;
5372
1.53k
            if (!tok->astOperand2())
5373
0
                continue;
5374
1.53k
            if (tok->astOperand1()->hasKnownIntValue())
5375
0
                continue;
5376
1.53k
            if (tok->astOperand2()->hasKnownIntValue())
5377
216
                continue;
5378
1.32k
            if (tok->astOperand1()->exprId() == 0)
5379
0
                continue;
5380
1.32k
            if (tok->astOperand2()->exprId() == 0)
5381
0
                continue;
5382
1.32k
            if (!isConstExpression(tok->astOperand2(), settings->library, tokenlist.isCPP()))
5383
508
                continue;
5384
814
            if (tok->astOperand1()->valueType() && tok->astOperand2()->valueType()) {
5385
332
                if (isTruncated(
5386
332
                        tok->astOperand2()->valueType(), tok->astOperand1()->valueType(), settings))
5387
0
                    continue;
5388
482
            } else if (isDifferentType(tok->astOperand2(), tok->astOperand1())) {
5389
0
                continue;
5390
0
            }
5391
814
            const std::set<nonneg int> rhsVarIds = getVarIds(tok->astOperand2());
5392
814
            const std::vector<const Variable*> vars = getLHSVariables(tok);
5393
814
            if (std::any_of(vars.cbegin(), vars.cend(), [&](const Variable* var) {
5394
562
                if (rhsVarIds.count(var->declarationId()) > 0)
5395
109
                    return true;
5396
453
                if (var->isLocal())
5397
0
                    return var->isStatic();
5398
453
                return !var->isArgument();
5399
453
            }))
5400
562
                continue;
5401
5402
504
            if (findAstNode(tok, [](const Token* child) {
5403
504
                return child->isIncompleteVar();
5404
504
            }))
5405
252
                continue;
5406
5407
0
            Token* start = nextAfterAstRightmostLeaf(tok);
5408
0
            const Token* end = ValueFlow::getEndOfExprScope(tok->astOperand1(), scope);
5409
5410
0
            ValueFlow::Value rhs = makeSymbolic(tok->astOperand2());
5411
0
            rhs.errorPath.emplace_back(tok,
5412
0
                                       tok->astOperand1()->expressionString() + " is assigned '" +
5413
0
                                       tok->astOperand2()->expressionString() + "' here.");
5414
0
            valueFlowForward(start, end, tok->astOperand1(), rhs, tokenlist, settings);
5415
5416
0
            ValueFlow::Value lhs = makeSymbolic(tok->astOperand1());
5417
0
            lhs.errorPath.emplace_back(tok,
5418
0
                                       tok->astOperand1()->expressionString() + " is assigned '" +
5419
0
                                       tok->astOperand2()->expressionString() + "' here.");
5420
0
            valueFlowForward(start, end, tok->astOperand2(), lhs, tokenlist, settings);
5421
0
        }
5422
1.73k
    }
5423
1.36k
}
5424
5425
static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth = 10)
5426
0
{
5427
0
    if (depth < 0)
5428
0
        return nullptr;
5429
0
    if (!tok)
5430
0
        return nullptr;
5431
0
    if (!expr)
5432
0
        return nullptr;
5433
0
    if (expr->exprId() == 0)
5434
0
        return nullptr;
5435
0
    if (Token::simpleMatch(tok->previous(), "strlen (")) {
5436
0
        if (tok->astOperand2()->exprId() == expr->exprId())
5437
0
            return tok;
5438
0
    } else {
5439
0
        for (const ValueFlow::Value& v : tok->values()) {
5440
0
            if (!v.isSymbolicValue())
5441
0
                continue;
5442
0
            if (!v.isKnown())
5443
0
                continue;
5444
0
            if (v.intvalue != 0)
5445
0
                continue;
5446
0
            if (const Token* next = isStrlenOf(v.tokvalue, expr, depth - 1))
5447
0
                return next;
5448
0
        }
5449
0
    }
5450
0
    return nullptr;
5451
0
}
5452
5453
static ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val);
5454
5455
static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, const Settings* settings)
5456
2.27k
{
5457
2.90k
    for (const Scope* scope : symboldatabase.functionScopes) {
5458
69.6k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5459
66.7k
            if (tok->hasKnownIntValue())
5460
6.90k
                continue;
5461
5462
59.8k
            if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) {
5463
0
                const Token* arg = tok->next()->astOperand2();
5464
0
                if (!arg)
5465
0
                    continue;
5466
0
                if (arg->exprId() == 0)
5467
0
                    continue;
5468
0
                ValueFlow::Value c = inferCondition(">=", arg, 0);
5469
0
                if (!c.isKnown())
5470
0
                    continue;
5471
5472
0
                ValueFlow::Value v = makeSymbolic(arg);
5473
0
                v.errorPath = c.errorPath;
5474
0
                v.errorPath.emplace_back(tok, "Passed to " + tok->str());
5475
0
                if (c.intvalue == 0)
5476
0
                    v.setImpossible();
5477
0
                else
5478
0
                    v.setKnown();
5479
0
                setTokenValue(tok->next(), std::move(v), settings);
5480
59.8k
            } else if (Token::Match(tok, "*|/|<<|>>|^|+|-|%or%")) {
5481
2.79k
                if (!tok->astOperand1())
5482
3
                    continue;
5483
2.79k
                if (!tok->astOperand2())
5484
0
                    continue;
5485
2.79k
                if (!astIsIntegral(tok->astOperand1(), false) && !astIsIntegral(tok->astOperand2(), false))
5486
184
                    continue;
5487
2.60k
                const ValueFlow::Value* constant = nullptr;
5488
2.60k
                const Token* vartok = nullptr;
5489
2.60k
                if (tok->astOperand1()->hasKnownIntValue()) {
5490
416
                    constant = &tok->astOperand1()->values().front();
5491
416
                    vartok = tok->astOperand2();
5492
416
                }
5493
2.60k
                if (tok->astOperand2()->hasKnownIntValue()) {
5494
509
                    constant = &tok->astOperand2()->values().front();
5495
509
                    vartok = tok->astOperand1();
5496
509
                }
5497
2.60k
                if (!constant)
5498
1.68k
                    continue;
5499
924
                if (!vartok)
5500
0
                    continue;
5501
924
                if (vartok->exprId() == 0)
5502
0
                    continue;
5503
924
                if (Token::Match(tok, "<<|>>|/") && !astIsLHS(vartok))
5504
66
                    continue;
5505
858
                if (Token::Match(tok, "<<|>>|^|+|-|%or%") && constant->intvalue != 0)
5506
506
                    continue;
5507
352
                if (Token::Match(tok, "*|/") && constant->intvalue != 1)
5508
260
                    continue;
5509
92
                std::vector<ValueFlow::Value> values = {makeSymbolic(vartok)};
5510
92
                std::unordered_set<nonneg int> ids = {vartok->exprId()};
5511
92
                std::copy_if(vartok->values().cbegin(),
5512
92
                             vartok->values().cend(),
5513
92
                             std::back_inserter(values),
5514
92
                             [&](const ValueFlow::Value& v) {
5515
45
                    if (!v.isSymbolicValue())
5516
40
                        return false;
5517
5
                    if (!v.tokvalue)
5518
0
                        return false;
5519
5
                    return ids.insert(v.tokvalue->exprId()).second;
5520
5
                });
5521
92
                for (ValueFlow::Value& v : values)
5522
95
                    setTokenValue(tok, std::move(v), settings);
5523
57.0k
            } else if (Token::simpleMatch(tok, "[")) {
5524
0
                const Token* arrayTok = tok->astOperand1();
5525
0
                const Token* indexTok = tok->astOperand2();
5526
0
                if (!arrayTok)
5527
0
                    continue;
5528
0
                if (!indexTok)
5529
0
                    continue;
5530
0
                for (const ValueFlow::Value& value : indexTok->values()) {
5531
0
                    if (!value.isSymbolicValue())
5532
0
                        continue;
5533
0
                    if (value.intvalue != 0)
5534
0
                        continue;
5535
0
                    const Token* strlenTok = isStrlenOf(value.tokvalue, arrayTok);
5536
0
                    if (!strlenTok)
5537
0
                        continue;
5538
0
                    ValueFlow::Value v = value;
5539
0
                    v.bound = ValueFlow::Value::Bound::Point;
5540
0
                    v.valueType = ValueFlow::Value::ValueType::INT;
5541
0
                    v.errorPath.emplace_back(strlenTok, "Return index of first '\\0' character in string");
5542
0
                    setTokenValue(tok, std::move(v), settings);
5543
0
                }
5544
0
            }
5545
59.8k
        }
5546
2.90k
    }
5547
2.27k
}
5548
5549
struct SymbolicInferModel : InferModel {
5550
    const Token* expr;
5551
5.47k
    explicit SymbolicInferModel(const Token* tok) : expr(tok) {
5552
5.47k
        assert(expr->exprId() != 0);
5553
5.47k
    }
5554
    bool match(const ValueFlow::Value& value) const override
5555
6.61k
    {
5556
6.61k
        return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId();
5557
6.61k
    }
5558
    ValueFlow::Value yield(MathLib::bigint value) const override
5559
5.47k
    {
5560
5.47k
        ValueFlow::Value result(value);
5561
5.47k
        result.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
5562
5.47k
        result.tokvalue = expr;
5563
5.47k
        result.setKnown();
5564
5.47k
        return result;
5565
5.47k
    }
5566
};
5567
5568
static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings* settings)
5569
2.27k
{
5570
2.90k
    for (const Scope* scope : symboldatabase.functionScopes) {
5571
69.6k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5572
66.7k
            if (!Token::Match(tok, "-|%comp%"))
5573
62.4k
                continue;
5574
4.37k
            if (tok->hasKnownIntValue())
5575
591
                continue;
5576
3.78k
            if (!tok->astOperand1())
5577
0
                continue;
5578
3.78k
            if (!tok->astOperand2())
5579
0
                continue;
5580
3.78k
            if (tok->astOperand1()->exprId() == 0)
5581
361
                continue;
5582
3.42k
            if (tok->astOperand2()->exprId() == 0)
5583
353
                continue;
5584
3.07k
            if (tok->astOperand1()->hasKnownIntValue())
5585
206
                continue;
5586
2.86k
            if (tok->astOperand2()->hasKnownIntValue())
5587
127
                continue;
5588
2.73k
            if (astIsFloat(tok->astOperand1(), false))
5589
0
                continue;
5590
2.73k
            if (astIsFloat(tok->astOperand2(), false))
5591
0
                continue;
5592
5593
2.73k
            SymbolicInferModel leftModel{tok->astOperand1()};
5594
2.73k
            std::vector<ValueFlow::Value> values = infer(leftModel, tok->str(), 0, tok->astOperand2()->values());
5595
2.73k
            if (values.empty()) {
5596
2.73k
                SymbolicInferModel rightModel{tok->astOperand2()};
5597
2.73k
                values = infer(rightModel, tok->str(), tok->astOperand1()->values(), 0);
5598
2.73k
            }
5599
2.73k
            for (ValueFlow::Value& value : values) {
5600
6
                setTokenValue(tok, std::move(value), settings);
5601
6
            }
5602
2.73k
        }
5603
2.90k
    }
5604
2.27k
}
5605
5606
template<class ContainerOfValue>
5607
static void valueFlowForwardConst(Token* start,
5608
                                  const Token* end,
5609
                                  const Variable* var,
5610
                                  const ContainerOfValue& values,
5611
                                  const Settings* const settings,
5612
                                  int /*unused*/ = 0)
5613
0
{
5614
0
    if (!precedes(start, end))
5615
0
        throw InternalError(var->nameToken(), "valueFlowForwardConst: start token does not precede the end token.");
5616
0
    for (Token* tok = start; tok != end; tok = tok->next()) {
5617
0
        if (tok->varId() == var->declarationId()) {
5618
0
            for (const ValueFlow::Value& value : values)
5619
0
                setTokenValue(tok, value, settings);
5620
0
        } else {
5621
0
            [&] {
5622
                // Follow references
5623
0
                auto refs = followAllReferences(tok);
5624
0
                auto it = std::find_if(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
5625
0
                    return ref.token->varId() == var->declarationId();
5626
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
5627
0
                if (it != refs.end()) {
5628
0
                    for (ValueFlow::Value value : values) {
5629
0
                        if (refs.size() > 1)
5630
0
                            value.setInconclusive();
5631
0
                        value.errorPath.insert(value.errorPath.end(), it->errors.cbegin(), it->errors.cend());
5632
0
                        setTokenValue(tok, std::move(value), settings);
5633
0
                    }
5634
0
                    return;
5635
0
                }
5636
                // Follow symbolic values
5637
0
                for (const ValueFlow::Value& v : tok->values()) {
5638
0
                    if (!v.isSymbolicValue())
5639
0
                        continue;
5640
0
                    if (!v.tokvalue)
5641
0
                        continue;
5642
0
                    if (v.tokvalue->varId() != var->declarationId())
5643
0
                        continue;
5644
0
                    for (ValueFlow::Value value : values) {
5645
0
                        if (v.intvalue != 0) {
5646
0
                            if (!value.isIntValue())
5647
0
                                continue;
5648
0
                            value.intvalue += v.intvalue;
5649
0
                        }
5650
0
                        value.valueKind = v.valueKind;
5651
0
                        value.bound = v.bound;
5652
0
                        value.errorPath.insert(value.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
5653
0
                        setTokenValue(tok, std::move(value), settings);
5654
0
                    }
5655
0
                }
5656
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
5657
0
        }
5658
0
    }
5659
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)
5660
5661
static void valueFlowForwardConst(Token* start,
5662
                                  const Token* end,
5663
                                  const Variable* var,
5664
                                  const std::initializer_list<ValueFlow::Value>& values,
5665
                                  const Settings* const settings)
5666
0
{
5667
0
    valueFlowForwardConst(start, end, var, values, settings, 0);
5668
0
}
5669
5670
static void valueFlowForwardAssign(Token* const tok,
5671
                                   const Token* expr,
5672
                                   std::vector<const Variable*> vars,
5673
                                   std::list<ValueFlow::Value> values,
5674
                                   const bool init,
5675
                                   TokenList& tokenlist,
5676
                                   ErrorLogger* const errorLogger,
5677
                                   const Settings* const settings)
5678
749
{
5679
749
    if (Token::simpleMatch(tok->astParent(), "return"))
5680
0
        return;
5681
749
    const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
5682
749
    if (std::any_of(values.cbegin(), values.cend(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
5683
0
        valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
5684
0
        values.remove_if(std::mem_fn(&ValueFlow::Value::isLifetimeValue));
5685
0
    }
5686
749
    if (std::all_of(
5687
749
            vars.cbegin(), vars.cend(), [&](const Variable* var) {
5688
625
        return !var->isPointer() && !var->isSmartPointer();
5689
625
    }))
5690
749
        values.remove_if(std::mem_fn(&ValueFlow::Value::isTokValue));
5691
749
    if (tok->astParent()) {
5692
954
        for (ValueFlow::Value& value : values) {
5693
954
            std::string valueKind;
5694
954
            if (value.valueKind == ValueFlow::Value::ValueKind::Impossible) {
5695
423
                if (value.bound == ValueFlow::Value::Bound::Point)
5696
4
                    valueKind = "never ";
5697
419
                else if (value.bound == ValueFlow::Value::Bound::Lower)
5698
226
                    valueKind = "less than ";
5699
193
                else if (value.bound == ValueFlow::Value::Bound::Upper)
5700
193
                    valueKind = "greater than ";
5701
423
            }
5702
954
            std::string info = "Assignment '" + tok->astParent()->expressionString() + "', assigned value is " + valueKind + value.infoString();
5703
954
            value.errorPath.emplace_back(tok, std::move(info));
5704
954
        }
5705
749
    }
5706
5707
749
    if (tokenlist.isCPP() && vars.size() == 1 && Token::Match(vars.front()->typeStartToken(), "bool|_Bool")) {
5708
0
        for (ValueFlow::Value& value : values) {
5709
0
            if (value.isImpossible())
5710
0
                continue;
5711
0
            if (value.isIntValue())
5712
0
                value.intvalue = (value.intvalue != 0);
5713
0
            if (value.isTokValue())
5714
0
                value.intvalue = (value.tokvalue != nullptr);
5715
0
        }
5716
0
    }
5717
5718
    // Static variable initialisation?
5719
749
    if (vars.size() == 1 && vars.front()->isStatic() && init)
5720
0
        lowerToPossible(values);
5721
5722
    // is volatile
5723
749
    if (std::any_of(vars.cbegin(), vars.cend(), [&](const Variable* var) {
5724
625
        return var->isVolatile();
5725
625
    }))
5726
0
        lowerToPossible(values);
5727
5728
    // Skip RHS
5729
749
    const Token * nextExpression = tok->astParent() ? nextAfterAstRightmostLeaf(tok->astParent()) : tok->next();
5730
749
    if (!nextExpression)
5731
0
        return;
5732
5733
954
    for (ValueFlow::Value& value : values) {
5734
954
        if (value.isSymbolicValue())
5735
61
            continue;
5736
893
        if (value.isTokValue())
5737
0
            continue;
5738
893
        value.tokvalue = tok;
5739
893
    }
5740
    // Const variable
5741
749
    if (expr->variable() && expr->variable()->isConst() && !expr->variable()->isReference()) {
5742
0
        auto it = std::remove_if(values.begin(), values.end(), [](const ValueFlow::Value& value) {
5743
0
            if (!value.isKnown())
5744
0
                return false;
5745
0
            if (value.isIntValue())
5746
0
                return true;
5747
0
            if (value.isFloatValue())
5748
0
                return true;
5749
0
            if (value.isContainerSizeValue())
5750
0
                return true;
5751
0
            if (value.isIteratorValue())
5752
0
                return true;
5753
0
            return false;
5754
0
        });
5755
0
        std::list<ValueFlow::Value> constValues;
5756
0
        constValues.splice(constValues.end(), values, it, values.end());
5757
0
        valueFlowForwardConst(const_cast<Token*>(nextExpression), endOfVarScope, expr->variable(), constValues, settings);
5758
0
    }
5759
749
    valueFlowForward(const_cast<Token*>(nextExpression), endOfVarScope, expr, values, tokenlist, settings);
5760
749
}
5761
5762
static void valueFlowForwardAssign(Token* const tok,
5763
                                   const Variable* const var,
5764
                                   const std::list<ValueFlow::Value>& values,
5765
                                   const bool /*unused*/,
5766
                                   const bool init,
5767
                                   TokenList& tokenlist,
5768
                                   ErrorLogger* const errorLogger,
5769
                                   const Settings* const settings)
5770
0
{
5771
0
    valueFlowForwardAssign(tok, var->nameToken(), {var}, values, init, tokenlist, errorLogger, settings);
5772
0
}
5773
5774
static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> values,
5775
                                                  const ValueType* dst,
5776
                                                  const ValueType* src,
5777
                                                  const Settings* settings)
5778
749
{
5779
749
    if (!dst || !dst->isIntegral())
5780
124
        return values;
5781
5782
625
    const size_t sz = ValueFlow::getSizeOf(*dst, settings);
5783
5784
625
    if (src) {
5785
611
        const size_t osz = ValueFlow::getSizeOf(*src, settings);
5786
611
        if (osz >= sz && dst->sign == ValueType::Sign::SIGNED && src->sign == ValueType::Sign::UNSIGNED) {
5787
0
            values.remove_if([&](const ValueFlow::Value& value) {
5788
0
                if (!value.isIntValue())
5789
0
                    return false;
5790
0
                if (!value.isImpossible())
5791
0
                    return false;
5792
0
                if (value.bound != ValueFlow::Value::Bound::Upper)
5793
0
                    return false;
5794
0
                if (osz == sz && value.intvalue < 0)
5795
0
                    return true;
5796
0
                if (osz > sz)
5797
0
                    return true;
5798
0
                return false;
5799
0
            });
5800
0
        }
5801
611
    }
5802
5803
790
    for (ValueFlow::Value &value : values) {
5804
        // Don't truncate impossible values since those can be outside of the valid range
5805
790
        if (value.isImpossible())
5806
347
            continue;
5807
443
        if (value.isFloatValue()) {
5808
0
            value.intvalue = value.floatValue;
5809
0
            value.valueType = ValueFlow::Value::ValueType::INT;
5810
0
        }
5811
5812
443
        if (value.isIntValue() && sz > 0 && sz < 8) {
5813
414
            const MathLib::biguint unsignedMaxValue = (1ULL << (sz * 8)) - 1ULL;
5814
414
            const MathLib::biguint signBit = 1ULL << (sz * 8 - 1);
5815
414
            value.intvalue &= unsignedMaxValue;
5816
414
            if (dst->sign == ValueType::Sign::SIGNED && (value.intvalue & signBit))
5817
34
                value.intvalue |= ~unsignedMaxValue;
5818
414
        }
5819
443
    }
5820
625
    return values;
5821
749
}
5822
5823
static bool isVariableInit(const Token *tok)
5824
63.3k
{
5825
63.3k
    return (tok->str() == "(" || tok->str() == "{") &&
5826
63.3k
           (tok->isBinaryOp() || (tok->astOperand1() && tok->link() == tok->next())) &&
5827
63.3k
           tok->astOperand1()->variable() &&
5828
63.3k
           tok->astOperand1()->variable()->nameToken() == tok->astOperand1() &&
5829
63.3k
           tok->astOperand1()->variable()->valueType() &&
5830
63.3k
           tok->astOperand1()->variable()->valueType()->type >= ValueType::Type::VOID &&
5831
63.3k
           !Token::simpleMatch(tok->astOperand2(), ",");
5832
63.3k
}
5833
5834
// Return true if two associative containers intersect
5835
template<class C1, class C2>
5836
static bool intersects(const C1& c1, const C2& c2)
5837
61
{
5838
61
    if (c1.size() > c2.size())
5839
0
        return intersects(c2, c1);
5840
    // NOLINTNEXTLINE(readability-use-anyofallof) - TODO: fix if possible / also Cppcheck false negative
5841
61
    for (auto&& x : c1) {
5842
15
        if (c2.find(x) != c2.end())
5843
15
            return true;
5844
15
    }
5845
46
    return false;
5846
61
}
5847
5848
static void valueFlowAfterAssign(TokenList &tokenlist,
5849
                                 const SymbolDatabase& symboldatabase,
5850
                                 ErrorLogger *errorLogger,
5851
                                 const Settings *settings,
5852
                                 const std::set<const Scope*>& skippedFunctions)
5853
2.27k
{
5854
2.90k
    for (const Scope * scope : symboldatabase.functionScopes) {
5855
2.90k
        if (skippedFunctions.count(scope))
5856
0
            continue;
5857
2.90k
        std::unordered_map<nonneg int, std::unordered_set<nonneg int>> backAssigns;
5858
69.6k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5859
            // Assignment
5860
66.7k
            bool isInit = false;
5861
66.7k
            if (tok->str() != "=" && !(isInit = isVariableInit(tok)))
5862
63.3k
                continue;
5863
5864
3.43k
            if (tok->astParent() && !((tok->astParent()->str() == ";" && astIsLHS(tok)) || tok->astParent()->str() == "*"))
5865
619
                continue;
5866
5867
            // Lhs should be a variable
5868
2.81k
            if (!tok->astOperand1() || !tok->astOperand1()->exprId())
5869
0
                continue;
5870
2.81k
            std::vector<const Variable*> vars = getLHSVariables(tok);
5871
5872
            // Rhs values..
5873
2.81k
            Token* rhs = tok->astOperand2();
5874
2.81k
            if (!rhs && isInit)
5875
0
                rhs = tok;
5876
2.81k
            if (!rhs || rhs->values().empty())
5877
2.06k
                continue;
5878
5879
749
            std::list<ValueFlow::Value> values = truncateValues(
5880
749
                rhs->values(), tok->astOperand1()->valueType(), rhs->valueType(), settings);
5881
            // Remove known values
5882
749
            std::set<ValueFlow::Value::ValueType> types;
5883
749
            if (tok->astOperand1()->hasKnownValue()) {
5884
0
                for (const ValueFlow::Value& value:tok->astOperand1()->values()) {
5885
0
                    if (value.isKnown() && !value.isSymbolicValue())
5886
0
                        types.insert(value.valueType);
5887
0
                }
5888
0
            }
5889
954
            values.remove_if([&](const ValueFlow::Value& value) {
5890
954
                return types.count(value.valueType) > 0;
5891
954
            });
5892
            // Remove container size if its not a container
5893
749
            if (!astIsContainer(tok->astOperand2()))
5894
954
                values.remove_if([&](const ValueFlow::Value& value) {
5895
954
                    return value.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE;
5896
954
                });
5897
            // Remove symbolic values that are the same as the LHS
5898
954
            values.remove_if([&](const ValueFlow::Value& value) {
5899
954
                if (value.isSymbolicValue() && value.tokvalue)
5900
61
                    return value.tokvalue->exprId() == tok->astOperand1()->exprId();
5901
893
                return false;
5902
954
            });
5903
            // Find references to LHS in RHS
5904
794
            auto isIncremental = [&](const Token* tok2) -> bool {
5905
794
                return findAstNode(tok2,
5906
2.15k
                                   [&](const Token* child) {
5907
2.15k
                    return child->exprId() == tok->astOperand1()->exprId();
5908
2.15k
                });
5909
794
            };
5910
            // Check symbolic values as well
5911
749
            const bool incremental = isIncremental(tok->astOperand2()) ||
5912
839
                                     std::any_of(values.cbegin(), values.cend(), [&](const ValueFlow::Value& value) {
5913
839
                if (!value.isSymbolicValue())
5914
794
                    return false;
5915
45
                return isIncremental(value.tokvalue);
5916
839
            });
5917
            // Remove values from the same assignment if it is incremental
5918
749
            if (incremental) {
5919
115
                values.remove_if([&](const ValueFlow::Value& value) {
5920
115
                    if (value.tokvalue)
5921
30
                        return value.tokvalue == tok->astOperand2();
5922
85
                    return false;
5923
115
                });
5924
80
            }
5925
            // If assignment copy by value, remove Uninit values..
5926
749
            if ((tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->pointer == 0) ||
5927
749
                (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isReference() && tok->astOperand1()->variable()->nameToken() == tok->astOperand1()))
5928
790
                values.remove_if([&](const ValueFlow::Value& value) {
5929
790
                    return value.isUninitValue();
5930
790
                });
5931
749
            if (values.empty())
5932
0
                continue;
5933
749
            const bool init = vars.size() == 1 && (vars.front()->nameToken() == tok->astOperand1() || tok->isSplittedVarDeclEq());
5934
749
            valueFlowForwardAssign(
5935
749
                rhs, tok->astOperand1(), vars, values, init, tokenlist, errorLogger, settings);
5936
            // Back propagate symbolic values
5937
749
            if (tok->astOperand1()->exprId() > 0) {
5938
749
                Token* start = nextAfterAstRightmostLeaf(tok);
5939
749
                const Token* end = scope->bodyEnd;
5940
                // Collect symbolic ids
5941
749
                std::unordered_set<nonneg int> ids;
5942
954
                for (const ValueFlow::Value& value : values) {
5943
954
                    if (!value.isSymbolicValue())
5944
893
                        continue;
5945
61
                    if (!value.tokvalue)
5946
0
                        continue;
5947
61
                    if (value.tokvalue->exprId() == 0)
5948
0
                        continue;
5949
61
                    ids.insert(value.tokvalue->exprId());
5950
61
                }
5951
954
                for (ValueFlow::Value value : values) {
5952
954
                    if (!value.isSymbolicValue())
5953
893
                        continue;
5954
61
                    const Token* expr = value.tokvalue;
5955
61
                    value.intvalue = -value.intvalue;
5956
61
                    value.tokvalue = tok->astOperand1();
5957
5958
                    // Skip if it intersects with an already assigned symbol
5959
61
                    auto& s = backAssigns[value.tokvalue->exprId()];
5960
61
                    if (intersects(s, ids))
5961
15
                        continue;
5962
46
                    s.insert(expr->exprId());
5963
5964
46
                    value.errorPath.emplace_back(tok,
5965
46
                                                 tok->astOperand1()->expressionString() + " is assigned '" +
5966
46
                                                 tok->astOperand2()->expressionString() + "' here.");
5967
46
                    valueFlowForward(start, end, expr, value, tokenlist, settings);
5968
46
                }
5969
749
            }
5970
749
        }
5971
2.90k
    }
5972
2.27k
}
5973
5974
static std::vector<const Variable*> getVariables(const Token* tok)
5975
0
{
5976
0
    std::vector<const Variable*> result;
5977
0
    visitAstNodes(tok, [&](const Token* child) {
5978
0
        if (child->variable())
5979
0
            result.push_back(child->variable());
5980
0
        return ChildrenToVisit::op1_and_op2;
5981
0
    });
5982
0
    return result;
5983
0
}
5984
5985
static void valueFlowAfterSwap(TokenList& tokenlist,
5986
                               const SymbolDatabase& symboldatabase,
5987
                               ErrorLogger* errorLogger,
5988
                               const Settings* settings)
5989
2.27k
{
5990
2.90k
    for (const Scope* scope : symboldatabase.functionScopes) {
5991
69.6k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5992
66.7k
            if (!Token::simpleMatch(tok, "swap ("))
5993
66.7k
                continue;
5994
0
            if (!Token::simpleMatch(tok->next()->astOperand2(), ","))
5995
0
                continue;
5996
0
            std::vector<Token*> args = astFlatten(tok->next()->astOperand2(), ",");
5997
0
            if (args.size() != 2)
5998
0
                continue;
5999
0
            if (args[0]->exprId() == 0)
6000
0
                continue;
6001
0
            if (args[1]->exprId() == 0)
6002
0
                continue;
6003
0
            for (int i = 0; i < 2; i++) {
6004
0
                std::vector<const Variable*> vars = getVariables(args[0]);
6005
0
                const std::list<ValueFlow::Value>& values = args[0]->values();
6006
0
                valueFlowForwardAssign(args[0], args[1], vars, values, false, tokenlist, errorLogger, settings);
6007
0
                std::swap(args[0], args[1]);
6008
0
            }
6009
0
        }
6010
2.90k
    }
6011
2.27k
}
6012
6013
static void valueFlowSetConditionToKnown(const Token* tok, std::list<ValueFlow::Value>& values, bool then)
6014
2.77k
{
6015
2.77k
    if (values.empty())
6016
0
        return;
6017
2.77k
    if (then && !Token::Match(tok, "==|!|("))
6018
1.77k
        return;
6019
1.00k
    if (!then && !Token::Match(tok, "!=|%var%|("))
6020
699
        return;
6021
304
    if (isConditionKnown(tok, then))
6022
304
        changePossibleToKnown(values);
6023
304
}
6024
6025
static bool isBreakScope(const Token* const endToken)
6026
220
{
6027
220
    if (!Token::simpleMatch(endToken, "}"))
6028
0
        return false;
6029
220
    if (!Token::simpleMatch(endToken->link(), "{"))
6030
0
        return false;
6031
220
    return Token::findmatch(endToken->link(), "break|goto", endToken);
6032
220
}
6033
6034
ValueFlow::Value ValueFlow::asImpossible(ValueFlow::Value v)
6035
2.82k
{
6036
2.82k
    v.invertRange();
6037
2.82k
    v.setImpossible();
6038
2.82k
    return v;
6039
2.82k
}
6040
6041
static void insertImpossible(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
6042
2.77k
{
6043
2.77k
    std::transform(input.cbegin(), input.cend(), std::back_inserter(values), &ValueFlow::asImpossible);
6044
2.77k
}
6045
6046
static void insertNegateKnown(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
6047
166
{
6048
166
    for (ValueFlow::Value value:input) {
6049
166
        if (!value.isIntValue() && !value.isContainerSizeValue())
6050
112
            continue;
6051
54
        value.intvalue = !value.intvalue;
6052
54
        value.setKnown();
6053
54
        values.push_back(std::move(value));
6054
54
    }
6055
166
}
6056
6057
struct ConditionHandler {
6058
    struct Condition {
6059
        const Token* vartok{};
6060
        std::list<ValueFlow::Value> true_values;
6061
        std::list<ValueFlow::Value> false_values;
6062
        bool inverted = false;
6063
        // Whether to insert impossible values for the condition or only use possible values
6064
        bool impossible = true;
6065
6066
1.57k
        bool isBool() const {
6067
1.57k
            return astIsBool(vartok);
6068
1.57k
        }
6069
6070
        static MathLib::bigint findPath(const std::list<ValueFlow::Value>& values)
6071
22.9k
        {
6072
22.9k
            auto it = std::find_if(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) {
6073
22.9k
                return v.path > 0;
6074
22.9k
            });
6075
22.9k
            if (it == values.end())
6076
22.9k
                return 0;
6077
0
            assert(std::all_of(it, values.end(), [&](const ValueFlow::Value& v) {
6078
0
                return v.path == 0 || v.path == it->path;
6079
0
            }));
6080
0
            return it->path;
6081
22.9k
        }
6082
6083
        MathLib::bigint getPath() const
6084
5.74k
        {
6085
5.74k
            assert(std::abs(findPath(true_values) - findPath(false_values)) == 0);
6086
0
            return findPath(true_values) | findPath(false_values);
6087
5.74k
        }
6088
6089
        Token* getContextAndValues(Token* condTok,
6090
                                   std::list<ValueFlow::Value>& thenValues,
6091
                                   std::list<ValueFlow::Value>& elseValues,
6092
                                   bool known = false) const
6093
2.87k
        {
6094
2.87k
            const MathLib::bigint path = getPath();
6095
2.87k
            const bool allowKnown = path == 0;
6096
2.87k
            const bool allowImpossible = impossible && allowKnown;
6097
6098
2.87k
            bool inverted2 = inverted;
6099
2.87k
            Token* ctx = skipNotAndCasts(condTok, &inverted2);
6100
2.87k
            bool then = !inverted || !inverted2;
6101
6102
2.87k
            if (!Token::Match(condTok, "!=|=|(|.") && condTok != vartok) {
6103
2.24k
                thenValues.insert(thenValues.end(), true_values.cbegin(), true_values.cend());
6104
2.24k
                if (allowImpossible && (known || isConditionKnown(ctx, !then)))
6105
1.20k
                    insertImpossible(elseValues, false_values);
6106
2.24k
            }
6107
2.87k
            if (!Token::Match(condTok, "==|!")) {
6108
2.58k
                elseValues.insert(elseValues.end(), false_values.cbegin(), false_values.cend());
6109
2.58k
                if (allowImpossible && (known || isConditionKnown(ctx, then))) {
6110
1.57k
                    insertImpossible(thenValues, true_values);
6111
1.57k
                    if (isBool())
6112
166
                        insertNegateKnown(thenValues, true_values);
6113
1.57k
                }
6114
2.58k
            }
6115
6116
2.87k
            if (inverted2)
6117
6
                std::swap(thenValues, elseValues);
6118
6119
2.87k
            return ctx;
6120
2.87k
        }
6121
    };
6122
6123
    virtual std::vector<Condition> parse(const Token* tok, const Settings* settings) const = 0;
6124
6125
    virtual Analyzer::Result forward(Token* start,
6126
                                     const Token* stop,
6127
                                     const Token* exprTok,
6128
                                     const std::list<ValueFlow::Value>& values,
6129
                                     TokenList& tokenlist,
6130
                                     const Settings* settings,
6131
                                     SourceLocation loc = SourceLocation::current()) const
6132
2.83k
    {
6133
2.83k
        return valueFlowForward(start->next(), stop, exprTok, values, tokenlist, settings, loc);
6134
2.83k
    }
6135
6136
    virtual Analyzer::Result forward(Token* top,
6137
                                     const Token* exprTok,
6138
                                     const std::list<ValueFlow::Value>& values,
6139
                                     TokenList& tokenlist,
6140
                                     const Settings* settings,
6141
                                     SourceLocation loc = SourceLocation::current()) const
6142
0
    {
6143
0
        return valueFlowForwardRecursive(top, exprTok, values, tokenlist, settings, loc);
6144
0
    }
6145
6146
    virtual void reverse(Token* start,
6147
                         const Token* endToken,
6148
                         const Token* exprTok,
6149
                         const std::list<ValueFlow::Value>& values,
6150
                         TokenList& tokenlist,
6151
                         const Settings* settings,
6152
                         SourceLocation loc = SourceLocation::current()) const
6153
1.79k
    {
6154
1.79k
        return valueFlowReverse(start, endToken, exprTok, values, tokenlist, settings, loc);
6155
1.79k
    }
6156
6157
    void traverseCondition(const TokenList& tokenlist,
6158
                           const SymbolDatabase& symboldatabase,
6159
                           const Settings* settings,
6160
                           const std::set<const Scope*>& skippedFunctions,
6161
                           const std::function<void(const Condition& cond, Token* tok, const Scope* scope)>& f) const
6162
18.1k
    {
6163
23.2k
        for (const Scope *scope : symboldatabase.functionScopes) {
6164
23.2k
            if (skippedFunctions.count(scope))
6165
0
                continue;
6166
557k
            for (Token *tok = const_cast<Token *>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
6167
534k
                if (Token::Match(tok, "if|while|for ("))
6168
21.6k
                    continue;
6169
512k
                if (Token::Match(tok, ":|;|,"))
6170
48.2k
                    continue;
6171
6172
464k
                const Token* top = tok->astTop();
6173
464k
                if (!top)
6174
0
                    continue;
6175
6176
464k
                if (!Token::Match(top->previous(), "if|while|for (") && !Token::Match(tok->astParent(), "&&|%oror%|?|!"))
6177
305k
                    continue;
6178
158k
                for (const Condition& cond : parse(tok, settings)) {
6179
46.6k
                    if (!cond.vartok)
6180
39.6k
                        continue;
6181
6.93k
                    if (cond.vartok->exprId() == 0)
6182
0
                        continue;
6183
6.93k
                    if (cond.vartok->hasKnownIntValue())
6184
78
                        continue;
6185
6.86k
                    if (cond.true_values.empty() || cond.false_values.empty())
6186
0
                        continue;
6187
6.86k
                    if (!isConstExpression(cond.vartok, settings->library, tokenlist.isCPP()))
6188
1.11k
                        continue;
6189
5.74k
                    f(cond, tok, scope);
6190
5.74k
                }
6191
158k
            }
6192
23.2k
        }
6193
18.1k
    }
6194
6195
    void beforeCondition(TokenList& tokenlist,
6196
                         const SymbolDatabase& symboldatabase,
6197
                         ErrorLogger* errorLogger,
6198
                         const Settings* settings,
6199
9.09k
                         const std::set<const Scope*>& skippedFunctions) const {
6200
9.09k
        traverseCondition(tokenlist, symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* tok, const Scope*) {
6201
2.87k
            if (cond.vartok->exprId() == 0)
6202
0
                return;
6203
6204
            // If condition is known then don't propagate value
6205
2.87k
            if (tok->hasKnownIntValue())
6206
66
                return;
6207
6208
2.80k
            Token* top = tok->astTop();
6209
6210
2.80k
            if (Token::Match(top, "%assign%"))
6211
0
                return;
6212
2.80k
            if (Token::Match(cond.vartok->astParent(), "%assign%|++|--"))
6213
110
                return;
6214
6215
2.69k
            if (Token::simpleMatch(tok->astParent(), "?") && tok->astParent()->isExpandedMacro()) {
6216
0
                if (settings->debugwarnings)
6217
0
                    bailout(tokenlist,
6218
0
                            errorLogger,
6219
0
                            tok,
6220
0
                            "variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
6221
0
                return;
6222
0
            }
6223
6224
            // if,macro => bailout
6225
2.69k
            if (Token::simpleMatch(top->previous(), "if (") && top->previous()->isExpandedMacro()) {
6226
0
                if (settings->debugwarnings)
6227
0
                    bailout(tokenlist,
6228
0
                            errorLogger,
6229
0
                            tok,
6230
0
                            "variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
6231
0
                return;
6232
0
            }
6233
6234
2.69k
            std::list<ValueFlow::Value> values = cond.true_values;
6235
2.69k
            if (cond.true_values != cond.false_values)
6236
1.92k
                values.insert(values.end(), cond.false_values.cbegin(), cond.false_values.cend());
6237
6238
            // extra logic for unsigned variables 'i>=1' => possible value can also be 0
6239
2.69k
            if (Token::Match(tok, "<|>")) {
6240
2.36k
                values.remove_if([](const ValueFlow::Value& v) {
6241
2.36k
                    if (v.isIntValue())
6242
528
                        return v.intvalue != 0;
6243
1.84k
                    return false;
6244
2.36k
                });
6245
1.18k
                if (cond.vartok->valueType() && cond.vartok->valueType()->sign != ValueType::Sign::UNSIGNED)
6246
768
                    return;
6247
1.18k
            }
6248
1.92k
            if (values.empty())
6249
70
                return;
6250
6251
            // bailout: for/while-condition, variable is changed in while loop
6252
1.85k
            if (Token::Match(top->previous(), "for|while (") && Token::simpleMatch(top->link(), ") {")) {
6253
6254
                // Variable changed in 3rd for-expression
6255
765
                if (Token::simpleMatch(top->previous(), "for (")) {
6256
0
                    if (top->astOperand2() && top->astOperand2()->astOperand2() &&
6257
0
                        isExpressionChanged(
6258
0
                            cond.vartok, top->astOperand2()->astOperand2(), top->link(), settings, tokenlist.isCPP())) {
6259
0
                        if (settings->debugwarnings)
6260
0
                            bailout(tokenlist,
6261
0
                                    errorLogger,
6262
0
                                    tok,
6263
0
                                    "variable '" + cond.vartok->expressionString() + "' used in loop");
6264
0
                        return;
6265
0
                    }
6266
0
                }
6267
6268
                // Variable changed in loop code
6269
765
                const Token* const start = top;
6270
765
                const Token* const block = top->link()->next();
6271
765
                const Token* const end = block->link();
6272
6273
765
                if (isExpressionChanged(cond.vartok, start, end, settings, tokenlist.isCPP())) {
6274
                    // If its reassigned in loop then analyze from the end
6275
88
                    if (!Token::Match(tok, "%assign%|++|--") &&
6276
154
                        findExpression(cond.vartok->exprId(), start, end, [&](const Token* tok2) {
6277
154
                        return Token::Match(tok2->astParent(), "%assign%") && astIsLHS(tok2);
6278
154
                    })) {
6279
                        // Start at the end of the loop body
6280
24
                        Token* bodyTok = top->link()->next();
6281
24
                        reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist, settings);
6282
24
                    }
6283
88
                    if (settings->debugwarnings)
6284
88
                        bailout(tokenlist,
6285
88
                                errorLogger,
6286
88
                                tok,
6287
88
                                "variable '" + cond.vartok->expressionString() + "' used in loop");
6288
88
                    return;
6289
88
                }
6290
765
            }
6291
6292
1.77k
            Token* startTok = nullptr;
6293
1.77k
            if (astIsRHS(tok))
6294
1.39k
                startTok = tok->astParent();
6295
378
            else if (astIsLHS(tok))
6296
376
                startTok = previousBeforeAstLeftmostLeaf(tok->astParent());
6297
1.77k
            if (!startTok)
6298
2
                startTok = tok->previous();
6299
6300
1.77k
            reverse(startTok, nullptr, cond.vartok, values, tokenlist, settings);
6301
1.77k
        });
6302
9.09k
    }
6303
6304
    static Token* skipNotAndCasts(Token* tok, bool* inverted = nullptr)
6305
2.87k
    {
6306
2.88k
        for (; tok->astParent(); tok = tok->astParent()) {
6307
2.88k
            if (Token::simpleMatch(tok->astParent(), "!")) {
6308
0
                if (inverted)
6309
0
                    *inverted ^= true;
6310
0
                continue;
6311
0
            }
6312
2.88k
            if (Token::Match(tok->astParent(), "==|!=")) {
6313
84
                const Token* sibling = tok->astSibling();
6314
84
                if (sibling->hasKnownIntValue() && (astIsBool(tok) || astIsBool(sibling))) {
6315
8
                    const bool value = sibling->values().front().intvalue;
6316
8
                    if (inverted)
6317
8
                        *inverted ^= value == Token::simpleMatch(tok->astParent(), "!=");
6318
8
                    continue;
6319
8
                }
6320
84
            }
6321
2.87k
            if (tok->astParent()->isCast() && astIsBool(tok->astParent()))
6322
0
                continue;
6323
2.87k
            return tok;
6324
2.87k
        }
6325
0
        return tok;
6326
2.87k
    }
6327
6328
    static void fillFromPath(ProgramMemory& pm, const Token* top, MathLib::bigint path)
6329
0
    {
6330
0
        if (path < 1)
6331
0
            return;
6332
0
        visitAstNodes(top, [&](const Token* tok) {
6333
0
            const ValueFlow::Value* v = ValueFlow::findValue(tok->values(), nullptr, [&](const ValueFlow::Value& v) {
6334
0
                return v.path == path && isNonConditionalPossibleIntValue(v);
6335
0
            });
6336
0
            if (v == nullptr)
6337
0
                return ChildrenToVisit::op1_and_op2;
6338
0
            pm.setValue(tok, *v);
6339
0
            return ChildrenToVisit::op1_and_op2;
6340
0
        });
6341
0
    }
6342
6343
    void afterCondition(TokenList& tokenlist,
6344
                        const SymbolDatabase& symboldatabase,
6345
                        ErrorLogger* errorLogger,
6346
                        const Settings* settings,
6347
9.09k
                        const std::set<const Scope*>& skippedFunctions) const {
6348
9.09k
        traverseCondition(tokenlist, symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* condTok, const Scope* scope) {
6349
2.87k
            Token* top = condTok->astTop();
6350
6351
2.87k
            const MathLib::bigint path = cond.getPath();
6352
2.87k
            const bool allowKnown = path == 0;
6353
6354
2.87k
            std::list<ValueFlow::Value> thenValues;
6355
2.87k
            std::list<ValueFlow::Value> elseValues;
6356
6357
2.87k
            Token* ctx = cond.getContextAndValues(condTok, thenValues, elseValues);
6358
6359
2.87k
            if (Token::Match(ctx->astParent(), "%oror%|&&")) {
6360
0
                Token* parent = ctx->astParent();
6361
0
                if (astIsRHS(ctx) && astIsLHS(parent) && parent->astParent() &&
6362
0
                    parent->str() == parent->astParent()->str())
6363
0
                    parent = parent->astParent();
6364
0
                else if (!astIsLHS(ctx)) {
6365
0
                    parent = nullptr;
6366
0
                }
6367
0
                if (parent) {
6368
0
                    std::vector<Token*> nextExprs = {parent->astOperand2()};
6369
0
                    if (astIsLHS(parent) && parent->astParent() && parent->astParent()->str() == parent->str()) {
6370
0
                        nextExprs.push_back(parent->astParent()->astOperand2());
6371
0
                    }
6372
0
                    std::list<ValueFlow::Value> andValues;
6373
0
                    std::list<ValueFlow::Value> orValues;
6374
0
                    cond.getContextAndValues(condTok, andValues, orValues, true);
6375
6376
0
                    const std::string& op(parent->str());
6377
0
                    std::list<ValueFlow::Value> values;
6378
0
                    if (op == "&&")
6379
0
                        values = andValues;
6380
0
                    else if (op == "||")
6381
0
                        values = orValues;
6382
0
                    if (allowKnown && (Token::Match(condTok, "==|!=") || cond.isBool()))
6383
0
                        changePossibleToKnown(values);
6384
0
                    if (astIsFloat(cond.vartok, false) ||
6385
0
                        (!cond.vartok->valueType() &&
6386
0
                         std::all_of(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) {
6387
0
                        return v.isIntValue() || v.isFloatValue();
6388
0
                    })))
6389
0
                        values.remove_if([&](const ValueFlow::Value& v) {
6390
0
                            return v.isImpossible();
6391
0
                        });
6392
0
                    for (Token* start:nextExprs) {
6393
0
                        Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, settings);
6394
0
                        if (r.terminate != Analyzer::Terminate::None || r.action.isModified())
6395
0
                            return;
6396
0
                    }
6397
0
                }
6398
0
            }
6399
6400
2.87k
            {
6401
2.87k
                const Token* tok2 = condTok;
6402
2.87k
                std::string op;
6403
2.87k
                bool mixedOperators = false;
6404
7.34k
                while (tok2->astParent()) {
6405
4.47k
                    const Token* parent = tok2->astParent();
6406
4.47k
                    if (Token::Match(parent, "%oror%|&&")) {
6407
0
                        if (op.empty()) {
6408
0
                            op = parent->str();
6409
0
                        } else if (op != parent->str()) {
6410
0
                            mixedOperators = true;
6411
0
                            break;
6412
0
                        }
6413
0
                    }
6414
4.47k
                    if (parent->str() == "!") {
6415
0
                        op = (op == "&&" ? "||" : "&&");
6416
0
                    }
6417
4.47k
                    tok2 = parent;
6418
4.47k
                }
6419
6420
2.87k
                if (mixedOperators) {
6421
0
                    return;
6422
0
                }
6423
2.87k
            }
6424
6425
2.87k
            if (!top)
6426
0
                return;
6427
6428
2.87k
            if (top->previous()->isExpandedMacro()) {
6429
0
                for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
6430
0
                    for (ValueFlow::Value& v : *values)
6431
0
                        v.macro = true;
6432
0
                }
6433
0
            }
6434
6435
2.87k
            Token* condTop = ctx->astParent();
6436
2.87k
            {
6437
2.87k
                bool inverted2 = false;
6438
2.87k
                while (Token::Match(condTop, "%oror%|&&")) {
6439
0
                    Token* parent = skipNotAndCasts(condTop, &inverted2)->astParent();
6440
0
                    if (!parent)
6441
0
                        break;
6442
0
                    condTop = parent;
6443
0
                }
6444
2.87k
                if (inverted2)
6445
0
                    std::swap(thenValues, elseValues);
6446
2.87k
            }
6447
6448
2.87k
            if (!condTop)
6449
0
                return;
6450
6451
2.87k
            if (Token::simpleMatch(condTop, "?")) {
6452
0
                Token* colon = condTop->astOperand2();
6453
0
                forward(colon->astOperand1(), cond.vartok, thenValues, tokenlist, settings);
6454
0
                forward(colon->astOperand2(), cond.vartok, elseValues, tokenlist, settings);
6455
                // TODO: Handle after condition
6456
0
                return;
6457
0
            }
6458
6459
2.87k
            if (condTop != top && condTop->str() != ";")
6460
1.10k
                return;
6461
6462
1.76k
            if (!Token::Match(top->previous(), "if|while|for ("))
6463
0
                return;
6464
6465
1.76k
            if (top->previous()->str() == "for") {
6466
0
                if (!Token::Match(condTok, "%comp%"))
6467
0
                    return;
6468
0
                if (!Token::simpleMatch(condTok->astParent(), ";"))
6469
0
                    return;
6470
0
                const Token* stepTok = getStepTok(top);
6471
0
                if (cond.vartok->varId() == 0)
6472
0
                    return;
6473
0
                if (!cond.vartok->variable())
6474
0
                    return;
6475
0
                if (!Token::Match(stepTok, "++|--"))
6476
0
                    return;
6477
0
                std::set<ValueFlow::Value::Bound> bounds;
6478
0
                for (const ValueFlow::Value& v : thenValues) {
6479
0
                    if (v.bound != ValueFlow::Value::Bound::Point && v.isImpossible())
6480
0
                        continue;
6481
0
                    bounds.insert(v.bound);
6482
0
                }
6483
0
                if (Token::simpleMatch(stepTok, "++") && bounds.count(ValueFlow::Value::Bound::Lower) > 0)
6484
0
                    return;
6485
0
                if (Token::simpleMatch(stepTok, "--") && bounds.count(ValueFlow::Value::Bound::Upper) > 0)
6486
0
                    return;
6487
0
                const Token* childTok = condTok->astOperand1();
6488
0
                if (!childTok)
6489
0
                    childTok = condTok->astOperand2();
6490
0
                if (!childTok)
6491
0
                    return;
6492
0
                if (childTok->varId() != cond.vartok->varId())
6493
0
                    return;
6494
0
                const Token* startBlock = top->link()->next();
6495
0
                if (isVariableChanged(startBlock,
6496
0
                                      startBlock->link(),
6497
0
                                      cond.vartok->varId(),
6498
0
                                      cond.vartok->variable()->isGlobal(),
6499
0
                                      settings,
6500
0
                                      tokenlist.isCPP()))
6501
0
                    return;
6502
                // Check if condition in for loop is always false
6503
0
                const Token* initTok = getInitTok(top);
6504
0
                ProgramMemory pm;
6505
0
                fillFromPath(pm, initTok, path);
6506
0
                fillFromPath(pm, condTok, path);
6507
0
                execute(initTok, pm, nullptr, nullptr);
6508
0
                MathLib::bigint result = 1;
6509
0
                execute(condTok, pm, &result, nullptr);
6510
0
                if (result == 0)
6511
0
                    return;
6512
                // Remove condition since for condition is not redundant
6513
0
                for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
6514
0
                    for (ValueFlow::Value& v : *values) {
6515
0
                        v.condition = nullptr;
6516
0
                        v.conditional = true;
6517
0
                    }
6518
0
                }
6519
0
            }
6520
6521
1.76k
            bool deadBranch[] = {false, false};
6522
            // start token of conditional code
6523
1.76k
            Token* startTokens[] = {nullptr, nullptr};
6524
            // determine startToken(s)
6525
1.76k
            if (Token::simpleMatch(top->link(), ") {"))
6526
1.76k
                startTokens[0] = top->link()->next();
6527
1.76k
            if (Token::simpleMatch(top->link()->linkAt(1), "} else {"))
6528
541
                startTokens[1] = top->link()->linkAt(1)->tokAt(2);
6529
6530
1.76k
            int changeBlock = -1;
6531
1.76k
            int bailBlock = -1;
6532
6533
5.29k
            for (int i = 0; i < 2; i++) {
6534
3.53k
                const Token* const startToken = startTokens[i];
6535
3.53k
                if (!startToken)
6536
1.22k
                    continue;
6537
2.30k
                std::list<ValueFlow::Value>& values = (i == 0 ? thenValues : elseValues);
6538
2.30k
                if (allowKnown)
6539
2.30k
                    valueFlowSetConditionToKnown(condTok, values, i == 0);
6540
6541
2.30k
                Analyzer::Result r = forward(startTokens[i], startTokens[i]->link(), cond.vartok, values, tokenlist, settings);
6542
2.30k
                deadBranch[i] = r.terminate == Analyzer::Terminate::Escape;
6543
2.30k
                if (r.action.isModified() && !deadBranch[i])
6544
93
                    changeBlock = i;
6545
2.30k
                if (r.terminate != Analyzer::Terminate::None && r.terminate != Analyzer::Terminate::Escape &&
6546
2.30k
                    r.terminate != Analyzer::Terminate::Modified)
6547
1.53k
                    bailBlock = i;
6548
2.30k
                changeKnownToPossible(values);
6549
2.30k
            }
6550
1.76k
            if (changeBlock >= 0 && !Token::simpleMatch(top->previous(), "while (")) {
6551
55
                if (settings->debugwarnings)
6552
55
                    bailout(tokenlist,
6553
55
                            errorLogger,
6554
55
                            startTokens[changeBlock]->link(),
6555
55
                            "valueFlowAfterCondition: " + cond.vartok->expressionString() +
6556
55
                            " is changed in conditional block");
6557
55
                return;
6558
55
            }
6559
1.71k
            if (bailBlock >= 0) {
6560
1.17k
                if (settings->debugwarnings)
6561
1.17k
                    bailout(tokenlist,
6562
1.17k
                            errorLogger,
6563
1.17k
                            startTokens[bailBlock]->link(),
6564
1.17k
                            "valueFlowAfterCondition: bailing in conditional block");
6565
1.17k
                return;
6566
1.17k
            }
6567
6568
            // After conditional code..
6569
536
            if (Token::simpleMatch(top->link(), ") {")) {
6570
536
                Token* after = top->link()->linkAt(1);
6571
536
                bool dead_if = deadBranch[0];
6572
536
                bool dead_else = deadBranch[1];
6573
536
                const Token* unknownFunction = nullptr;
6574
536
                if (condTok->astParent() && Token::Match(top->previous(), "while|for ("))
6575
220
                    dead_if = !isBreakScope(after);
6576
316
                else if (!dead_if)
6577
300
                    dead_if = isReturnScope(after, &settings->library, &unknownFunction);
6578
6579
536
                if (!dead_if && unknownFunction) {
6580
0
                    if (settings->debugwarnings)
6581
0
                        bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
6582
0
                    return;
6583
0
                }
6584
6585
536
                if (Token::simpleMatch(after, "} else {")) {
6586
154
                    after = after->linkAt(2);
6587
154
                    unknownFunction = nullptr;
6588
154
                    if (!dead_else)
6589
150
                        dead_else = isReturnScope(after, &settings->library, &unknownFunction);
6590
154
                    if (!dead_else && unknownFunction) {
6591
0
                        if (settings->debugwarnings)
6592
0
                            bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
6593
0
                        return;
6594
0
                    }
6595
154
                }
6596
6597
536
                if (dead_if && dead_else)
6598
4
                    return;
6599
6600
532
                std::list<ValueFlow::Value> values;
6601
532
                if (dead_if) {
6602
234
                    values = elseValues;
6603
298
                } else if (dead_else) {
6604
0
                    values = thenValues;
6605
298
                } else {
6606
298
                    std::copy_if(thenValues.cbegin(),
6607
298
                                 thenValues.cend(),
6608
298
                                 std::back_inserter(values),
6609
298
                                 std::mem_fn(&ValueFlow::Value::isPossible));
6610
298
                    std::copy_if(elseValues.cbegin(),
6611
298
                                 elseValues.cend(),
6612
298
                                 std::back_inserter(values),
6613
298
                                 std::mem_fn(&ValueFlow::Value::isPossible));
6614
298
                }
6615
6616
532
                if (values.empty())
6617
0
                    return;
6618
6619
532
                if (dead_if || dead_else) {
6620
234
                    const Token* parent = condTok->astParent();
6621
                    // Skip the not operator
6622
234
                    while (Token::simpleMatch(parent, "!"))
6623
0
                        parent = parent->astParent();
6624
234
                    bool possible = false;
6625
234
                    if (Token::Match(parent, "&&|%oror%")) {
6626
0
                        const std::string& op(parent->str());
6627
0
                        while (parent && parent->str() == op)
6628
0
                            parent = parent->astParent();
6629
0
                        if (Token::simpleMatch(parent, "!") || Token::simpleMatch(parent, "== false"))
6630
0
                            possible = op == "||";
6631
0
                        else
6632
0
                            possible = op == "&&";
6633
0
                    }
6634
234
                    if (possible) {
6635
0
                        values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible));
6636
0
                        changeKnownToPossible(values);
6637
234
                    } else if (allowKnown) {
6638
234
                        valueFlowSetConditionToKnown(condTok, values, true);
6639
234
                        valueFlowSetConditionToKnown(condTok, values, false);
6640
234
                    }
6641
234
                }
6642
532
                if (values.empty())
6643
0
                    return;
6644
712
                const bool isKnown = std::any_of(values.cbegin(), values.cend(), [&](const ValueFlow::Value& v) {
6645
712
                    return v.isKnown() || v.isImpossible();
6646
712
                });
6647
532
                if (isKnown && isBreakOrContinueScope(after)) {
6648
0
                    const Scope* loopScope = getLoopScope(cond.vartok);
6649
0
                    if (loopScope) {
6650
0
                        Analyzer::Result r = forward(after, loopScope->bodyEnd, cond.vartok, values, tokenlist, settings);
6651
0
                        if (r.terminate != Analyzer::Terminate::None)
6652
0
                            return;
6653
0
                        if (r.action.isModified())
6654
0
                            return;
6655
0
                        Token* start = const_cast<Token*>(loopScope->bodyEnd);
6656
0
                        if (Token::simpleMatch(start, "} while (")) {
6657
0
                            start = start->tokAt(2);
6658
0
                            forward(start, start->link(), cond.vartok, values, tokenlist, settings);
6659
0
                            start = start->link();
6660
0
                        }
6661
0
                        values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible));
6662
0
                        changeKnownToPossible(values);
6663
0
                    }
6664
0
                }
6665
532
                forward(after, ValueFlow::getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, settings);
6666
532
            }
6667
536
        });
6668
9.09k
    }
6669
18.1k
    virtual ~ConditionHandler() = default;
6670
9.09k
    ConditionHandler(const ConditionHandler&) = default;
6671
protected:
6672
9.09k
    ConditionHandler() = default;
6673
};
6674
6675
static void valueFlowCondition(const ValuePtr<ConditionHandler>& handler,
6676
                               TokenList& tokenlist,
6677
                               SymbolDatabase& symboldatabase,
6678
                               ErrorLogger* errorLogger,
6679
                               const Settings* settings,
6680
                               const std::set<const Scope*>& skippedFunctions)
6681
9.09k
{
6682
9.09k
    handler->beforeCondition(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
6683
9.09k
    handler->afterCondition(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
6684
9.09k
}
6685
6686
struct SimpleConditionHandler : ConditionHandler {
6687
39.6k
    std::vector<Condition> parse(const Token* tok, const Settings* /*settings*/) const override {
6688
6689
39.6k
        std::vector<Condition> conds;
6690
39.6k
        parseCompareEachInt(tok, [&](const Token* vartok, ValueFlow::Value true_value, ValueFlow::Value false_value) {
6691
1.70k
            if (vartok->hasKnownIntValue())
6692
0
                return;
6693
1.70k
            if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
6694
16
                vartok = vartok->astOperand1();
6695
1.70k
            Condition cond;
6696
1.70k
            cond.true_values.push_back(std::move(true_value));
6697
1.70k
            cond.false_values.push_back(std::move(false_value));
6698
1.70k
            cond.vartok = vartok;
6699
1.70k
            conds.push_back(std::move(cond));
6700
1.70k
        });
6701
39.6k
        if (!conds.empty())
6702
1.70k
            return conds;
6703
6704
37.9k
        const Token* vartok = nullptr;
6705
6706
37.9k
        if (tok->str() == "!") {
6707
0
            vartok = tok->astOperand1();
6708
6709
37.9k
        } else if (tok->astParent() && (Token::Match(tok->astParent(), "%oror%|&&|?") ||
6710
32.5k
                                        Token::Match(tok->astParent()->previous(), "if|while ("))) {
6711
4.43k
            if (Token::simpleMatch(tok, "="))
6712
394
                vartok = tok->astOperand1();
6713
4.03k
            else if (!Token::Match(tok, "%comp%|%assign%"))
6714
1.10k
                vartok = tok;
6715
4.43k
        }
6716
6717
37.9k
        if (!vartok)
6718
36.4k
            return {};
6719
1.49k
        Condition cond;
6720
1.49k
        cond.true_values.emplace_back(tok, 0LL);
6721
1.49k
        cond.false_values.emplace_back(tok, 0LL);
6722
1.49k
        cond.vartok = vartok;
6723
6724
1.49k
        return {std::move(cond)};
6725
37.9k
    }
6726
};
6727
6728
struct IntegralInferModel : InferModel {
6729
8.11k
    bool match(const ValueFlow::Value& value) const override {
6730
8.11k
        return value.isIntValue();
6731
8.11k
    }
6732
    ValueFlow::Value yield(MathLib::bigint value) const override
6733
3.37k
    {
6734
3.37k
        ValueFlow::Value result(value);
6735
3.37k
        result.valueType = ValueFlow::Value::ValueType::INT;
6736
3.37k
        result.setKnown();
6737
3.37k
        return result;
6738
3.37k
    }
6739
};
6740
6741
2.23k
ValuePtr<InferModel> ValueFlow::makeIntegralInferModel() {
6742
2.23k
    return IntegralInferModel{};
6743
2.23k
}
6744
6745
ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val)
6746
0
{
6747
0
    if (!varTok)
6748
0
        return ValueFlow::Value{};
6749
0
    if (varTok->hasKnownIntValue())
6750
0
        return ValueFlow::Value{};
6751
0
    std::vector<ValueFlow::Value> r = infer(IntegralInferModel{}, op, varTok->values(), val);
6752
0
    if (r.size() == 1 && r.front().isKnown())
6753
0
        return r.front();
6754
0
    return ValueFlow::Value{};
6755
0
}
6756
6757
struct IteratorInferModel : InferModel {
6758
    virtual ValueFlow::Value::ValueType getType() const = 0;
6759
0
    bool match(const ValueFlow::Value& value) const override {
6760
0
        return value.valueType == getType();
6761
0
    }
6762
    ValueFlow::Value yield(MathLib::bigint value) const override
6763
0
    {
6764
0
        ValueFlow::Value result(value);
6765
0
        result.valueType = getType();
6766
0
        result.setKnown();
6767
0
        return result;
6768
0
    }
6769
};
6770
6771
struct EndIteratorInferModel : IteratorInferModel {
6772
0
    ValueFlow::Value::ValueType getType() const override {
6773
0
        return ValueFlow::Value::ValueType::ITERATOR_END;
6774
0
    }
6775
};
6776
6777
struct StartIteratorInferModel : IteratorInferModel {
6778
0
    ValueFlow::Value::ValueType getType() const override {
6779
0
        return ValueFlow::Value::ValueType::ITERATOR_END;
6780
0
    }
6781
};
6782
6783
3.79k
static bool isIntegralOnlyOperator(const Token* tok) {
6784
3.79k
    return Token::Match(tok, "%|<<|>>|&|^|~|%or%");
6785
3.79k
}
6786
6787
static bool isIntegralOrPointer(const Token* tok)
6788
7.45k
{
6789
7.45k
    if (!tok)
6790
0
        return false;
6791
7.45k
    if (astIsIntegral(tok, false))
6792
5.40k
        return true;
6793
2.05k
    if (astIsPointer(tok))
6794
0
        return true;
6795
2.05k
    if (Token::Match(tok, "NULL|nullptr"))
6796
0
        return true;
6797
2.05k
    if (tok->valueType())
6798
0
        return false;
6799
    // These operators only work on integers
6800
2.05k
    if (isIntegralOnlyOperator(tok))
6801
314
        return true;
6802
1.73k
    if (isIntegralOnlyOperator(tok->astParent()))
6803
0
        return true;
6804
1.73k
    if (Token::Match(tok, "+|-|*|/") && tok->isBinaryOp())
6805
469
        return isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2());
6806
1.26k
    return false;
6807
1.73k
}
6808
6809
static void valueFlowInferCondition(TokenList& tokenlist,
6810
                                    const Settings* settings)
6811
2.27k
{
6812
163k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
6813
160k
        if (!tok->astParent())
6814
102k
            continue;
6815
58.4k
        if (tok->hasKnownIntValue())
6816
17.9k
            continue;
6817
40.4k
        if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) {
6818
3.77k
            if (astIsIterator(tok->astOperand1()) || astIsIterator(tok->astOperand2())) {
6819
0
                static const std::array<ValuePtr<InferModel>, 2> iteratorModels = {EndIteratorInferModel{},
6820
0
                                                                                   StartIteratorInferModel{}};
6821
0
                for (const ValuePtr<InferModel>& model : iteratorModels) {
6822
0
                    std::vector<ValueFlow::Value> result =
6823
0
                        infer(model, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
6824
0
                    for (ValueFlow::Value value : result) {
6825
0
                        value.valueType = ValueFlow::Value::ValueType::INT;
6826
0
                        setTokenValue(tok, std::move(value), settings);
6827
0
                    }
6828
0
                }
6829
3.77k
            } else if (isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2())) {
6830
2.50k
                std::vector<ValueFlow::Value> result =
6831
2.50k
                    infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
6832
2.50k
                for (ValueFlow::Value& value : result) {
6833
67
                    setTokenValue(tok, std::move(value), settings);
6834
67
                }
6835
2.50k
            }
6836
36.6k
        } else if (Token::Match(tok->astParent(), "?|&&|!|%oror%") ||
6837
36.6k
                   Token::Match(tok->astParent()->previous(), "if|while (") ||
6838
36.6k
                   (astIsPointer(tok) && isUsedAsBool(tok, settings))) {
6839
3.37k
            std::vector<ValueFlow::Value> result = infer(IntegralInferModel{}, "!=", tok->values(), 0);
6840
3.37k
            if (result.size() != 1)
6841
3.37k
                continue;
6842
0
            ValueFlow::Value value = result.front();
6843
0
            setTokenValue(tok, std::move(value), settings);
6844
0
        }
6845
40.4k
    }
6846
2.27k
}
6847
6848
struct SymbolicConditionHandler : SimpleConditionHandler {
6849
6850
    static bool isNegatedBool(const Token* tok)
6851
780
    {
6852
780
        if (!Token::simpleMatch(tok, "!"))
6853
780
            return false;
6854
0
        return (astIsBool(tok->astOperand1()));
6855
780
    }
6856
6857
    static const Token* skipNot(const Token* tok)
6858
0
    {
6859
0
        if (!Token::simpleMatch(tok, "!"))
6860
0
            return tok;
6861
0
        return tok->astOperand1();
6862
0
    }
6863
6864
    std::vector<Condition> parse(const Token* tok, const Settings* settings) const override
6865
39.6k
    {
6866
39.6k
        if (!Token::Match(tok, "%comp%"))
6867
32.8k
            return {};
6868
6.80k
        if (tok->hasKnownIntValue())
6869
938
            return {};
6870
5.86k
        if (!tok->astOperand1() || tok->astOperand1()->hasKnownIntValue() || tok->astOperand1()->isLiteral())
6871
892
            return {};
6872
4.97k
        if (!tok->astOperand2() || tok->astOperand2()->hasKnownIntValue() || tok->astOperand2()->isLiteral())
6873
720
            return {};
6874
4.25k
        if (!isConstExpression(tok, settings->library, true))
6875
2.38k
            return {};
6876
6877
1.87k
        std::vector<Condition> result;
6878
1.87k
        auto addCond = [&](const Token* lhsTok, const Token* rhsTok, bool inverted) {
6879
5.62k
            for (int i = 0; i < 2; i++) {
6880
3.74k
                const bool lhs = i == 0;
6881
3.74k
                const Token* vartok = lhs ? lhsTok : rhsTok;
6882
3.74k
                const Token* valuetok = lhs ? rhsTok : lhsTok;
6883
3.74k
                if (valuetok->exprId() == 0)
6884
0
                    continue;
6885
3.74k
                if (valuetok->hasKnownSymbolicValue(vartok))
6886
6
                    continue;
6887
3.74k
                if (vartok->hasKnownSymbolicValue(valuetok))
6888
6
                    continue;
6889
3.73k
                ValueFlow::Value true_value;
6890
3.73k
                ValueFlow::Value false_value;
6891
3.73k
                setConditionalValues(tok, !lhs, 0, true_value, false_value);
6892
3.73k
                setSymbolic(true_value, valuetok);
6893
3.73k
                setSymbolic(false_value, valuetok);
6894
6895
3.73k
                Condition cond;
6896
3.73k
                cond.true_values = {std::move(true_value)};
6897
3.73k
                cond.false_values = {std::move(false_value)};
6898
3.73k
                cond.vartok = vartok;
6899
3.73k
                cond.inverted = inverted;
6900
3.73k
                result.push_back(std::move(cond));
6901
3.73k
            }
6902
1.87k
        };
6903
1.87k
        addCond(tok->astOperand1(), tok->astOperand2(), false);
6904
1.87k
        if (Token::Match(tok, "==|!=") && (isNegatedBool(tok->astOperand1()) || isNegatedBool(tok->astOperand2()))) {
6905
0
            const Token* lhsTok = skipNot(tok->astOperand1());
6906
0
            const Token* rhsTok = skipNot(tok->astOperand2());
6907
0
            addCond(lhsTok, rhsTok, !(isNegatedBool(tok->astOperand1()) && isNegatedBool(tok->astOperand2())));
6908
0
        }
6909
1.87k
        return result;
6910
4.25k
    }
6911
};
6912
6913
static bool valueFlowForLoop2(const Token *tok,
6914
                              ProgramMemory *memory1,
6915
                              ProgramMemory *memory2,
6916
                              ProgramMemory *memoryAfter)
6917
0
{
6918
    // for ( firstExpression ; secondExpression ; thirdExpression )
6919
0
    const Token *firstExpression  = tok->next()->astOperand2()->astOperand1();
6920
0
    const Token *secondExpression = tok->next()->astOperand2()->astOperand2()->astOperand1();
6921
0
    const Token *thirdExpression = tok->next()->astOperand2()->astOperand2()->astOperand2();
6922
6923
0
    ProgramMemory programMemory;
6924
0
    MathLib::bigint result(0);
6925
0
    bool error = false;
6926
0
    execute(firstExpression, programMemory, &result, &error);
6927
0
    if (error)
6928
0
        return false;
6929
0
    execute(secondExpression, programMemory, &result, &error);
6930
0
    if (result == 0) // 2nd expression is false => no looping
6931
0
        return false;
6932
0
    if (error) {
6933
        // If a variable is reassigned in second expression, return false
6934
0
        bool reassign = false;
6935
0
        visitAstNodes(secondExpression,
6936
0
                      [&](const Token *t) {
6937
0
            if (t->str() == "=" && t->astOperand1() && programMemory.hasValue(t->astOperand1()->varId()))
6938
                // TODO: investigate what variable is assigned.
6939
0
                reassign = true;
6940
0
            return reassign ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
6941
0
        });
6942
0
        if (reassign)
6943
0
            return false;
6944
0
    }
6945
6946
0
    ProgramMemory startMemory(programMemory);
6947
0
    ProgramMemory endMemory;
6948
6949
0
    int maxcount = 10000;
6950
0
    while (result != 0 && !error && --maxcount > 0) {
6951
0
        endMemory = programMemory;
6952
0
        execute(thirdExpression, programMemory, &result, &error);
6953
0
        if (!error)
6954
0
            execute(secondExpression, programMemory, &result, &error);
6955
0
    }
6956
6957
0
    if (memory1)
6958
0
        memory1->swap(startMemory);
6959
0
    if (!error) {
6960
0
        if (memory2)
6961
0
            memory2->swap(endMemory);
6962
0
        if (memoryAfter)
6963
0
            memoryAfter->swap(programMemory);
6964
0
    }
6965
6966
0
    return true;
6967
0
}
6968
6969
static void valueFlowForLoopSimplify(Token* const bodyStart,
6970
                                     const Token* expr,
6971
                                     bool globalvar,
6972
                                     const MathLib::bigint value,
6973
                                     TokenList& tokenlist,
6974
                                     ErrorLogger* errorLogger,
6975
                                     const Settings* settings)
6976
0
{
6977
    // TODO: Refactor this to use arbitrary expressions
6978
0
    assert(expr->varId() > 0);
6979
0
    const Token * const bodyEnd = bodyStart->link();
6980
6981
    // Is variable modified inside for loop
6982
0
    if (isVariableChanged(bodyStart, bodyEnd, expr->varId(), globalvar, settings, tokenlist.isCPP()))
6983
0
        return;
6984
6985
0
    for (Token *tok2 = bodyStart->next(); tok2 != bodyEnd; tok2 = tok2->next()) {
6986
0
        if (tok2->varId() == expr->varId()) {
6987
0
            const Token * parent = tok2->astParent();
6988
0
            while (parent) {
6989
0
                const Token * const p = parent;
6990
0
                parent = parent->astParent();
6991
0
                if (!parent || parent->str() == ":")
6992
0
                    break;
6993
0
                if (parent->str() == "?") {
6994
0
                    if (parent->astOperand2() != p)
6995
0
                        parent = nullptr;
6996
0
                    break;
6997
0
                }
6998
0
            }
6999
0
            if (parent) {
7000
0
                if (settings->debugwarnings)
7001
0
                    bailout(tokenlist, errorLogger, tok2, "For loop variable " + tok2->str() + " stopping on ?");
7002
0
                continue;
7003
0
            }
7004
7005
0
            ValueFlow::Value value1(value);
7006
0
            value1.varId = tok2->varId();
7007
0
            setTokenValue(tok2, std::move(value1), settings);
7008
0
        }
7009
7010
0
        if (Token::Match(tok2, "%oror%|&&")) {
7011
0
            const ProgramMemory programMemory(getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings));
7012
0
            if ((tok2->str() == "&&" && !conditionIsTrue(tok2->astOperand1(), programMemory)) ||
7013
0
                (tok2->str() == "||" && !conditionIsFalse(tok2->astOperand1(), programMemory))) {
7014
                // Skip second expression..
7015
0
                Token *parent = tok2;
7016
0
                while (parent && parent->str() == tok2->str())
7017
0
                    parent = parent->astParent();
7018
                // Jump to end of condition
7019
0
                if (parent && parent->str() == "(") {
7020
0
                    tok2 = parent->link();
7021
                    // cast
7022
0
                    if (Token::simpleMatch(tok2, ") ("))
7023
0
                        tok2 = tok2->linkAt(1);
7024
0
                }
7025
0
            }
7026
7027
0
        }
7028
0
        const Token* vartok = expr;
7029
0
        const Token* rml = nextAfterAstRightmostLeaf(vartok);
7030
0
        if (rml)
7031
0
            vartok = rml->str() == "]" ? rml : rml->previous();
7032
0
        if (vartok->str() == "]" && vartok->link()->previous())
7033
0
            vartok = vartok->link()->previous();
7034
7035
0
        if ((tok2->str() == "&&" &&
7036
0
             conditionIsFalse(tok2->astOperand1(),
7037
0
                              getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings))) ||
7038
0
            (tok2->str() == "||" &&
7039
0
             conditionIsTrue(tok2->astOperand1(),
7040
0
                             getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings))))
7041
0
            break;
7042
7043
0
        if (Token::simpleMatch(tok2, ") {")) {
7044
0
            if (vartok->varId() && Token::findmatch(tok2->link(), "%varid%", tok2, vartok->varId())) {
7045
0
                if (Token::findmatch(tok2, "continue|break|return", tok2->linkAt(1), vartok->varId())) {
7046
0
                    if (settings->debugwarnings)
7047
0
                        bailout(tokenlist, errorLogger, tok2, "For loop variable bailout on conditional continue|break|return");
7048
0
                    break;
7049
0
                }
7050
0
                if (settings->debugwarnings)
7051
0
                    bailout(tokenlist, errorLogger, tok2, "For loop variable skipping conditional scope");
7052
0
                tok2 = tok2->next()->link();
7053
0
                if (Token::simpleMatch(tok2, "} else {")) {
7054
0
                    if (Token::findmatch(tok2, "continue|break|return", tok2->linkAt(2), vartok->varId())) {
7055
0
                        if (settings->debugwarnings)
7056
0
                            bailout(tokenlist, errorLogger, tok2, "For loop variable bailout on conditional continue|break|return");
7057
0
                        break;
7058
0
                    }
7059
0
                    tok2 = tok2->linkAt(2);
7060
0
                }
7061
0
            }
7062
0
            else {
7063
0
                if (settings->debugwarnings)
7064
0
                    bailout(tokenlist, errorLogger, tok2, "For loop skipping {} code");
7065
0
                tok2 = tok2->linkAt(1);
7066
0
                if (Token::simpleMatch(tok2, "} else {"))
7067
0
                    tok2 = tok2->linkAt(2);
7068
0
            }
7069
0
        }
7070
0
    }
7071
0
}
7072
7073
static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, const Settings* settings)
7074
0
{
7075
0
    const Token *vartok = nullptr;
7076
0
    for (const Token *tok = fortok; tok; tok = tok->next()) {
7077
0
        if (tok->varId() == varid) {
7078
0
            vartok = tok;
7079
0
            break;
7080
0
        }
7081
0
    }
7082
0
    if (!vartok || !vartok->variable())
7083
0
        return;
7084
7085
0
    const Variable *var = vartok->variable();
7086
0
    const Token *endToken = nullptr;
7087
0
    if (var->isLocal())
7088
0
        endToken = var->scope()->bodyEnd;
7089
0
    else
7090
0
        endToken = fortok->scope()->bodyEnd;
7091
7092
0
    Token* blockTok = fortok->linkAt(1)->linkAt(1);
7093
0
    if (blockTok != endToken) {
7094
0
        ValueFlow::Value v{num};
7095
0
        v.errorPath.emplace_back(fortok,"After for loop, " + var->name() + " has value " + v.infoString());
7096
7097
0
        valueFlowForward(blockTok->next(), endToken, vartok, v, tokenlist, settings);
7098
0
    }
7099
0
}
7100
7101
static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
7102
2.27k
{
7103
8.76k
    for (const Scope &scope : symboldatabase.scopeList) {
7104
8.76k
        if (scope.type != Scope::eFor)
7105
8.76k
            continue;
7106
7107
0
        Token* tok = const_cast<Token*>(scope.classDef);
7108
0
        Token* const bodyStart = const_cast<Token*>(scope.bodyStart);
7109
7110
0
        if (!Token::simpleMatch(tok->next()->astOperand2(), ";") ||
7111
0
            !Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";"))
7112
0
            continue;
7113
7114
0
        nonneg int varid;
7115
0
        bool knownInitValue, partialCond;
7116
0
        MathLib::bigint initValue, stepValue, lastValue;
7117
7118
0
        if (extractForLoopValues(tok, varid, knownInitValue, initValue, partialCond, stepValue, lastValue)) {
7119
0
            const bool executeBody = !knownInitValue || initValue <= lastValue;
7120
0
            const Token* vartok = Token::findmatch(tok, "%varid%", bodyStart, varid);
7121
0
            if (executeBody && vartok) {
7122
0
                std::list<ValueFlow::Value> initValues;
7123
0
                initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower);
7124
0
                initValues.push_back(ValueFlow::asImpossible(initValues.back()));
7125
0
                Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, initValues, tokenlist, settings);
7126
7127
0
                if (!result.action.isModified()) {
7128
0
                    std::list<ValueFlow::Value> lastValues;
7129
0
                    lastValues.emplace_back(lastValue, ValueFlow::Value::Bound::Upper);
7130
0
                    lastValues.back().conditional = true;
7131
0
                    lastValues.push_back(ValueFlow::asImpossible(lastValues.back()));
7132
0
                    if (stepValue != 1)
7133
0
                        lastValues.pop_front();
7134
0
                    valueFlowForward(bodyStart, bodyStart->link(), vartok, lastValues, tokenlist, settings);
7135
0
                }
7136
0
            }
7137
0
            const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue;
7138
0
            valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, settings);
7139
0
        } else {
7140
0
            ProgramMemory mem1, mem2, memAfter;
7141
0
            if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) {
7142
0
                for (const auto& p : mem1) {
7143
0
                    if (!p.second.isIntValue())
7144
0
                        continue;
7145
0
                    if (p.second.isImpossible())
7146
0
                        continue;
7147
0
                    if (p.first.tok->varId() == 0)
7148
0
                        continue;
7149
0
                    valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
7150
0
                }
7151
0
                for (const auto& p : mem2) {
7152
0
                    if (!p.second.isIntValue())
7153
0
                        continue;
7154
0
                    if (p.second.isImpossible())
7155
0
                        continue;
7156
0
                    if (p.first.tok->varId() == 0)
7157
0
                        continue;
7158
0
                    valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
7159
0
                }
7160
0
                for (const auto& p : memAfter) {
7161
0
                    if (!p.second.isIntValue())
7162
0
                        continue;
7163
0
                    if (p.second.isImpossible())
7164
0
                        continue;
7165
0
                    if (p.first.tok->varId() == 0)
7166
0
                        continue;
7167
0
                    valueFlowForLoopSimplifyAfter(tok, p.first.getExpressionId(), p.second.intvalue, tokenlist, settings);
7168
0
                }
7169
0
            }
7170
0
        }
7171
0
    }
7172
2.27k
}
7173
7174
struct MultiValueFlowAnalyzer : ValueFlowAnalyzer {
7175
    std::unordered_map<nonneg int, ValueFlow::Value> values;
7176
    std::unordered_map<nonneg int, const Variable*> vars;
7177
7178
    MultiValueFlowAnalyzer(const std::unordered_map<const Variable*, ValueFlow::Value>& args, const TokenList& t, const Settings* set)
7179
0
        : ValueFlowAnalyzer(t, set) {
7180
0
        for (const auto& p:args) {
7181
0
            values[p.first->declarationId()] = p.second;
7182
0
            vars[p.first->declarationId()] = p.first;
7183
0
        }
7184
0
    }
7185
7186
0
    virtual const std::unordered_map<nonneg int, const Variable*>& getVars() const {
7187
0
        return vars;
7188
0
    }
7189
7190
0
    const ValueFlow::Value* getValue(const Token* tok) const override {
7191
0
        if (tok->varId() == 0)
7192
0
            return nullptr;
7193
0
        auto it = values.find(tok->varId());
7194
0
        if (it == values.end())
7195
0
            return nullptr;
7196
0
        return &it->second;
7197
0
    }
7198
0
    ValueFlow::Value* getValue(const Token* tok) override {
7199
0
        if (tok->varId() == 0)
7200
0
            return nullptr;
7201
0
        auto it = values.find(tok->varId());
7202
0
        if (it == values.end())
7203
0
            return nullptr;
7204
0
        return &it->second;
7205
0
    }
7206
7207
0
    void makeConditional() override {
7208
0
        for (auto&& p:values) {
7209
0
            p.second.conditional = true;
7210
0
        }
7211
0
    }
7212
7213
0
    void addErrorPath(const Token* tok, const std::string& s) override {
7214
0
        for (auto&& p:values) {
7215
0
            p.second.errorPath.emplace_back(tok, s);
7216
0
        }
7217
0
    }
7218
7219
0
    bool isAlias(const Token* tok, bool& inconclusive) const override {
7220
0
        const auto range = SelectValueFromVarIdMapRange(&values);
7221
7222
0
        for (const auto& p:getVars()) {
7223
0
            nonneg int const varid = p.first;
7224
0
            const Variable* var = p.second;
7225
0
            if (tok->varId() == varid)
7226
0
                return true;
7227
0
            if (isAliasOf(var, tok, varid, range, &inconclusive))
7228
0
                return true;
7229
0
        }
7230
0
        return false;
7231
0
    }
7232
7233
0
    bool lowerToPossible() override {
7234
0
        for (auto&& p:values) {
7235
0
            if (p.second.isImpossible())
7236
0
                return false;
7237
0
            p.second.changeKnownToPossible();
7238
0
        }
7239
0
        return true;
7240
0
    }
7241
0
    bool lowerToInconclusive() override {
7242
0
        for (auto&& p:values) {
7243
0
            if (p.second.isImpossible())
7244
0
                return false;
7245
0
            p.second.setInconclusive();
7246
0
        }
7247
0
        return true;
7248
0
    }
7249
7250
0
    bool isConditional() const override {
7251
0
        for (auto&& p:values) {
7252
0
            if (p.second.conditional)
7253
0
                return true;
7254
0
            if (p.second.condition)
7255
0
                return !p.second.isImpossible();
7256
0
        }
7257
0
        return false;
7258
0
    }
7259
7260
0
    bool stopOnCondition(const Token* /*condTok*/) const override {
7261
0
        return isConditional();
7262
0
    }
7263
7264
0
    bool updateScope(const Token* endBlock, bool /*modified*/) const override {
7265
0
        const Scope* scope = endBlock->scope();
7266
0
        if (!scope)
7267
0
            return false;
7268
0
        if (scope->type == Scope::eLambda) {
7269
0
            return std::all_of(values.cbegin(), values.cend(), [](const std::pair<nonneg int, ValueFlow::Value>& p) {
7270
0
                return p.second.isLifetimeValue();
7271
0
            });
7272
0
        }
7273
0
        if (scope->type == Scope::eIf || scope->type == Scope::eElse || scope->type == Scope::eWhile ||
7274
0
            scope->type == Scope::eFor) {
7275
0
            auto pred = [](const ValueFlow::Value& value) {
7276
0
                if (value.isKnown())
7277
0
                    return true;
7278
0
                if (value.isImpossible())
7279
0
                    return true;
7280
0
                if (value.isLifetimeValue())
7281
0
                    return true;
7282
0
                return false;
7283
0
            };
7284
0
            if (std::all_of(values.cbegin(), values.cend(), std::bind(pred, std::bind(SelectMapValues{}, std::placeholders::_1))))
7285
0
                return true;
7286
0
            if (isConditional())
7287
0
                return false;
7288
0
            const Token* condTok = getCondTokFromEnd(endBlock);
7289
0
            std::set<nonneg int> varids;
7290
0
            std::transform(getVars().cbegin(), getVars().cend(), std::inserter(varids, varids.begin()), SelectMapKeys{});
7291
0
            return bifurcate(condTok, varids, getSettings());
7292
0
        }
7293
7294
0
        return false;
7295
0
    }
7296
7297
0
    bool match(const Token* tok) const override {
7298
0
        return values.count(tok->varId()) > 0;
7299
0
    }
7300
7301
0
    ProgramState getProgramState() const override {
7302
0
        ProgramState ps;
7303
0
        for (const auto& p : values) {
7304
0
            const Variable* var = vars.at(p.first);
7305
0
            if (!var)
7306
0
                continue;
7307
0
            ps[var->nameToken()] = p.second;
7308
0
        }
7309
0
        return ps;
7310
0
    }
7311
};
7312
7313
template<class Key, class F>
7314
bool productParams(const Settings* settings, const std::unordered_map<Key, std::list<ValueFlow::Value>>& vars, F f)
7315
0
{
7316
0
    using Args = std::vector<std::unordered_map<Key, ValueFlow::Value>>;
7317
0
    Args args(1);
7318
    // Compute cartesian product of all arguments
7319
0
    for (const auto& p:vars) {
7320
0
        if (p.second.empty())
7321
0
            continue;
7322
0
        args.back()[p.first] = p.second.front();
7323
0
    }
7324
0
    bool bail = false;
7325
0
    int max = 8;
7326
0
    if (settings)
7327
0
        max = settings->performanceValueFlowMaxSubFunctionArgs;
7328
0
    for (const auto& p:vars) {
7329
0
        if (args.size() > max) {
7330
0
            bail = true;
7331
0
            break;
7332
0
        }
7333
0
        if (p.second.empty())
7334
0
            continue;
7335
0
        std::for_each(std::next(p.second.begin()), p.second.end(), [&](const ValueFlow::Value& value) {
7336
0
            Args new_args;
7337
0
            for (auto arg:args) {
7338
0
                if (value.path != 0) {
7339
0
                    for (const auto& q:arg) {
7340
0
                        if (q.first == p.first)
7341
0
                            continue;
7342
0
                        if (q.second.path == 0)
7343
0
                            continue;
7344
0
                        if (q.second.path != value.path)
7345
0
                            return;
7346
0
                    }
7347
0
                }
7348
0
                arg[p.first] = value;
7349
0
                new_args.push_back(std::move(arg));
7350
0
            }
7351
0
            std::copy(new_args.cbegin(), new_args.cend(), std::back_inserter(args));
7352
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*)::$_87>(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*)::$_87)::{lambda(ValueFlow::Value const&)#1}::operator()(ValueFlow::Value const&) const
Unexecuted instantiation: valueflow.cpp:productParams<Variable const*, valueFlowInjectParameter(TokenList&, 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&)::$_86>(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&, 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&)::$_86)::{lambda(ValueFlow::Value const&)#1}::operator()(ValueFlow::Value const&) const
7353
0
    }
7354
7355
0
    if (args.size() > max) {
7356
0
        bail = true;
7357
0
        args.resize(max);
7358
0
    }
7359
7360
0
    for (const auto& arg:args) {
7361
0
        if (arg.empty())
7362
0
            continue;
7363
        // Make sure all arguments are the same path
7364
0
        const MathLib::bigint path = arg.cbegin()->second.path;
7365
0
        if (std::any_of(arg.cbegin(), arg.cend(), [&](const std::pair<Key, ValueFlow::Value>& p) {
7366
0
            return p.second.path != path;
7367
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*)::$_87>(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*)::$_87)::{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&, 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&)::$_86>(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&, 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&)::$_86)::{lambda(std::__1::pair<Variable const*, ValueFlow::Value> const&)#1}::operator()(std::__1::pair<Variable const*, ValueFlow::Value> const&) const
7368
0
            continue;
7369
0
        f(arg);
7370
0
    }
7371
0
    return !bail;
7372
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*)::$_87>(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*)::$_87)
Unexecuted instantiation: valueflow.cpp:bool productParams<Variable const*, valueFlowInjectParameter(TokenList&, 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&)::$_86>(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&, 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&)::$_86)
7373
7374
static void valueFlowInjectParameter(TokenList& tokenlist,
7375
                                     ErrorLogger* errorLogger,
7376
                                     const Settings& settings,
7377
                                     const Scope* functionScope,
7378
                                     const std::unordered_map<const Variable*, std::list<ValueFlow::Value>>& vars)
7379
0
{
7380
0
    const bool r = productParams(&settings, vars, [&](const std::unordered_map<const Variable*, ValueFlow::Value>& arg) {
7381
0
        MultiValueFlowAnalyzer a(arg, tokenlist, &settings);
7382
0
        valueFlowGenericForward(const_cast<Token*>(functionScope->bodyStart), functionScope->bodyEnd, a, settings);
7383
0
    });
7384
0
    if (!r) {
7385
0
        std::string fname = "<unknown>";
7386
0
        if (const Function* f = functionScope->function)
7387
0
            fname = f->name();
7388
0
        if (settings.debugwarnings)
7389
0
            bailout(tokenlist, errorLogger, functionScope->bodyStart, "Too many argument passed to " + fname);
7390
0
    }
7391
0
}
7392
7393
static void valueFlowInjectParameter(const TokenList& tokenlist,
7394
                                     const Settings* settings,
7395
                                     const Variable* arg,
7396
                                     const Scope* functionScope,
7397
                                     const std::list<ValueFlow::Value>& argvalues)
7398
0
{
7399
    // Is argument passed by value or const reference, and is it a known non-class type?
7400
0
    if (arg->isReference() && !arg->isConst() && !arg->isClass())
7401
0
        return;
7402
7403
    // Set value in function scope..
7404
0
    const nonneg int varid2 = arg->declarationId();
7405
0
    if (!varid2)
7406
0
        return;
7407
7408
0
    valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
7409
0
                     functionScope->bodyEnd,
7410
0
                     arg->nameToken(),
7411
0
                     argvalues,
7412
0
                     tokenlist,
7413
0
                     settings);
7414
0
}
7415
7416
static void valueFlowSwitchVariable(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
7417
2.27k
{
7418
8.76k
    for (const Scope &scope : symboldatabase.scopeList) {
7419
8.76k
        if (scope.type != Scope::ScopeType::eSwitch)
7420
8.76k
            continue;
7421
0
        if (!Token::Match(scope.classDef, "switch ( %var% ) {"))
7422
0
            continue;
7423
0
        const Token *vartok = scope.classDef->tokAt(2);
7424
0
        const Variable *var = vartok->variable();
7425
0
        if (!var)
7426
0
            continue;
7427
7428
        // bailout: global non-const variables
7429
0
        if (!(var->isLocal() || var->isArgument()) && !var->isConst()) {
7430
0
            if (settings->debugwarnings)
7431
0
                bailout(tokenlist, errorLogger, vartok, "switch variable " + var->name() + " is global");
7432
0
            continue;
7433
0
        }
7434
7435
0
        for (const Token *tok = scope.bodyStart->next(); tok != scope.bodyEnd; tok = tok->next()) {
7436
0
            if (tok->str() == "{") {
7437
0
                tok = tok->link();
7438
0
                continue;
7439
0
            }
7440
0
            if (Token::Match(tok, "case %num% :")) {
7441
0
                std::list<ValueFlow::Value> values;
7442
0
                values.emplace_back(MathLib::toLongNumber(tok->next()->str()));
7443
0
                values.back().condition = tok;
7444
0
                values.back().errorPath.emplace_back(tok, "case " + tok->next()->str() + ": " + vartok->str() + " is " + tok->next()->str() + " here.");
7445
0
                bool known = false;
7446
0
                if ((Token::simpleMatch(tok->previous(), "{") || Token::simpleMatch(tok->tokAt(-2), "break ;")) && !Token::Match(tok->tokAt(3), ";| case"))
7447
0
                    known = true;
7448
0
                while (Token::Match(tok->tokAt(3), ";| case %num% :")) {
7449
0
                    known = false;
7450
0
                    tok = tok->tokAt(3);
7451
0
                    if (!tok->isName())
7452
0
                        tok = tok->next();
7453
0
                    values.emplace_back(MathLib::toLongNumber(tok->next()->str()));
7454
0
                    values.back().condition = tok;
7455
0
                    values.back().errorPath.emplace_back(tok, "case " + tok->next()->str() + ": " + vartok->str() + " is " + tok->next()->str() + " here.");
7456
0
                }
7457
0
                for (std::list<ValueFlow::Value>::const_iterator val = values.cbegin(); val != values.cend(); ++val) {
7458
0
                    valueFlowReverse(tokenlist,
7459
0
                                     const_cast<Token*>(scope.classDef),
7460
0
                                     vartok,
7461
0
                                     *val,
7462
0
                                     ValueFlow::Value(),
7463
0
                                     errorLogger,
7464
0
                                     settings);
7465
0
                }
7466
0
                if (vartok->variable()->scope()) {
7467
0
                    if (known)
7468
0
                        values.back().setKnown();
7469
7470
                    // FIXME We must check if there is a return. See #9276
7471
                    /*
7472
                       valueFlowForwardVariable(tok->tokAt(3),
7473
                                             vartok->variable()->scope()->bodyEnd,
7474
                                             vartok->variable(),
7475
                                             vartok->varId(),
7476
                                             values,
7477
                                             values.back().isKnown(),
7478
                                             false,
7479
                                             tokenlist,
7480
                                             errorLogger,
7481
                                             settings);
7482
                     */
7483
0
                }
7484
0
            }
7485
0
        }
7486
0
    }
7487
2.27k
}
7488
7489
static std::list<ValueFlow::Value> getFunctionArgumentValues(const Token *argtok)
7490
0
{
7491
0
    std::list<ValueFlow::Value> argvalues(argtok->values());
7492
0
    removeImpossible(argvalues);
7493
0
    if (argvalues.empty() && Token::Match(argtok, "%comp%|%oror%|&&|!")) {
7494
0
        argvalues.emplace_back(0);
7495
0
        argvalues.emplace_back(1);
7496
0
    }
7497
0
    return argvalues;
7498
0
}
7499
7500
static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue, const Settings *settings)
7501
0
{
7502
0
    std::unordered_map<nonneg int, std::list<ValueFlow::Value>> argValues;
7503
0
    int argn = 1;
7504
0
    for (const Token *argtok : getArguments(tok->previous())) {
7505
0
        argValues[argn] = getFunctionArgumentValues(argtok);
7506
0
        argn++;
7507
0
    }
7508
0
    if (returnValue.find("arg") != std::string::npos && argValues.empty())
7509
0
        return;
7510
0
    productParams(settings, argValues, [&](const std::unordered_map<nonneg int, ValueFlow::Value>& arg) {
7511
0
        ValueFlow::Value value = evaluateLibraryFunction(arg, returnValue, settings);
7512
0
        if (value.isUninitValue())
7513
0
            return;
7514
0
        ValueFlow::Value::ValueKind kind = ValueFlow::Value::ValueKind::Known;
7515
0
        for (auto&& p : arg) {
7516
0
            if (p.second.isPossible())
7517
0
                kind = p.second.valueKind;
7518
0
            if (p.second.isInconclusive()) {
7519
0
                kind = p.second.valueKind;
7520
0
                break;
7521
0
            }
7522
0
        }
7523
0
        if (value.isImpossible() && kind != ValueFlow::Value::ValueKind::Known)
7524
0
            return;
7525
0
        if (!value.isImpossible())
7526
0
            value.valueKind = kind;
7527
0
        setTokenValue(tok, std::move(value), settings);
7528
0
    });
7529
0
}
7530
7531
template<class Iterator>
7532
struct IteratorRange
7533
{
7534
    Iterator mBegin;
7535
    Iterator mEnd;
7536
7537
2.27k
    Iterator begin() const {
7538
2.27k
        return mBegin;
7539
2.27k
    }
7540
7541
2.27k
    Iterator end() const {
7542
2.27k
        return mEnd;
7543
2.27k
    }
7544
};
7545
7546
template<class Iterator>
7547
IteratorRange<Iterator> MakeIteratorRange(Iterator start, Iterator last)
7548
2.27k
{
7549
2.27k
    return {start, last};
7550
2.27k
}
7551
7552
static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase& symboldatabase,  ErrorLogger* errorLogger, const Settings& settings)
7553
2.27k
{
7554
2.27k
    int id = 0;
7555
2.90k
    for (const Scope* scope : MakeIteratorRange(symboldatabase.functionScopes.crbegin(), symboldatabase.functionScopes.crend())) {
7556
2.90k
        const Function* function = scope->function;
7557
2.90k
        if (!function)
7558
0
            continue;
7559
69.6k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
7560
66.7k
            if (tok->isKeyword() || !Token::Match(tok, "%name% ("))
7561
66.7k
                continue;
7562
7563
0
            const Function * const calledFunction = tok->function();
7564
0
            if (!calledFunction) {
7565
                // library function?
7566
0
                const std::string& returnValue(settings.library.returnValue(tok));
7567
0
                if (!returnValue.empty())
7568
0
                    valueFlowLibraryFunction(tok->next(), returnValue, &settings);
7569
0
                continue;
7570
0
            }
7571
7572
0
            const Scope * const calledFunctionScope = calledFunction->functionScope;
7573
0
            if (!calledFunctionScope)
7574
0
                continue;
7575
7576
0
            id++;
7577
0
            std::unordered_map<const Variable*, std::list<ValueFlow::Value>> argvars;
7578
            // TODO: Rewrite this. It does not work well to inject 1 argument at a time.
7579
0
            const std::vector<const Token *> &callArguments = getArguments(tok);
7580
0
            for (int argnr = 0U; argnr < callArguments.size(); ++argnr) {
7581
0
                const Token *argtok = callArguments[argnr];
7582
                // Get function argument
7583
0
                const Variable * const argvar = calledFunction->getArgumentVar(argnr);
7584
0
                if (!argvar)
7585
0
                    break;
7586
7587
                // passing value(s) to function
7588
0
                std::list<ValueFlow::Value> argvalues(getFunctionArgumentValues(argtok));
7589
7590
                // Remove non-local lifetimes
7591
0
                argvalues.remove_if([](const ValueFlow::Value& v) {
7592
0
                    if (v.isLifetimeValue())
7593
0
                        return !v.isLocalLifetimeValue() && !v.isSubFunctionLifetimeValue();
7594
0
                    return false;
7595
0
                });
7596
                // Remove uninit values if argument is passed by value
7597
0
                if (argtok->variable() && !argtok->variable()->isPointer() && argvalues.size() == 1 && argvalues.front().isUninitValue()) {
7598
0
                    if (CheckUninitVar::isVariableUsage(tokenlist.isCPP(), argtok, settings.library, false, CheckUninitVar::Alloc::NO_ALLOC, 0))
7599
0
                        continue;
7600
0
                }
7601
7602
0
                if (argvalues.empty())
7603
0
                    continue;
7604
7605
                // Error path..
7606
0
                for (ValueFlow::Value &v : argvalues) {
7607
0
                    const std::string nr = std::to_string(argnr + 1) + getOrdinalText(argnr + 1);
7608
7609
0
                    v.errorPath.emplace_back(argtok,
7610
0
                                             "Calling function '" +
7611
0
                                             calledFunction->name() +
7612
0
                                             "', " +
7613
0
                                             nr +
7614
0
                                             " argument '" +
7615
0
                                             argtok->expressionString() +
7616
0
                                             "' value is " +
7617
0
                                             v.infoString());
7618
0
                    v.path = 256 * v.path + id % 256;
7619
                    // Change scope of lifetime values
7620
0
                    if (v.isLifetimeValue())
7621
0
                        v.lifetimeScope = ValueFlow::Value::LifetimeScope::SubFunction;
7622
0
                }
7623
7624
                // passed values are not "known"..
7625
0
                lowerToPossible(argvalues);
7626
7627
0
                argvars[argvar] = argvalues;
7628
0
            }
7629
0
            valueFlowInjectParameter(tokenlist, errorLogger, settings, calledFunctionScope, argvars);
7630
0
        }
7631
2.90k
    }
7632
2.27k
}
7633
7634
static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings)
7635
2.27k
{
7636
2.27k
    if (!tokenlist.isCPP())
7637
0
        return;
7638
7639
2.90k
    for (const Scope* scope : symboldatabase.functionScopes) {
7640
2.90k
        const Function* function = scope->function;
7641
2.90k
        if (!function)
7642
0
            continue;
7643
2.90k
        for (std::size_t arg = function->minArgCount(); arg < function->argCount(); arg++) {
7644
0
            const Variable* var = function->getArgumentVar(arg);
7645
0
            if (var && var->hasDefault() && Token::Match(var->nameToken(), "%var% = %num%|%str% [,)]")) {
7646
0
                const std::list<ValueFlow::Value> &values = var->nameToken()->tokAt(2)->values();
7647
0
                std::list<ValueFlow::Value> argvalues;
7648
0
                for (const ValueFlow::Value &value : values) {
7649
0
                    ValueFlow::Value v(value);
7650
0
                    v.defaultArg = true;
7651
0
                    v.changeKnownToPossible();
7652
0
                    if (v.isPossible())
7653
0
                        argvalues.push_back(std::move(v));
7654
0
                }
7655
0
                if (!argvalues.empty())
7656
0
                    valueFlowInjectParameter(tokenlist, settings, var, scope, argvalues);
7657
0
            }
7658
0
        }
7659
2.90k
    }
7660
2.27k
}
7661
7662
static const ValueFlow::Value* getKnownValueFromToken(const Token* tok)
7663
0
{
7664
0
    if (!tok)
7665
0
        return nullptr;
7666
0
    auto it = std::find_if(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) {
7667
0
        return (v.isIntValue() || v.isContainerSizeValue() || v.isFloatValue()) && v.isKnown();
7668
0
    });
7669
0
    if (it == tok->values().end())
7670
0
        return nullptr;
7671
0
    return std::addressof(*it);
7672
0
}
7673
7674
static const ValueFlow::Value* getKnownValueFromTokens(const std::vector<const Token*>& toks)
7675
0
{
7676
0
    if (toks.empty())
7677
0
        return nullptr;
7678
0
    const ValueFlow::Value* result = getKnownValueFromToken(toks.front());
7679
0
    if (!result)
7680
0
        return nullptr;
7681
0
    if (!std::all_of(std::next(toks.begin()), toks.end(), [&](const Token* tok) {
7682
0
        return std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) {
7683
0
            return v.equalValue(*result) && v.valueKind == result->valueKind;
7684
0
        });
7685
0
    }))
7686
0
        return nullptr;
7687
0
    return result;
7688
0
}
7689
7690
static void setFunctionReturnValue(const Function* f, Token* tok, ValueFlow::Value v, const Settings* settings)
7691
0
{
7692
0
    if (f->hasVirtualSpecifier()) {
7693
0
        if (v.isImpossible())
7694
0
            return;
7695
0
        v.setPossible();
7696
0
    } else if (!v.isImpossible()) {
7697
0
        v.setKnown();
7698
0
    }
7699
0
    v.errorPath.emplace_back(tok, "Calling function '" + f->name() + "' returns " + v.toString());
7700
0
    setTokenValue(tok, std::move(v), settings);
7701
0
}
7702
7703
static void valueFlowFunctionReturn(TokenList &tokenlist, ErrorLogger *errorLogger, const Settings* settings)
7704
2.27k
{
7705
163k
    for (Token *tok = tokenlist.back(); tok; tok = tok->previous()) {
7706
160k
        if (tok->str() != "(" || !tok->astOperand1())
7707
158k
            continue;
7708
7709
2.70k
        const Function* function = nullptr;
7710
2.70k
        if (Token::Match(tok->previous(), "%name% ("))
7711
2.70k
            function = tok->previous()->function();
7712
0
        else
7713
0
            function = tok->astOperand1()->function();
7714
2.70k
        if (!function)
7715
2.70k
            continue;
7716
        // TODO: Check if member variable is a pointer or reference
7717
0
        if (function->isImplicitlyVirtual() && !function->hasFinalSpecifier())
7718
0
            continue;
7719
7720
0
        if (tok->hasKnownValue())
7721
0
            continue;
7722
7723
0
        std::vector<const Token*> returns = Function::findReturns(function);
7724
0
        if (returns.empty())
7725
0
            continue;
7726
7727
0
        if (const ValueFlow::Value* v = getKnownValueFromTokens(returns)) {
7728
0
            setFunctionReturnValue(function, tok, *v, settings);
7729
0
            continue;
7730
0
        }
7731
7732
        // Arguments..
7733
0
        std::vector<const Token*> arguments = getArguments(tok);
7734
7735
0
        ProgramMemory programMemory;
7736
0
        for (std::size_t i = 0; i < arguments.size(); ++i) {
7737
0
            const Variable * const arg = function->getArgumentVar(i);
7738
0
            if (!arg) {
7739
0
                if (settings->debugwarnings)
7740
0
                    bailout(tokenlist, errorLogger, tok, "function return; unhandled argument type");
7741
0
                programMemory.clear();
7742
0
                break;
7743
0
            }
7744
0
            const ValueFlow::Value* v = getKnownValueFromToken(arguments[i]);
7745
0
            if (!v)
7746
0
                continue;
7747
0
            programMemory.setValue(arg->nameToken(), *v);
7748
0
        }
7749
0
        if (programMemory.empty() && !arguments.empty())
7750
0
            continue;
7751
0
        std::vector<ValueFlow::Value> values = execute(function->functionScope, programMemory, settings);
7752
0
        for (const ValueFlow::Value& v : values) {
7753
0
            if (v.isUninitValue())
7754
0
                continue;
7755
0
            setFunctionReturnValue(function, tok, v, settings);
7756
0
        }
7757
0
    }
7758
2.27k
}
7759
7760
static bool needsInitialization(const Variable* var, bool cpp)
7761
0
{
7762
0
    if (!var)
7763
0
        return false;
7764
0
    if (var->hasDefault())
7765
0
        return false;
7766
0
    if (var->isPointer())
7767
0
        return true;
7768
0
    if (var->type() && var->type()->isUnionType())
7769
0
        return false;
7770
0
    if (!cpp)
7771
0
        return true;
7772
0
    if (var->type() && var->type()->needInitialization == Type::NeedInitialization::True)
7773
0
        return true;
7774
0
    if (var->valueType()) {
7775
0
        if (var->valueType()->isPrimitive())
7776
0
            return true;
7777
0
        if (var->valueType()->type == ValueType::Type::POD)
7778
0
            return true;
7779
0
        if (var->valueType()->type == ValueType::Type::ITERATOR)
7780
0
            return true;
7781
0
    }
7782
0
    return false;
7783
0
}
7784
7785
static void addToErrorPath(ValueFlow::Value& value, const ValueFlow::Value& from)
7786
0
{
7787
0
    std::unordered_set<const Token*> locations;
7788
0
    std::transform(value.errorPath.cbegin(),
7789
0
                   value.errorPath.cend(),
7790
0
                   std::inserter(locations, locations.begin()),
7791
0
                   [](const ErrorPathItem& e) {
7792
0
        return e.first;
7793
0
    });
7794
0
    if (from.condition && !value.condition)
7795
0
        value.condition = from.condition;
7796
0
    std::copy_if(from.errorPath.cbegin(),
7797
0
                 from.errorPath.cend(),
7798
0
                 std::back_inserter(value.errorPath),
7799
0
                 [&](const ErrorPathItem& e) {
7800
0
        return locations.insert(e.first).second;
7801
0
    });
7802
0
}
7803
7804
static std::vector<Token*> findAllUsages(const Variable* var,
7805
                                         Token* start, // cppcheck-suppress constParameterPointer // FP
7806
                                         const Library* library)
7807
0
{
7808
    // std::vector<Token*> result;
7809
0
    const Scope* scope = var->scope();
7810
0
    if (!scope)
7811
0
        return {};
7812
0
    return findTokensSkipDeadCode(library, start, scope->bodyEnd, [&](const Token* tok) {
7813
0
        return tok->varId() == var->declarationId();
7814
0
    });
7815
0
}
7816
7817
static Token* findStartToken(const Variable* var, Token* start, const Library* library)
7818
0
{
7819
0
    std::vector<Token*> uses = findAllUsages(var, start, library);
7820
0
    if (uses.empty())
7821
0
        return start;
7822
0
    Token* first = uses.front();
7823
0
    if (Token::findmatch(start, "goto|asm|setjmp|longjmp", first))
7824
0
        return start;
7825
0
    if (first != var->nameToken()) {
7826
        // if this is lhs in assignment then set first to the first token in LHS expression
7827
0
        Token* temp = first;
7828
0
        while (Token::Match(temp->astParent(), "[&*(]") && precedes(temp->astParent(), temp))
7829
0
            temp = temp->astParent();
7830
0
        if (Token::simpleMatch(temp->astParent(), "=") && precedes(temp, temp->astParent()))
7831
0
            first = temp;
7832
0
    }
7833
    // If there is only one usage
7834
0
    if (uses.size() == 1)
7835
0
        return first->previous();
7836
0
    const Scope* scope = first->scope();
7837
    // If first usage is in variable scope
7838
0
    if (scope == var->scope()) {
7839
0
        bool isLoopExpression = false;
7840
0
        for (const Token* parent = first; parent; parent = parent->astParent()) {
7841
0
            if (Token::simpleMatch(parent->astParent(), ";") &&
7842
0
                Token::simpleMatch(parent->astParent()->astParent(), ";") &&
7843
0
                Token::simpleMatch(parent->astParent()->astParent()->astParent(), "(") &&
7844
0
                Token::simpleMatch(parent->astParent()->astParent()->astParent()->astOperand1(), "for (") &&
7845
0
                parent == parent->astParent()->astParent()->astParent()->astOperand2()->astOperand2()->astOperand2()) {
7846
0
                isLoopExpression = true;
7847
0
            }
7848
0
        }
7849
0
        return isLoopExpression ? start : first->previous();
7850
0
    }
7851
    // If all uses are in the same scope
7852
0
    if (std::all_of(uses.begin() + 1, uses.end(), [&](const Token* tok) {
7853
0
        return tok->scope() == scope;
7854
0
    }))
7855
0
        return first->previous();
7856
    // Compute the outer scope
7857
0
    while (scope && scope->nestedIn != var->scope())
7858
0
        scope = scope->nestedIn;
7859
0
    if (!scope)
7860
0
        return start;
7861
0
    Token* tok = const_cast<Token*>(scope->bodyStart);
7862
0
    if (!tok)
7863
0
        return start;
7864
0
    if (Token::simpleMatch(tok->tokAt(-2), "} else {"))
7865
0
        tok = tok->linkAt(-2);
7866
0
    if (Token::simpleMatch(tok->previous(), ") {"))
7867
0
        return tok->linkAt(-1)->previous();
7868
0
    return tok;
7869
0
}
7870
7871
static void valueFlowUninit(TokenList& tokenlist, const Settings* settings)
7872
2.27k
{
7873
163k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
7874
160k
        if (!tok->scope()->isExecutable())
7875
91.1k
            continue;
7876
69.6k
        if (!Token::Match(tok, "%var% ;|["))
7877
67.4k
            continue;
7878
2.23k
        const Variable* var = tok->variable();
7879
2.23k
        if (!var)
7880
0
            continue;
7881
2.23k
        if (var->nameToken() != tok || var->isInit())
7882
2.23k
            continue;
7883
0
        if (!needsInitialization(var, tokenlist.isCPP()))
7884
0
            continue;
7885
0
        if (!var->isLocal() || var->isStatic() || var->isExtern() || var->isReference() || var->isThrow())
7886
0
            continue;
7887
7888
0
        ValueFlow::Value uninitValue;
7889
0
        uninitValue.setKnown();
7890
0
        uninitValue.valueType = ValueFlow::Value::ValueType::UNINIT;
7891
0
        uninitValue.tokvalue = tok;
7892
0
        if (var->isArray())
7893
0
            uninitValue.indirect = var->dimensions().size();
7894
7895
0
        bool partial = false;
7896
7897
0
        Token* start = findStartToken(var, tok->next(), &settings->library);
7898
7899
0
        std::map<Token*, ValueFlow::Value> partialReads;
7900
0
        if (const Scope* scope = var->typeScope()) {
7901
0
            if (Token::findsimplematch(scope->bodyStart, "union", scope->bodyEnd))
7902
0
                continue;
7903
0
            for (const Variable& memVar : scope->varlist) {
7904
0
                if (!memVar.isPublic())
7905
0
                    continue;
7906
                // Skip array since we can't track partial initialization from nested subexpressions
7907
0
                if (memVar.isArray())
7908
0
                    continue;
7909
0
                if (!needsInitialization(&memVar, tokenlist.isCPP())) {
7910
0
                    partial = true;
7911
0
                    continue;
7912
0
                }
7913
0
                MemberExpressionAnalyzer analyzer(memVar.nameToken()->str(), tok, uninitValue, tokenlist, settings);
7914
0
                valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, *settings);
7915
7916
0
                for (auto&& p : *analyzer.partialReads) {
7917
0
                    Token* tok2 = p.first;
7918
0
                    const ValueFlow::Value& v = p.second;
7919
                    // Try to insert into map
7920
0
                    auto pp = partialReads.insert(std::make_pair(tok2, v));
7921
0
                    ValueFlow::Value& v2 = pp.first->second;
7922
0
                    const bool inserted = pp.second;
7923
                    // Merge the two values if it is already in map
7924
0
                    if (!inserted) {
7925
0
                        if (v.valueType != v2.valueType)
7926
0
                            continue;
7927
0
                        addToErrorPath(v2, v);
7928
0
                    }
7929
0
                    v2.subexpressions.push_back(memVar.nameToken()->str());
7930
0
                }
7931
0
            }
7932
0
        }
7933
7934
0
        for (auto&& p : partialReads) {
7935
0
            Token* tok2 = p.first;
7936
0
            ValueFlow::Value& v = p.second;
7937
7938
0
            setTokenValue(tok2, std::move(v), settings);
7939
0
        }
7940
7941
0
        if (partial)
7942
0
            continue;
7943
7944
0
        valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist, settings);
7945
0
    }
7946
2.27k
}
7947
7948
static bool isContainerSizeChanged(const Token* expr,
7949
                                   const Token* start,
7950
                                   const Token* end,
7951
                                   int indirect,
7952
                                   const Settings* settings = nullptr,
7953
                                   int depth = 20);
7954
7955
static bool isContainerSizeChangedByFunction(const Token* tok,
7956
                                             int indirect,
7957
                                             const Settings* settings = nullptr,
7958
                                             int depth = 20)
7959
0
{
7960
0
    if (!tok->valueType())
7961
0
        return false;
7962
0
    if (!astIsContainer(tok))
7963
0
        return false;
7964
    // If we are accessing an element then we are not changing the container size
7965
0
    if (Token::Match(tok, "%name% . %name% (")) {
7966
0
        const Library::Container::Yield yield = getLibraryContainer(tok)->getYield(tok->strAt(2));
7967
0
        if (yield != Library::Container::Yield::NO_YIELD)
7968
0
            return false;
7969
0
    }
7970
0
    if (Token::simpleMatch(tok->astParent(), "["))
7971
0
        return false;
7972
7973
    // address of variable
7974
0
    const bool addressOf = tok->valueType()->pointer || (tok->astParent() && tok->astParent()->isUnaryOp("&"));
7975
7976
0
    int narg;
7977
0
    const Token * ftok = getTokenArgumentFunction(tok, narg);
7978
0
    if (!ftok)
7979
0
        return false; // not a function => variable not changed
7980
0
    const Function * fun = ftok->function();
7981
0
    if (fun && !fun->isImplicitlyVirtual()) {
7982
0
        const Variable *arg = fun->getArgumentVar(narg);
7983
0
        if (arg) {
7984
0
            const bool isPointer = addressOf || indirect > 0;
7985
0
            if (!arg->isReference() && !isPointer)
7986
0
                return false;
7987
0
            if (!isPointer && arg->isConst())
7988
0
                return false;
7989
0
            if (arg->valueType() && arg->valueType()->constness == 1)
7990
0
                return false;
7991
0
            const Scope * scope = fun->functionScope;
7992
0
            if (scope) {
7993
                // Argument not used
7994
0
                if (!arg->nameToken())
7995
0
                    return false;
7996
0
                if (depth > 0)
7997
0
                    return isContainerSizeChanged(arg->nameToken(),
7998
0
                                                  scope->bodyStart,
7999
0
                                                  scope->bodyEnd,
8000
0
                                                  addressOf ? indirect + 1 : indirect,
8001
0
                                                  settings,
8002
0
                                                  depth - 1);
8003
0
            }
8004
            // Don't know => Safe guess
8005
0
            return true;
8006
0
        }
8007
0
    }
8008
8009
0
    bool inconclusive = false;
8010
0
    const bool isChanged = isVariableChangedByFunctionCall(tok, indirect, settings, &inconclusive);
8011
0
    return (isChanged || inconclusive);
8012
0
}
8013
8014
struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
8015
    ContainerExpressionAnalyzer(const Token* expr, ValueFlow::Value val, const TokenList& t, const Settings* s)
8016
        : ExpressionAnalyzer(expr, std::move(val), t, s)
8017
0
    {}
8018
8019
0
    bool match(const Token* tok) const override {
8020
0
        return tok->exprId() == expr->exprId() || (astIsIterator(tok) && isAliasOf(tok, expr->exprId()));
8021
0
    }
8022
8023
    Action isWritable(const Token* tok, Direction /*d*/) const override
8024
0
    {
8025
0
        if (astIsIterator(tok))
8026
0
            return Action::None;
8027
0
        if (!getValue(tok))
8028
0
            return Action::None;
8029
0
        if (!tok->valueType())
8030
0
            return Action::None;
8031
0
        if (!astIsContainer(tok))
8032
0
            return Action::None;
8033
0
        const Token* parent = tok->astParent();
8034
0
        const Library::Container* container = getLibraryContainer(tok);
8035
8036
0
        if (container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) {
8037
0
            const Token* rhs = parent->astOperand2();
8038
0
            if (rhs->tokType() == Token::eString)
8039
0
                return Action::Read | Action::Write | Action::Incremental;
8040
0
            const Library::Container* rhsContainer = getLibraryContainer(rhs);
8041
0
            if (rhsContainer && rhsContainer->stdStringLike) {
8042
0
                if (std::any_of(rhs->values().cbegin(), rhs->values().cend(), [&](const ValueFlow::Value &rhsval) {
8043
0
                    return rhsval.isKnown() && rhsval.isContainerSizeValue();
8044
0
                }))
8045
0
                    return Action::Read | Action::Write | Action::Incremental;
8046
0
            }
8047
0
        } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
8048
0
            const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
8049
0
            if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) {
8050
0
                std::vector<const Token*> args = getArguments(tok->tokAt(3));
8051
0
                if (args.size() < 2)
8052
0
                    return Action::Read | Action::Write | Action::Incremental;
8053
0
            }
8054
0
        }
8055
0
        return Action::None;
8056
0
    }
8057
8058
0
    void writeValue(ValueFlow::Value* val, const Token* tok, Direction d) const override {
8059
0
        if (!val)
8060
0
            return;
8061
0
        if (!tok->astParent())
8062
0
            return;
8063
0
        if (!tok->valueType())
8064
0
            return;
8065
0
        if (!astIsContainer(tok))
8066
0
            return;
8067
0
        const Token* parent = tok->astParent();
8068
0
        const Library::Container* container = getLibraryContainer(tok);
8069
0
        int n = 0;
8070
8071
0
        if (container->stdStringLike && Token::simpleMatch(parent, "+=") && parent->astOperand2()) {
8072
0
            const Token* rhs = parent->astOperand2();
8073
0
            const Library::Container* rhsContainer = getLibraryContainer(rhs);
8074
0
            if (rhs->tokType() == Token::eString)
8075
0
                n = Token::getStrLength(rhs);
8076
0
            else if (rhsContainer && rhsContainer->stdStringLike) {
8077
0
                auto it = std::find_if(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value& rhsval) {
8078
0
                    return rhsval.isKnown() && rhsval.isContainerSizeValue();
8079
0
                });
8080
0
                if (it != rhs->values().end())
8081
0
                    n = it->intvalue;
8082
0
            }
8083
0
        } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
8084
0
            const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
8085
0
            if (action == Library::Container::Action::PUSH)
8086
0
                n = 1;
8087
0
            if (action == Library::Container::Action::POP)
8088
0
                n = -1;
8089
0
        }
8090
0
        if (d == Direction::Reverse)
8091
0
            val->intvalue -= n;
8092
0
        else
8093
0
            val->intvalue += n;
8094
0
    }
8095
8096
    int getIndirect(const Token* tok) const override
8097
0
    {
8098
0
        if (tok->valueType()) {
8099
0
            return tok->valueType()->pointer;
8100
0
        }
8101
0
        return ValueFlowAnalyzer::getIndirect(tok);
8102
0
    }
8103
8104
0
    Action isModified(const Token* tok) const override {
8105
0
        Action read = Action::Read;
8106
        // An iterator won't change the container size
8107
0
        if (astIsIterator(tok))
8108
0
            return read;
8109
0
        if (Token::Match(tok->astParent(), "%assign%") && astIsLHS(tok))
8110
0
            return Action::Invalid;
8111
0
        if (isLikelyStreamRead(isCPP(), tok->astParent()))
8112
0
            return Action::Invalid;
8113
0
        if (astIsContainer(tok) && ValueFlow::isContainerSizeChanged(tok, getIndirect(tok), getSettings()))
8114
0
            return read | Action::Invalid;
8115
0
        return read;
8116
0
    }
8117
};
8118
8119
static const Token* parseBinaryIntOp(const Token* expr,
8120
                                     const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
8121
                                     MathLib::bigint& known)
8122
6.34k
{
8123
6.34k
    if (!expr)
8124
0
        return nullptr;
8125
6.34k
    if (!expr->astOperand1() || !expr->astOperand2())
8126
5.23k
        return nullptr;
8127
1.10k
    if (expr->astOperand1()->exprId() == 0 && expr->astOperand2()->exprId() == 0)
8128
0
        return nullptr;
8129
1.10k
    std::vector<MathLib::bigint> x1 = eval(expr->astOperand1());
8130
1.10k
    std::vector<MathLib::bigint> x2 = eval(expr->astOperand2());
8131
1.10k
    if (expr->astOperand1()->exprId() == 0 && x1.empty())
8132
6
        return nullptr;
8133
1.10k
    if (expr->astOperand2()->exprId() == 0 && x2.empty())
8134
0
        return nullptr;
8135
1.10k
    const Token* varTok = nullptr;
8136
1.10k
    if (!x1.empty() && x2.empty()) {
8137
245
        varTok = expr->astOperand2();
8138
245
        known = x1.front();
8139
858
    } else if (x1.empty() && !x2.empty()) {
8140
186
        varTok = expr->astOperand1();
8141
186
        known = x2.front();
8142
186
    }
8143
1.10k
    return varTok;
8144
1.10k
}
8145
8146
const Token* ValueFlow::solveExprValue(const Token* expr,
8147
                                       const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
8148
                                       ValueFlow::Value& value)
8149
10.5k
{
8150
10.5k
    if (!value.isIntValue() && !value.isIteratorValue() && !value.isSymbolicValue())
8151
247
        return expr;
8152
10.3k
    if (value.isSymbolicValue() && !Token::Match(expr, "+|-"))
8153
3.95k
        return expr;
8154
6.34k
    MathLib::bigint intval;
8155
6.34k
    const Token* binaryTok = parseBinaryIntOp(expr, eval, intval);
8156
6.34k
    const bool rhs = astIsRHS(binaryTok);
8157
    // If its on the rhs, then -1 multiplication is needed, which is not possible with simple delta analysis used currently for symbolic values
8158
6.34k
    if (value.isSymbolicValue() && rhs && Token::simpleMatch(expr, "-"))
8159
8
        return expr;
8160
6.33k
    if (binaryTok && expr->str().size() == 1) {
8161
311
        switch (expr->str()[0]) {
8162
61
        case '+': {
8163
61
            value.intvalue -= intval;
8164
61
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8165
0
        }
8166
24
        case '-': {
8167
24
            if (rhs)
8168
2
                value.intvalue = intval - value.intvalue;
8169
22
            else
8170
22
                value.intvalue += intval;
8171
24
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8172
0
        }
8173
8
        case '*': {
8174
8
            if (intval == 0)
8175
0
                break;
8176
8
            value.intvalue /= intval;
8177
8
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8178
8
        }
8179
86
        case '^': {
8180
86
            value.intvalue ^= intval;
8181
86
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8182
8
        }
8183
311
        }
8184
311
    }
8185
6.15k
    return expr;
8186
6.33k
}
8187
8188
static const Token* solveExprValue(const Token* expr, ValueFlow::Value& value)
8189
5.55k
{
8190
5.55k
    return ValueFlow::solveExprValue(
8191
5.55k
        expr,
8192
5.55k
        [](const Token* tok) -> std::vector<MathLib::bigint> {
8193
1.46k
        if (tok->hasKnownIntValue())
8194
283
            return {tok->values().front().intvalue};
8195
1.17k
        return {};
8196
1.46k
    },
8197
5.55k
        value);
8198
5.55k
}
8199
8200
ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings* settings)
8201
5.55k
{
8202
5.55k
    if (value.isContainerSizeValue())
8203
0
        return ContainerExpressionAnalyzer(exprTok, std::move(value), tokenlist, settings);
8204
5.55k
    const Token* expr = solveExprValue(exprTok, value);
8205
5.55k
    return ExpressionAnalyzer(expr, std::move(value), tokenlist, settings);
8206
5.55k
}
8207
8208
ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings* settings)
8209
2.84k
{
8210
2.84k
    if (value.isContainerSizeValue())
8211
0
        return ContainerExpressionAnalyzer(exprTok, std::move(value), tokenlist, settings);
8212
2.84k
    return ExpressionAnalyzer(exprTok, std::move(value), tokenlist, settings);
8213
2.84k
}
8214
8215
bool ValueFlow::isContainerSizeChanged(const Token* tok, int indirect, const Settings* settings, int depth)
8216
0
{
8217
0
    if (!tok)
8218
0
        return false;
8219
0
    if (!tok->valueType() || !tok->valueType()->container)
8220
0
        return true;
8221
0
    if (astIsLHS(tok) && Token::Match(tok->astParent(), "%assign%|<<"))
8222
0
        return true;
8223
0
    const Library::Container* container = tok->valueType()->container;
8224
0
    if (astIsLHS(tok) && Token::simpleMatch(tok->astParent(), "["))
8225
0
        return container->stdAssociativeLike;
8226
0
    const Library::Container::Action action = astContainerAction(tok);
8227
0
    switch (action) {
8228
0
    case Library::Container::Action::RESIZE:
8229
0
    case Library::Container::Action::CLEAR:
8230
0
    case Library::Container::Action::PUSH:
8231
0
    case Library::Container::Action::POP:
8232
0
    case Library::Container::Action::CHANGE:
8233
0
    case Library::Container::Action::INSERT:
8234
0
    case Library::Container::Action::ERASE:
8235
0
        return true;
8236
0
    case Library::Container::Action::NO_ACTION:
8237
        // Is this an unknown member function call?
8238
0
        if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
8239
0
            const Library::Container::Yield yield = astContainerYield(tok);
8240
0
            return yield == Library::Container::Yield::NO_YIELD;
8241
0
        }
8242
0
        break;
8243
0
    case Library::Container::Action::FIND:
8244
0
    case Library::Container::Action::CHANGE_CONTENT:
8245
0
    case Library::Container::Action::CHANGE_INTERNAL:
8246
0
        break;
8247
0
    }
8248
0
    return isContainerSizeChangedByFunction(tok, indirect, settings, depth);
8249
0
}
8250
8251
static bool isContainerSizeChanged(const Token* expr,
8252
                                   const Token* start,
8253
                                   const Token* end,
8254
                                   int indirect,
8255
                                   const Settings* settings,
8256
                                   int depth)
8257
0
{
8258
0
    for (const Token *tok = start; tok != end; tok = tok->next()) {
8259
0
        if (tok->exprId() != expr->exprId() && !isAliasOf(tok, expr))
8260
0
            continue;
8261
0
        if (ValueFlow::isContainerSizeChanged(tok, indirect, settings, depth))
8262
0
            return true;
8263
0
    }
8264
0
    return false;
8265
0
}
8266
8267
static void valueFlowSmartPointer(TokenList &tokenlist, ErrorLogger * errorLogger, const Settings *settings)
8268
2.27k
{
8269
163k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
8270
160k
        if (!tok->scope())
8271
0
            continue;
8272
160k
        if (!tok->scope()->isExecutable())
8273
91.1k
            continue;
8274
69.6k
        if (!astIsSmartPointer(tok))
8275
69.6k
            continue;
8276
0
        if (tok->variable() && Token::Match(tok, "%var% (|{|;")) {
8277
0
            const Variable* var = tok->variable();
8278
0
            if (!var->isSmartPointer())
8279
0
                continue;
8280
0
            if (var->nameToken() == tok) {
8281
0
                if (Token::Match(tok, "%var% (|{") && tok->next()->astOperand2() &&
8282
0
                    tok->next()->astOperand2()->str() != ",") {
8283
0
                    Token* inTok = tok->next()->astOperand2();
8284
0
                    const std::list<ValueFlow::Value>& values = inTok->values();
8285
0
                    const bool constValue = inTok->isNumber();
8286
0
                    valueFlowForwardAssign(inTok, var, values, constValue, true, tokenlist, errorLogger, settings);
8287
8288
0
                } else if (Token::Match(tok, "%var% ;")) {
8289
0
                    ValueFlow::Value v(0);
8290
0
                    v.setKnown();
8291
0
                    valueFlowForwardAssign(tok, var, {std::move(v)}, false, true, tokenlist, errorLogger, settings);
8292
0
                }
8293
0
            }
8294
0
        } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (") &&
8295
0
                   tok->astParent()->originalName() != "->") {
8296
0
            std::vector<const Variable*> vars = getVariables(tok);
8297
0
            Token* ftok = tok->astParent()->tokAt(2);
8298
0
            if (Token::simpleMatch(tok->astParent(), ". reset (")) {
8299
0
                if (Token::simpleMatch(ftok, "( )")) {
8300
0
                    ValueFlow::Value v(0);
8301
0
                    v.setKnown();
8302
0
                    valueFlowForwardAssign(ftok, tok, vars, {std::move(v)}, false, tokenlist, errorLogger, settings);
8303
0
                } else {
8304
0
                    tok->removeValues(std::mem_fn(&ValueFlow::Value::isIntValue));
8305
0
                    Token* inTok = ftok->astOperand2();
8306
0
                    if (!inTok)
8307
0
                        continue;
8308
0
                    const std::list<ValueFlow::Value>& values = inTok->values();
8309
0
                    valueFlowForwardAssign(inTok, tok, vars, values, false, tokenlist, errorLogger, settings);
8310
0
                }
8311
0
            } else if (Token::simpleMatch(tok->astParent(), ". release ( )")) {
8312
0
                const Token* parent = ftok->astParent();
8313
0
                bool hasParentReset = false;
8314
0
                while (parent) {
8315
0
                    if (Token::Match(parent->tokAt(-2), ". release|reset (") &&
8316
0
                        parent->tokAt(-2)->astOperand1()->exprId() == tok->exprId()) {
8317
0
                        hasParentReset = true;
8318
0
                        break;
8319
0
                    }
8320
0
                    parent = parent->astParent();
8321
0
                }
8322
0
                if (hasParentReset)
8323
0
                    continue;
8324
0
                ValueFlow::Value v(0);
8325
0
                v.setKnown();
8326
0
                valueFlowForwardAssign(ftok, tok, vars, {std::move(v)}, false, tokenlist, errorLogger, settings);
8327
0
            } else if (Token::simpleMatch(tok->astParent(), ". get ( )")) {
8328
0
                ValueFlow::Value v = makeSymbolic(tok);
8329
0
                setTokenValue(tok->astParent()->tokAt(2), std::move(v), settings);
8330
0
            }
8331
0
        } else if (Token::Match(tok->previous(), "%name%|> (|{") && astIsSmartPointer(tok) &&
8332
0
                   astIsSmartPointer(tok->astOperand1())) {
8333
0
            std::vector<const Token*> args = getArguments(tok);
8334
0
            if (args.empty())
8335
0
                continue;
8336
0
            for (const ValueFlow::Value& v : args.front()->values())
8337
0
                setTokenValue(tok, v, settings);
8338
0
        }
8339
0
    }
8340
2.27k
}
8341
8342
static Library::Container::Yield findIteratorYield(Token* tok, const Token** ftok, const Settings *settings)
8343
0
{
8344
0
    auto yield = astContainerYield(tok, ftok);
8345
0
    if (*ftok)
8346
0
        return yield;
8347
8348
0
    if (!tok->astParent())
8349
0
        return yield;
8350
8351
    //begin/end free functions
8352
0
    return astFunctionYield(tok->astParent()->previous(), settings, ftok);
8353
0
}
8354
8355
static void valueFlowIterators(TokenList &tokenlist, const Settings *settings)
8356
2.27k
{
8357
163k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
8358
160k
        if (!tok->scope())
8359
0
            continue;
8360
160k
        if (!tok->scope()->isExecutable())
8361
91.1k
            continue;
8362
69.6k
        if (!astIsContainer(tok))
8363
69.6k
            continue;
8364
0
        Token* ftok = nullptr;
8365
0
        const Library::Container::Yield yield = findIteratorYield(tok, const_cast<const Token**>(&ftok), settings);
8366
0
        if (ftok) {
8367
0
            ValueFlow::Value v(0);
8368
0
            v.setKnown();
8369
0
            if (yield == Library::Container::Yield::START_ITERATOR) {
8370
0
                v.valueType = ValueFlow::Value::ValueType::ITERATOR_START;
8371
0
                setTokenValue(ftok->next(), std::move(v), settings);
8372
0
            } else if (yield == Library::Container::Yield::END_ITERATOR) {
8373
0
                v.valueType = ValueFlow::Value::ValueType::ITERATOR_END;
8374
0
                setTokenValue(ftok->next(), std::move(v), settings);
8375
0
            }
8376
0
        }
8377
0
    }
8378
2.27k
}
8379
8380
static std::list<ValueFlow::Value> getIteratorValues(std::list<ValueFlow::Value> values, const ValueFlow::Value::ValueKind* kind = nullptr)
8381
73.4k
{
8382
73.4k
    values.remove_if([&](const ValueFlow::Value& v) {
8383
16.6k
        if (kind && v.valueKind != *kind)
8384
488
            return true;
8385
16.1k
        return !v.isIteratorValue();
8386
16.6k
    });
8387
73.4k
    return values;
8388
73.4k
}
8389
8390
struct IteratorConditionHandler : SimpleConditionHandler {
8391
39.6k
    std::vector<Condition> parse(const Token* tok, const Settings* /*settings*/) const override {
8392
39.6k
        Condition cond;
8393
8394
39.6k
        if (Token::Match(tok, "==|!=")) {
8395
1.87k
            if (!tok->astOperand1() || !tok->astOperand2())
8396
0
                return {};
8397
8398
1.87k
            const ValueFlow::Value::ValueKind kind = ValueFlow::Value::ValueKind::Known;
8399
1.87k
            std::list<ValueFlow::Value> values = getIteratorValues(tok->astOperand1()->values(), &kind);
8400
1.87k
            if (!values.empty()) {
8401
0
                cond.vartok = tok->astOperand2();
8402
1.87k
            } else {
8403
1.87k
                values = getIteratorValues(tok->astOperand2()->values(), &kind);
8404
1.87k
                if (!values.empty())
8405
0
                    cond.vartok = tok->astOperand1();
8406
1.87k
            }
8407
1.87k
            for (ValueFlow::Value& v:values) {
8408
0
                v.setPossible();
8409
0
                v.assumeCondition(tok);
8410
0
            }
8411
1.87k
            cond.true_values = values;
8412
1.87k
            cond.false_values = values;
8413
1.87k
        }
8414
8415
39.6k
        return {std::move(cond)};
8416
39.6k
    }
8417
};
8418
8419
static void valueFlowIteratorInfer(TokenList &tokenlist, const Settings *settings)
8420
2.27k
{
8421
163k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
8422
160k
        if (!tok->scope())
8423
0
            continue;
8424
160k
        if (!tok->scope()->isExecutable())
8425
91.1k
            continue;
8426
69.6k
        std::list<ValueFlow::Value> values = getIteratorValues(tok->values());
8427
69.6k
        values.remove_if([&](const ValueFlow::Value& v) {
8428
0
            if (!v.isImpossible())
8429
0
                return true;
8430
0
            if (!v.condition)
8431
0
                return true;
8432
0
            if (v.bound != ValueFlow::Value::Bound::Point)
8433
0
                return true;
8434
0
            if (v.isIteratorEndValue() && v.intvalue <= 0)
8435
0
                return true;
8436
0
            if (v.isIteratorStartValue() && v.intvalue >= 0)
8437
0
                return true;
8438
0
            return false;
8439
0
        });
8440
69.6k
        for (ValueFlow::Value& v:values) {
8441
0
            v.setPossible();
8442
0
            if (v.isIteratorStartValue())
8443
0
                v.intvalue++;
8444
0
            if (v.isIteratorEndValue())
8445
0
                v.intvalue--;
8446
0
            setTokenValue(tok, std::move(v), settings);
8447
0
        }
8448
69.6k
    }
8449
2.27k
}
8450
8451
static std::vector<ValueFlow::Value> getContainerValues(const Token* tok)
8452
0
{
8453
0
    std::vector<ValueFlow::Value> values;
8454
0
    if (tok) {
8455
0
        std::copy_if(tok->values().cbegin(),
8456
0
                     tok->values().cend(),
8457
0
                     std::back_inserter(values),
8458
0
                     std::mem_fn(&ValueFlow::Value::isContainerSizeValue));
8459
0
    }
8460
0
    return values;
8461
0
}
8462
8463
static ValueFlow::Value makeContainerSizeValue(std::size_t s, bool known = true)
8464
0
{
8465
0
    ValueFlow::Value value(s);
8466
0
    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8467
0
    if (known)
8468
0
        value.setKnown();
8469
0
    return value;
8470
0
}
8471
8472
static std::vector<ValueFlow::Value> makeContainerSizeValue(const Token* tok, bool known = true)
8473
0
{
8474
0
    if (tok->hasKnownIntValue())
8475
0
        return {makeContainerSizeValue(tok->values().front().intvalue, known)};
8476
0
    return {};
8477
0
}
8478
8479
static std::vector<ValueFlow::Value> getContainerSizeFromConstructorArgs(const std::vector<const Token*>& args,
8480
                                                                         const Library::Container* container,
8481
                                                                         bool known)
8482
0
{
8483
0
    if (astIsIntegral(args[0], false)) { // { count, i } or { count }
8484
0
        if (args.size() == 1 || (args.size() > 1 && !astIsIntegral(args[1], false)))
8485
0
            return {makeContainerSizeValue(args[0], known)};
8486
0
    } else if (astIsContainer(args[0]) && args.size() == 1) { // copy constructor
8487
0
        return getContainerValues(args[0]);
8488
0
    } else if (isIteratorPair(args)) {
8489
0
        std::vector<ValueFlow::Value> result = getContainerValues(args[0]);
8490
0
        if (!result.empty())
8491
0
            return result;
8492
        // (ptr, ptr + size)
8493
0
        if (astIsPointer(args[0]) && args[0]->exprId() != 0) {
8494
            // (ptr, ptr) is empty
8495
            // TODO: Use lifetime values to check if it points to the same address
8496
0
            if (args[0]->exprId() == args[1]->exprId())
8497
0
                return {makeContainerSizeValue(std::size_t{0}, known)};
8498
            // TODO: Insert iterator positions for pointers
8499
0
            if (Token::simpleMatch(args[1], "+")) {
8500
0
                nonneg int const eid = args[0]->exprId();
8501
0
                const Token* vartok = args[1]->astOperand1();
8502
0
                const Token* sizetok = args[1]->astOperand2();
8503
0
                if (sizetok->exprId() == eid)
8504
0
                    std::swap(vartok, sizetok);
8505
0
                if (vartok->exprId() == eid && sizetok->hasKnownIntValue())
8506
0
                    return {makeContainerSizeValue(sizetok, known)};
8507
0
            }
8508
0
        }
8509
0
    } else if (container->stdStringLike) {
8510
0
        if (astIsPointer(args[0])) {
8511
            // TODO: Try to read size of string literal { "abc" }
8512
0
            if (args.size() == 2 && astIsIntegral(args[1], false)) // { char*, count }
8513
0
                return {makeContainerSizeValue(args[1], known)};
8514
0
        } else if (astIsContainer(args[0])) {
8515
0
            if (args.size() == 1) // copy constructor { str }
8516
0
                return getContainerValues(args[0]);
8517
0
            if (args.size() == 3) // { str, pos, count }
8518
0
                return {makeContainerSizeValue(args[2], known)};
8519
            // TODO: { str, pos }, { ..., alloc }
8520
0
        }
8521
0
    }
8522
0
    return {};
8523
0
}
8524
8525
static bool valueFlowIsSameContainerType(const ValueType& contType, const Token* tok, const Settings* settings)
8526
0
{
8527
0
    if (!tok || !tok->valueType() || !tok->valueType()->containerTypeToken)
8528
0
        return false;
8529
8530
0
    const ValueType tokType = ValueType::parseDecl(tok->valueType()->containerTypeToken, *settings);
8531
0
    return contType.isTypeEqual(&tokType);
8532
0
}
8533
8534
static std::vector<ValueFlow::Value> getInitListSize(const Token* tok,
8535
                                                     const ValueType* valueType,
8536
                                                     const Settings* settings,
8537
                                                     bool known = true)
8538
0
{
8539
0
    std::vector<const Token*> args = getArguments(tok);
8540
0
    if (args.empty())
8541
0
        return {makeContainerSizeValue(std::size_t{0}, known)};
8542
0
    bool initList = true;
8543
    // Try to disambiguate init list from constructor
8544
0
    if (args.size() < 4) {
8545
0
        initList = !isIteratorPair(args) && !(args.size() < 3 && astIsIntegral(args[0], false));
8546
0
        const Token* containerTypeToken = valueType->containerTypeToken;
8547
0
        if (valueType->container->stdStringLike) {
8548
0
            initList = astIsGenericChar(args[0]) && !astIsPointer(args[0]);
8549
0
        } else if (containerTypeToken && settings) {
8550
0
            ValueType vt = ValueType::parseDecl(containerTypeToken, *settings);
8551
0
            if (vt.pointer > 0 && astIsPointer(args[0]))
8552
0
                initList = true;
8553
0
            else if (vt.type == ValueType::ITERATOR && astIsIterator(args[0]))
8554
0
                initList = true;
8555
0
            else if (vt.isIntegral() && astIsIntegral(args[0], false))
8556
0
                initList = true;
8557
0
            else if (args.size() == 1 && valueFlowIsSameContainerType(vt, tok->astOperand2(), settings))
8558
0
                initList = false; // copy ctor
8559
0
        }
8560
0
    }
8561
0
    if (!initList)
8562
0
        return getContainerSizeFromConstructorArgs(args, valueType->container, known);
8563
0
    return {makeContainerSizeValue(args.size(), known)};
8564
0
}
8565
8566
static std::vector<ValueFlow::Value> getContainerSizeFromConstructor(const Token* tok,
8567
                                                                     const ValueType* valueType,
8568
                                                                     const Settings* settings,
8569
                                                                     bool known = true)
8570
0
{
8571
0
    std::vector<const Token*> args = getArguments(tok);
8572
0
    if (args.empty())
8573
0
        return {makeContainerSizeValue(std::size_t{0}, known)};
8574
    // Init list in constructor
8575
0
    if (args.size() == 1 && Token::simpleMatch(args[0], "{"))
8576
0
        return getInitListSize(args[0], valueType, settings, known);
8577
0
    return getContainerSizeFromConstructorArgs(args, valueType->container, known);
8578
0
}
8579
8580
static void valueFlowContainerSetTokValue(TokenList& tokenlist, const Settings* settings, const Token* tok, Token* initList)
8581
0
{
8582
0
    ValueFlow::Value value;
8583
0
    value.valueType = ValueFlow::Value::ValueType::TOK;
8584
0
    value.tokvalue = initList;
8585
0
    if (astIsContainerString(tok) && Token::simpleMatch(initList, "{") && Token::Match(initList->astOperand2(), "%str%")) {
8586
0
        value.tokvalue = initList->astOperand2();
8587
0
    }
8588
0
    value.setKnown();
8589
0
    Token* start = initList->link() ? initList->link() : initList->next();
8590
0
    if (tok->variable() && tok->variable()->isConst()) {
8591
0
        valueFlowForwardConst(start, tok->variable()->scope()->bodyEnd, tok->variable(), {value}, settings);
8592
0
    } else {
8593
0
        valueFlowForward(start, tok, value, tokenlist, settings);
8594
0
    }
8595
0
}
8596
8597
0
static const Scope* getFunctionScope(const Scope* scope) {
8598
0
    while (scope && scope->type != Scope::ScopeType::eFunction)
8599
0
        scope = scope->nestedIn;
8600
0
    return scope;
8601
0
}
8602
8603
static MathLib::bigint valueFlowGetStrLength(const Token* tok)
8604
0
{
8605
0
    if (tok->tokType() == Token::eString)
8606
0
        return Token::getStrLength(tok);
8607
0
    if (astIsGenericChar(tok) || tok->tokType() == Token::eChar)
8608
0
        return 1;
8609
0
    if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE))
8610
0
        return v->intvalue;
8611
0
    if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::TOK)) {
8612
0
        if (v->tokvalue != tok)
8613
0
            return valueFlowGetStrLength(v->tokvalue);
8614
0
    }
8615
0
    return 0;
8616
0
}
8617
8618
static void valueFlowContainerSize(TokenList& tokenlist,
8619
                                   const SymbolDatabase& symboldatabase,
8620
                                   ErrorLogger* /*errorLogger*/,
8621
                                   const Settings* settings,
8622
                                   const std::set<const Scope*>& skippedFunctions)
8623
2.27k
{
8624
    // declaration
8625
13.6k
    for (const Variable *var : symboldatabase.variableList()) {
8626
13.6k
        if (!var)
8627
2.27k
            continue;
8628
11.3k
        if (!var->scope() || !var->scope()->bodyEnd || !var->scope()->bodyStart)
8629
11.3k
            continue;
8630
0
        if (!var->valueType() || !var->valueType()->container)
8631
0
            continue;
8632
0
        if (!astIsContainer(var->nameToken()))
8633
0
            continue;
8634
0
        if (skippedFunctions.count(getFunctionScope(var->scope())))
8635
0
            continue;
8636
8637
0
        bool known = true;
8638
0
        int size = 0;
8639
0
        const bool nonLocal = !var->isLocal() || var->isPointer() || var->isReference() || var->isStatic();
8640
0
        bool constSize = var->isConst() && !nonLocal;
8641
0
        bool staticSize = false;
8642
0
        if (var->valueType()->container->size_templateArgNo >= 0) {
8643
0
            staticSize = true;
8644
0
            constSize = true;
8645
0
            size = -1;
8646
0
            if (var->dimensions().size() == 1) {
8647
0
                const Dimension& dim = var->dimensions().front();
8648
0
                if (dim.known) {
8649
0
                    size = dim.num;
8650
0
                } else if (dim.tok && dim.tok->hasKnownIntValue()) {
8651
0
                    size = dim.tok->values().front().intvalue;
8652
0
                }
8653
0
            }
8654
0
            if (size < 0)
8655
0
                continue;
8656
0
        }
8657
0
        if (!staticSize && nonLocal)
8658
0
            continue;
8659
0
        Token* nameToken = const_cast<Token*>(var->nameToken());
8660
0
        if (nameToken->hasKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE))
8661
0
            continue;
8662
0
        if (!staticSize) {
8663
0
            if (!Token::Match(nameToken, "%name% ;") &&
8664
0
                !(Token::Match(nameToken, "%name% {") && Token::simpleMatch(nameToken->next()->link(), "} ;")) &&
8665
0
                !Token::Match(nameToken, "%name% ("))
8666
0
                continue;
8667
0
        }
8668
0
        if (nameToken->astTop() && Token::Match(nameToken->astTop()->previous(), "for|while"))
8669
0
            known = !isVariableChanged(var, settings, true);
8670
0
        std::vector<ValueFlow::Value> values{ValueFlow::Value{size}};
8671
0
        values.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8672
0
        if (known)
8673
0
            values.back().setKnown();
8674
0
        if (!staticSize) {
8675
0
            if (Token::simpleMatch(nameToken->next(), "{")) {
8676
0
                Token* initList = nameToken->next();
8677
0
                valueFlowContainerSetTokValue(tokenlist, settings, nameToken, initList);
8678
0
                values = getInitListSize(initList, var->valueType(), settings, known);
8679
0
            } else if (Token::simpleMatch(nameToken->next(), "(")) {
8680
0
                const Token* constructorArgs = nameToken->next();
8681
0
                values = getContainerSizeFromConstructor(constructorArgs, var->valueType(), settings, known);
8682
0
            }
8683
0
        }
8684
8685
0
        if (constSize) {
8686
0
            valueFlowForwardConst(nameToken->next(), var->scope()->bodyEnd, var, values, settings);
8687
0
            continue;
8688
0
        }
8689
8690
0
        for (const ValueFlow::Value& value : values) {
8691
0
            valueFlowForward(nameToken->next(), var->nameToken(), value, tokenlist, settings);
8692
0
        }
8693
0
    }
8694
8695
    // after assignment
8696
2.90k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
8697
69.6k
        for (Token* tok = const_cast<Token*>(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) {
8698
66.7k
            if (Token::Match(tok, "%name%|;|{|} %var% = %str% ;")) {
8699
0
                Token* containerTok = tok->next();
8700
0
                if (containerTok->exprId() == 0)
8701
0
                    continue;
8702
0
                if (containerTok->valueType() && containerTok->valueType()->container &&
8703
0
                    containerTok->valueType()->container->stdStringLike) {
8704
0
                    valueFlowContainerSetTokValue(tokenlist, settings, containerTok, containerTok->tokAt(2));
8705
0
                    ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2)));
8706
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8707
0
                    value.setKnown();
8708
0
                    valueFlowForward(containerTok->next(), containerTok, value, tokenlist, settings);
8709
0
                }
8710
66.7k
            } else if (Token::Match(tok->previous(), ">|return (|{") && astIsContainer(tok) && getLibraryContainer(tok)->size_templateArgNo < 0) {
8711
0
                std::vector<ValueFlow::Value> values;
8712
0
                if (Token::simpleMatch(tok, "{")) {
8713
0
                    values = getInitListSize(tok, tok->valueType(), settings, true);
8714
0
                    ValueFlow::Value value;
8715
0
                    value.valueType = ValueFlow::Value::ValueType::TOK;
8716
0
                    value.tokvalue = tok;
8717
0
                    value.setKnown();
8718
0
                    values.push_back(value);
8719
0
                } else if (Token::simpleMatch(tok, "(")) {
8720
0
                    const Token* constructorArgs = tok;
8721
0
                    values = getContainerSizeFromConstructor(constructorArgs, tok->valueType(), settings, true);
8722
0
                }
8723
0
                for (const ValueFlow::Value& value : values)
8724
0
                    setTokenValue(tok, value, settings);
8725
66.7k
            } else if (Token::Match(tok, "%name%|;|{|}|> %var% = {") && Token::simpleMatch(tok->linkAt(3), "} ;")) {
8726
0
                Token* containerTok = tok->next();
8727
0
                if (containerTok->exprId() == 0)
8728
0
                    continue;
8729
0
                if (astIsContainer(containerTok) && containerTok->valueType()->container->size_templateArgNo < 0) {
8730
0
                    std::vector<ValueFlow::Value> values =
8731
0
                        getInitListSize(tok->tokAt(3), containerTok->valueType(), settings);
8732
0
                    valueFlowContainerSetTokValue(tokenlist, settings, containerTok, tok->tokAt(3));
8733
0
                    for (const ValueFlow::Value& value : values)
8734
0
                        valueFlowForward(containerTok->next(), containerTok, value, tokenlist, settings);
8735
0
                }
8736
66.7k
            } else if (Token::Match(tok, ". %name% (") && tok->astOperand1() && tok->astOperand1()->valueType() &&
8737
66.7k
                       tok->astOperand1()->valueType()->container) {
8738
0
                const Token* containerTok = tok->astOperand1();
8739
0
                if (containerTok->exprId() == 0)
8740
0
                    continue;
8741
0
                const Library::Container::Action action = containerTok->valueType()->container->getAction(tok->strAt(1));
8742
0
                if (action == Library::Container::Action::CLEAR) {
8743
0
                    ValueFlow::Value value(0);
8744
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8745
0
                    value.setKnown();
8746
0
                    valueFlowForward(tok->next(), containerTok, value, tokenlist, settings);
8747
0
                } else if (action == Library::Container::Action::RESIZE && tok->tokAt(2)->astOperand2() &&
8748
0
                           tok->tokAt(2)->astOperand2()->hasKnownIntValue()) {
8749
0
                    ValueFlow::Value value(tok->tokAt(2)->astOperand2()->values().front());
8750
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8751
0
                    value.setKnown();
8752
0
                    valueFlowForward(tok->linkAt(2), containerTok, value, tokenlist, settings);
8753
0
                } else if (action == Library::Container::Action::PUSH && !isIteratorPair(getArguments(tok->tokAt(2)))) {
8754
0
                    ValueFlow::Value value(0);
8755
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8756
0
                    value.setImpossible();
8757
0
                    valueFlowForward(tok->linkAt(2), containerTok, value, tokenlist, settings);
8758
0
                }
8759
66.7k
            } else if (Token::simpleMatch(tok, "+=") && astIsContainer(tok->astOperand1())) {
8760
0
                const Token* containerTok = tok->astOperand1();
8761
0
                const Token* valueTok = tok->astOperand2();
8762
0
                MathLib::bigint size = valueFlowGetStrLength(valueTok);
8763
0
                if (size == 0)
8764
0
                    continue;
8765
0
                ValueFlow::Value value(size - 1);
8766
0
                value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8767
0
                value.bound = ValueFlow::Value::Bound::Upper;
8768
0
                value.setImpossible();
8769
0
                Token* next = nextAfterAstRightmostLeaf(tok);
8770
0
                if (!next)
8771
0
                    next = tok->next();
8772
0
                valueFlowForward(next, containerTok, value, tokenlist, settings);
8773
0
            }
8774
66.7k
        }
8775
2.90k
    }
8776
2.27k
}
8777
8778
struct ContainerConditionHandler : ConditionHandler {
8779
    std::vector<Condition> parse(const Token* tok, const Settings* settings) const override
8780
39.6k
    {
8781
39.6k
        std::vector<Condition> conds;
8782
39.6k
        parseCompareEachInt(tok, [&](const Token* vartok, ValueFlow::Value true_value, ValueFlow::Value false_value) {
8783
1.71k
            vartok = settings->library.getContainerFromYield(vartok, Library::Container::Yield::SIZE);
8784
1.71k
            if (!vartok)
8785
1.71k
                return;
8786
0
            true_value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8787
0
            false_value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8788
0
            Condition cond;
8789
0
            cond.true_values.push_back(std::move(true_value));
8790
0
            cond.false_values.push_back(std::move(false_value));
8791
0
            cond.vartok = vartok;
8792
0
            conds.push_back(std::move(cond));
8793
0
        });
8794
39.6k
        if (!conds.empty())
8795
0
            return conds;
8796
8797
39.6k
        const Token* vartok = nullptr;
8798
8799
        // Empty check
8800
39.6k
        if (tok->str() == "(") {
8801
5.40k
            vartok = settings->library.getContainerFromYield(tok, Library::Container::Yield::EMPTY);
8802
            // TODO: Handle .size()
8803
5.40k
            if (!vartok)
8804
5.40k
                return {};
8805
0
            const Token *parent = tok->astParent();
8806
0
            while (parent) {
8807
0
                if (Token::Match(parent, "%comp%"))
8808
0
                    return {};
8809
0
                parent = parent->astParent();
8810
0
            }
8811
0
            ValueFlow::Value value(tok, 0LL);
8812
0
            value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8813
0
            Condition cond;
8814
0
            cond.true_values.emplace_back(value);
8815
0
            cond.false_values.emplace_back(std::move(value));
8816
0
            cond.vartok = vartok;
8817
0
            cond.inverted = true;
8818
0
            return {std::move(cond)};
8819
0
        }
8820
        // String compare
8821
34.2k
        if (Token::Match(tok, "==|!=")) {
8822
1.87k
            const Token *strtok = nullptr;
8823
1.87k
            if (Token::Match(tok->astOperand1(), "%str%")) {
8824
0
                strtok = tok->astOperand1();
8825
0
                vartok = tok->astOperand2();
8826
1.87k
            } else if (Token::Match(tok->astOperand2(), "%str%")) {
8827
0
                strtok = tok->astOperand2();
8828
0
                vartok = tok->astOperand1();
8829
0
            }
8830
1.87k
            if (!strtok)
8831
1.87k
                return {};
8832
0
            if (!astIsContainer(vartok))
8833
0
                return {};
8834
0
            ValueFlow::Value value(tok, Token::getStrLength(strtok));
8835
0
            value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8836
0
            Condition cond;
8837
0
            cond.false_values.emplace_back(value);
8838
0
            cond.true_values.emplace_back(std::move(value));
8839
0
            cond.vartok = vartok;
8840
0
            cond.impossible = false;
8841
0
            return {std::move(cond)};
8842
0
        }
8843
32.4k
        return {};
8844
34.2k
    }
8845
};
8846
8847
static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings)
8848
1.36k
{
8849
1.36k
    auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint {
8850
0
        MathLib::bigint sizeValue = -1;
8851
0
        const Library::AllocFunc* allocFunc = settings->library.getAllocFuncInfo(funcTok);
8852
0
        if (!allocFunc)
8853
0
            allocFunc = settings->library.getReallocFuncInfo(funcTok);
8854
0
        if (!allocFunc || allocFunc->bufferSize == Library::AllocFunc::BufferSize::none)
8855
0
            return sizeValue;
8856
8857
0
        const std::vector<const Token*> args = getArguments(funcTok);
8858
8859
0
        const Token* const arg1 = (args.size() >= allocFunc->bufferSizeArg1) ? args[allocFunc->bufferSizeArg1 - 1] : nullptr;
8860
0
        const Token* const arg2 = (args.size() >= allocFunc->bufferSizeArg2) ? args[allocFunc->bufferSizeArg2 - 1] : nullptr;
8861
8862
0
        switch (allocFunc->bufferSize) {
8863
0
        case Library::AllocFunc::BufferSize::none:
8864
0
            break;
8865
0
        case Library::AllocFunc::BufferSize::malloc:
8866
0
            if (arg1 && arg1->hasKnownIntValue())
8867
0
                sizeValue = arg1->getKnownIntValue();
8868
0
            break;
8869
0
        case Library::AllocFunc::BufferSize::calloc:
8870
0
            if (arg1 && arg2 && arg1->hasKnownIntValue() && arg2->hasKnownIntValue())
8871
0
                sizeValue = arg1->getKnownIntValue() * arg2->getKnownIntValue();
8872
0
            break;
8873
0
        case Library::AllocFunc::BufferSize::strdup:
8874
0
            if (arg1 && arg1->hasKnownValue()) {
8875
0
                const ValueFlow::Value& value = arg1->values().back();
8876
0
                if (value.isTokValue() && value.tokvalue->tokType() == Token::eString)
8877
0
                    sizeValue = Token::getStrLength(value.tokvalue) + 1; // Add one for the null terminator
8878
0
            }
8879
0
            break;
8880
0
        }
8881
0
        return sizeValue;
8882
0
    };
8883
8884
1.36k
    auto getBufferSizeFromNew = [&](const Token* newTok) -> MathLib::bigint {
8885
0
        MathLib::bigint sizeValue = -1, numElem = -1;
8886
8887
0
        if (newTok && newTok->astOperand1()) { // number of elements
8888
0
            const Token* bracTok = nullptr, *typeTok = nullptr;
8889
0
            if (newTok->astOperand1()->str() == "[")
8890
0
                bracTok = newTok->astOperand1();
8891
0
            else if (Token::Match(newTok->astOperand1(), "(|{")) {
8892
0
                if (newTok->astOperand1()->astOperand1() && newTok->astOperand1()->astOperand1()->str() == "[")
8893
0
                    bracTok = newTok->astOperand1()->astOperand1();
8894
0
                else
8895
0
                    typeTok = newTok->astOperand1()->astOperand1();
8896
0
            }
8897
0
            else
8898
0
                typeTok = newTok->astOperand1();
8899
0
            if (bracTok && bracTok->astOperand2() && bracTok->astOperand2()->hasKnownIntValue())
8900
0
                numElem = bracTok->astOperand2()->getKnownIntValue();
8901
0
            else if (Token::Match(typeTok, "%type%"))
8902
0
                numElem = 1;
8903
0
        }
8904
8905
0
        if (numElem >= 0 && newTok->astParent() && newTok->astParent()->isAssignmentOp()) { // size of the allocated type
8906
0
            const Token* typeTok = newTok->astParent()->astOperand1(); // TODO: implement fallback for e.g. "auto p = new Type;"
8907
0
            if (!typeTok || !typeTok->varId())
8908
0
                typeTok = newTok->astParent()->previous(); // hack for "int** z = ..."
8909
0
            if (typeTok && typeTok->valueType()) {
8910
0
                const MathLib::bigint typeSize = typeTok->valueType()->typeSize(settings->platform, typeTok->valueType()->pointer > 1);
8911
0
                if (typeSize >= 0)
8912
0
                    sizeValue = numElem * typeSize;
8913
0
            }
8914
0
        }
8915
0
        return sizeValue;
8916
0
    };
8917
8918
1.73k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
8919
37.6k
        for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) {
8920
35.9k
            if (!Token::Match(tok, "[;{}] %var% ="))
8921
34.7k
                continue;
8922
8923
1.14k
            if (!tok->next()->variable())
8924
0
                continue;
8925
8926
1.14k
            const Token *rhs = tok->tokAt(2)->astOperand2();
8927
1.14k
            while (rhs && rhs->isCast())
8928
0
                rhs = rhs->astOperand2() ? rhs->astOperand2() : rhs->astOperand1();
8929
1.14k
            if (!rhs)
8930
0
                continue;
8931
8932
1.14k
            const bool isNew = symboldatabase.isCPP() && rhs->str() == "new";
8933
1.14k
            if (!isNew && !Token::Match(rhs->previous(), "%name% ("))
8934
1.14k
                continue;
8935
8936
0
            const MathLib::bigint sizeValue = isNew ? getBufferSizeFromNew(rhs) : getBufferSizeFromAllocFunc(rhs->previous());
8937
0
            if (sizeValue < 0)
8938
0
                continue;
8939
8940
0
            ValueFlow::Value value(sizeValue);
8941
0
            value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + std::to_string(sizeValue));
8942
0
            value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
8943
0
            value.setKnown();
8944
0
            valueFlowForward(const_cast<Token*>(rhs), functionScope->bodyEnd, tok->next(), std::move(value), tokenlist, settings);
8945
0
        }
8946
1.73k
    }
8947
1.36k
}
8948
8949
static bool getMinMaxValues(const ValueType *vt, const cppcheck::Platform &platform, MathLib::bigint &minValue, MathLib::bigint &maxValue)
8950
0
{
8951
0
    if (!vt || !vt->isIntegral() || vt->pointer)
8952
0
        return false;
8953
8954
0
    int bits;
8955
0
    switch (vt->type) {
8956
0
    case ValueType::Type::BOOL:
8957
0
        bits = 1;
8958
0
        break;
8959
0
    case ValueType::Type::CHAR:
8960
0
        bits = platform.char_bit;
8961
0
        break;
8962
0
    case ValueType::Type::SHORT:
8963
0
        bits = platform.short_bit;
8964
0
        break;
8965
0
    case ValueType::Type::INT:
8966
0
        bits = platform.int_bit;
8967
0
        break;
8968
0
    case ValueType::Type::LONG:
8969
0
        bits = platform.long_bit;
8970
0
        break;
8971
0
    case ValueType::Type::LONGLONG:
8972
0
        bits = platform.long_long_bit;
8973
0
        break;
8974
0
    default:
8975
0
        return false;
8976
0
    }
8977
8978
0
    if (bits == 1) {
8979
0
        minValue = 0;
8980
0
        maxValue = 1;
8981
0
    } else if (bits < 62) {
8982
0
        if (vt->sign == ValueType::Sign::UNSIGNED) {
8983
0
            minValue = 0;
8984
0
            maxValue = (1LL << bits) - 1;
8985
0
        } else {
8986
0
            minValue = -(1LL << (bits - 1));
8987
0
            maxValue = (1LL << (bits - 1)) - 1;
8988
0
        }
8989
0
    } else if (bits == 64) {
8990
0
        if (vt->sign == ValueType::Sign::UNSIGNED) {
8991
0
            minValue = 0;
8992
0
            maxValue = LLONG_MAX; // todo max unsigned value
8993
0
        } else {
8994
0
            minValue = LLONG_MIN;
8995
0
            maxValue = LLONG_MAX;
8996
0
        }
8997
0
    } else {
8998
0
        return false;
8999
0
    }
9000
9001
0
    return true;
9002
0
}
9003
9004
static bool getMinMaxValues(const std::string &typestr, const Settings *settings, MathLib::bigint &minvalue, MathLib::bigint &maxvalue)
9005
0
{
9006
0
    TokenList typeTokens(settings);
9007
0
    std::istringstream istr(typestr+";");
9008
0
    if (!typeTokens.createTokens(istr))
9009
0
        return false;
9010
0
    typeTokens.simplifyPlatformTypes();
9011
0
    typeTokens.simplifyStdType();
9012
0
    const ValueType &vt = ValueType::parseDecl(typeTokens.front(), *settings);
9013
0
    return getMinMaxValues(&vt, settings->platform, minvalue, maxvalue);
9014
0
}
9015
9016
static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings)
9017
2.27k
{
9018
2.90k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
9019
2.90k
        if (!functionScope->bodyStart)
9020
0
            continue;
9021
2.90k
        const Function *function = functionScope->function;
9022
2.90k
        if (!function)
9023
0
            continue;
9024
9025
2.90k
        const bool safe = function->isSafe(settings);
9026
2.90k
        const bool all = safe && settings->platform.type != cppcheck::Platform::Type::Unspecified;
9027
9028
2.90k
        for (const Variable &arg : function->argumentList) {
9029
0
            if (!arg.nameToken() || !arg.valueType())
9030
0
                continue;
9031
9032
0
            if (arg.valueType()->type == ValueType::Type::CONTAINER) {
9033
0
                if (!safe)
9034
0
                    continue;
9035
0
                std::list<ValueFlow::Value> argValues;
9036
0
                argValues.emplace_back(0);
9037
0
                argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
9038
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " is empty");
9039
0
                argValues.back().safe = true;
9040
0
                argValues.emplace_back(1000000);
9041
0
                argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
9042
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000");
9043
0
                argValues.back().safe = true;
9044
0
                for (const ValueFlow::Value &value : argValues)
9045
0
                    valueFlowForward(const_cast<Token*>(functionScope->bodyStart), arg.nameToken(), value, tokenlist, settings);
9046
0
                continue;
9047
0
            }
9048
9049
0
            MathLib::bigint low, high;
9050
0
            bool isLow = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, low);
9051
0
            bool isHigh = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, high);
9052
9053
0
            if (!isLow && !isHigh && !all)
9054
0
                continue;
9055
9056
0
            const bool safeLow = !isLow;
9057
0
            const bool safeHigh = !isHigh;
9058
9059
0
            if ((!isLow || !isHigh) && all) {
9060
0
                MathLib::bigint minValue, maxValue;
9061
0
                if (getMinMaxValues(arg.valueType(), settings->platform, minValue, maxValue)) {
9062
0
                    if (!isLow)
9063
0
                        low = minValue;
9064
0
                    if (!isHigh)
9065
0
                        high = maxValue;
9066
0
                    isLow = isHigh = true;
9067
0
                } else if (arg.valueType()->type == ValueType::Type::FLOAT || arg.valueType()->type == ValueType::Type::DOUBLE || arg.valueType()->type == ValueType::Type::LONGDOUBLE) {
9068
0
                    std::list<ValueFlow::Value> argValues;
9069
0
                    argValues.emplace_back(0);
9070
0
                    argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
9071
0
                    argValues.back().floatValue = isLow ? low : -1E25;
9072
0
                    argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
9073
0
                    argValues.back().safe = true;
9074
0
                    argValues.emplace_back(0);
9075
0
                    argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
9076
0
                    argValues.back().floatValue = isHigh ? high : 1E25;
9077
0
                    argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
9078
0
                    argValues.back().safe = true;
9079
0
                    valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
9080
0
                                     functionScope->bodyEnd,
9081
0
                                     arg.nameToken(),
9082
0
                                     argValues,
9083
0
                                     tokenlist,
9084
0
                                     settings);
9085
0
                    continue;
9086
0
                }
9087
0
            }
9088
9089
0
            std::list<ValueFlow::Value> argValues;
9090
0
            if (isLow) {
9091
0
                argValues.emplace_back(low);
9092
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeLow ? "Safe checks: " : "") + "Assuming argument has value " + std::to_string(low));
9093
0
                argValues.back().safe = safeLow;
9094
0
            }
9095
0
            if (isHigh) {
9096
0
                argValues.emplace_back(high);
9097
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeHigh ? "Safe checks: " : "") + "Assuming argument has value " + std::to_string(high));
9098
0
                argValues.back().safe = safeHigh;
9099
0
            }
9100
9101
0
            if (!argValues.empty())
9102
0
                valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
9103
0
                                 functionScope->bodyEnd,
9104
0
                                 arg.nameToken(),
9105
0
                                 argValues,
9106
0
                                 tokenlist,
9107
0
                                 settings);
9108
0
        }
9109
2.90k
    }
9110
2.27k
}
9111
9112
static void valueFlowUnknownFunctionReturn(TokenList &tokenlist, const Settings *settings)
9113
1.36k
{
9114
1.36k
    if (settings->checkUnknownFunctionReturn.empty())
9115
1.36k
        return;
9116
0
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
9117
0
        if (!tok->astParent() || tok->str() != "(" || !tok->previous()->isName())
9118
0
            continue;
9119
0
        if (settings->checkUnknownFunctionReturn.find(tok->previous()->str()) == settings->checkUnknownFunctionReturn.end())
9120
0
            continue;
9121
0
        std::vector<MathLib::bigint> unknownValues = settings->library.unknownReturnValues(tok->astOperand1());
9122
0
        if (unknownValues.empty())
9123
0
            continue;
9124
9125
        // Get min/max values for return type
9126
0
        const std::string &typestr = settings->library.returnValueType(tok->previous());
9127
0
        MathLib::bigint minvalue, maxvalue;
9128
0
        if (!getMinMaxValues(typestr, settings, minvalue, maxvalue))
9129
0
            continue;
9130
9131
0
        for (MathLib::bigint value : unknownValues) {
9132
0
            if (value < minvalue)
9133
0
                value = minvalue;
9134
0
            else if (value > maxvalue)
9135
0
                value = maxvalue;
9136
0
            setTokenValue(const_cast<Token *>(tok), ValueFlow::Value(value), settings);
9137
0
        }
9138
0
    }
9139
0
}
9140
9141
static void valueFlowDebug(TokenList& tokenlist, ErrorLogger* errorLogger, const Settings* settings)
9142
1.36k
{
9143
1.36k
    if (!settings->debugnormal && !settings->debugwarnings)
9144
1.36k
        return;
9145
0
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
9146
0
        if (tok->getTokenDebug() != TokenDebug::ValueFlow)
9147
0
            continue;
9148
0
        if (tok->astParent() && tok->astParent()->getTokenDebug() == TokenDebug::ValueFlow)
9149
0
            continue;
9150
0
        for (const ValueFlow::Value& v : tok->values()) {
9151
0
            std::string msg = "The value is " + debugString(v);
9152
0
            ErrorPath errorPath = v.errorPath;
9153
0
            errorPath.insert(errorPath.end(), v.debugPath.cbegin(), v.debugPath.cend());
9154
0
            errorPath.emplace_back(tok, "");
9155
0
            errorLogger->reportErr({errorPath, &tokenlist, Severity::debug, "valueFlow", msg, CWE{0}, Certainty::normal});
9156
0
        }
9157
0
    }
9158
0
}
9159
9160
const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(Token *expr, const Settings *settings)
9161
0
{
9162
0
    if (expr && expr->values().empty()) {
9163
0
        valueFlowConstantFoldAST(expr->astOperand1(), settings);
9164
0
        valueFlowConstantFoldAST(expr->astOperand2(), settings);
9165
0
        valueFlowSetConstantValue(expr, settings, true /* TODO: this is a guess */);
9166
0
    }
9167
0
    return expr && expr->hasKnownValue() ? &expr->values().front() : nullptr;
9168
0
}
9169
9170
struct ValueFlowState {
9171
    explicit ValueFlowState(TokenList& tokenlist,
9172
                            SymbolDatabase& symboldatabase,
9173
                            ErrorLogger* errorLogger = nullptr,
9174
                            const Settings* settings = nullptr)
9175
        : tokenlist(tokenlist), symboldatabase(symboldatabase), errorLogger(errorLogger), settings(settings)
9176
1.36k
    {}
9177
9178
    TokenList& tokenlist;
9179
    SymbolDatabase& symboldatabase;
9180
    ErrorLogger* errorLogger = nullptr;
9181
    const Settings* settings = nullptr;
9182
    std::set<const Scope*> skippedFunctions = {};
9183
};
9184
9185
struct ValueFlowPass {
9186
58.5k
    ValueFlowPass() = default;
9187
58.5k
    ValueFlowPass(const ValueFlowPass&) = default;
9188
    // Name of pass
9189
    virtual const char* name() const = 0;
9190
    // Run the pass
9191
    virtual void run(const ValueFlowState& state) const = 0;
9192
    // Returns true if pass needs C++
9193
    virtual bool cpp() const = 0;
9194
117k
    virtual ~ValueFlowPass() noexcept = default;
9195
};
9196
9197
struct ValueFlowPassRunner {
9198
    using Clock = std::chrono::steady_clock;
9199
    using TimePoint = std::chrono::time_point<Clock>;
9200
    explicit ValueFlowPassRunner(ValueFlowState state, TimerResultsIntf* timerResults = nullptr)
9201
        : state(std::move(state)), stop(TimePoint::max()), timerResults(timerResults)
9202
1.36k
    {
9203
1.36k
        setSkippedFunctions();
9204
1.36k
        setStopTime();
9205
1.36k
    }
9206
9207
    bool run_once(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
9208
2.72k
    {
9209
23.1k
        return std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
9210
23.1k
            return run(pass);
9211
23.1k
        });
9212
2.72k
    }
9213
9214
    bool run(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
9215
1.36k
    {
9216
1.36k
        std::size_t values = 0;
9217
1.36k
        std::size_t n = state.settings->valueFlowMaxIterations;
9218
3.63k
        while (n > 0 && values != getTotalValues()) {
9219
2.27k
            values = getTotalValues();
9220
59.0k
            if (std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
9221
59.0k
                return run(pass);
9222
59.0k
            }))
9223
0
                return true;
9224
2.27k
            --n;
9225
2.27k
        }
9226
1.36k
        if (state.settings->debugwarnings) {
9227
0
            if (n == 0 && values != getTotalValues()) {
9228
0
                ErrorMessage::FileLocation loc;
9229
0
                loc.setfile(state.tokenlist.getFiles()[0]);
9230
0
                ErrorMessage errmsg({std::move(loc)},
9231
0
                                    emptyString,
9232
0
                                    Severity::debug,
9233
0
                                    "ValueFlow maximum iterations exceeded",
9234
0
                                    "valueFlowMaxIterations",
9235
0
                                    Certainty::normal);
9236
0
                state.errorLogger->reportErr(errmsg);
9237
0
            }
9238
0
        }
9239
1.36k
        return false;
9240
1.36k
    }
9241
9242
    bool run(const ValuePtr<ValueFlowPass>& pass) const
9243
82.2k
    {
9244
82.2k
        auto start = Clock::now();
9245
82.2k
        if (start > stop)
9246
0
            return true;
9247
82.2k
        if (!state.tokenlist.isCPP() && pass->cpp())
9248
0
            return false;
9249
82.2k
        if (timerResults) {
9250
0
            Timer t(pass->name(), state.settings->showtime, timerResults);
9251
0
            pass->run(state);
9252
82.2k
        } else {
9253
82.2k
            pass->run(state);
9254
82.2k
        }
9255
82.2k
        return false;
9256
82.2k
    }
9257
9258
    std::size_t getTotalValues() const
9259
5.90k
    {
9260
5.90k
        std::size_t n = 1;
9261
419k
        for (Token* tok = state.tokenlist.front(); tok; tok = tok->next())
9262
413k
            n += tok->values().size();
9263
5.90k
        return n;
9264
5.90k
    }
9265
9266
    void setSkippedFunctions()
9267
1.36k
    {
9268
1.36k
        if (state.settings->performanceValueFlowMaxIfCount > 0) {
9269
1.73k
            for (const Scope* functionScope : state.symboldatabase.functionScopes) {
9270
1.73k
                int countIfScopes = 0;
9271
1.73k
                std::vector<const Scope*> scopes{functionScope};
9272
5.32k
                while (!scopes.empty()) {
9273
3.58k
                    const Scope* s = scopes.back();
9274
3.58k
                    scopes.pop_back();
9275
3.58k
                    for (const Scope* s2 : s->nestedList) {
9276
1.84k
                        scopes.emplace_back(s2);
9277
1.84k
                        if (s2->type == Scope::ScopeType::eIf)
9278
919
                            ++countIfScopes;
9279
1.84k
                    }
9280
3.58k
                }
9281
1.73k
                if (countIfScopes > state.settings->performanceValueFlowMaxIfCount) {
9282
0
                    state.skippedFunctions.emplace(functionScope);
9283
9284
0
                    if (state.settings->severity.isEnabled(Severity::information)) {
9285
0
                        const std::string& functionName = functionScope->className;
9286
0
                        const std::list<ErrorMessage::FileLocation> callstack(
9287
0
                            1,
9288
0
                            ErrorMessage::FileLocation(functionScope->bodyStart, &state.tokenlist));
9289
0
                        const ErrorMessage errmsg(callstack,
9290
0
                                                  state.tokenlist.getSourceFilePath(),
9291
0
                                                  Severity::information,
9292
0
                                                  "ValueFlow analysis is limited in " + functionName +
9293
0
                                                  ". Use --check-level=exhaustive if full analysis is wanted.",
9294
0
                                                  "checkLevelNormal",
9295
0
                                                  Certainty::normal);
9296
0
                        state.errorLogger->reportErr(errmsg);
9297
0
                    }
9298
0
                }
9299
1.73k
            }
9300
1.36k
        }
9301
1.36k
    }
9302
9303
    void setStopTime()
9304
1.36k
    {
9305
1.36k
        if (state.settings->performanceValueFlowMaxTime >= 0)
9306
0
            stop = Clock::now() + std::chrono::seconds{state.settings->performanceValueFlowMaxTime};
9307
1.36k
    }
9308
9309
    ValueFlowState state;
9310
    TimePoint stop;
9311
    TimerResultsIntf* timerResults;
9312
};
9313
9314
template<class F>
9315
struct ValueFlowPassAdaptor : ValueFlowPass {
9316
    const char* mName = nullptr;
9317
    bool mCPP = false;
9318
    F mRun;
9319
58.5k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : 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
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49)
Line
Count
Source
9319
1.36k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
9320
0
    const char* name() const override {
9321
0
        return mName;
9322
0
    }
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
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48>::name() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49>::name() const
9323
    void run(const ValueFlowState& state) const override
9324
82.2k
    {
9325
82.2k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
82.2k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_7>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_8>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_9>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_10>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_11>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_12>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_13>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_14>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_15>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_16>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_17>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_18>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_19>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_20>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_21>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_22>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_23>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_24>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_25>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_26>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_27>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_28>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_29>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_30>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_31>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_32>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_33>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_34>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_35>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_36>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_37>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_38>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_39>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_40>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_41>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47>::run(ValueFlowState const&) const
Line
Count
Source
9324
2.27k
    {
9325
2.27k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
2.27k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49>::run(ValueFlowState const&) const
Line
Count
Source
9324
1.36k
    {
9325
1.36k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9326
1.36k
    }
9327
0
    bool cpp() const override {
9328
0
        return mCPP;
9329
0
    }
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
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48>::cpp() const
Unexecuted instantiation: valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49>::cpp() const
9330
};
9331
9332
template<class F>
9333
ValueFlowPassAdaptor<F> makeValueFlowPassAdaptor(const char* name, bool cpp, F run)
9334
58.5k
{
9335
58.5k
    return {name, cpp, run};
9336
58.5k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
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
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49> makeValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49>(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49)
Line
Count
Source
9334
1.36k
{
9335
1.36k
    return {name, cpp, run};
9336
1.36k
}
9337
9338
#define VALUEFLOW_ADAPTOR(cpp, ...)                                                                                    \
9339
58.5k
    makeValueFlowPassAdaptor(#__VA_ARGS__,                                                                             \
9340
58.5k
                             cpp,                                                                                      \
9341
58.5k
                             [](TokenList& tokenlist,                                                                  \
9342
58.5k
                                SymbolDatabase& symboldatabase,                                                        \
9343
58.5k
                                ErrorLogger* errorLogger,                                                              \
9344
58.5k
                                const Settings* settings,                                                              \
9345
82.2k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
82.2k
        (void)tokenlist;                                                                      \
9347
82.2k
        (void)symboldatabase;                                                                 \
9348
82.2k
        (void)errorLogger;                                                                    \
9349
82.2k
        (void)settings;                                                                       \
9350
82.2k
        (void)skippedFunctions;                                                               \
9351
82.2k
        __VA_ARGS__;                                                                          \
9352
82.2k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_42::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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_43::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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_44::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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_45::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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_46::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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_47::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
9345
2.27k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
2.27k
        (void)tokenlist;                                                                      \
9347
2.27k
        (void)symboldatabase;                                                                 \
9348
2.27k
        (void)errorLogger;                                                                    \
9349
2.27k
        (void)settings;                                                                       \
9350
2.27k
        (void)skippedFunctions;                                                               \
9351
2.27k
        __VA_ARGS__;                                                                          \
9352
2.27k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_48::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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
valueflow.cpp:ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const*, TimerResultsIntf*)::$_49::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
9345
1.36k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9346
1.36k
        (void)tokenlist;                                                                      \
9347
1.36k
        (void)symboldatabase;                                                                 \
9348
1.36k
        (void)errorLogger;                                                                    \
9349
1.36k
        (void)settings;                                                                       \
9350
1.36k
        (void)skippedFunctions;                                                               \
9351
1.36k
        __VA_ARGS__;                                                                          \
9352
1.36k
    })
9353
9354
47.6k
#define VFA(...) VALUEFLOW_ADAPTOR(false, __VA_ARGS__)
9355
10.8k
#define VFA_CPP(...) VALUEFLOW_ADAPTOR(true, __VA_ARGS__)
9356
9357
void ValueFlow::setValues(TokenList& tokenlist,
9358
                          SymbolDatabase& symboldatabase,
9359
                          ErrorLogger* errorLogger,
9360
                          const Settings* settings,
9361
                          TimerResultsIntf* timerResults)
9362
1.36k
{
9363
93.5k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next())
9364
92.2k
        tok->clearValueFlow();
9365
9366
    // commas in init..
9367
93.5k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
9368
92.2k
        if (tok->str() != "{" || !tok->astOperand1())
9369
92.2k
            continue;
9370
0
        for (Token* tok2 = tok->next(); tok2 != tok->link(); tok2 = tok2->next()) {
9371
0
            if (tok2->link() && Token::Match(tok2, "[{[(<]"))
9372
0
                tok2 = tok2->link();
9373
0
            else if (tok2->str() == ",")
9374
0
                tok2->isInitComma(true);
9375
0
        }
9376
0
    }
9377
9378
1.36k
    ValueFlowPassRunner runner{ValueFlowState{tokenlist, symboldatabase, errorLogger, settings}, timerResults};
9379
1.36k
    runner.run_once({
9380
1.36k
        VFA(valueFlowEnumValue(symboldatabase, settings)),
9381
1.36k
        VFA(valueFlowNumber(tokenlist, settings)),
9382
1.36k
        VFA(valueFlowString(tokenlist, settings)),
9383
1.36k
        VFA(valueFlowArray(tokenlist, settings)),
9384
1.36k
        VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)),
9385
1.36k
        VFA(valueFlowGlobalConstVar(tokenlist, settings)),
9386
1.36k
        VFA(valueFlowEnumValue(symboldatabase, settings)),
9387
1.36k
        VFA(valueFlowNumber(tokenlist, settings)),
9388
1.36k
        VFA(valueFlowGlobalStaticVar(tokenlist, settings)),
9389
1.36k
        VFA(valueFlowPointerAlias(tokenlist, settings)),
9390
1.36k
        VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
9391
1.36k
        VFA(valueFlowSymbolic(tokenlist, symboldatabase, settings)),
9392
1.36k
        VFA(valueFlowBitAnd(tokenlist, settings)),
9393
1.36k
        VFA(valueFlowSameExpressions(tokenlist, settings)),
9394
1.36k
        VFA(valueFlowConditionExpressions(tokenlist, symboldatabase, errorLogger, *settings)),
9395
1.36k
    });
9396
9397
1.36k
    runner.run({
9398
1.36k
        VFA(valueFlowImpossibleValues(tokenlist, settings)),
9399
1.36k
        VFA(valueFlowSymbolicOperators(symboldatabase, settings)),
9400
1.36k
        VFA(valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9401
1.36k
        VFA(valueFlowSymbolicInfer(symboldatabase, settings)),
9402
1.36k
        VFA(valueFlowArrayBool(tokenlist, settings)),
9403
1.36k
        VFA(valueFlowArrayElement(tokenlist, settings)),
9404
1.36k
        VFA(valueFlowRightShift(tokenlist, settings)),
9405
1.36k
        VFA(valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9406
1.36k
        VFA_CPP(valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings)),
9407
1.36k
        VFA(valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9408
1.36k
        VFA(valueFlowInferCondition(tokenlist, settings)),
9409
1.36k
        VFA(valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings)),
9410
1.36k
        VFA(valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings)),
9411
1.36k
        VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, *settings)),
9412
1.36k
        VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)),
9413
1.36k
        VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
9414
1.36k
        VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, settings)),
9415
1.36k
        VFA(valueFlowUninit(tokenlist, settings)),
9416
1.36k
        VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, settings)),
9417
1.36k
        VFA_CPP(valueFlowSmartPointer(tokenlist, errorLogger, settings)),
9418
1.36k
        VFA_CPP(valueFlowIterators(tokenlist, settings)),
9419
1.36k
        VFA_CPP(
9420
1.36k
            valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9421
1.36k
        VFA_CPP(valueFlowIteratorInfer(tokenlist, settings)),
9422
1.36k
        VFA_CPP(valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9423
1.36k
        VFA_CPP(
9424
1.36k
            valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9425
1.36k
        VFA(valueFlowSafeFunctions(tokenlist, symboldatabase, settings)),
9426
1.36k
    });
9427
9428
1.36k
    runner.run_once({
9429
1.36k
        VFA(valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings)),
9430
1.36k
        VFA(valueFlowDebug(tokenlist, errorLogger, settings)),
9431
1.36k
    });
9432
1.36k
}
9433
9434
std::string ValueFlow::eitherTheConditionIsRedundant(const Token *condition)
9435
0
{
9436
0
    if (!condition)
9437
0
        return "Either the condition is redundant";
9438
0
    if (condition->str() == "case") {
9439
0
        std::string expr;
9440
0
        for (const Token *tok = condition; tok && tok->str() != ":"; tok = tok->next()) {
9441
0
            expr += tok->str();
9442
0
            if (Token::Match(tok, "%name%|%num% %name%|%num%"))
9443
0
                expr += ' ';
9444
0
        }
9445
0
        return "Either the switch case '" + expr + "' is redundant";
9446
0
    }
9447
0
    return "Either the condition '" + condition->expressionString() + "' is redundant";
9448
0
}
9449
9450
const ValueFlow::Value* ValueFlow::findValue(const std::list<ValueFlow::Value>& values,
9451
                                             const Settings* settings,
9452
                                             const std::function<bool(const ValueFlow::Value&)> &pred)
9453
466
{
9454
466
    const ValueFlow::Value* ret = nullptr;
9455
478
    for (const ValueFlow::Value& v : values) {
9456
478
        if (pred(v)) {
9457
47
            if (!ret || ret->isInconclusive() || (ret->condition && !v.isInconclusive()))
9458
47
                ret = &v;
9459
47
            if (!ret->isInconclusive() && !ret->condition)
9460
43
                break;
9461
47
        }
9462
478
    }
9463
466
    if (settings && ret) {
9464
47
        if (ret->isInconclusive() && !settings->certainty.isEnabled(Certainty::inconclusive))
9465
0
            return nullptr;
9466
47
        if (ret->condition && !settings->severity.isEnabled(Severity::warning))
9467
0
            return nullptr;
9468
47
    }
9469
466
    return ret;
9470
466
}
9471
9472
// TODO: returns a single value at most - no need for std::vector
9473
static std::vector<ValueFlow::Value> isOutOfBoundsImpl(const ValueFlow::Value& size,
9474
                                                       const Token* indexTok,
9475
                                                       bool condition)
9476
0
{
9477
0
    if (!indexTok)
9478
0
        return {};
9479
0
    const ValueFlow::Value* indexValue = indexTok->getMaxValue(condition, size.path);
9480
0
    if (!indexValue)
9481
0
        return {};
9482
0
    if (indexValue->intvalue >= size.intvalue)
9483
0
        return {*indexValue};
9484
0
    if (!condition)
9485
0
        return {};
9486
    // TODO: Use a better way to decide if the variable in unconstrained
9487
0
    if (!indexTok->variable() || !indexTok->variable()->isArgument())
9488
0
        return {};
9489
0
    if (std::any_of(indexTok->values().cbegin(), indexTok->values().cend(), [&](const ValueFlow::Value& v) {
9490
0
        return v.isSymbolicValue() && v.isPossible() && v.bound == ValueFlow::Value::Bound::Upper;
9491
0
    }))
9492
0
        return {};
9493
0
    if (indexValue->bound != ValueFlow::Value::Bound::Lower)
9494
0
        return {};
9495
0
    if (size.bound == ValueFlow::Value::Bound::Lower)
9496
0
        return {};
9497
    // Checking for underflow doesn't mean it could be out of bounds
9498
0
    if (indexValue->intvalue == 0)
9499
0
        return {};
9500
0
    ValueFlow::Value value = inferCondition(">=", indexTok, indexValue->intvalue);
9501
0
    if (!value.isKnown())
9502
0
        return {};
9503
0
    if (value.intvalue == 0)
9504
0
        return {};
9505
0
    value.intvalue = size.intvalue;
9506
0
    value.bound = ValueFlow::Value::Bound::Lower;
9507
0
    return {std::move(value)};
9508
0
}
9509
9510
// TODO: return single value at most - no need for std::vector
9511
std::vector<ValueFlow::Value> ValueFlow::isOutOfBounds(const Value& size, const Token* indexTok, bool possible)
9512
0
{
9513
0
    ValueFlow::Value inBoundsValue = inferCondition("<", indexTok, size.intvalue);
9514
0
    if (inBoundsValue.isKnown() && inBoundsValue.intvalue != 0)
9515
0
        return {};
9516
0
    std::vector<ValueFlow::Value> result = isOutOfBoundsImpl(size, indexTok, false);
9517
0
    if (!result.empty())
9518
0
        return result;
9519
0
    if (!possible)
9520
0
        return result;
9521
0
    return isOutOfBoundsImpl(size, indexTok, true);
9522
0
}