Coverage Report

Created: 2024-02-11 06:44

/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, const 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
    const std::string location = Path::stripDirectoryPart(file) + ":" + std::to_string(line) + ":";
136
0
    ErrorMessage errmsg(std::move(callstack), tokenlist.getSourceFilePath(), Severity::debug,
137
0
                        (file.empty() ? "" : location) + function + " bailout: " + what, type, Certainty::normal);
138
0
    errorLogger->reportErr(errmsg);
139
0
}
140
141
0
#define bailout2(type, tokenlist, errorLogger, tok, what) bailoutInternal((type), (tokenlist), (errorLogger), (tok), (what), __FILE__, __LINE__, __func__)
142
143
0
#define bailout(tokenlist, errorLogger, tok, what) bailout2("valueFlowBailout", (tokenlist), (errorLogger), (tok), (what))
144
145
0
#define bailoutIncompleteVar(tokenlist, errorLogger, tok, what) bailoutInternal("valueFlowBailoutIncompleteVar", (tokenlist), (errorLogger), (tok), (what), "", 0, __func__)
146
147
static std::string debugString(const ValueFlow::Value& v)
148
0
{
149
0
    std::string kind;
150
0
    switch (v.valueKind) {
151
152
0
    case ValueFlow::Value::ValueKind::Impossible:
153
0
    case ValueFlow::Value::ValueKind::Known:
154
0
        kind = "always";
155
0
        break;
156
0
    case ValueFlow::Value::ValueKind::Inconclusive:
157
0
        kind = "inconclusive";
158
0
        break;
159
0
    case ValueFlow::Value::ValueKind::Possible:
160
0
        kind = "possible";
161
0
        break;
162
0
    }
163
0
    return kind + " " + v.toString();
164
0
}
165
166
static void setSourceLocation(ValueFlow::Value& v,
167
                              SourceLocation ctx,
168
                              const Token* tok,
169
                              SourceLocation local = SourceLocation::current())
170
0
{
171
0
    std::string file = ctx.file_name();
172
0
    if (file.empty())
173
0
        return;
174
0
    std::string s = Path::stripDirectoryPart(file) + ":" + std::to_string(ctx.line()) + ": " + ctx.function_name() +
175
0
                    " => " + local.function_name() + ": " + debugString(v);
176
0
    v.debugPath.emplace_back(tok, std::move(s));
177
0
}
178
179
static void changeKnownToPossible(std::list<ValueFlow::Value> &values, int indirect=-1)
180
2.60k
{
181
4.06k
    for (ValueFlow::Value& v: values) {
182
4.06k
        if (indirect >= 0 && v.indirect != indirect)
183
0
            continue;
184
4.06k
        v.changeKnownToPossible();
185
4.06k
    }
186
2.60k
}
187
188
static void removeImpossible(std::list<ValueFlow::Value>& values, int indirect = -1)
189
0
{
190
0
    values.remove_if([&](const ValueFlow::Value& v) {
191
0
        if (indirect >= 0 && v.indirect != indirect)
192
0
            return false;
193
0
        return v.isImpossible();
194
0
    });
195
0
}
196
197
static void lowerToPossible(std::list<ValueFlow::Value>& values, int indirect = -1)
198
0
{
199
0
    changeKnownToPossible(values, indirect);
200
0
    removeImpossible(values, indirect);
201
0
}
202
203
static void changePossibleToKnown(std::list<ValueFlow::Value>& values, int indirect = -1)
204
403
{
205
403
    for (ValueFlow::Value& v : values) {
206
403
        if (indirect >= 0 && v.indirect != indirect)
207
0
            continue;
208
403
        if (!v.isPossible())
209
46
            continue;
210
357
        if (v.bound != ValueFlow::Value::Bound::Point)
211
0
            continue;
212
357
        v.setKnown();
213
357
    }
214
403
}
215
216
static bool isNonConditionalPossibleIntValue(const ValueFlow::Value& v)
217
0
{
218
0
    if (v.conditional)
219
0
        return false;
220
0
    if (v.condition)
221
0
        return false;
222
0
    if (!v.isPossible())
223
0
        return false;
224
0
    if (!v.isIntValue())
225
0
        return false;
226
0
    return true;
227
0
}
228
229
static void setValueUpperBound(ValueFlow::Value& value, bool upper)
230
12.2k
{
231
12.2k
    if (upper)
232
6.11k
        value.bound = ValueFlow::Value::Bound::Upper;
233
6.11k
    else
234
6.11k
        value.bound = ValueFlow::Value::Bound::Lower;
235
12.2k
}
236
237
static void setValueBound(ValueFlow::Value& value, const Token* tok, bool invert)
238
16.7k
{
239
16.7k
    if (Token::Match(tok, "<|<=")) {
240
6.87k
        setValueUpperBound(value, !invert);
241
9.86k
    } else if (Token::Match(tok, ">|>=")) {
242
5.35k
        setValueUpperBound(value, invert);
243
5.35k
    }
244
16.7k
}
245
246
static void setConditionalValue(ValueFlow::Value& value, const Token* tok, MathLib::bigint i)
247
16.7k
{
248
16.7k
    assert(value.isIntValue());
249
0
    value.intvalue = i;
250
16.7k
    value.assumeCondition(tok);
251
16.7k
    value.setPossible();
252
16.7k
}
253
254
static void setConditionalValues(const Token* tok,
255
                                 bool lhs,
256
                                 MathLib::bigint value,
257
                                 ValueFlow::Value& true_value,
258
                                 ValueFlow::Value& false_value)
259
8.36k
{
260
8.36k
    if (Token::Match(tok, "==|!=|>=|<=")) {
261
4.25k
        setConditionalValue(true_value, tok, value);
262
4.25k
        const char* greaterThan = ">=";
263
4.25k
        const char* lessThan = "<=";
264
4.25k
        if (lhs)
265
2.17k
            std::swap(greaterThan, lessThan);
266
4.25k
        if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
267
992
            setConditionalValue(false_value, tok, value - 1);
268
3.26k
        } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) {
269
1.01k
            setConditionalValue(false_value, tok, value + 1);
270
2.25k
        } else {
271
2.25k
            setConditionalValue(false_value, tok, value);
272
2.25k
        }
273
4.25k
    } else {
274
4.11k
        const char* greaterThan = ">";
275
4.11k
        const char* lessThan = "<";
276
4.11k
        if (lhs)
277
2.15k
            std::swap(greaterThan, lessThan);
278
4.11k
        if (Token::simpleMatch(tok, greaterThan, strlen(greaterThan))) {
279
2.08k
            setConditionalValue(true_value, tok, value + 1);
280
2.08k
            setConditionalValue(false_value, tok, value);
281
2.08k
        } else if (Token::simpleMatch(tok, lessThan, strlen(lessThan))) {
282
2.02k
            setConditionalValue(true_value, tok, value - 1);
283
2.02k
            setConditionalValue(false_value, tok, value);
284
2.02k
        }
285
4.11k
    }
286
8.36k
    setValueBound(true_value, tok, lhs);
287
8.36k
    setValueBound(false_value, tok, !lhs);
288
8.36k
}
289
290
static bool isSaturated(MathLib::bigint value)
291
4.32k
{
292
4.32k
    return value == std::numeric_limits<MathLib::bigint>::max() || value == std::numeric_limits<MathLib::bigint>::min();
293
4.32k
}
294
295
static void parseCompareEachInt(
296
    const Token* tok,
297
    const std::function<void(const Token* varTok, ValueFlow::Value true_value, ValueFlow::Value false_value)>& each,
298
    const std::function<std::vector<ValueFlow::Value>(const Token*)>& evaluate)
299
83.3k
{
300
83.3k
    if (!tok->astOperand1() || !tok->astOperand2())
301
44.1k
        return;
302
39.1k
    if (tok->isComparisonOp()) {
303
17.6k
        std::vector<ValueFlow::Value> value1 = evaluate(tok->astOperand1());
304
17.6k
        std::vector<ValueFlow::Value> value2 = evaluate(tok->astOperand2());
305
17.6k
        if (!value1.empty() && !value2.empty()) {
306
394
            if (tok->astOperand1()->hasKnownIntValue())
307
353
                value2.clear();
308
394
            if (tok->astOperand2()->hasKnownIntValue())
309
344
                value1.clear();
310
394
        }
311
17.6k
        for (const ValueFlow::Value& v1 : value1) {
312
2.30k
            ValueFlow::Value true_value = v1;
313
2.30k
            ValueFlow::Value false_value = v1;
314
2.30k
            if (isSaturated(v1.intvalue) || astIsFloat(tok->astOperand2(), /*unknown*/ false))
315
0
                continue;
316
2.30k
            setConditionalValues(tok, true, v1.intvalue, true_value, false_value);
317
2.30k
            each(tok->astOperand2(), std::move(true_value), std::move(false_value));
318
2.30k
        }
319
17.6k
        for (const ValueFlow::Value& v2 : value2) {
320
2.01k
            ValueFlow::Value true_value = v2;
321
2.01k
            ValueFlow::Value false_value = v2;
322
2.01k
            if (isSaturated(v2.intvalue) || astIsFloat(tok->astOperand1(), /*unknown*/ false))
323
0
                continue;
324
2.01k
            setConditionalValues(tok, false, v2.intvalue, true_value, false_value);
325
2.01k
            each(tok->astOperand1(), std::move(true_value), std::move(false_value));
326
2.01k
        }
327
17.6k
    }
328
39.1k
}
329
330
static void parseCompareEachInt(
331
    const Token* tok,
332
    const std::function<void(const Token* varTok, ValueFlow::Value true_value, ValueFlow::Value false_value)>& each)
333
79.2k
{
334
79.2k
    parseCompareEachInt(tok, each, [](const Token* t) -> std::vector<ValueFlow::Value> {
335
27.1k
        if (t->hasKnownIntValue())
336
4.24k
            return {t->values().front()};
337
22.9k
        std::vector<ValueFlow::Value> result;
338
22.9k
        std::copy_if(t->values().cbegin(), t->values().cend(), std::back_inserter(result), [&](const ValueFlow::Value& v) {
339
4.68k
            if (v.path < 1)
340
4.68k
                return false;
341
0
            if (!isNonConditionalPossibleIntValue(v))
342
0
                return false;
343
0
            return true;
344
0
        });
345
22.9k
        return result;
346
27.1k
    });
347
79.2k
}
348
349
const Token* ValueFlow::parseCompareInt(const Token* tok,
350
                                        ValueFlow::Value& true_value,
351
                                        ValueFlow::Value& false_value,
352
                                        const std::function<std::vector<MathLib::bigint>(const Token*)>& evaluate)
353
4.08k
{
354
4.08k
    const Token* result = nullptr;
355
4.08k
    parseCompareEachInt(
356
4.08k
        tok,
357
4.08k
        [&](const Token* vartok, ValueFlow::Value true_value2, ValueFlow::Value false_value2) {
358
722
        if (result)
359
24
            return;
360
698
        result = vartok;
361
698
        true_value = std::move(true_value2);
362
698
        false_value = std::move(false_value2);
363
698
    },
364
8.17k
        [&](const Token* t) -> std::vector<ValueFlow::Value> {
365
8.17k
        std::vector<ValueFlow::Value> r;
366
8.17k
        std::vector<MathLib::bigint> v = evaluate(t);
367
368
8.17k
        std::transform(v.cbegin(), v.cend(), std::back_inserter(r), [&](MathLib::bigint i) {
369
773
            return ValueFlow::Value{i};
370
773
        });
371
8.17k
        return r;
372
8.17k
    });
373
4.08k
    return result;
374
4.08k
}
375
376
const Token *ValueFlow::parseCompareInt(const Token *tok, ValueFlow::Value &true_value, ValueFlow::Value &false_value)
377
0
{
378
0
    return parseCompareInt(tok, true_value, false_value, [](const Token* t) -> std::vector<MathLib::bigint> {
379
0
        if (t->hasKnownIntValue())
380
0
            return {t->values().front().intvalue};
381
0
        return std::vector<MathLib::bigint>{};
382
0
    });
383
0
}
384
385
static bool isEscapeScope(const Token* tok, const Settings& settings, bool unknown = false)
386
0
{
387
0
    if (!Token::simpleMatch(tok, "{"))
388
0
        return false;
389
    // TODO this search for termTok in all subscopes. It should check the end of the scope.
390
0
    const Token * termTok = Token::findmatch(tok, "return|continue|break|throw|goto", tok->link());
391
0
    if (termTok && termTok->scope() == tok->scope())
392
0
        return true;
393
0
    std::string unknownFunction;
394
0
    if (settings.library.isScopeNoReturn(tok->link(), &unknownFunction))
395
0
        return unknownFunction.empty() || unknown;
396
0
    return false;
397
0
}
398
399
static ValueFlow::Value castValue(ValueFlow::Value value, const ValueType::Sign sign, nonneg int bit)
400
236
{
401
236
    if (value.isFloatValue()) {
402
0
        value.valueType = ValueFlow::Value::ValueType::INT;
403
0
        if (value.floatValue >= std::numeric_limits<int>::min() && value.floatValue <= std::numeric_limits<int>::max()) {
404
0
            value.intvalue = value.floatValue;
405
0
        } else { // don't perform UB
406
0
            value.intvalue = 0;
407
0
        }
408
0
    }
409
236
    if (bit < MathLib::bigint_bits) {
410
236
        constexpr MathLib::biguint one = 1;
411
236
        value.intvalue &= (one << bit) - 1;
412
236
        if (sign == ValueType::Sign::SIGNED && value.intvalue & (one << (bit - 1))) {
413
12
            value.intvalue |= ~((one << bit) - 1ULL);
414
12
        }
415
236
    }
416
236
    return value;
417
236
}
418
419
0
static bool isNumeric(const ValueFlow::Value& value) {
420
0
    return value.isIntValue() || value.isFloatValue();
421
0
}
422
423
void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value &result)
424
10.8k
{
425
10.8k
    if (value1.isKnown() && value2.isKnown())
426
673
        result.setKnown();
427
10.2k
    else if (value1.isImpossible() || value2.isImpossible())
428
4.99k
        result.setImpossible();
429
5.21k
    else if (value1.isInconclusive() || value2.isInconclusive())
430
0
        result.setInconclusive();
431
5.21k
    else
432
5.21k
        result.setPossible();
433
10.8k
    if (value1.tokvalue)
434
2.14k
        result.tokvalue = value1.tokvalue;
435
8.73k
    else if (value2.tokvalue)
436
2.96k
        result.tokvalue = value2.tokvalue;
437
10.8k
    if (value1.isSymbolicValue()) {
438
1.51k
        result.valueType = value1.valueType;
439
1.51k
        result.tokvalue = value1.tokvalue;
440
1.51k
    }
441
10.8k
    if (value2.isSymbolicValue()) {
442
4.17k
        result.valueType = value2.valueType;
443
4.17k
        result.tokvalue = value2.tokvalue;
444
4.17k
    }
445
10.8k
    if (value1.isIteratorValue())
446
0
        result.valueType = value1.valueType;
447
10.8k
    if (value2.isIteratorValue())
448
0
        result.valueType = value2.valueType;
449
10.8k
    result.condition = value1.condition ? value1.condition : value2.condition;
450
10.8k
    result.varId = (value1.varId != 0) ? value1.varId : value2.varId;
451
10.8k
    result.varvalue = (result.varId == value1.varId) ? value1.varvalue : value2.varvalue;
452
10.8k
    result.errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath;
453
10.8k
    result.safe = value1.safe || value2.safe;
454
10.8k
    if (value1.bound == ValueFlow::Value::Bound::Point || value2.bound == ValueFlow::Value::Bound::Point) {
455
7.72k
        if (value1.bound == ValueFlow::Value::Bound::Upper || value2.bound == ValueFlow::Value::Bound::Upper)
456
2.42k
            result.bound = ValueFlow::Value::Bound::Upper;
457
7.72k
        if (value1.bound == ValueFlow::Value::Bound::Lower || value2.bound == ValueFlow::Value::Bound::Lower)
458
3.42k
            result.bound = ValueFlow::Value::Bound::Lower;
459
7.72k
    }
460
10.8k
    if (value1.path != value2.path)
461
0
        result.path = -1;
462
10.8k
    else
463
10.8k
        result.path = value1.path;
464
10.8k
}
465
466
static const Token *getCastTypeStartToken(const Token *parent, const Settings& settings)
467
7.30k
{
468
    // TODO: This might be a generic utility function?
469
7.30k
    if (!Token::Match(parent, "{|("))
470
5.08k
        return nullptr;
471
    // Functional cast
472
2.21k
    if (parent->isBinaryOp() && Token::Match(parent->astOperand1(), "%type% (|{") &&
473
2.21k
        parent->astOperand1()->tokType() == Token::eType && astIsPrimitive(parent))
474
0
        return parent->astOperand1();
475
2.21k
    if (parent->str() != "(")
476
0
        return nullptr;
477
2.21k
    if (!parent->astOperand2() && Token::Match(parent, "( %name%|::")) {
478
0
        const Token* ftok = parent->next();
479
0
        if (ftok->isStandardType())
480
0
            return ftok;
481
0
        if (Token::simpleMatch(ftok, "::"))
482
0
            ftok = ftok->next();
483
0
        while (Token::Match(ftok, "%name% ::"))
484
0
            ftok = ftok->tokAt(2);
485
0
        if (settings.library.isNotLibraryFunction(ftok))
486
0
            return parent->next();
487
0
    }
488
2.21k
    if (parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
489
0
        return parent->astOperand1()->tokAt(2);
490
2.21k
    return nullptr;
491
2.21k
}
492
493
// does the operation cause a loss of information?
494
static bool isNonInvertibleOperation(const Token* tok)
495
4.43k
{
496
4.43k
    return !Token::Match(tok, "+|-");
497
4.43k
}
498
499
static bool isComputableValue(const Token* parent, const ValueFlow::Value& value)
500
1.33k
{
501
1.33k
    const bool noninvertible = isNonInvertibleOperation(parent);
502
1.33k
    if (noninvertible && value.isImpossible())
503
44
        return false;
504
1.29k
    if (!value.isIntValue() && !value.isFloatValue() && !value.isTokValue() && !value.isIteratorValue())
505
51
        return false;
506
1.24k
    if (value.isIteratorValue() && !Token::Match(parent, "+|-"))
507
0
        return false;
508
1.24k
    if (value.isTokValue() && (!parent->isComparisonOp() || !Token::Match(value.tokvalue, "{|%str%")))
509
0
        return false;
510
1.24k
    return true;
511
1.24k
}
512
513
static Library::Container::Yield getContainerYield(Token* tok, const Settings& settings, Token** parent = nullptr)
514
0
{
515
0
    if (Token::Match(tok, ". %name% (") && tok->astParent() == tok->tokAt(2) && tok->astOperand1() &&
516
0
        tok->astOperand1()->valueType()) {
517
0
        const Library::Container* c = getLibraryContainer(tok->astOperand1());
518
0
        if (parent)
519
0
            *parent = tok->astParent();
520
0
        return c ? c->getYield(tok->strAt(1)) : Library::Container::Yield::NO_YIELD;
521
0
    }
522
0
    if (Token::Match(tok->previous(), "%name% (")) {
523
0
        if (parent)
524
0
            *parent = tok;
525
0
        if (const Library::Function* f = settings.library.getFunction(tok->previous())) {
526
0
            return f->containerYield;
527
0
        }
528
0
    }
529
0
    return Library::Container::Yield::NO_YIELD;
530
0
}
531
532
/** Set token value for cast */
533
static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings &settings);
534
535
static bool isCompatibleValueTypes(ValueFlow::Value::ValueType x, ValueFlow::Value::ValueType y)
536
225
{
537
225
    static const std::unordered_map<ValueFlow::Value::ValueType,
538
225
                                    std::unordered_set<ValueFlow::Value::ValueType, EnumClassHash>,
539
225
                                    EnumClassHash>
540
225
    compatibleTypes = {
541
225
        {ValueFlow::Value::ValueType::INT,
542
225
         {ValueFlow::Value::ValueType::FLOAT,
543
225
          ValueFlow::Value::ValueType::SYMBOLIC,
544
225
          ValueFlow::Value::ValueType::TOK}},
545
225
        {ValueFlow::Value::ValueType::FLOAT, {ValueFlow::Value::ValueType::INT}},
546
225
        {ValueFlow::Value::ValueType::TOK, {ValueFlow::Value::ValueType::INT}},
547
225
        {ValueFlow::Value::ValueType::ITERATOR_START, {ValueFlow::Value::ValueType::INT}},
548
225
        {ValueFlow::Value::ValueType::ITERATOR_END, {ValueFlow::Value::ValueType::INT}},
549
225
    };
550
225
    if (x == y)
551
225
        return true;
552
0
    auto it = compatibleTypes.find(x);
553
0
    if (it == compatibleTypes.end())
554
0
        return false;
555
0
    return it->second.count(y) > 0;
556
0
}
557
558
static bool isCompatibleValues(const ValueFlow::Value& value1, const ValueFlow::Value& value2)
559
225
{
560
225
    if (value1.isSymbolicValue() && value2.isSymbolicValue() && value1.tokvalue->exprId() != value2.tokvalue->exprId())
561
0
        return false;
562
225
    if (!isCompatibleValueTypes(value1.valueType, value2.valueType))
563
0
        return false;
564
225
    if (value1.isKnown() || value2.isKnown())
565
214
        return true;
566
11
    if (value1.isImpossible() || value2.isImpossible())
567
1
        return false;
568
10
    if (value1.varId == 0 || value2.varId == 0)
569
0
        return true;
570
10
    if (value1.varId == value2.varId && value1.varvalue == value2.varvalue && value1.isIntValue() && value2.isIntValue())
571
10
        return true;
572
0
    return false;
573
10
}
574
575
static ValueFlow::Value truncateImplicitConversion(Token* parent, const ValueFlow::Value& value, const Settings& settings)
576
17.8k
{
577
17.8k
    if (!value.isIntValue() && !value.isFloatValue())
578
0
        return value;
579
17.8k
    if (!parent)
580
6.98k
        return value;
581
10.8k
    if (!parent->isBinaryOp())
582
1.78k
        return value;
583
9.03k
    if (!parent->isConstOp())
584
7.34k
        return value;
585
1.69k
    if (!astIsIntegral(parent->astOperand1(), false))
586
196
        return value;
587
1.49k
    if (!astIsIntegral(parent->astOperand2(), false))
588
143
        return value;
589
1.35k
    const ValueType* vt1 = parent->astOperand1()->valueType();
590
1.35k
    const ValueType* vt2 = parent->astOperand2()->valueType();
591
    // If the sign is the same there is no truncation
592
1.35k
    if (vt1->sign == vt2->sign)
593
1.11k
        return value;
594
236
    const size_t n1 = ValueFlow::getSizeOf(*vt1, settings);
595
236
    const size_t n2 = ValueFlow::getSizeOf(*vt2, settings);
596
236
    ValueType::Sign sign = ValueType::Sign::UNSIGNED;
597
236
    if (n1 < n2)
598
124
        sign = vt2->sign;
599
112
    else if (n1 > n2)
600
112
        sign = vt1->sign;
601
236
    ValueFlow::Value v = castValue(value, sign, std::max(n1, n2) * 8);
602
236
    v.wideintvalue = value.intvalue;
603
236
    return v;
604
1.35k
}
605
606
/** set ValueFlow value and perform calculations if possible */
607
static void setTokenValue(Token* tok,
608
                          ValueFlow::Value value,
609
                          const Settings& settings,
610
                          SourceLocation loc = SourceLocation::current())
611
25.8k
{
612
    // Skip setting values that are too big since its ambiguous
613
25.8k
    if (!value.isImpossible() && value.isIntValue() && value.intvalue < 0 && astIsUnsigned(tok) &&
614
25.8k
        ValueFlow::getSizeOf(*tok->valueType(), settings) >= sizeof(MathLib::bigint))
615
0
        return;
616
617
25.8k
    if (!value.isImpossible() && value.isIntValue())
618
17.8k
        value = truncateImplicitConversion(tok->astParent(), value, settings);
619
620
25.8k
    if (settings.debugnormal)
621
0
        setSourceLocation(value, loc, tok);
622
623
25.8k
    if (!tok->addValue(value))
624
3.84k
        return;
625
626
22.0k
    if (value.path < 0)
627
0
        return;
628
629
22.0k
    Token *parent = tok->astParent();
630
22.0k
    if (!parent)
631
7.23k
        return;
632
633
14.7k
    if (Token::simpleMatch(parent, ",") && !parent->isInitComma() && astIsRHS(tok)) {
634
0
        const Token* callParent = findParent(parent, [](const Token* p) {
635
0
            return !Token::simpleMatch(p, ",");
636
0
        });
637
        // Ensure that the comma isn't a function call
638
0
        if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{") &&
639
0
                            (!Token::Match(callParent, "( %name%") || settings.library.isNotLibraryFunction(callParent->next())) &&
640
0
                            !(callParent->str() == "(" && (Token::simpleMatch(callParent->astOperand1(), "*") || Token::Match(callParent->astOperand1(), "%name%|("))))) {
641
0
            setTokenValue(parent, std::move(value), settings);
642
0
            return;
643
0
        }
644
0
    }
645
646
14.7k
    if (Token::simpleMatch(parent, "=") && astIsRHS(tok)) {
647
7.46k
        setTokenValue(parent, value, settings);
648
7.46k
        if (!value.isUninitValue())
649
7.46k
            return;
650
7.46k
    }
651
652
7.30k
    if (value.isContainerSizeValue() && astIsContainer(tok)) {
653
        // .empty, .size, +"abc", +'a'
654
0
        if (Token::Match(parent, "+|==|!=") && parent->astOperand1() && parent->astOperand2()) {
655
0
            for (const ValueFlow::Value &value1 : parent->astOperand1()->values()) {
656
0
                if (value1.isImpossible())
657
0
                    continue;
658
0
                for (const ValueFlow::Value &value2 : parent->astOperand2()->values()) {
659
0
                    if (value2.isImpossible())
660
0
                        continue;
661
0
                    if (value1.path != value2.path)
662
0
                        continue;
663
0
                    ValueFlow::Value result;
664
0
                    if (Token::Match(parent, "%comp%"))
665
0
                        result.valueType = ValueFlow::Value::ValueType::INT;
666
0
                    else
667
0
                        result.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
668
669
0
                    if (value1.isContainerSizeValue() && value2.isContainerSizeValue())
670
0
                        result.intvalue = calculate(parent->str(), value1.intvalue, value2.intvalue);
671
0
                    else if (value1.isContainerSizeValue() && value2.isTokValue() && value2.tokvalue->tokType() == Token::eString)
672
0
                        result.intvalue = calculate(parent->str(), value1.intvalue, MathLib::bigint(Token::getStrLength(value2.tokvalue)));
673
0
                    else if (value2.isContainerSizeValue() && value1.isTokValue() && value1.tokvalue->tokType() == Token::eString)
674
0
                        result.intvalue = calculate(parent->str(), MathLib::bigint(Token::getStrLength(value1.tokvalue)), value2.intvalue);
675
0
                    else
676
0
                        continue;
677
678
0
                    combineValueProperties(value1, value2, result);
679
680
0
                    if (Token::simpleMatch(parent, "==") && result.intvalue)
681
0
                        continue;
682
0
                    if (Token::simpleMatch(parent, "!=") && !result.intvalue)
683
0
                        continue;
684
685
0
                    setTokenValue(parent, std::move(result), settings);
686
0
                }
687
0
            }
688
0
        }
689
0
        Token* next = nullptr;
690
0
        const Library::Container::Yield yields = getContainerYield(parent, settings, &next);
691
0
        if (yields == Library::Container::Yield::SIZE) {
692
0
            ValueFlow::Value v(value);
693
0
            v.valueType = ValueFlow::Value::ValueType::INT;
694
0
            setTokenValue(next, std::move(v), settings);
695
0
        } else if (yields == Library::Container::Yield::EMPTY) {
696
0
            ValueFlow::Value v(value);
697
0
            v.valueType = ValueFlow::Value::ValueType::INT;
698
0
            v.bound = ValueFlow::Value::Bound::Point;
699
0
            if (value.isImpossible()) {
700
0
                if (value.intvalue == 0)
701
0
                    v.setKnown();
702
0
                else if ((value.bound == ValueFlow::Value::Bound::Upper && value.intvalue > 0) ||
703
0
                         (value.bound == ValueFlow::Value::Bound::Lower && value.intvalue < 0)) {
704
0
                    v.intvalue = 0;
705
0
                    v.setKnown();
706
0
                } else
707
0
                    v.setPossible();
708
0
            } else {
709
0
                v.intvalue = !v.intvalue;
710
0
            }
711
0
            setTokenValue(next, std::move(v), settings);
712
0
        }
713
0
        return;
714
0
    }
715
716
7.30k
    if (value.isLifetimeValue()) {
717
0
        if (!ValueFlow::isLifetimeBorrowed(parent, settings))
718
0
            return;
719
0
        if (value.lifetimeKind == ValueFlow::Value::LifetimeKind::Iterator && astIsIterator(parent)) {
720
0
            setTokenValue(parent,std::move(value),settings);
721
0
        } else if (astIsPointer(tok) && astIsPointer(parent) && !parent->isUnaryOp("*") &&
722
0
                   (parent->isArithmeticalOp() || parent->isCast())) {
723
0
            setTokenValue(parent,std::move(value),settings);
724
0
        }
725
0
        return;
726
0
    }
727
728
7.30k
    if (value.isUninitValue()) {
729
0
        if (Token::Match(tok, ". %var%"))
730
0
            setTokenValue(tok->next(), value, settings);
731
0
        if (parent->isCast()) {
732
0
            setTokenValue(parent, std::move(value), settings);
733
0
            return;
734
0
        }
735
0
        ValueFlow::Value pvalue = value;
736
0
        if (!value.subexpressions.empty() && Token::Match(parent, ". %var%")) {
737
0
            if (contains(value.subexpressions, parent->next()->str()))
738
0
                pvalue.subexpressions.clear();
739
0
            else
740
0
                return;
741
0
        }
742
0
        if (parent->isUnaryOp("&")) {
743
0
            pvalue.indirect++;
744
0
            setTokenValue(parent, std::move(pvalue), settings);
745
0
        } else if (Token::Match(parent, ". %var%") && parent->astOperand1() == tok && parent->astOperand2()) {
746
0
            if (parent->originalName() == "->" && pvalue.indirect > 0)
747
0
                pvalue.indirect--;
748
0
            setTokenValue(parent->astOperand2(), std::move(pvalue), settings);
749
0
        } else if (Token::Match(parent->astParent(), ". %var%") && parent->astParent()->astOperand1() == parent) {
750
0
            if (parent->astParent()->originalName() == "->" && pvalue.indirect > 0)
751
0
                pvalue.indirect--;
752
0
            setTokenValue(parent->astParent()->astOperand2(), std::move(pvalue), settings);
753
0
        } else if (parent->isUnaryOp("*") && pvalue.indirect > 0) {
754
0
            pvalue.indirect--;
755
0
            setTokenValue(parent, std::move(pvalue), settings);
756
0
        }
757
0
        return;
758
0
    }
759
760
    // cast..
761
7.30k
    if (const Token *castType = getCastTypeStartToken(parent, settings)) {
762
0
        if (contains({ValueFlow::Value::ValueType::INT, ValueFlow::Value::ValueType::SYMBOLIC}, value.valueType) &&
763
0
            Token::simpleMatch(parent->astOperand1(), "dynamic_cast"))
764
0
            return;
765
0
        const ValueType &valueType = ValueType::parseDecl(castType, settings);
766
0
        if (value.isImpossible() && value.isIntValue() && value.intvalue < 0 && astIsUnsigned(tok) &&
767
0
            valueType.sign == ValueType::SIGNED && tok->valueType() &&
768
0
            ValueFlow::getSizeOf(*tok->valueType(), settings) >= ValueFlow::getSizeOf(valueType, settings))
769
0
            return;
770
0
        setTokenValueCast(parent, valueType, value, settings);
771
0
    }
772
773
7.30k
    else if (parent->str() == ":") {
774
0
        setTokenValue(parent,value,settings);
775
0
    }
776
777
7.30k
    else if (parent->str() == "?" && tok->str() == ":" && tok == parent->astOperand2() && parent->astOperand1()) {
778
        // is condition always true/false?
779
0
        if (parent->astOperand1()->hasKnownValue()) {
780
0
            const ValueFlow::Value &condvalue = parent->astOperand1()->values().front();
781
0
            const bool cond(condvalue.isTokValue() || (condvalue.isIntValue() && condvalue.intvalue != 0));
782
0
            if (cond && !tok->astOperand1()) { // true condition, no second operator
783
0
                setTokenValue(parent, condvalue, settings);
784
0
            } else {
785
0
                const Token *op = cond ? tok->astOperand1() : tok->astOperand2();
786
0
                if (!op) // #7769 segmentation fault at setTokenValue()
787
0
                    return;
788
0
                const std::list<ValueFlow::Value> &values = op->values();
789
0
                if (std::find(values.cbegin(), values.cend(), value) != values.cend())
790
0
                    setTokenValue(parent, std::move(value), settings);
791
0
            }
792
0
        } else if (!value.isImpossible()) {
793
            // is condition only depending on 1 variable?
794
            // cppcheck-suppress[variableScope] #8541
795
0
            nonneg int varId = 0;
796
0
            bool ret = false;
797
0
            visitAstNodes(parent->astOperand1(),
798
0
                          [&](const Token *t) {
799
0
                if (t->varId()) {
800
0
                    if (varId > 0 || value.varId != 0)
801
0
                        ret = true;
802
0
                    varId = t->varId();
803
0
                } else if (t->str() == "(" && Token::Match(t->previous(), "%name%"))
804
0
                    ret = true; // function call
805
0
                return ret ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
806
0
            });
807
0
            if (ret)
808
0
                return;
809
810
0
            ValueFlow::Value v(value);
811
0
            v.conditional = true;
812
0
            v.changeKnownToPossible();
813
814
0
            setTokenValue(parent, std::move(v), settings);
815
0
        }
816
0
    }
817
818
7.30k
    else if (parent->str() == "?" && value.isIntValue() && tok == parent->astOperand1() && value.isKnown() &&
819
7.30k
             parent->astOperand2() && parent->astOperand2()->astOperand1() && parent->astOperand2()->astOperand2()) {
820
0
        const std::list<ValueFlow::Value> &values = (value.intvalue == 0
821
0
                ? parent->astOperand2()->astOperand2()->values()
822
0
                : parent->astOperand2()->astOperand1()->values());
823
824
0
        for (const ValueFlow::Value &v : values)
825
0
            setTokenValue(parent, v, settings);
826
0
    }
827
828
    // Calculations..
829
7.30k
    else if ((parent->isArithmeticalOp() || parent->isComparisonOp() || (parent->tokType() == Token::eBitOp) || (parent->tokType() == Token::eLogicalOp)) &&
830
7.30k
             parent->astOperand1() &&
831
7.30k
             parent->astOperand2()) {
832
833
3.09k
        const bool noninvertible = isNonInvertibleOperation(parent);
834
835
        // Skip operators with impossible values that are not invertible
836
3.09k
        if (noninvertible && value.isImpossible())
837
1.36k
            return;
838
839
        // known result when a operand is 0.
840
1.73k
        if (Token::Match(parent, "[&*]") && astIsIntegral(parent, true) && value.isKnown() && value.isIntValue() &&
841
1.73k
            value.intvalue == 0) {
842
38
            setTokenValue(parent, std::move(value), settings);
843
38
            return;
844
38
        }
845
846
        // known result when a operand is true.
847
1.69k
        if (Token::simpleMatch(parent, "&&") && value.isKnown() && value.isIntValue() && value.intvalue==0) {
848
0
            setTokenValue(parent, std::move(value), settings);
849
0
            return;
850
0
        }
851
852
        // known result when a operand is false.
853
1.69k
        if (Token::simpleMatch(parent, "||") && value.isKnown() && value.isIntValue() && value.intvalue!=0) {
854
0
            setTokenValue(parent, std::move(value), settings);
855
0
            return;
856
0
        }
857
858
1.69k
        for (const ValueFlow::Value &value1 : parent->astOperand1()->values()) {
859
1.08k
            if (!isComputableValue(parent, value1))
860
69
                continue;
861
1.01k
            for (const ValueFlow::Value &value2 : parent->astOperand2()->values()) {
862
251
                if (value1.path != value2.path)
863
0
                    continue;
864
251
                if (!isComputableValue(parent, value2))
865
26
                    continue;
866
225
                if (value1.isIteratorValue() && value2.isIteratorValue())
867
0
                    continue;
868
225
                if (!isCompatibleValues(value1, value2))
869
1
                    continue;
870
224
                ValueFlow::Value result(0);
871
224
                combineValueProperties(value1, value2, result);
872
224
                if (astIsFloat(parent, false)) {
873
0
                    if (!result.isIntValue() && !result.isFloatValue())
874
0
                        continue;
875
0
                    result.valueType = ValueFlow::Value::ValueType::FLOAT;
876
0
                }
877
224
                const double floatValue1 = value1.isFloatValue() ? value1.floatValue : value1.intvalue;
878
224
                const double floatValue2 = value2.isFloatValue() ? value2.floatValue : value2.intvalue;
879
224
                const auto intValue1 = [&]() -> MathLib::bigint {
880
224
                    return value1.isFloatValue() ? static_cast<MathLib::bigint>(value1.floatValue) : value1.intvalue;
881
224
                };
882
224
                const auto intValue2 = [&]() -> MathLib::bigint {
883
224
                    return value2.isFloatValue() ? static_cast<MathLib::bigint>(value2.floatValue) : value2.intvalue;
884
224
                };
885
224
                if ((value1.isFloatValue() || value2.isFloatValue()) && Token::Match(parent, "&|^|%|<<|>>|==|!=|%or%"))
886
0
                    continue;
887
224
                if (Token::Match(parent, "==|!=")) {
888
44
                    if ((value1.isIntValue() && value2.isTokValue()) || (value1.isTokValue() && value2.isIntValue())) {
889
0
                        if (parent->str() == "==")
890
0
                            result.intvalue = 0;
891
0
                        else if (parent->str() == "!=")
892
0
                            result.intvalue = 1;
893
44
                    } else if (value1.isIntValue() && value2.isIntValue()) {
894
44
                        bool error = false;
895
44
                        result.intvalue = calculate(parent->str(), intValue1(), intValue2(), &error);
896
44
                        if (error)
897
0
                            continue;
898
44
                    } else if (value1.isTokValue() && value2.isTokValue() &&
899
0
                               (astIsContainer(parent->astOperand1()) || astIsContainer(parent->astOperand2()))) {
900
0
                        const Token* tok1 = value1.tokvalue;
901
0
                        const Token* tok2 = value2.tokvalue;
902
0
                        bool equal = false;
903
0
                        if (Token::Match(tok1, "%str%") && Token::Match(tok2, "%str%")) {
904
0
                            equal = tok1->str() == tok2->str();
905
0
                        } else if (Token::simpleMatch(tok1, "{") && Token::simpleMatch(tok2, "{")) {
906
0
                            std::vector<const Token*> args1 = getArguments(tok1);
907
0
                            std::vector<const Token*> args2 = getArguments(tok2);
908
0
                            if (args1.size() == args2.size()) {
909
0
                                if (!std::all_of(args1.begin(), args1.end(), std::mem_fn(&Token::hasKnownIntValue)))
910
0
                                    continue;
911
0
                                if (!std::all_of(args2.begin(), args2.end(), std::mem_fn(&Token::hasKnownIntValue)))
912
0
                                    continue;
913
0
                                equal = std::equal(args1.begin(),
914
0
                                                   args1.end(),
915
0
                                                   args2.begin(),
916
0
                                                   [&](const Token* atok, const Token* btok) {
917
0
                                    return atok->values().front().intvalue ==
918
0
                                    btok->values().front().intvalue;
919
0
                                });
920
0
                            } else {
921
0
                                equal = false;
922
0
                            }
923
0
                        } else {
924
0
                            continue;
925
0
                        }
926
0
                        result.intvalue = parent->str() == "==" ? equal : !equal;
927
0
                    } else {
928
0
                        continue;
929
0
                    }
930
44
                    setTokenValue(parent, std::move(result), settings);
931
180
                } else if (Token::Match(parent, "%op%")) {
932
180
                    if (Token::Match(parent, "%comp%")) {
933
69
                        if (!result.isFloatValue() && !value1.isIntValue() && !value2.isIntValue())
934
0
                            continue;
935
111
                    } else {
936
111
                        if (value1.isTokValue() || value2.isTokValue())
937
0
                            break;
938
111
                    }
939
180
                    bool error = false;
940
180
                    if (result.isFloatValue()) {
941
0
                        result.floatValue = calculate(parent->str(), floatValue1, floatValue2, &error);
942
180
                    } else {
943
180
                        result.intvalue = calculate(parent->str(), intValue1(), intValue2(), &error);
944
180
                    }
945
180
                    if (error)
946
0
                        continue;
947
                    // If the bound comes from the second value then invert the bound when subtracting
948
180
                    if (Token::simpleMatch(parent, "-") && value2.bound == result.bound &&
949
180
                        value2.bound != ValueFlow::Value::Bound::Point)
950
2
                        result.invertBound();
951
180
                    setTokenValue(parent, std::move(result), settings);
952
180
                }
953
224
            }
954
1.01k
        }
955
1.69k
    }
956
957
    // !
958
4.20k
    else if (parent->str() == "!") {
959
0
        for (const ValueFlow::Value &val : tok->values()) {
960
0
            if (!val.isIntValue())
961
0
                continue;
962
0
            if (val.isImpossible() && val.intvalue != 0)
963
0
                continue;
964
0
            ValueFlow::Value v(val);
965
0
            if (val.isImpossible())
966
0
                v.setKnown();
967
0
            else
968
0
                v.intvalue = !v.intvalue;
969
0
            setTokenValue(parent, std::move(v), settings);
970
0
        }
971
0
    }
972
973
    // ~
974
4.20k
    else if (parent->str() == "~") {
975
236
        for (const ValueFlow::Value &val : tok->values()) {
976
236
            if (!val.isIntValue())
977
8
                continue;
978
228
            ValueFlow::Value v(val);
979
228
            v.intvalue = ~v.intvalue;
980
228
            int bits = 0;
981
228
            if (tok->valueType() &&
982
228
                tok->valueType()->sign == ValueType::Sign::UNSIGNED &&
983
228
                tok->valueType()->pointer == 0) {
984
0
                if (tok->valueType()->type == ValueType::Type::INT)
985
0
                    bits = settings.platform.int_bit;
986
0
                else if (tok->valueType()->type == ValueType::Type::LONG)
987
0
                    bits = settings.platform.long_bit;
988
0
            }
989
228
            if (bits > 0 && bits < MathLib::bigint_bits)
990
0
                v.intvalue &= (((MathLib::biguint)1)<<bits) - 1;
991
228
            setTokenValue(parent, std::move(v), settings);
992
228
        }
993
232
    }
994
995
    // unary minus
996
3.97k
    else if (parent->isUnaryOp("-")) {
997
0
        for (const ValueFlow::Value &val : tok->values()) {
998
0
            if (!val.isIntValue() && !val.isFloatValue())
999
0
                continue;
1000
0
            ValueFlow::Value v(val);
1001
0
            if (v.isIntValue()) {
1002
0
                if (v.intvalue == LLONG_MIN)
1003
                    // Value can't be inverted
1004
0
                    continue;
1005
0
                v.intvalue = -v.intvalue;
1006
0
            } else
1007
0
                v.floatValue = -v.floatValue;
1008
0
            v.invertBound();
1009
0
            setTokenValue(parent, std::move(v), settings);
1010
0
        }
1011
0
    }
1012
1013
    // increment
1014
3.97k
    else if (parent->str() == "++") {
1015
55
        for (const ValueFlow::Value &val : tok->values()) {
1016
55
            if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue())
1017
0
                continue;
1018
55
            ValueFlow::Value v(val);
1019
55
            if (parent == tok->previous()) {
1020
54
                if (v.isIntValue() || v.isSymbolicValue())
1021
54
                    v.intvalue = v.intvalue + 1;
1022
0
                else
1023
0
                    v.floatValue = v.floatValue + 1.0;
1024
54
            }
1025
55
            setTokenValue(parent, std::move(v), settings);
1026
55
        }
1027
51
    }
1028
1029
    // decrement
1030
3.92k
    else if (parent->str() == "--") {
1031
73
        for (const ValueFlow::Value &val : tok->values()) {
1032
73
            if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue())
1033
0
                continue;
1034
73
            ValueFlow::Value v(val);
1035
73
            if (parent == tok->previous()) {
1036
70
                if (v.isIntValue() || v.isSymbolicValue())
1037
70
                    v.intvalue = v.intvalue - 1;
1038
0
                else
1039
0
                    v.floatValue = v.floatValue - 1.0;
1040
70
            }
1041
73
            setTokenValue(parent, std::move(v), settings);
1042
73
        }
1043
63
    }
1044
1045
    // C++ init
1046
3.86k
    else if (parent->str() == "{" && Token::simpleMatch(parent->previous(), "= {") && Token::simpleMatch(parent->link(), "} ;")) {
1047
0
        const Token* lhs = parent->previous()->astOperand1();
1048
0
        if (lhs && lhs->valueType()) {
1049
0
            if (lhs->valueType()->isIntegral() || lhs->valueType()->isFloat() || (lhs->valueType()->pointer > 0 && value.isIntValue())) {
1050
0
                setTokenValue(parent, std::move(value), settings);
1051
0
            }
1052
0
        }
1053
0
    }
1054
1055
3.86k
    else if (Token::Match(parent, ":: %name%") && parent->astOperand2() == tok) {
1056
0
        setTokenValue(parent, value, settings);
1057
0
    }
1058
    // Calling std::size or std::empty on an array
1059
3.86k
    else if (value.isTokValue() && Token::simpleMatch(value.tokvalue, "{") && tok->variable() &&
1060
3.86k
             tok->variable()->isArray() && Token::Match(parent->previous(), "%name% (") && astIsRHS(tok)) {
1061
0
        std::vector<const Token*> args = getArguments(value.tokvalue);
1062
0
        if (const Library::Function* f = settings.library.getFunction(parent->previous())) {
1063
0
            if (f->containerYield == Library::Container::Yield::SIZE) {
1064
0
                ValueFlow::Value v(value);
1065
0
                v.valueType = ValueFlow::Value::ValueType::INT;
1066
0
                v.intvalue = args.size();
1067
0
                setTokenValue(parent, std::move(v), settings);
1068
0
            } else if (f->containerYield == Library::Container::Yield::EMPTY) {
1069
0
                ValueFlow::Value v(value);
1070
0
                v.intvalue = args.empty();
1071
0
                v.valueType = ValueFlow::Value::ValueType::INT;
1072
0
                setTokenValue(parent, std::move(v), settings);
1073
0
            }
1074
0
        }
1075
0
    }
1076
7.30k
}
1077
1078
static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings &settings)
1079
0
{
1080
0
    if (valueType.pointer || value.isImpossible())
1081
0
        setTokenValue(parent,value,settings);
1082
0
    else if (valueType.type == ValueType::Type::CHAR)
1083
0
        setTokenValue(parent, castValue(value, valueType.sign, settings.platform.char_bit), settings);
1084
0
    else if (valueType.type == ValueType::Type::SHORT)
1085
0
        setTokenValue(parent, castValue(value, valueType.sign, settings.platform.short_bit), settings);
1086
0
    else if (valueType.type == ValueType::Type::INT)
1087
0
        setTokenValue(parent, castValue(value, valueType.sign, settings.platform.int_bit), settings);
1088
0
    else if (valueType.type == ValueType::Type::LONG)
1089
0
        setTokenValue(parent, castValue(value, valueType.sign, settings.platform.long_bit), settings);
1090
0
    else if (valueType.type == ValueType::Type::LONGLONG)
1091
0
        setTokenValue(parent, castValue(value, valueType.sign, settings.platform.long_long_bit), settings);
1092
0
    else if (valueType.isFloat() && isNumeric(value)) {
1093
0
        ValueFlow::Value floatValue = value;
1094
0
        floatValue.valueType = ValueFlow::Value::ValueType::FLOAT;
1095
0
        if (value.isIntValue())
1096
0
            floatValue.floatValue = value.intvalue;
1097
0
        setTokenValue(parent, std::move(floatValue), settings);
1098
0
    } else if (value.isIntValue()) {
1099
0
        const long long charMax = settings.platform.signedCharMax();
1100
0
        const long long charMin = settings.platform.signedCharMin();
1101
0
        if (charMin <= value.intvalue && value.intvalue <= charMax) {
1102
            // unknown type, but value is small so there should be no truncation etc
1103
0
            setTokenValue(parent,value,settings);
1104
0
        }
1105
0
    }
1106
0
}
1107
1108
template<class F>
1109
static size_t accumulateStructMembers(const Scope* scope, F f)
1110
0
{
1111
0
    size_t total = 0;
1112
0
    for (const Variable& var : scope->varlist) {
1113
0
        if (var.isStatic())
1114
0
            continue;
1115
0
        if (const ValueType* vt = var.valueType()) {
1116
0
            if (vt->type == ValueType::Type::RECORD && vt->typeScope == scope)
1117
0
                return 0;
1118
0
            total = f(total, *vt);
1119
0
        }
1120
0
        if (total == 0)
1121
0
            return 0;
1122
0
    }
1123
0
    return total;
1124
0
}
Unexecuted instantiation: valueflow.cpp:unsigned long accumulateStructMembers<getAlignOf(ValueType const&, Settings const&)::$_55>(Scope const*, getAlignOf(ValueType const&, Settings const&)::$_55)
Unexecuted instantiation: valueflow.cpp:unsigned long accumulateStructMembers<ValueFlow::getSizeOf(ValueType const&, Settings const&)::$_3>(Scope const*, ValueFlow::getSizeOf(ValueType const&, Settings const&)::$_3)
1125
1126
static size_t bitCeil(size_t x)
1127
0
{
1128
0
    if (x <= 1)
1129
0
        return 1;
1130
0
    --x;
1131
0
    x |= x >> 1;
1132
0
    x |= x >> 2;
1133
0
    x |= x >> 4;
1134
0
    x |= x >> 8;
1135
0
    x |= x >> 16;
1136
0
    x |= x >> 32;
1137
0
    return x + 1;
1138
0
}
1139
1140
static size_t getAlignOf(const ValueType& vt, const Settings& settings)
1141
0
{
1142
0
    if (vt.pointer || vt.reference != Reference::None || vt.isPrimitive()) {
1143
0
        auto align = ValueFlow::getSizeOf(vt, settings);
1144
0
        return align == 0 ? 0 : bitCeil(align);
1145
0
    }
1146
0
    if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
1147
0
        return accumulateStructMembers(vt.typeScope, [&](size_t max, const ValueType& vt2) {
1148
0
            size_t a = getAlignOf(vt2, settings);
1149
0
            return std::max(max, a);
1150
0
        });
1151
0
    }
1152
0
    return 0;
1153
0
}
1154
1155
static nonneg int getSizeOfType(const Token *typeTok, const Settings &settings)
1156
0
{
1157
0
    const ValueType &valueType = ValueType::parseDecl(typeTok, settings);
1158
1159
0
    return ValueFlow::getSizeOf(valueType, settings);
1160
0
}
1161
1162
size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings)
1163
2.12k
{
1164
2.12k
    if (vt.pointer || vt.reference != Reference::None)
1165
0
        return settings.platform.sizeof_pointer;
1166
2.12k
    if (vt.type == ValueType::Type::BOOL || vt.type == ValueType::Type::CHAR)
1167
466
        return 1;
1168
1.65k
    if (vt.type == ValueType::Type::SHORT)
1169
0
        return settings.platform.sizeof_short;
1170
1.65k
    if (vt.type == ValueType::Type::WCHAR_T)
1171
0
        return settings.platform.sizeof_wchar_t;
1172
1.65k
    if (vt.type == ValueType::Type::INT)
1173
1.65k
        return settings.platform.sizeof_int;
1174
0
    if (vt.type == ValueType::Type::LONG)
1175
0
        return settings.platform.sizeof_long;
1176
0
    if (vt.type == ValueType::Type::LONGLONG)
1177
0
        return settings.platform.sizeof_long_long;
1178
0
    if (vt.type == ValueType::Type::FLOAT)
1179
0
        return settings.platform.sizeof_float;
1180
0
    if (vt.type == ValueType::Type::DOUBLE)
1181
0
        return settings.platform.sizeof_double;
1182
0
    if (vt.type == ValueType::Type::LONGDOUBLE)
1183
0
        return settings.platform.sizeof_long_double;
1184
0
    if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
1185
0
        size_t total = accumulateStructMembers(vt.typeScope, [&](size_t total, const ValueType& vt2) -> size_t {
1186
0
            size_t n = ValueFlow::getSizeOf(vt2, settings);
1187
0
            size_t a = getAlignOf(vt2, settings);
1188
0
            if (n == 0 || a == 0)
1189
0
                return 0;
1190
0
            size_t padding = (a - (total % a)) % a;
1191
0
            return total + padding + n;
1192
0
        });
1193
0
        if (total == 0)
1194
0
            return 0;
1195
0
        size_t align = getAlignOf(vt, settings);
1196
0
        if (align == 0)
1197
0
            return 0;
1198
0
        total += (align - (total % align)) % align;
1199
0
        return total;
1200
0
    }
1201
0
    return 0;
1202
0
}
1203
1204
1205
static bool getMinMaxValues(const ValueType* vt, const Platform& platform, MathLib::bigint& minValue, MathLib::bigint& maxValue);
1206
1207
// Handle various constants..
1208
static Token * valueFlowSetConstantValue(Token *tok, const Settings &settings, bool cpp)
1209
91.8k
{
1210
91.8k
    if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
1211
9.50k
        try {
1212
9.50k
            MathLib::bigint signedValue = MathLib::toBigNumber(tok->str());
1213
9.50k
            const ValueType* vt = tok->valueType();
1214
9.50k
            if (vt && vt->sign == ValueType::UNSIGNED && signedValue < 0 && ValueFlow::getSizeOf(*vt, settings) < sizeof(MathLib::bigint)) {
1215
0
                MathLib::bigint minValue{}, maxValue{};
1216
0
                if (getMinMaxValues(tok->valueType(), settings.platform, minValue, maxValue))
1217
0
                    signedValue += maxValue + 1;
1218
0
            }
1219
9.50k
            ValueFlow::Value value(signedValue);
1220
9.50k
            if (!tok->isTemplateArg())
1221
9.50k
                value.setKnown();
1222
9.50k
            setTokenValue(tok, std::move(value), settings);
1223
9.50k
        } catch (const std::exception & /*e*/) {
1224
            // Bad character literal
1225
0
        }
1226
82.3k
    } else if (tok->isNumber() && MathLib::isFloat(tok->str())) {
1227
0
        ValueFlow::Value value;
1228
0
        value.valueType = ValueFlow::Value::ValueType::FLOAT;
1229
0
        value.floatValue = MathLib::toDoubleNumber(tok->str());
1230
0
        if (!tok->isTemplateArg())
1231
0
            value.setKnown();
1232
0
        setTokenValue(tok, std::move(value), settings);
1233
82.3k
    } else if (tok->enumerator() && tok->enumerator()->value_known) {
1234
0
        ValueFlow::Value value(tok->enumerator()->value);
1235
0
        if (!tok->isTemplateArg())
1236
0
            value.setKnown();
1237
0
        setTokenValue(tok, std::move(value), settings);
1238
82.3k
    } else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
1239
0
        ValueFlow::Value value(0);
1240
0
        if (!tok->isTemplateArg())
1241
0
            value.setKnown();
1242
0
        setTokenValue(tok, std::move(value), settings);
1243
82.3k
    } else if (Token::simpleMatch(tok, "sizeof (")) {
1244
0
        if (tok->next()->astOperand2() && !tok->next()->astOperand2()->isLiteral() && tok->next()->astOperand2()->valueType() &&
1245
0
            (tok->next()->astOperand2()->valueType()->pointer == 0 || // <- TODO this is a bailout, abort when there are array->pointer conversions
1246
0
             (tok->next()->astOperand2()->variable() && !tok->next()->astOperand2()->variable()->isArray())) &&
1247
0
            !tok->next()->astOperand2()->valueType()->isEnum()) { // <- TODO this is a bailout, handle enum with non-int types
1248
0
            const size_t sz = ValueFlow::getSizeOf(*tok->next()->astOperand2()->valueType(), settings);
1249
0
            if (sz) {
1250
0
                ValueFlow::Value value(sz);
1251
0
                value.setKnown();
1252
0
                setTokenValue(tok->next(), std::move(value), settings);
1253
0
                return tok->linkAt(1);
1254
0
            }
1255
0
        }
1256
1257
0
        const Token *tok2 = tok->tokAt(2);
1258
        // skip over tokens to find variable or type
1259
0
        while (tok2 && !tok2->isStandardType() && Token::Match(tok2, "%name% ::|.|[")) {
1260
0
            if (tok2->next()->str() == "[")
1261
0
                tok2 = tok2->linkAt(1)->next();
1262
0
            else
1263
0
                tok2 = tok2->tokAt(2);
1264
0
        }
1265
0
        if (Token::simpleMatch(tok, "sizeof ( *")) {
1266
0
            const ValueType *vt = tok->tokAt(2)->valueType();
1267
0
            const size_t sz = vt ? ValueFlow::getSizeOf(*vt, settings) : 0;
1268
0
            if (sz > 0) {
1269
0
                ValueFlow::Value value(sz);
1270
0
                if (!tok2->isTemplateArg() && settings.platform.type != Platform::Type::Unspecified)
1271
0
                    value.setKnown();
1272
0
                setTokenValue(tok->next(), std::move(value), settings);
1273
0
            }
1274
0
        } else if (tok2->enumerator() && tok2->enumerator()->scope) {
1275
0
            long long size = settings.platform.sizeof_int;
1276
0
            const Token * type = tok2->enumerator()->scope->enumType;
1277
0
            if (type) {
1278
0
                size = getSizeOfType(type, settings);
1279
0
                if (size == 0)
1280
0
                    tok->linkAt(1);
1281
0
            }
1282
0
            ValueFlow::Value value(size);
1283
0
            if (!tok2->isTemplateArg() && settings.platform.type != Platform::Type::Unspecified)
1284
0
                value.setKnown();
1285
0
            setTokenValue(tok, value, settings);
1286
0
            setTokenValue(tok->next(), std::move(value), settings);
1287
0
        } else if (tok2->type() && tok2->type()->isEnumType()) {
1288
0
            long long size = settings.platform.sizeof_int;
1289
0
            if (tok2->type()->classScope) {
1290
0
                const Token * type = tok2->type()->classScope->enumType;
1291
0
                if (type) {
1292
0
                    size = getSizeOfType(type, settings);
1293
0
                }
1294
0
            }
1295
0
            ValueFlow::Value value(size);
1296
0
            if (!tok2->isTemplateArg() && settings.platform.type != Platform::Type::Unspecified)
1297
0
                value.setKnown();
1298
0
            setTokenValue(tok, value, settings);
1299
0
            setTokenValue(tok->next(), std::move(value), settings);
1300
0
        } else if (Token::Match(tok, "sizeof ( %var% ) /") && tok->next()->astParent() == tok->tokAt(4) &&
1301
0
                   tok->tokAt(4)->astOperand2() && Token::simpleMatch(tok->tokAt(4)->astOperand2()->previous(), "sizeof (")) {
1302
            // Get number of elements in array
1303
0
            const Token *sz1 = tok->tokAt(2);
1304
0
            const Token *sz2 = tok->tokAt(4)->astOperand2(); // left parenthesis of sizeof on rhs
1305
0
            const nonneg int varid1 = sz1->varId();
1306
0
            if (varid1 &&
1307
0
                sz1->variable() &&
1308
0
                sz1->variable()->isArray() &&
1309
0
                !sz1->variable()->dimensions().empty() &&
1310
0
                sz1->variable()->dimensionKnown(0) &&
1311
0
                Token::Match(sz2->astOperand2(), "*|[") && Token::Match(sz2->astOperand2()->astOperand1(), "%varid%", varid1)) {
1312
0
                ValueFlow::Value value(sz1->variable()->dimension(0));
1313
0
                if (!tok2->isTemplateArg() && settings.platform.type != Platform::Type::Unspecified)
1314
0
                    value.setKnown();
1315
0
                setTokenValue(tok->tokAt(4), std::move(value), settings);
1316
0
            }
1317
0
        } else if (Token::Match(tok2, "%var% )")) {
1318
0
            const Variable *var = tok2->variable();
1319
            // only look for single token types (no pointers or references yet)
1320
0
            if (var && var->typeStartToken() == var->typeEndToken()) {
1321
                // find the size of the type
1322
0
                size_t size = 0;
1323
0
                if (var->isEnumType()) {
1324
0
                    size = settings.platform.sizeof_int;
1325
0
                    if (var->type()->classScope && var->type()->classScope->enumType)
1326
0
                        size = getSizeOfType(var->type()->classScope->enumType, settings);
1327
0
                } else if (var->valueType()) {
1328
0
                    size = ValueFlow::getSizeOf(*var->valueType(), settings);
1329
0
                } else if (!var->type()) {
1330
0
                    size = getSizeOfType(var->typeStartToken(), settings);
1331
0
                }
1332
                // find the number of elements
1333
0
                size_t count = 1;
1334
0
                for (size_t i = 0; i < var->dimensions().size(); ++i) {
1335
0
                    if (var->dimensionKnown(i))
1336
0
                        count *= var->dimension(i);
1337
0
                    else
1338
0
                        count = 0;
1339
0
                }
1340
0
                if (size && count > 0) {
1341
0
                    ValueFlow::Value value(count * size);
1342
0
                    if (settings.platform.type != Platform::Type::Unspecified)
1343
0
                        value.setKnown();
1344
0
                    setTokenValue(tok, value, settings);
1345
0
                    setTokenValue(tok->next(), std::move(value), settings);
1346
0
                }
1347
0
            }
1348
0
        } else if (tok2->tokType() == Token::eString) {
1349
0
            const size_t sz = Token::getStrSize(tok2, settings);
1350
0
            if (sz > 0) {
1351
0
                ValueFlow::Value value(sz);
1352
0
                value.setKnown();
1353
0
                setTokenValue(tok->next(), std::move(value), settings);
1354
0
            }
1355
0
        } else if (tok2->tokType() == Token::eChar) {
1356
0
            nonneg int sz = 0;
1357
0
            if (cpp && settings.standards.cpp >= Standards::CPP20 && tok2->isUtf8())
1358
0
                sz = 1;
1359
0
            else if (tok2->isUtf16())
1360
0
                sz = 2;
1361
0
            else if (tok2->isUtf32())
1362
0
                sz = 4;
1363
0
            else if (tok2->isLong())
1364
0
                sz = settings.platform.sizeof_wchar_t;
1365
0
            else if ((tok2->isCChar() && !cpp) || (tok2->isCMultiChar()))
1366
0
                sz = settings.platform.sizeof_int;
1367
0
            else
1368
0
                sz = 1;
1369
1370
0
            if (sz > 0) {
1371
0
                ValueFlow::Value value(sz);
1372
0
                value.setKnown();
1373
0
                setTokenValue(tok->next(), std::move(value), settings);
1374
0
            }
1375
0
        } else if (!tok2->type()) {
1376
0
            const ValueType& vt = ValueType::parseDecl(tok2, settings);
1377
0
            size_t sz = ValueFlow::getSizeOf(vt, settings);
1378
0
            const Token* brac = tok2->astParent();
1379
0
            while (Token::simpleMatch(brac, "[")) {
1380
0
                const Token* num = brac->astOperand2();
1381
0
                if (num && ((num->isNumber() && MathLib::isInt(num->str())) || num->tokType() == Token::eChar)) {
1382
0
                    try {
1383
0
                        const MathLib::biguint dim = MathLib::toBigUNumber(num->str());
1384
0
                        sz *= dim;
1385
0
                        brac = brac->astParent();
1386
0
                        continue;
1387
0
                    }
1388
0
                    catch (const std::exception& /*e*/) {
1389
                        // Bad integer literal
1390
0
                    }
1391
0
                }
1392
0
                sz = 0;
1393
0
                break;
1394
0
            }
1395
0
            if (sz > 0) {
1396
0
                ValueFlow::Value value(sz);
1397
0
                if (!tok2->isTemplateArg() && settings.platform.type != Platform::Type::Unspecified)
1398
0
                    value.setKnown();
1399
0
                setTokenValue(tok->next(), std::move(value), settings);
1400
0
            }
1401
0
        }
1402
        // skip over enum
1403
0
        tok = tok->linkAt(1);
1404
82.3k
    } else if (Token::Match(tok, "%name% [{(] [)}]") && (tok->isStandardType() ||
1405
2.21k
                                                         (tok->variable() && tok->variable()->nameToken() == tok &&
1406
2.21k
                                                          (tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))))) {
1407
0
        ValueFlow::Value value(0);
1408
0
        if (!tok->isTemplateArg())
1409
0
            value.setKnown();
1410
0
        setTokenValue(tok->next(), std::move(value), settings);
1411
82.3k
    } else if (Token::simpleMatch(tok, "= { } ;")) {
1412
0
        const Token* lhs = tok->astOperand1();
1413
0
        if (lhs && lhs->valueType() && (lhs->valueType()->isIntegral() || lhs->valueType()->pointer > 0)) {
1414
0
            ValueFlow::Value value(0);
1415
0
            value.setKnown();
1416
0
            setTokenValue(tok->next(), std::move(value), settings);
1417
0
        }
1418
0
    }
1419
91.8k
    return tok->next();
1420
91.8k
}
1421
1422
static void valueFlowNumber(TokenList &tokenlist, const Settings& settings)
1423
1.34k
{
1424
93.2k
    for (Token *tok = tokenlist.front(); tok;) {
1425
91.8k
        tok = valueFlowSetConstantValue(tok, settings, tokenlist.isCPP());
1426
91.8k
    }
1427
1428
1.34k
    if (tokenlist.isCPP()) {
1429
93.2k
        for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1430
91.8k
            if (tok->isName() && !tok->varId() && Token::Match(tok, "false|true")) {
1431
0
                ValueFlow::Value value(tok->str() == "true");
1432
0
                if (!tok->isTemplateArg())
1433
0
                    value.setKnown();
1434
0
                setTokenValue(tok, std::move(value), settings);
1435
91.8k
            } else if (Token::Match(tok, "[(,] NULL [,)]")) {
1436
                // NULL function parameters are not simplified in the
1437
                // normal tokenlist
1438
0
                ValueFlow::Value value(0);
1439
0
                if (!tok->isTemplateArg())
1440
0
                    value.setKnown();
1441
0
                setTokenValue(tok->next(), std::move(value), settings);
1442
0
            }
1443
91.8k
        }
1444
1.34k
    }
1445
1.34k
}
1446
1447
static void valueFlowString(TokenList &tokenlist, const Settings& settings)
1448
1.34k
{
1449
93.2k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1450
91.8k
        if (tok->tokType() == Token::eString) {
1451
0
            ValueFlow::Value strvalue;
1452
0
            strvalue.valueType = ValueFlow::Value::ValueType::TOK;
1453
0
            strvalue.tokvalue = tok;
1454
0
            strvalue.setKnown();
1455
0
            setTokenValue(tok, std::move(strvalue), settings);
1456
0
        }
1457
91.8k
    }
1458
1.34k
}
1459
1460
static void valueFlowArray(TokenList &tokenlist, const Settings &settings)
1461
1.34k
{
1462
1.34k
    std::map<nonneg int, const Token *> constantArrays;
1463
1464
93.2k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1465
91.8k
        if (tok->varId() > 0) {
1466
            // array
1467
19.5k
            const std::map<nonneg int, const Token *>::const_iterator it = constantArrays.find(tok->varId());
1468
19.5k
            if (it != constantArrays.end()) {
1469
0
                ValueFlow::Value value;
1470
0
                value.valueType = ValueFlow::Value::ValueType::TOK;
1471
0
                value.tokvalue = it->second;
1472
0
                value.setKnown();
1473
0
                setTokenValue(tok, std::move(value), settings);
1474
0
            }
1475
1476
            // const array decl
1477
19.5k
            else if (tok->variable() && tok->variable()->isArray() && tok->variable()->isConst() &&
1478
19.5k
                     tok->variable()->nameToken() == tok && Token::Match(tok, "%var% [ %num%| ] = {")) {
1479
0
                Token* rhstok = tok->next()->link()->tokAt(2);
1480
0
                constantArrays[tok->varId()] = rhstok;
1481
0
                tok = rhstok->link();
1482
0
            }
1483
1484
            // pointer = array
1485
19.5k
            else if (tok->variable() && tok->variable()->isArray() && Token::simpleMatch(tok->astParent(), "=") &&
1486
19.5k
                     astIsRHS(tok) && tok->astParent()->astOperand1() &&
1487
19.5k
                     tok->astParent()->astOperand1()->variable() &&
1488
19.5k
                     tok->astParent()->astOperand1()->variable()->isPointer()) {
1489
0
                ValueFlow::Value value;
1490
0
                value.valueType = ValueFlow::Value::ValueType::TOK;
1491
0
                value.tokvalue = tok;
1492
0
                value.setKnown();
1493
0
                setTokenValue(tok, std::move(value), settings);
1494
0
            }
1495
19.5k
            continue;
1496
19.5k
        }
1497
1498
72.3k
        if (Token::Match(tok, "const %type% %var% [ %num%| ] = {")) {
1499
0
            Token *vartok = tok->tokAt(2);
1500
0
            Token *rhstok = vartok->next()->link()->tokAt(2);
1501
0
            constantArrays[vartok->varId()] = rhstok;
1502
0
            tok = rhstok->link();
1503
0
            continue;
1504
0
        }
1505
1506
72.3k
        if (Token::Match(tok, "const char %var% [ %num%| ] = %str% ;")) {
1507
0
            Token *vartok = tok->tokAt(2);
1508
0
            Token *strtok = vartok->next()->link()->tokAt(2);
1509
0
            constantArrays[vartok->varId()] = strtok;
1510
0
            tok = strtok->next();
1511
0
            continue;
1512
0
        }
1513
72.3k
    }
1514
1.34k
}
1515
1516
static bool isNonZero(const Token *tok)
1517
0
{
1518
0
    return tok && (!tok->hasKnownIntValue() || tok->values().front().intvalue != 0);
1519
0
}
1520
1521
static const Token *getOtherOperand(const Token *tok)
1522
0
{
1523
0
    if (!tok)
1524
0
        return nullptr;
1525
0
    if (!tok->astParent())
1526
0
        return nullptr;
1527
0
    if (tok->astParent()->astOperand1() != tok)
1528
0
        return tok->astParent()->astOperand1();
1529
0
    if (tok->astParent()->astOperand2() != tok)
1530
0
        return tok->astParent()->astOperand2();
1531
0
    return nullptr;
1532
0
}
1533
1534
static void valueFlowArrayBool(TokenList &tokenlist, const Settings &settings)
1535
2.23k
{
1536
161k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1537
159k
        if (tok->hasKnownIntValue())
1538
29.1k
            continue;
1539
130k
        const Variable *var = nullptr;
1540
130k
        bool known = false;
1541
130k
        const std::list<ValueFlow::Value>::const_iterator val =
1542
130k
            std::find_if(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isTokValue));
1543
130k
        if (val == tok->values().end()) {
1544
130k
            var = tok->variable();
1545
130k
            known = true;
1546
130k
        } else {
1547
0
            var = val->tokvalue->variable();
1548
0
            known = val->isKnown();
1549
0
        }
1550
130k
        if (!var)
1551
97.0k
            continue;
1552
33.5k
        if (!var->isArray() || var->isArgument() || var->isStlType())
1553
33.5k
            continue;
1554
0
        if (isNonZero(getOtherOperand(tok)) && Token::Match(tok->astParent(), "%comp%"))
1555
0
            continue;
1556
        // TODO: Check for function argument
1557
0
        if ((astIsBool(tok->astParent()) && !Token::Match(tok->astParent(), "(|%name%")) ||
1558
0
            (tok->astParent() && Token::Match(tok->astParent()->previous(), "if|while|for ("))) {
1559
0
            ValueFlow::Value value{1};
1560
0
            if (known)
1561
0
                value.setKnown();
1562
0
            setTokenValue(tok, std::move(value), settings);
1563
0
        }
1564
0
    }
1565
2.23k
}
1566
1567
static void valueFlowArrayElement(TokenList& tokenlist, const Settings& settings)
1568
2.23k
{
1569
161k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
1570
159k
        if (tok->hasKnownIntValue())
1571
29.1k
            continue;
1572
130k
        const Token* indexTok = nullptr;
1573
130k
        const Token* arrayTok = nullptr;
1574
130k
        if (Token::simpleMatch(tok, "[") && tok->isBinaryOp()) {
1575
0
            indexTok = tok->astOperand2();
1576
0
            arrayTok = tok->astOperand1();
1577
130k
        } else if (Token::Match(tok->tokAt(-2), ". %name% (") && astIsContainer(tok->tokAt(-2)->astOperand1())) {
1578
0
            arrayTok = tok->tokAt(-2)->astOperand1();
1579
0
            const Library::Container* container = getLibraryContainer(arrayTok);
1580
0
            if (!container || container->stdAssociativeLike)
1581
0
                continue;
1582
0
            const Library::Container::Yield yield = container->getYield(tok->strAt(-1));
1583
0
            if (yield != Library::Container::Yield::AT_INDEX)
1584
0
                continue;
1585
0
            indexTok = tok->astOperand2();
1586
0
        }
1587
1588
130k
        if (!indexTok || !arrayTok)
1589
130k
            continue;
1590
1591
0
        for (const ValueFlow::Value& arrayValue : arrayTok->values()) {
1592
0
            if (!arrayValue.isTokValue())
1593
0
                continue;
1594
0
            if (arrayValue.isImpossible())
1595
0
                continue;
1596
0
            for (const ValueFlow::Value& indexValue : indexTok->values()) {
1597
0
                if (!indexValue.isIntValue())
1598
0
                    continue;
1599
0
                if (indexValue.isImpossible())
1600
0
                    continue;
1601
0
                if (!arrayValue.isKnown() && !indexValue.isKnown() && arrayValue.varId != 0 && indexValue.varId != 0 &&
1602
0
                    !(arrayValue.varId == indexValue.varId && arrayValue.varvalue == indexValue.varvalue))
1603
0
                    continue;
1604
1605
0
                ValueFlow::Value result(0);
1606
0
                result.condition = arrayValue.condition ? arrayValue.condition : indexValue.condition;
1607
0
                result.setInconclusive(arrayValue.isInconclusive() || indexValue.isInconclusive());
1608
0
                result.varId = (arrayValue.varId != 0) ? arrayValue.varId : indexValue.varId;
1609
0
                result.varvalue = (result.varId == arrayValue.varId) ? arrayValue.intvalue : indexValue.intvalue;
1610
0
                if (arrayValue.valueKind == indexValue.valueKind)
1611
0
                    result.valueKind = arrayValue.valueKind;
1612
1613
0
                result.errorPath.insert(result.errorPath.end(), arrayValue.errorPath.cbegin(), arrayValue.errorPath.cend());
1614
0
                result.errorPath.insert(result.errorPath.end(), indexValue.errorPath.cbegin(), indexValue.errorPath.cend());
1615
1616
0
                const MathLib::bigint index = indexValue.intvalue;
1617
1618
0
                if (arrayValue.tokvalue->tokType() == Token::eString) {
1619
0
                    const std::string s = arrayValue.tokvalue->strValue();
1620
0
                    if (index == s.size()) {
1621
0
                        result.intvalue = 0;
1622
0
                        setTokenValue(tok, result, settings);
1623
0
                    } else if (index >= 0 && index < s.size()) {
1624
0
                        result.intvalue = s[index];
1625
0
                        setTokenValue(tok, std::move(result), settings);
1626
0
                    }
1627
0
                } else if (Token::simpleMatch(arrayValue.tokvalue, "{")) {
1628
0
                    std::vector<const Token*> args = getArguments(arrayValue.tokvalue);
1629
0
                    if (index < 0 || index >= args.size())
1630
0
                        continue;
1631
0
                    const Token* arg = args[index];
1632
0
                    if (!arg->hasKnownIntValue())
1633
0
                        continue;
1634
0
                    const ValueFlow::Value& v = arg->values().front();
1635
0
                    result.intvalue = v.intvalue;
1636
0
                    result.errorPath.insert(result.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
1637
0
                    setTokenValue(tok, std::move(result), settings);
1638
0
                }
1639
0
            }
1640
0
        }
1641
0
    }
1642
2.23k
}
1643
1644
static void valueFlowPointerAlias(TokenList &tokenlist, const Settings& settings)
1645
1.34k
{
1646
93.2k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1647
        // not address of
1648
91.8k
        if (!tok->isUnaryOp("&"))
1649
91.8k
            continue;
1650
1651
        // parent should be a '='
1652
0
        if (!Token::simpleMatch(tok->astParent(), "="))
1653
0
            continue;
1654
1655
        // child should be some buffer or variable
1656
0
        const Token *vartok = tok->astOperand1();
1657
0
        while (vartok) {
1658
0
            if (vartok->str() == "[")
1659
0
                vartok = vartok->astOperand1();
1660
0
            else if (vartok->str() == "." || vartok->str() == "::")
1661
0
                vartok = vartok->astOperand2();
1662
0
            else
1663
0
                break;
1664
0
        }
1665
0
        if (!(vartok && vartok->variable() && !vartok->variable()->isPointer()))
1666
0
            continue;
1667
1668
0
        ValueFlow::Value value;
1669
0
        value.valueType = ValueFlow::Value::ValueType::TOK;
1670
0
        value.tokvalue = tok;
1671
0
        setTokenValue(tok, std::move(value), settings);
1672
0
    }
1673
1.34k
}
1674
1675
static void valueFlowBitAnd(TokenList &tokenlist, const Settings& settings)
1676
1.34k
{
1677
93.2k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1678
91.8k
        if (tok->str() != "&")
1679
91.6k
            continue;
1680
1681
270
        if (tok->hasKnownValue())
1682
10
            continue;
1683
1684
260
        if (!tok->astOperand1() || !tok->astOperand2())
1685
1
            continue;
1686
1687
259
        MathLib::bigint number;
1688
259
        if (MathLib::isInt(tok->astOperand1()->str()))
1689
32
            number = MathLib::toBigNumber(tok->astOperand1()->str());
1690
227
        else if (MathLib::isInt(tok->astOperand2()->str()))
1691
27
            number = MathLib::toBigNumber(tok->astOperand2()->str());
1692
200
        else
1693
200
            continue;
1694
1695
59
        int bit = 0;
1696
797
        while (bit <= (MathLib::bigint_bits - 2) && ((((MathLib::bigint)1) << bit) < number))
1697
738
            ++bit;
1698
1699
59
        if ((((MathLib::bigint)1) << bit) == number) {
1700
4
            setTokenValue(tok, ValueFlow::Value(0), settings);
1701
4
            setTokenValue(tok, ValueFlow::Value(number), settings);
1702
4
        }
1703
59
    }
1704
1.34k
}
1705
1706
static void valueFlowSameExpressions(TokenList &tokenlist, const Settings& settings)
1707
1.34k
{
1708
93.2k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
1709
91.8k
        if (tok->hasKnownIntValue())
1710
16.7k
            continue;
1711
1712
75.1k
        if (!tok->astOperand1() || !tok->astOperand2())
1713
68.1k
            continue;
1714
1715
6.96k
        if (tok->astOperand1()->isLiteral() || tok->astOperand2()->isLiteral())
1716
842
            continue;
1717
1718
6.12k
        if (!astIsIntegral(tok->astOperand1(), false) && !astIsIntegral(tok->astOperand2(), false))
1719
366
            continue;
1720
1721
5.75k
        ValueFlow::Value val;
1722
1723
5.75k
        if (Token::Match(tok, "==|>=|<=|/")) {
1724
712
            val = ValueFlow::Value(1);
1725
712
            val.setKnown();
1726
712
        }
1727
1728
5.75k
        if (Token::Match(tok, "!=|>|<|%|-")) {
1729
1.20k
            val = ValueFlow::Value(0);
1730
1.20k
            val.setKnown();
1731
1.20k
        }
1732
1733
5.75k
        if (!val.isKnown())
1734
3.84k
            continue;
1735
1736
1.91k
        if (isSameExpression(tokenlist.isCPP(), false, tok->astOperand1(), tok->astOperand2(), settings.library, true, true, &val.errorPath)) {
1737
301
            setTokenValue(tok, std::move(val), settings);
1738
301
        }
1739
1.91k
    }
1740
1.34k
}
1741
1742
static bool getExpressionRange(const Token *expr, MathLib::bigint *minvalue, MathLib::bigint *maxvalue)
1743
0
{
1744
0
    if (expr->hasKnownIntValue()) {
1745
0
        if (minvalue)
1746
0
            *minvalue = expr->values().front().intvalue;
1747
0
        if (maxvalue)
1748
0
            *maxvalue = expr->values().front().intvalue;
1749
0
        return true;
1750
0
    }
1751
1752
0
    if (expr->str() == "&" && expr->astOperand1() && expr->astOperand2()) {
1753
0
        MathLib::bigint vals[4];
1754
0
        const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]);
1755
0
        const bool rhsHasKnownRange = getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]);
1756
0
        if (!lhsHasKnownRange && !rhsHasKnownRange)
1757
0
            return false;
1758
0
        if (!lhsHasKnownRange || !rhsHasKnownRange) {
1759
0
            if (minvalue)
1760
0
                *minvalue = lhsHasKnownRange ? vals[0] : vals[2];
1761
0
            if (maxvalue)
1762
0
                *maxvalue = lhsHasKnownRange ? vals[1] : vals[3];
1763
0
        } else {
1764
0
            if (minvalue)
1765
0
                *minvalue = vals[0] & vals[2];
1766
0
            if (maxvalue)
1767
0
                *maxvalue = vals[1] & vals[3];
1768
0
        }
1769
0
        return true;
1770
0
    }
1771
1772
0
    if (expr->str() == "%" && expr->astOperand1() && expr->astOperand2()) {
1773
0
        MathLib::bigint vals[4];
1774
0
        if (!getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]))
1775
0
            return false;
1776
0
        if (vals[2] <= 0)
1777
0
            return false;
1778
0
        const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]);
1779
0
        if (lhsHasKnownRange && vals[0] < 0)
1780
0
            return false;
1781
        // If lhs has unknown value, it must be unsigned
1782
0
        if (!lhsHasKnownRange && (!expr->astOperand1()->valueType() || expr->astOperand1()->valueType()->sign != ValueType::Sign::UNSIGNED))
1783
0
            return false;
1784
0
        if (minvalue)
1785
0
            *minvalue = 0;
1786
0
        if (maxvalue)
1787
0
            *maxvalue = vals[3] - 1;
1788
0
        return true;
1789
0
    }
1790
1791
0
    return false;
1792
0
}
1793
1794
static void valueFlowRightShift(TokenList &tokenList, const Settings& settings)
1795
2.23k
{
1796
161k
    for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
1797
159k
        if (tok->str() != ">>")
1798
159k
            continue;
1799
1800
0
        if (tok->hasKnownValue())
1801
0
            continue;
1802
1803
0
        if (!tok->astOperand1() || !tok->astOperand2())
1804
0
            continue;
1805
1806
0
        if (!tok->astOperand2()->hasKnownValue())
1807
0
            continue;
1808
1809
0
        const MathLib::bigint rhsvalue = tok->astOperand2()->values().front().intvalue;
1810
0
        if (rhsvalue < 0)
1811
0
            continue;
1812
1813
0
        if (!tok->astOperand1()->valueType() || !tok->astOperand1()->valueType()->isIntegral())
1814
0
            continue;
1815
1816
0
        if (!tok->astOperand2()->valueType() || !tok->astOperand2()->valueType()->isIntegral())
1817
0
            continue;
1818
1819
0
        MathLib::bigint lhsmax=0;
1820
0
        if (!getExpressionRange(tok->astOperand1(), nullptr, &lhsmax))
1821
0
            continue;
1822
0
        if (lhsmax < 0)
1823
0
            continue;
1824
0
        int lhsbits;
1825
0
        if ((tok->astOperand1()->valueType()->type == ValueType::Type::CHAR) ||
1826
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::SHORT) ||
1827
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::WCHAR_T) ||
1828
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::BOOL) ||
1829
0
            (tok->astOperand1()->valueType()->type == ValueType::Type::INT))
1830
0
            lhsbits = settings.platform.int_bit;
1831
0
        else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONG)
1832
0
            lhsbits = settings.platform.long_bit;
1833
0
        else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONGLONG)
1834
0
            lhsbits = settings.platform.long_long_bit;
1835
0
        else
1836
0
            continue;
1837
0
        if (rhsvalue >= lhsbits || rhsvalue >= MathLib::bigint_bits || (1ULL << rhsvalue) <= lhsmax)
1838
0
            continue;
1839
1840
0
        ValueFlow::Value val(0);
1841
0
        val.setKnown();
1842
0
        setTokenValue(tok, std::move(val), settings);
1843
0
    }
1844
2.23k
}
1845
1846
static std::vector<MathLib::bigint> minUnsignedValue(const Token* tok, int depth = 8)
1847
0
{
1848
0
    std::vector<MathLib::bigint> result;
1849
0
    if (!tok)
1850
0
        return result;
1851
0
    if (depth < 0)
1852
0
        return result;
1853
0
    if (tok->hasKnownIntValue()) {
1854
0
        result = {tok->values().front().intvalue};
1855
0
    } else if (!Token::Match(tok, "-|%|&|^") && tok->isConstOp() && tok->astOperand1() && tok->astOperand2()) {
1856
0
        std::vector<MathLib::bigint> op1 = minUnsignedValue(tok->astOperand1(), depth - 1);
1857
0
        std::vector<MathLib::bigint> op2 = minUnsignedValue(tok->astOperand2(), depth - 1);
1858
0
        if (!op1.empty() && !op2.empty()) {
1859
0
            result = calculate<std::vector<MathLib::bigint>>(tok->str(), op1.front(), op2.front());
1860
0
        }
1861
0
    }
1862
0
    if (result.empty() && astIsUnsigned(tok))
1863
0
        result = {0};
1864
0
    return result;
1865
0
}
1866
1867
static bool isConvertedToIntegral(const Token* tok, const Settings& settings)
1868
0
{
1869
0
    if (!tok)
1870
0
        return false;
1871
0
    std::vector<ValueType> parentTypes = getParentValueTypes(tok, &settings);
1872
0
    if (parentTypes.empty())
1873
0
        return false;
1874
0
    const ValueType& vt = parentTypes.front();
1875
0
    return vt.type != ValueType::UNKNOWN_INT && vt.isIntegral();
1876
0
}
1877
1878
static bool isSameToken(const Token* tok1, const Token* tok2)
1879
0
{
1880
0
    if (!tok1 || !tok2)
1881
0
        return false;
1882
0
    if (tok1->exprId() != 0 && tok1->exprId() == tok2->exprId())
1883
0
        return true;
1884
0
    if (tok1->hasKnownIntValue() && tok2->hasKnownIntValue())
1885
0
        return tok1->values().front().intvalue == tok2->values().front().intvalue;
1886
0
    return false;
1887
0
}
1888
1889
static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& settings)
1890
2.23k
{
1891
161k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
1892
159k
        if (tok->hasKnownIntValue())
1893
29.1k
            continue;
1894
130k
        if (Token::Match(tok, "true|false"))
1895
0
            continue;
1896
130k
        if (astIsBool(tok) || Token::Match(tok, "%comp%")) {
1897
3.49k
            ValueFlow::Value lower{-1};
1898
3.49k
            lower.bound = ValueFlow::Value::Bound::Upper;
1899
3.49k
            lower.setImpossible();
1900
3.49k
            setTokenValue(tok, std::move(lower), settings);
1901
1902
3.49k
            ValueFlow::Value upper{2};
1903
3.49k
            upper.bound = ValueFlow::Value::Bound::Lower;
1904
3.49k
            upper.setImpossible();
1905
3.49k
            setTokenValue(tok, std::move(upper), settings);
1906
127k
        } else if (astIsUnsigned(tok) && !astIsPointer(tok)) {
1907
0
            std::vector<MathLib::bigint> minvalue = minUnsignedValue(tok);
1908
0
            if (minvalue.empty())
1909
0
                continue;
1910
0
            ValueFlow::Value value{std::max<MathLib::bigint>(0, minvalue.front()) - 1};
1911
0
            value.bound = ValueFlow::Value::Bound::Upper;
1912
0
            value.setImpossible();
1913
0
            setTokenValue(tok, std::move(value), settings);
1914
0
        }
1915
130k
        if (Token::simpleMatch(tok, "?") && Token::Match(tok->astOperand1(), "<|<=|>|>=")) {
1916
0
            const Token* condTok = tok->astOperand1();
1917
0
            const Token* branchesTok = tok->astOperand2();
1918
1919
0
            auto tokens = makeArray(condTok->astOperand1(), condTok->astOperand2());
1920
0
            auto branches = makeArray(branchesTok->astOperand1(), branchesTok->astOperand2());
1921
0
            bool flipped = false;
1922
0
            if (std::equal(tokens.cbegin(), tokens.cend(), branches.crbegin(), &isSameToken))
1923
0
                flipped = true;
1924
0
            else if (!std::equal(tokens.cbegin(), tokens.cend(), branches.cbegin(), &isSameToken))
1925
0
                continue;
1926
0
            const bool isMin = Token::Match(condTok, "<|<=") ^ flipped;
1927
0
            std::vector<ValueFlow::Value> values;
1928
0
            for (const Token* tok2 : tokens) {
1929
0
                if (tok2->hasKnownIntValue()) {
1930
0
                    values.emplace_back(tok2->values().front());
1931
0
                } else {
1932
0
                    ValueFlow::Value symValue{};
1933
0
                    symValue.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
1934
0
                    symValue.tokvalue = tok2;
1935
0
                    values.push_back(symValue);
1936
0
                    std::copy_if(tok2->values().cbegin(),
1937
0
                                 tok2->values().cend(),
1938
0
                                 std::back_inserter(values),
1939
0
                                 [](const ValueFlow::Value& v) {
1940
0
                        if (!v.isKnown())
1941
0
                            return false;
1942
0
                        return v.isSymbolicValue();
1943
0
                    });
1944
0
                }
1945
0
            }
1946
0
            for (ValueFlow::Value& value : values) {
1947
0
                value.setImpossible();
1948
0
                if (isMin) {
1949
0
                    value.intvalue++;
1950
0
                    value.bound = ValueFlow::Value::Bound::Lower;
1951
0
                } else {
1952
0
                    value.intvalue--;
1953
0
                    value.bound = ValueFlow::Value::Bound::Upper;
1954
0
                }
1955
0
                setTokenValue(tok, std::move(value), settings);
1956
0
            }
1957
1958
130k
        } else if (Token::simpleMatch(tok, "%") && tok->astOperand2() && tok->astOperand2()->hasKnownIntValue()) {
1959
85
            ValueFlow::Value value{tok->astOperand2()->values().front()};
1960
85
            value.bound = ValueFlow::Value::Bound::Lower;
1961
85
            value.setImpossible();
1962
85
            setTokenValue(tok, std::move(value), settings);
1963
130k
        } else if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) {
1964
0
            ValueFlow::Value value{-1};
1965
0
            value.bound = ValueFlow::Value::Bound::Upper;
1966
0
            value.setImpossible();
1967
0
            setTokenValue(tok->next(), std::move(value), settings);
1968
130k
        } else if (Token::Match(tok, ". data|c_str (") && astIsContainerOwned(tok->astOperand1())) {
1969
0
            const Library::Container* container = getLibraryContainer(tok->astOperand1());
1970
0
            if (!container)
1971
0
                continue;
1972
0
            if (!container->stdStringLike)
1973
0
                continue;
1974
0
            if (container->view)
1975
0
                continue;
1976
0
            ValueFlow::Value value{0};
1977
0
            value.setImpossible();
1978
0
            setTokenValue(tok->tokAt(2), std::move(value), settings);
1979
130k
        } else if (Token::Match(tok, "make_shared|make_unique <") && Token::simpleMatch(tok->linkAt(1), "> (")) {
1980
0
            ValueFlow::Value value{0};
1981
0
            value.setImpossible();
1982
0
            setTokenValue(tok->linkAt(1)->next(), std::move(value), settings);
1983
130k
        } else if ((tokenList.isCPP() && Token::simpleMatch(tok, "this")) || tok->isUnaryOp("&")) {
1984
0
            ValueFlow::Value value{0};
1985
0
            value.setImpossible();
1986
0
            setTokenValue(tok, std::move(value), settings);
1987
130k
        } else if (tok->isIncompleteVar() && tok->astParent() && tok->astParent()->isUnaryOp("-") &&
1988
130k
                   isConvertedToIntegral(tok->astParent(), settings)) {
1989
0
            ValueFlow::Value value{0};
1990
0
            value.setImpossible();
1991
0
            setTokenValue(tok, std::move(value), settings);
1992
0
        }
1993
130k
    }
1994
2.23k
}
1995
1996
static void valueFlowEnumValue(SymbolDatabase & symboldatabase, const Settings & settings)
1997
2.68k
{
1998
10.0k
    for (Scope & scope : symboldatabase.scopeList) {
1999
10.0k
        if (scope.type != Scope::eEnum)
2000
10.0k
            continue;
2001
0
        MathLib::bigint value = 0;
2002
0
        bool prev_enum_is_known = true;
2003
2004
0
        for (Enumerator & enumerator : scope.enumeratorList) {
2005
0
            if (enumerator.start) {
2006
0
                Token* rhs = const_cast<Token*>(enumerator.start->previous()->astOperand2());
2007
0
                ValueFlow::valueFlowConstantFoldAST(rhs, settings);
2008
0
                if (rhs && rhs->hasKnownIntValue()) {
2009
0
                    enumerator.value = rhs->values().front().intvalue;
2010
0
                    enumerator.value_known = true;
2011
0
                    value = enumerator.value + 1;
2012
0
                    prev_enum_is_known = true;
2013
0
                } else
2014
0
                    prev_enum_is_known = false;
2015
0
            } else if (prev_enum_is_known) {
2016
0
                enumerator.value = value++;
2017
0
                enumerator.value_known = true;
2018
0
            }
2019
0
        }
2020
0
    }
2021
2.68k
}
2022
2023
static void valueFlowGlobalConstVar(TokenList& tokenList, const Settings &settings)
2024
1.34k
{
2025
    // Get variable values...
2026
1.34k
    std::map<const Variable*, ValueFlow::Value> vars;
2027
93.2k
    for (const Token* tok = tokenList.front(); tok; tok = tok->next()) {
2028
91.8k
        if (!tok->variable())
2029
72.3k
            continue;
2030
        // Initialization...
2031
19.5k
        if (tok == tok->variable()->nameToken() &&
2032
19.5k
            !tok->variable()->isVolatile() &&
2033
19.5k
            !tok->variable()->isArgument() &&
2034
19.5k
            tok->variable()->isConst() &&
2035
19.5k
            tok->valueType() &&
2036
19.5k
            tok->valueType()->isIntegral() &&
2037
19.5k
            tok->valueType()->pointer == 0 &&
2038
19.5k
            tok->valueType()->constness == 1 &&
2039
19.5k
            Token::Match(tok, "%name% =") &&
2040
19.5k
            tok->next()->astOperand2() &&
2041
19.5k
            tok->next()->astOperand2()->hasKnownIntValue()) {
2042
0
            vars[tok->variable()] = tok->next()->astOperand2()->values().front();
2043
0
        }
2044
19.5k
    }
2045
2046
    // Set values..
2047
93.2k
    for (Token* tok = tokenList.front(); tok; tok = tok->next()) {
2048
91.8k
        if (!tok->variable())
2049
72.3k
            continue;
2050
19.5k
        const std::map<const Variable*, ValueFlow::Value>::const_iterator var = vars.find(tok->variable());
2051
19.5k
        if (var == vars.end())
2052
19.5k
            continue;
2053
0
        setTokenValue(tok, var->second, settings);
2054
0
    }
2055
1.34k
}
2056
2057
static void valueFlowGlobalStaticVar(TokenList &tokenList, const Settings &settings)
2058
1.34k
{
2059
    // Get variable values...
2060
1.34k
    std::map<const Variable *, ValueFlow::Value> vars;
2061
93.2k
    for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
2062
91.8k
        if (!tok->variable())
2063
72.3k
            continue;
2064
        // Initialization...
2065
19.5k
        if (tok == tok->variable()->nameToken() &&
2066
19.5k
            tok->variable()->isStatic() &&
2067
19.5k
            !tok->variable()->isConst() &&
2068
19.5k
            tok->valueType() &&
2069
19.5k
            tok->valueType()->isIntegral() &&
2070
19.5k
            tok->valueType()->pointer == 0 &&
2071
19.5k
            tok->valueType()->constness == 0 &&
2072
19.5k
            Token::Match(tok, "%name% =") &&
2073
19.5k
            tok->next()->astOperand2() &&
2074
19.5k
            tok->next()->astOperand2()->hasKnownIntValue()) {
2075
0
            vars[tok->variable()] = tok->next()->astOperand2()->values().front();
2076
19.5k
        } else {
2077
            // If variable is written anywhere in TU then remove it from vars
2078
19.5k
            if (!tok->astParent())
2079
6.72k
                continue;
2080
12.7k
            if (Token::Match(tok->astParent(), "++|--|&") && !tok->astParent()->astOperand2())
2081
1.32k
                vars.erase(tok->variable());
2082
11.4k
            else if (tok->astParent()->isAssignmentOp()) {
2083
8.68k
                if (tok == tok->astParent()->astOperand1())
2084
8.13k
                    vars.erase(tok->variable());
2085
555
                else if (tokenList.isCPP() && Token::Match(tok->astParent()->tokAt(-2), "& %name% ="))
2086
0
                    vars.erase(tok->variable());
2087
8.68k
            } else if (isLikelyStreamRead(tokenList.isCPP(), tok->astParent())) {
2088
0
                vars.erase(tok->variable());
2089
2.77k
            } else if (Token::Match(tok->astParent(), "[(,]"))
2090
4
                vars.erase(tok->variable());
2091
12.7k
        }
2092
19.5k
    }
2093
2094
    // Set values..
2095
93.2k
    for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
2096
91.8k
        if (!tok->variable())
2097
72.3k
            continue;
2098
19.5k
        const std::map<const Variable *, ValueFlow::Value>::const_iterator var = vars.find(tok->variable());
2099
19.5k
        if (var == vars.end())
2100
19.5k
            continue;
2101
0
        setTokenValue(tok, var->second, settings);
2102
0
    }
2103
1.34k
}
2104
2105
static ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings& settings);
2106
static ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings& settings);
2107
2108
static Analyzer::Result valueFlowForward(Token* startToken,
2109
                                         const Token* endToken,
2110
                                         const Token* exprTok,
2111
                                         ValueFlow::Value value,
2112
                                         const TokenList& tokenlist,
2113
                                         ErrorLogger* errorLogger,
2114
                                         const Settings& settings,
2115
                                         SourceLocation loc = SourceLocation::current())
2116
5.91k
{
2117
5.91k
    if (settings.debugnormal)
2118
0
        setSourceLocation(value, loc, startToken);
2119
5.91k
    return valueFlowGenericForward(startToken,
2120
5.91k
                                   endToken,
2121
5.91k
                                   makeAnalyzer(exprTok, std::move(value), tokenlist, settings),
2122
5.91k
                                   tokenlist,
2123
5.91k
                                   errorLogger,
2124
5.91k
                                   settings);
2125
5.91k
}
2126
2127
static Analyzer::Result valueFlowForward(Token* startToken,
2128
                                         const Token* endToken,
2129
                                         const Token* exprTok,
2130
                                         std::list<ValueFlow::Value> values,
2131
                                         const TokenList& tokenlist,
2132
                                         ErrorLogger* errorLogger,
2133
                                         const Settings& settings,
2134
                                         SourceLocation loc = SourceLocation::current())
2135
3.90k
{
2136
3.90k
    Analyzer::Result result{};
2137
5.87k
    for (ValueFlow::Value& v : values) {
2138
5.87k
        result.update(valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, errorLogger, settings, loc));
2139
5.87k
    }
2140
3.90k
    return result;
2141
3.90k
}
2142
2143
template<class ValueOrValues>
2144
static Analyzer::Result valueFlowForward(Token* startToken,
2145
                                         const Token* exprTok,
2146
                                         ValueOrValues v,
2147
                                         TokenList& tokenlist,
2148
                                         ErrorLogger* errorLogger,
2149
                                         const Settings& settings,
2150
                                         SourceLocation loc = SourceLocation::current())
2151
0
{
2152
0
    const Token* endToken = nullptr;
2153
0
    const Function* f = Scope::nestedInFunction(startToken->scope());
2154
0
    if (f && f->functionScope)
2155
0
        endToken = f->functionScope->bodyEnd;
2156
0
    return valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, errorLogger, settings, loc);
2157
0
}
2158
2159
static Analyzer::Result valueFlowForwardRecursive(Token* top,
2160
                                                  const Token* exprTok,
2161
                                                  std::list<ValueFlow::Value> values,
2162
                                                  const TokenList& tokenlist,
2163
                                                  ErrorLogger* errorLogger,
2164
                                                  const Settings& settings,
2165
                                                  SourceLocation loc = SourceLocation::current())
2166
0
{
2167
0
    Analyzer::Result result{};
2168
0
    for (ValueFlow::Value& v : values) {
2169
0
        if (settings.debugnormal)
2170
0
            setSourceLocation(v, loc, top);
2171
0
        result.update(
2172
0
            valueFlowGenericForward(top, makeAnalyzer(exprTok, std::move(v), tokenlist, settings), tokenlist, errorLogger, settings));
2173
0
    }
2174
0
    return result;
2175
0
}
2176
2177
static void valueFlowReverse(Token* tok,
2178
                             const Token* const endToken,
2179
                             const Token* const varToken,
2180
                             std::list<ValueFlow::Value> values,
2181
                             const TokenList& tokenlist,
2182
                             ErrorLogger* errorLogger,
2183
                             const Settings& settings,
2184
                             SourceLocation loc = SourceLocation::current())
2185
1.42k
{
2186
2.01k
    for (ValueFlow::Value& v : values) {
2187
2.01k
        if (settings.debugnormal)
2188
0
            setSourceLocation(v, loc, tok);
2189
2.01k
        valueFlowGenericReverse(tok, endToken, makeReverseAnalyzer(varToken, std::move(v), tokenlist, settings), tokenlist, errorLogger, settings);
2190
2.01k
    }
2191
1.42k
}
2192
2193
// Deprecated
2194
static void valueFlowReverse(const TokenList& tokenlist,
2195
                             Token* tok,
2196
                             const Token* const varToken,
2197
                             ValueFlow::Value val,
2198
                             const ValueFlow::Value& val2,
2199
                             ErrorLogger* errorLogger,
2200
                             const Settings& settings,
2201
                             SourceLocation loc = SourceLocation::current())
2202
0
{
2203
0
    std::list<ValueFlow::Value> values = {std::move(val)};
2204
0
    if (val2.varId != 0)
2205
0
        values.push_back(val2);
2206
0
    valueFlowReverse(tok, nullptr, varToken, std::move(values), tokenlist, errorLogger, settings, loc);
2207
0
}
2208
2209
static bool isConditionKnown(const Token* tok, bool then)
2210
5.50k
{
2211
5.50k
    const char* op = "||";
2212
5.50k
    if (then)
2213
3.04k
        op = "&&";
2214
5.50k
    const Token* parent = tok->astParent();
2215
5.50k
    while (parent && (parent->str() == op || parent->str() == "!" || parent->isCast()))
2216
0
        parent = parent->astParent();
2217
5.50k
    const Token* top = tok->astTop();
2218
5.50k
    if (top && Token::Match(top->previous(), "if|while|for ("))
2219
5.50k
        return parent == top || Token::simpleMatch(parent, ";");
2220
0
    return parent && parent->str() != op;
2221
5.50k
}
2222
2223
static const std::string& invertAssign(const std::string& assign)
2224
10
{
2225
10
    static std::unordered_map<std::string, std::string> lookup = {{"=", "="},
2226
10
        {"+=", "-="},
2227
10
        {"-=", "+="},
2228
10
        {"*=", "/="},
2229
10
        {"/=", "*="},
2230
10
        {"<<=", ">>="},
2231
10
        {">>=", "<<="},
2232
10
        {"^=", "^="}};
2233
10
    auto it = lookup.find(assign);
2234
10
    if (it == lookup.end()) {
2235
0
        return emptyString;
2236
0
    }
2237
10
    return it->second;
2238
10
}
2239
2240
0
static std::string removeAssign(const std::string& assign) {
2241
0
    return std::string{assign.cbegin(), assign.cend() - 1};
2242
0
}
2243
2244
template<class T, class U>
2245
static T calculateAssign(const std::string& assign, const T& x, const U& y, bool* error = nullptr)
2246
131
{
2247
131
    if (assign.empty() || assign.back() != '=') {
2248
0
        if (error)
2249
0
            *error = true;
2250
0
        return T{};
2251
0
    }
2252
131
    if (assign == "=")
2253
131
        return y;
2254
0
    return calculate<T, T>(removeAssign(assign), x, y, error);
2255
131
}
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
2246
131
{
2247
131
    if (assign.empty() || assign.back() != '=') {
2248
0
        if (error)
2249
0
            *error = true;
2250
0
        return T{};
2251
0
    }
2252
131
    if (assign == "=")
2253
131
        return y;
2254
0
    return calculate<T, T>(removeAssign(assign), x, y, error);
2255
131
}
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*)
2256
2257
template<class T, class U>
2258
static void assignValueIfMutable(T& x, const U& y)
2259
18
{
2260
18
    x = y;
2261
18
}
valueflow.cpp:void assignValueIfMutable<long long, long long>(long long&, long long const&)
Line
Count
Source
2259
18
{
2260
18
    x = y;
2261
18
}
Unexecuted instantiation: valueflow.cpp:void assignValueIfMutable<double, double>(double&, double const&)
2262
2263
template<class T, class U>
2264
static void assignValueIfMutable(const T& /*unused*/, const U& /*unused*/)
2265
113
{}
valueflow.cpp:void assignValueIfMutable<long long, long long>(long long const&, long long const&)
Line
Count
Source
2265
113
{}
Unexecuted instantiation: valueflow.cpp:void assignValueIfMutable<double, double>(double const&, double const&)
2266
2267
template<class Value, REQUIRES("Value must ValueFlow::Value", std::is_convertible<Value&, const ValueFlow::Value&> )>
2268
static bool evalAssignment(Value& lhsValue, const std::string& assign, const ValueFlow::Value& rhsValue)
2269
149
{
2270
149
    bool error = false;
2271
149
    if (lhsValue.isSymbolicValue() && rhsValue.isIntValue()) {
2272
18
        if (assign != "+=" && assign != "-=")
2273
18
            return false;
2274
0
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2275
131
    } else if (lhsValue.isIntValue() && rhsValue.isIntValue()) {
2276
131
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2277
131
    } else if (lhsValue.isFloatValue() && rhsValue.isIntValue()) {
2278
0
        assignValueIfMutable(lhsValue.floatValue,
2279
0
                             calculateAssign(assign, lhsValue.floatValue, rhsValue.intvalue, &error));
2280
0
    } else {
2281
0
        return false;
2282
0
    }
2283
131
    return !error;
2284
149
}
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
2269
131
{
2270
131
    bool error = false;
2271
131
    if (lhsValue.isSymbolicValue() && rhsValue.isIntValue()) {
2272
18
        if (assign != "+=" && assign != "-=")
2273
18
            return false;
2274
0
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2275
113
    } else if (lhsValue.isIntValue() && rhsValue.isIntValue()) {
2276
113
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2277
113
    } else if (lhsValue.isFloatValue() && rhsValue.isIntValue()) {
2278
0
        assignValueIfMutable(lhsValue.floatValue,
2279
0
                             calculateAssign(assign, lhsValue.floatValue, rhsValue.intvalue, &error));
2280
0
    } else {
2281
0
        return false;
2282
0
    }
2283
113
    return !error;
2284
131
}
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
2269
18
{
2270
18
    bool error = false;
2271
18
    if (lhsValue.isSymbolicValue() && rhsValue.isIntValue()) {
2272
0
        if (assign != "+=" && assign != "-=")
2273
0
            return false;
2274
0
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2275
18
    } else if (lhsValue.isIntValue() && rhsValue.isIntValue()) {
2276
18
        assignValueIfMutable(lhsValue.intvalue, calculateAssign(assign, lhsValue.intvalue, rhsValue.intvalue, &error));
2277
18
    } else if (lhsValue.isFloatValue() && rhsValue.isIntValue()) {
2278
0
        assignValueIfMutable(lhsValue.floatValue,
2279
0
                             calculateAssign(assign, lhsValue.floatValue, rhsValue.intvalue, &error));
2280
0
    } else {
2281
0
        return false;
2282
0
    }
2283
18
    return !error;
2284
18
}
2285
2286
static ValueFlow::Value::MoveKind isMoveOrForward(const Token* tok)
2287
0
{
2288
0
    if (!tok)
2289
0
        return ValueFlow::Value::MoveKind::NonMovedVariable;
2290
0
    const Token* parent = tok->astParent();
2291
0
    if (!Token::simpleMatch(parent, "("))
2292
0
        return ValueFlow::Value::MoveKind::NonMovedVariable;
2293
0
    const Token* ftok = parent->astOperand1();
2294
0
    if (!ftok)
2295
0
        return ValueFlow::Value::MoveKind::NonMovedVariable;
2296
0
    if (Token::simpleMatch(ftok->astOperand1(), "std :: move"))
2297
0
        return ValueFlow::Value::MoveKind::MovedVariable;
2298
0
    if (Token::simpleMatch(ftok->astOperand1(), "std :: forward"))
2299
0
        return ValueFlow::Value::MoveKind::ForwardedVariable;
2300
    // TODO: Check for cast
2301
0
    return ValueFlow::Value::MoveKind::NonMovedVariable;
2302
0
}
2303
2304
template<class T>
2305
struct SingleRange {
2306
    T* x;
2307
0
    T* begin() const {
2308
0
        return x;
2309
0
    }
2310
0
    T* end() const {
2311
0
        return x+1;
2312
0
    }
2313
};
2314
2315
template<class T>
2316
static SingleRange<T> MakeSingleRange(T& x)
2317
36.8k
{
2318
36.8k
    return {&x};
2319
36.8k
}
2320
2321
class SelectValueFromVarIdMapRange {
2322
    using M = std::unordered_map<nonneg int, ValueFlow::Value>;
2323
2324
    struct Iterator {
2325
        using iterator_category = std::forward_iterator_tag;
2326
        using value_type = const ValueFlow::Value;
2327
        using pointer = value_type *;
2328
        using reference = value_type &;
2329
        using difference_type = std::ptrdiff_t;
2330
2331
        explicit Iterator(const M::const_iterator & it)
2332
0
            : mIt(it) {}
2333
2334
0
        reference operator*() const {
2335
0
            return mIt->second;
2336
0
        }
2337
2338
0
        pointer operator->() const {
2339
0
            return &mIt->second;
2340
0
        }
2341
2342
0
        Iterator &operator++() {
2343
            // cppcheck-suppress postfixOperator - forward iterator needs to perform post-increment
2344
0
            mIt++;
2345
0
            return *this;
2346
0
        }
2347
2348
0
        friend bool operator==(const Iterator &a, const Iterator &b) {
2349
0
            return a.mIt == b.mIt;
2350
0
        }
2351
2352
0
        friend bool operator!=(const Iterator &a, const Iterator &b) {
2353
0
            return a.mIt != b.mIt;
2354
0
        }
2355
2356
    private:
2357
        M::const_iterator mIt;
2358
    };
2359
2360
public:
2361
    explicit SelectValueFromVarIdMapRange(const M *m)
2362
0
        : mMap(m) {}
2363
2364
0
    Iterator begin() const {
2365
0
        return Iterator(mMap->begin());
2366
0
    }
2367
0
    Iterator end() const {
2368
0
        return Iterator(mMap->end());
2369
0
    }
2370
2371
private:
2372
    const M *mMap;
2373
};
2374
2375
// Check if its an alias of the variable or is being aliased to this variable
2376
template<typename V>
2377
static bool isAliasOf(const Variable * var, const Token *tok, nonneg int varid, const V& values, bool* inconclusive = nullptr)
2378
36.8k
{
2379
36.8k
    if (tok->varId() == varid)
2380
0
        return false;
2381
36.8k
    if (tok->varId() == 0)
2382
30.4k
        return false;
2383
6.41k
    if (isAliasOf(tok, varid, inconclusive))
2384
0
        return true;
2385
6.41k
    if (var && !var->isPointer())
2386
6.41k
        return false;
2387
    // Search through non value aliases
2388
0
    return std::any_of(values.begin(), values.end(), [&](const ValueFlow::Value& val) {
2389
0
        if (!val.isNonValue())
2390
0
            return false;
2391
0
        if (val.isInconclusive())
2392
0
            return false;
2393
0
        if (val.isLifetimeValue() && !val.isLocalLifetimeValue())
2394
0
            return false;
2395
0
        if (val.isLifetimeValue() && val.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
2396
0
            return false;
2397
0
        if (!Token::Match(val.tokvalue, ".|&|*|%var%"))
2398
0
            return false;
2399
0
        return astHasVar(val.tokvalue, tok->varId());
2400
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
2401
6.41k
}
valueflow.cpp:bool isAliasOf<SingleRange<ValueFlow::Value const> >(Variable const*, Token const*, int, SingleRange<ValueFlow::Value const> const&, bool*)
Line
Count
Source
2378
36.8k
{
2379
36.8k
    if (tok->varId() == varid)
2380
0
        return false;
2381
36.8k
    if (tok->varId() == 0)
2382
30.4k
        return false;
2383
6.41k
    if (isAliasOf(tok, varid, inconclusive))
2384
0
        return true;
2385
6.41k
    if (var && !var->isPointer())
2386
6.41k
        return false;
2387
    // Search through non value aliases
2388
0
    return std::any_of(values.begin(), values.end(), [&](const ValueFlow::Value& val) {
2389
0
        if (!val.isNonValue())
2390
0
            return false;
2391
0
        if (val.isInconclusive())
2392
0
            return false;
2393
0
        if (val.isLifetimeValue() && !val.isLocalLifetimeValue())
2394
0
            return false;
2395
0
        if (val.isLifetimeValue() && val.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
2396
0
            return false;
2397
0
        if (!Token::Match(val.tokvalue, ".|&|*|%var%"))
2398
0
            return false;
2399
0
        return astHasVar(val.tokvalue, tok->varId());
2400
0
    });
2401
6.41k
}
Unexecuted instantiation: valueflow.cpp:bool isAliasOf<SelectValueFromVarIdMapRange>(Variable const*, Token const*, int, SelectValueFromVarIdMapRange const&, bool*)
2402
2403
static bool bifurcate(const Token* tok, const std::set<nonneg int>& varids, const Settings& settings, int depth = 20);
2404
2405
static bool bifurcateVariableChanged(const Variable* var,
2406
                                     const std::set<nonneg int>& varids,
2407
                                     const Token* start,
2408
                                     const Token* end,
2409
                                     const Settings& settings,
2410
                                     int depth = 20)
2411
2
{
2412
2
    bool result = false;
2413
2
    const Token* tok = start;
2414
4
    while ((tok = findVariableChanged(
2415
4
                tok->next(), end, var->isPointer(), var->declarationId(), var->isGlobal(), &settings, true))) {
2416
4
        if (Token::Match(tok->astParent(), "%assign%")) {
2417
2
            if (!bifurcate(tok->astParent()->astOperand2(), varids, settings, depth - 1))
2418
2
                return true;
2419
2
        } else {
2420
2
            result = true;
2421
2
        }
2422
4
    }
2423
0
    return result;
2424
2
}
2425
2426
static bool bifurcate(const Token* tok, const std::set<nonneg int>& varids, const Settings& settings, int depth)
2427
32
{
2428
32
    if (depth < 0)
2429
0
        return false;
2430
32
    if (!tok)
2431
0
        return true;
2432
32
    if (tok->hasKnownIntValue())
2433
0
        return true;
2434
32
    if (tok->isConstOp())
2435
16
        return bifurcate(tok->astOperand1(), varids, settings, depth) && bifurcate(tok->astOperand2(), varids, settings, depth);
2436
16
    if (tok->varId() != 0) {
2437
2
        if (varids.count(tok->varId()) > 0)
2438
0
            return true;
2439
2
        const Variable* var = tok->variable();
2440
2
        if (!var)
2441
0
            return false;
2442
2
        const Token* start = var->declEndToken();
2443
2
        if (!start)
2444
0
            return false;
2445
2
        if (start->strAt(-1) == ")" || start->strAt(-1) == "}")
2446
0
            return false;
2447
2
        if (Token::Match(start, "; %varid% =", var->declarationId()))
2448
2
            start = start->tokAt(2);
2449
2
        if (var->isConst() || !bifurcateVariableChanged(var, varids, start, tok, settings, depth))
2450
0
            return var->isArgument() || bifurcate(start->astOperand2(), varids, settings, depth - 1);
2451
2
        return false;
2452
2
    }
2453
14
    return false;
2454
16
}
2455
2456
struct ValueFlowAnalyzer : Analyzer {
2457
    const TokenList& tokenlist;
2458
    const Settings& settings;
2459
    ProgramMemoryState pms;
2460
2461
7.94k
    explicit ValueFlowAnalyzer(const TokenList& t, const Settings& s) : tokenlist(t), settings(s), pms(&settings) {}
2462
2463
    virtual const ValueFlow::Value* getValue(const Token* tok) const = 0;
2464
    virtual ValueFlow::Value* getValue(const Token* tok) = 0;
2465
2466
    virtual void makeConditional() = 0;
2467
2468
    virtual void addErrorPath(const Token* tok, const std::string& s) = 0;
2469
2470
    virtual bool match(const Token* tok) const = 0;
2471
2472
30.9k
    virtual bool internalMatch(const Token* /*tok*/) const {
2473
30.9k
        return false;
2474
30.9k
    }
2475
2476
    virtual bool isAlias(const Token* tok, bool& inconclusive) const = 0;
2477
2478
    using ProgramState = ProgramMemory::Map;
2479
2480
    virtual ProgramState getProgramState() const = 0;
2481
2482
3.68k
    virtual int getIndirect(const Token* tok) const {
2483
3.68k
        const ValueFlow::Value* value = getValue(tok);
2484
3.68k
        if (value)
2485
3.68k
            return value->indirect;
2486
0
        return 0;
2487
3.68k
    }
2488
2489
0
    virtual bool isGlobal() const {
2490
0
        return false;
2491
0
    }
2492
0
    virtual bool dependsOnThis() const {
2493
0
        return false;
2494
0
    }
2495
0
    virtual bool isVariable() const {
2496
0
        return false;
2497
0
    }
2498
2499
2.66k
    bool isCPP() const {
2500
2.66k
        return tokenlist.isCPP();
2501
2.66k
    }
2502
2503
6.41k
    const Settings& getSettings() const {
2504
6.41k
        return settings;
2505
6.41k
    }
2506
2507
    // Returns Action::Match if its an exact match, return Action::Read if it partially matches the lifetime
2508
    Action analyzeLifetime(const Token* tok) const
2509
0
    {
2510
0
        if (!tok)
2511
0
            return Action::None;
2512
0
        if (match(tok))
2513
0
            return Action::Match;
2514
0
        if (Token::simpleMatch(tok, ".") && analyzeLifetime(tok->astOperand1()) != Action::None)
2515
0
            return Action::Read;
2516
0
        if (astIsRHS(tok) && Token::simpleMatch(tok->astParent(), "."))
2517
0
            return analyzeLifetime(tok->astParent());
2518
0
        return Action::None;
2519
0
    }
2520
2521
    struct ConditionState {
2522
        bool dependent = true;
2523
        bool unknown = true;
2524
2525
627
        bool isUnknownDependent() const {
2526
627
            return unknown && dependent;
2527
627
        }
2528
    };
2529
2530
    std::unordered_map<nonneg int, const Token*> getSymbols(const Token* tok) const
2531
278
    {
2532
278
        std::unordered_map<nonneg int, const Token*> result;
2533
278
        if (!tok)
2534
0
            return result;
2535
278
        for (const ValueFlow::Value& v : tok->values()) {
2536
31
            if (!v.isSymbolicValue())
2537
31
                continue;
2538
0
            if (v.isImpossible())
2539
0
                continue;
2540
0
            if (!v.tokvalue)
2541
0
                continue;
2542
0
            if (v.tokvalue->exprId() == 0)
2543
0
                continue;
2544
0
            if (match(v.tokvalue))
2545
0
                continue;
2546
0
            result[v.tokvalue->exprId()] = v.tokvalue;
2547
0
        }
2548
278
        return result;
2549
278
    }
2550
2551
    ConditionState analyzeCondition(const Token* tok, int depth = 20) const
2552
627
    {
2553
627
        ConditionState result;
2554
627
        if (!tok)
2555
15
            return result;
2556
612
        if (depth < 0)
2557
0
            return result;
2558
612
        depth--;
2559
612
        if (analyze(tok, Direction::Forward).isRead()) {
2560
23
            result.dependent = true;
2561
23
            result.unknown = false;
2562
23
            return result;
2563
23
        }
2564
589
        if (tok->hasKnownIntValue() || tok->isLiteral()) {
2565
59
            result.dependent = false;
2566
59
            result.unknown = false;
2567
59
            return result;
2568
59
        }
2569
530
        if (Token::Match(tok, "%cop%")) {
2570
252
            if (isLikelyStream(isCPP(), tok->astOperand1())) {
2571
2
                result.dependent = false;
2572
2
                return result;
2573
2
            }
2574
250
            ConditionState lhs = analyzeCondition(tok->astOperand1(), depth - 1);
2575
250
            if (lhs.isUnknownDependent())
2576
22
                return lhs;
2577
228
            ConditionState rhs = analyzeCondition(tok->astOperand2(), depth - 1);
2578
228
            if (rhs.isUnknownDependent())
2579
44
                return rhs;
2580
184
            if (Token::Match(tok, "%comp%"))
2581
108
                result.dependent = lhs.dependent && rhs.dependent;
2582
76
            else
2583
76
                result.dependent = lhs.dependent || rhs.dependent;
2584
184
            result.unknown = lhs.unknown || rhs.unknown;
2585
184
            return result;
2586
228
        }
2587
278
        if (Token::Match(tok->previous(), "%name% (")) {
2588
0
            std::vector<const Token*> args = getArguments(tok->previous());
2589
0
            if (Token::Match(tok->tokAt(-2), ". %name% (")) {
2590
0
                args.push_back(tok->tokAt(-2)->astOperand1());
2591
0
            }
2592
0
            result.dependent = std::any_of(args.cbegin(), args.cend(), [&](const Token* arg) {
2593
0
                ConditionState cs = analyzeCondition(arg, depth - 1);
2594
0
                return cs.dependent;
2595
0
            });
2596
0
            if (result.dependent) {
2597
                // Check if we can evaluate the function
2598
0
                if (!evaluate(Evaluate::Integral, tok).empty())
2599
0
                    result.unknown = false;
2600
0
            }
2601
0
            return result;
2602
0
        }
2603
2604
278
        std::unordered_map<nonneg int, const Token*> symbols = getSymbols(tok);
2605
278
        result.dependent = false;
2606
278
        for (auto&& p : symbols) {
2607
0
            const Token* arg = p.second;
2608
0
            ConditionState cs = analyzeCondition(arg, depth - 1);
2609
0
            result.dependent = cs.dependent;
2610
0
            if (result.dependent)
2611
0
                break;
2612
0
        }
2613
278
        if (result.dependent) {
2614
            // Check if we can evaluate the token
2615
0
            if (!evaluate(Evaluate::Integral, tok).empty())
2616
0
                result.unknown = false;
2617
0
        }
2618
278
        return result;
2619
278
    }
2620
2621
1.84k
    virtual Action isModified(const Token* tok) const {
2622
1.84k
        const Action read = Action::Read;
2623
1.84k
        const ValueFlow::Value* value = getValue(tok);
2624
1.84k
        if (value) {
2625
            // Moving a moved value won't change the moved value
2626
1.84k
            if (value->isMovedValue() && isMoveOrForward(tok) != ValueFlow::Value::MoveKind::NonMovedVariable)
2627
0
                return read;
2628
            // Inserting elements to container won't change the lifetime
2629
1.84k
            if (astIsContainer(tok) && value->isLifetimeValue() &&
2630
1.84k
                contains({Library::Container::Action::PUSH,
2631
0
                          Library::Container::Action::INSERT,
2632
0
                          Library::Container::Action::CHANGE_INTERNAL},
2633
0
                         astContainerAction(tok)))
2634
0
                return read;
2635
1.84k
        }
2636
1.84k
        bool inconclusive = false;
2637
1.84k
        if (isVariableChangedByFunctionCall(tok, getIndirect(tok), &getSettings(), &inconclusive))
2638
4
            return read | Action::Invalid;
2639
1.84k
        if (inconclusive)
2640
0
            return read | Action::Inconclusive;
2641
1.84k
        if (isVariableChanged(tok, getIndirect(tok), &getSettings(), isCPP())) {
2642
322
            if (Token::Match(tok->astParent(), "*|[|.|++|--"))
2643
0
                return read | Action::Invalid;
2644
            // Check if its assigned to the same value
2645
322
            if (value && !value->isImpossible() && Token::simpleMatch(tok->astParent(), "=") && astIsLHS(tok) &&
2646
322
                astIsIntegral(tok->astParent()->astOperand2(), false)) {
2647
123
                std::vector<MathLib::bigint> result = evaluateInt(tok->astParent()->astOperand2());
2648
123
                if (!result.empty() && value->equalTo(result.front()))
2649
0
                    return Action::Idempotent;
2650
123
            }
2651
322
            return Action::Invalid;
2652
322
        }
2653
1.51k
        return read;
2654
1.84k
    }
2655
2656
576
    virtual Action isAliasModified(const Token* tok, int indirect = -1) const {
2657
        // Lambda function call
2658
576
        if (Token::Match(tok, "%var% ("))
2659
            // TODO: Check if modified in the lambda function
2660
0
            return Action::Invalid;
2661
576
        if (indirect == -1) {
2662
222
            indirect = 0;
2663
222
            if (const ValueType* vt = tok->valueType()) {
2664
222
                indirect = vt->pointer;
2665
222
                if (vt->type == ValueType::ITERATOR)
2666
0
                    ++indirect;
2667
222
            }
2668
222
        }
2669
966
        for (int i = 0; i <= indirect; ++i)
2670
576
            if (isVariableChanged(tok, i, &getSettings(), isCPP()))
2671
186
                return Action::Invalid;
2672
390
        return Action::None;
2673
576
    }
2674
2675
0
    virtual Action isThisModified(const Token* tok) const {
2676
0
        if (isThisChanged(tok, 0, &getSettings(), isCPP()))
2677
0
            return Action::Invalid;
2678
0
        return Action::None;
2679
0
    }
2680
2681
    Action isGlobalModified(const Token* tok) const
2682
10
    {
2683
10
        if (tok->function()) {
2684
0
            if (!tok->function()->isConstexpr() && !isConstFunctionCall(tok, getSettings().library))
2685
0
                return Action::Invalid;
2686
10
        } else if (getSettings().library.getFunction(tok)) {
2687
            // Assume library function doesn't modify user-global variables
2688
0
            return Action::None;
2689
10
        } else if (Token::simpleMatch(tok->astParent(), ".") && astIsContainer(tok->astParent()->astOperand1())) {
2690
            // Assume container member function doesn't modify user-global variables
2691
0
            return Action::None;
2692
10
        } else if (tok->tokType() == Token::eType && astIsPrimitive(tok->next())) {
2693
            // Function cast does not modify global variables
2694
0
            return Action::None;
2695
10
        } else if (!tok->isKeyword() && Token::Match(tok, "%name% (")) {
2696
0
            return Action::Invalid;
2697
0
        }
2698
10
        return Action::None;
2699
10
    }
2700
2701
    static const std::string& getAssign(const Token* tok, Direction d)
2702
149
    {
2703
149
        if (d == Direction::Forward)
2704
139
            return tok->str();
2705
10
        return invertAssign(tok->str());
2706
149
    }
2707
2708
2.29k
    virtual Action isWritable(const Token* tok, Direction d) const {
2709
2.29k
        const ValueFlow::Value* value = getValue(tok);
2710
2.29k
        if (!value)
2711
0
            return Action::None;
2712
2.29k
        if (!(value->isIntValue() || value->isFloatValue() || value->isSymbolicValue() || value->isLifetimeValue()))
2713
0
            return Action::None;
2714
2.29k
        const Token* parent = tok->astParent();
2715
        // Only if its invertible
2716
2.29k
        if (value->isImpossible() && !Token::Match(parent, "+=|-=|*=|++|--"))
2717
530
            return Action::None;
2718
1.76k
        if (value->isLifetimeValue()) {
2719
0
            if (value->lifetimeKind != ValueFlow::Value::LifetimeKind::Iterator)
2720
0
                return Action::None;
2721
0
            if (!Token::Match(parent, "++|--|+="))
2722
0
                return Action::None;
2723
0
            return Action::Read | Action::Write;
2724
0
        }
2725
1.76k
        if (parent && parent->isAssignmentOp() && astIsLHS(tok)) {
2726
292
            const Token* rhs = parent->astOperand2();
2727
292
            std::vector<MathLib::bigint> result = evaluateInt(rhs);
2728
292
            if (!result.empty()) {
2729
131
                ValueFlow::Value rhsValue{result.front()};
2730
131
                Action a;
2731
131
                if (!evalAssignment(*value, getAssign(parent, d), rhsValue))
2732
18
                    a = Action::Invalid;
2733
113
                else
2734
113
                    a = Action::Write;
2735
131
                if (parent->str() != "=") {
2736
0
                    a |= Action::Read | Action::Incremental;
2737
131
                } else {
2738
131
                    if (!value->isImpossible() && value->equalValue(rhsValue))
2739
70
                        a = Action::Idempotent;
2740
131
                    if (tok->exprId() != 0 &&
2741
275
                        findAstNode(rhs, [&](const Token* child) {
2742
275
                        return tok->exprId() == child->exprId();
2743
275
                    }))
2744
40
                        a |= Action::Incremental;
2745
131
                }
2746
131
                return a;
2747
131
            }
2748
292
        }
2749
2750
        // increment/decrement
2751
1.63k
        if (Token::Match(tok->astParent(), "++|--")) {
2752
317
            return Action::Read | Action::Write | Action::Incremental;
2753
317
        }
2754
1.31k
        return Action::None;
2755
1.63k
    }
2756
2757
202
    virtual void writeValue(ValueFlow::Value* value, const Token* tok, Direction d) const {
2758
202
        if (!value)
2759
0
            return;
2760
202
        if (!tok->astParent())
2761
0
            return;
2762
        // Lifetime value doesn't change
2763
202
        if (value->isLifetimeValue())
2764
0
            return;
2765
202
        if (tok->astParent()->isAssignmentOp()) {
2766
18
            const Token* rhs = tok->astParent()->astOperand2();
2767
18
            std::vector<MathLib::bigint> result = evaluateInt(rhs);
2768
18
            assert(!result.empty());
2769
0
            ValueFlow::Value rhsValue{result.front()};
2770
18
            if (evalAssignment(*value, getAssign(tok->astParent(), d), rhsValue)) {
2771
18
                std::string info("Compound assignment '" + tok->astParent()->str() + "', assigned value is " +
2772
18
                                 value->infoString());
2773
18
                if (tok->astParent()->str() == "=")
2774
18
                    value->errorPath.clear();
2775
18
                value->errorPath.emplace_back(tok, std::move(info));
2776
18
            } else {
2777
0
                assert(false && "Writable value cannot be evaluated");
2778
                // TODO: Don't set to zero
2779
0
                value->intvalue = 0;
2780
0
            }
2781
184
        } else if (tok->astParent()->tokType() == Token::eIncDecOp) {
2782
184
            bool inc = tok->astParent()->str() == "++";
2783
184
            const std::string opName(inc ? "incremented" : "decremented");
2784
184
            if (d == Direction::Reverse)
2785
11
                inc = !inc;
2786
184
            value->intvalue += (inc ? 1 : -1);
2787
184
            value->errorPath.emplace_back(tok, tok->str() + " is " + opName + "', new value is " + value->infoString());
2788
184
        }
2789
202
    }
2790
2791
0
    virtual bool useSymbolicValues() const {
2792
0
        return true;
2793
0
    }
2794
2795
    const Token* findMatch(const Token* tok) const
2796
48
    {
2797
84
        return findAstNode(tok, [&](const Token* child) {
2798
84
            return match(child);
2799
84
        });
2800
48
    }
2801
2802
    bool isSameSymbolicValue(const Token* tok, ValueFlow::Value* value = nullptr) const
2803
28.0k
    {
2804
28.0k
        if (!useSymbolicValues())
2805
0
            return false;
2806
28.0k
        if (Token::Match(tok, "%assign%"))
2807
1.61k
            return false;
2808
26.4k
        const ValueFlow::Value* currValue = getValue(tok);
2809
26.4k
        if (!currValue)
2810
0
            return false;
2811
        // If the same symbolic value is already there then skip
2812
26.4k
        if (currValue->isSymbolicValue() &&
2813
26.4k
            std::any_of(tok->values().cbegin(), tok->values().cend(), [&](const ValueFlow::Value& v) {
2814
4.14k
            return v.isSymbolicValue() && currValue->equalValue(v);
2815
4.14k
        }))
2816
38
            return false;
2817
26.4k
        const bool isPoint = currValue->bound == ValueFlow::Value::Bound::Point && currValue->isIntValue();
2818
26.4k
        const bool exact = !currValue->isIntValue() || currValue->isImpossible();
2819
26.4k
        for (const ValueFlow::Value& v : tok->values()) {
2820
9.97k
            if (!v.isSymbolicValue())
2821
9.70k
                continue;
2822
275
            if (currValue->equalValue(v))
2823
0
                continue;
2824
275
            const bool toImpossible = v.isImpossible() && currValue->isKnown();
2825
275
            if (!v.isKnown() && !toImpossible)
2826
158
                continue;
2827
117
            if (exact && v.intvalue != 0 && !isPoint)
2828
18
                continue;
2829
99
            std::vector<MathLib::bigint> r;
2830
99
            ValueFlow::Value::Bound bound = currValue->bound;
2831
99
            if (match(v.tokvalue)) {
2832
6
                r = {currValue->intvalue};
2833
93
            } else if (!exact && findMatch(v.tokvalue)) {
2834
0
                r = evaluate(Evaluate::Integral, v.tokvalue, tok);
2835
0
                if (bound == ValueFlow::Value::Bound::Point)
2836
0
                    bound = v.bound;
2837
0
            }
2838
99
            if (!r.empty()) {
2839
6
                if (value) {
2840
3
                    value->errorPath.insert(value->errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
2841
3
                    value->intvalue = r.front() + v.intvalue;
2842
3
                    if (toImpossible)
2843
0
                        value->setImpossible();
2844
3
                    value->bound = bound;
2845
3
                }
2846
6
                return true;
2847
6
            }
2848
99
        }
2849
26.4k
        return false;
2850
26.4k
    }
2851
2852
2.29k
    Action analyzeMatch(const Token* tok, Direction d) const {
2853
2.29k
        const Token* parent = tok->astParent();
2854
2.29k
        if (d == Direction::Reverse && isGlobal() && !dependsOnThis() && Token::Match(parent, ". %name% (")) {
2855
0
            Action a = isGlobalModified(parent->next());
2856
0
            if (a != Action::None)
2857
0
                return a;
2858
0
        }
2859
2.29k
        if ((astIsPointer(tok) || astIsSmartPointer(tok)) &&
2860
2.29k
            (Token::Match(parent, "*|[") || (parent && parent->originalName() == "->")) && getIndirect(tok) <= 0)
2861
0
            return Action::Read;
2862
2863
2.29k
        Action w = isWritable(tok, d);
2864
2.29k
        if (w != Action::None)
2865
448
            return w;
2866
2867
        // Check for modifications by function calls
2868
1.84k
        return isModified(tok);
2869
2.29k
    }
2870
2871
30.9k
    Action analyzeToken(const Token* ref, const Token* tok, Direction d, bool inconclusiveRef) const {
2872
30.9k
        if (!ref)
2873
0
            return Action::None;
2874
        // If its an inconclusiveRef then ref != tok
2875
30.9k
        assert(!inconclusiveRef || ref != tok);
2876
0
        bool inconclusive = false;
2877
30.9k
        if (match(ref)) {
2878
2.29k
            if (inconclusiveRef) {
2879
0
                Action a = isModified(tok);
2880
0
                if (a.isModified() || a.isInconclusive())
2881
0
                    return Action::Inconclusive;
2882
2.29k
            } else {
2883
2.29k
                return analyzeMatch(tok, d) | Action::Match;
2884
2.29k
            }
2885
28.6k
        } else if (ref->isUnaryOp("*") && !match(ref->astOperand1())) {
2886
0
            const Token* lifeTok = nullptr;
2887
0
            for (const ValueFlow::Value& v:ref->astOperand1()->values()) {
2888
0
                if (!v.isLocalLifetimeValue())
2889
0
                    continue;
2890
0
                if (lifeTok)
2891
0
                    return Action::None;
2892
0
                lifeTok = v.tokvalue;
2893
0
            }
2894
0
            if (!lifeTok)
2895
0
                return Action::None;
2896
0
            Action la = analyzeLifetime(lifeTok);
2897
0
            if (la.matches()) {
2898
0
                Action a = Action::Read;
2899
0
                if (isModified(tok).isModified())
2900
0
                    a = Action::Invalid;
2901
0
                if (Token::Match(tok->astParent(), "%assign%") && astIsLHS(tok))
2902
0
                    a |= Action::Invalid;
2903
0
                if (inconclusiveRef && a.isModified())
2904
0
                    return Action::Inconclusive;
2905
0
                return a;
2906
0
            }
2907
0
            if (la.isRead()) {
2908
0
                return isAliasModified(tok);
2909
0
            }
2910
0
            return Action::None;
2911
2912
28.6k
        } else if (isAlias(ref, inconclusive)) {
2913
576
            inconclusive |= inconclusiveRef;
2914
576
            Action a = isAliasModified(tok);
2915
576
            if (inconclusive && a.isModified())
2916
0
                return Action::Inconclusive;
2917
576
            return a;
2918
576
        }
2919
28.0k
        if (isSameSymbolicValue(ref))
2920
3
            return Action::Read | Action::SymbolicMatch;
2921
2922
28.0k
        return Action::None;
2923
28.0k
    }
2924
2925
30.9k
    Action analyze(const Token* tok, Direction d) const override {
2926
30.9k
        if (invalid())
2927
0
            return Action::Invalid;
2928
        // Follow references
2929
30.9k
        auto refs = followAllReferences(tok);
2930
30.9k
        const bool inconclusiveRefs = refs.size() != 1;
2931
30.9k
        if (std::none_of(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
2932
30.9k
            return tok == ref.token;
2933
30.9k
        }))
2934
0
            refs.emplace_back(ReferenceToken{tok, {}});
2935
30.9k
        for (const ReferenceToken& ref:refs) {
2936
30.9k
            Action a = analyzeToken(ref.token, tok, d, inconclusiveRefs && ref.token != tok);
2937
30.9k
            if (internalMatch(ref.token))
2938
0
                a |= Action::Internal;
2939
30.9k
            if (a != Action::None)
2940
2.48k
                return a;
2941
30.9k
        }
2942
28.4k
        if (dependsOnThis() && exprDependsOnThis(tok, !isVariable()))
2943
0
            return isThisModified(tok);
2944
2945
        // bailout: global non-const variables
2946
28.4k
        if (isGlobal() && !dependsOnThis() && Token::Match(tok, "%name% (") &&
2947
28.4k
            !Token::simpleMatch(tok->linkAt(1), ") {")) {
2948
10
            return isGlobalModified(tok);
2949
10
        }
2950
28.4k
        return Action::None;
2951
28.4k
    }
2952
2953
    template<class F>
2954
    std::vector<MathLib::bigint> evaluateInt(const Token* tok, F getProgramMemory) const
2955
1.67k
    {
2956
1.67k
        if (tok->hasKnownIntValue())
2957
269
            return {static_cast<int>(tok->values().front().intvalue)};
2958
1.40k
        std::vector<MathLib::bigint> result;
2959
1.40k
        ProgramMemory pm = getProgramMemory();
2960
1.40k
        if (Token::Match(tok, "&&|%oror%")) {
2961
0
            if (conditionIsTrue(tok, pm, &getSettings()))
2962
0
                result.push_back(1);
2963
0
            if (conditionIsFalse(tok, std::move(pm), &getSettings()))
2964
0
                result.push_back(0);
2965
1.40k
        } else {
2966
1.40k
            MathLib::bigint out = 0;
2967
1.40k
            bool error = false;
2968
1.40k
            execute(tok, pm, &out, &error, &getSettings());
2969
1.40k
            if (!error)
2970
128
                result.push_back(out);
2971
1.40k
        }
2972
1.40k
        return result;
2973
1.67k
    }
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
2955
433
    {
2956
433
        if (tok->hasKnownIntValue())
2957
136
            return {static_cast<int>(tok->values().front().intvalue)};
2958
297
        std::vector<MathLib::bigint> result;
2959
297
        ProgramMemory pm = getProgramMemory();
2960
297
        if (Token::Match(tok, "&&|%oror%")) {
2961
0
            if (conditionIsTrue(tok, pm, &getSettings()))
2962
0
                result.push_back(1);
2963
0
            if (conditionIsFalse(tok, std::move(pm), &getSettings()))
2964
0
                result.push_back(0);
2965
297
        } else {
2966
297
            MathLib::bigint out = 0;
2967
297
            bool error = false;
2968
297
            execute(tok, pm, &out, &error, &getSettings());
2969
297
            if (!error)
2970
13
                result.push_back(out);
2971
297
        }
2972
297
        return result;
2973
433
    }
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
2955
1.24k
    {
2956
1.24k
        if (tok->hasKnownIntValue())
2957
133
            return {static_cast<int>(tok->values().front().intvalue)};
2958
1.11k
        std::vector<MathLib::bigint> result;
2959
1.11k
        ProgramMemory pm = getProgramMemory();
2960
1.11k
        if (Token::Match(tok, "&&|%oror%")) {
2961
0
            if (conditionIsTrue(tok, pm, &getSettings()))
2962
0
                result.push_back(1);
2963
0
            if (conditionIsFalse(tok, std::move(pm), &getSettings()))
2964
0
                result.push_back(0);
2965
1.11k
        } else {
2966
1.11k
            MathLib::bigint out = 0;
2967
1.11k
            bool error = false;
2968
1.11k
            execute(tok, pm, &out, &error, &getSettings());
2969
1.11k
            if (!error)
2970
115
                result.push_back(out);
2971
1.11k
        }
2972
1.11k
        return result;
2973
1.24k
    }
2974
    std::vector<MathLib::bigint> evaluateInt(const Token* tok) const
2975
433
    {
2976
433
        return evaluateInt(tok, [&] {
2977
297
            return ProgramMemory{getProgramState()};
2978
297
        });
2979
433
    }
2980
2981
    std::vector<MathLib::bigint> evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const override
2982
1.24k
    {
2983
1.24k
        if (e == Evaluate::Integral) {
2984
1.24k
            return evaluateInt(tok, [&] {
2985
1.11k
                return pms.get(tok, ctx, getProgramState());
2986
1.11k
            });
2987
1.24k
        }
2988
0
        if (e == Evaluate::ContainerEmpty) {
2989
0
            const ValueFlow::Value* value = ValueFlow::findValue(tok->values(), nullptr, [](const ValueFlow::Value& v) {
2990
0
                return v.isKnown() && v.isContainerSizeValue();
2991
0
            });
2992
0
            if (value)
2993
0
                return {value->intvalue == 0};
2994
0
            ProgramMemory pm = pms.get(tok, ctx, getProgramState());
2995
0
            MathLib::bigint out = 0;
2996
0
            if (pm.getContainerEmptyValue(tok->exprId(), out))
2997
0
                return {static_cast<int>(out)};
2998
0
            return {};
2999
0
        }
3000
0
        return {};
3001
0
    }
3002
3003
462
    void assume(const Token* tok, bool state, unsigned int flags) override {
3004
        // Update program state
3005
462
        pms.removeModifiedVars(tok);
3006
462
        pms.addState(tok, getProgramState());
3007
462
        pms.assume(tok, state, flags & Assume::ContainerEmpty);
3008
3009
462
        bool isCondBlock = false;
3010
462
        const Token* parent = tok->astParent();
3011
462
        if (parent) {
3012
462
            isCondBlock = Token::Match(parent->previous(), "if|while (");
3013
462
        }
3014
3015
462
        if (isCondBlock) {
3016
462
            const Token* startBlock = parent->link()->next();
3017
462
            if (Token::simpleMatch(startBlock, ";") && Token::simpleMatch(parent->tokAt(-2), "} while ("))
3018
0
                startBlock = parent->linkAt(-2);
3019
462
            const Token* endBlock = startBlock->link();
3020
462
            if (state) {
3021
391
                pms.removeModifiedVars(endBlock);
3022
391
                pms.addState(endBlock->previous(), getProgramState());
3023
391
            } else {
3024
71
                if (Token::simpleMatch(endBlock, "} else {"))
3025
39
                    pms.addState(endBlock->linkAt(2)->previous(), getProgramState());
3026
71
            }
3027
462
        }
3028
3029
462
        if (!(flags & Assume::Quiet)) {
3030
62
            if (flags & Assume::ContainerEmpty) {
3031
0
                std::string s = state ? "empty" : "not empty";
3032
0
                addErrorPath(tok, "Assuming container is " + s);
3033
62
            } else {
3034
62
                std::string s = bool_to_string(state);
3035
62
                addErrorPath(tok, "Assuming condition is " + s);
3036
62
            }
3037
62
        }
3038
462
        if (!(flags & Assume::Absolute))
3039
442
            makeConditional();
3040
462
    }
3041
3042
    void updateState(const Token* tok) override
3043
4.21k
    {
3044
        // Update program state
3045
4.21k
        pms.removeModifiedVars(tok);
3046
4.21k
        pms.addState(tok, getProgramState());
3047
4.21k
    }
3048
3049
    virtual void internalUpdate(Token* /*tok*/, const ValueFlow::Value& /*v*/, Direction /*d*/)
3050
0
    {
3051
0
        assert(false && "Internal update unimplemented.");
3052
0
    }
3053
3054
981
    void update(Token* tok, Action a, Direction d) override {
3055
981
        ValueFlow::Value* value = getValue(tok);
3056
981
        if (!value)
3057
0
            return;
3058
981
        ValueFlow::Value localValue;
3059
981
        if (a.isSymbolicMatch()) {
3060
            // Make a copy of the value to modify it
3061
3
            localValue = *value;
3062
3
            value = &localValue;
3063
3
            isSameSymbolicValue(tok, &localValue);
3064
3
        }
3065
981
        if (a.isInternal())
3066
0
            internalUpdate(tok, *value, d);
3067
        // Read first when moving forward
3068
981
        if (d == Direction::Forward && a.isRead())
3069
695
            setTokenValue(tok, *value, getSettings());
3070
981
        if (a.isInconclusive())
3071
0
            lowerToInconclusive();
3072
981
        if (a.isWrite() && tok->astParent()) {
3073
202
            writeValue(value, tok, d);
3074
202
        }
3075
        // Read last when moving in reverse
3076
981
        if (d == Direction::Reverse && a.isRead())
3077
27
            setTokenValue(tok, *value, getSettings());
3078
981
    }
3079
3080
0
    ValuePtr<Analyzer> reanalyze(Token* /*tok*/, const std::string& /*msg*/) const override {
3081
0
        return {};
3082
0
    }
3083
};
3084
3085
struct SingleValueFlowAnalyzer : ValueFlowAnalyzer {
3086
    std::unordered_map<nonneg int, const Variable*> varids;
3087
    std::unordered_map<nonneg int, const Variable*> aliases;
3088
    ValueFlow::Value value;
3089
3090
7.94k
    SingleValueFlowAnalyzer(ValueFlow::Value v, const TokenList& t, const Settings& s) : ValueFlowAnalyzer(t, s), value(std::move(v)) {}
3091
3092
28.6k
    const std::unordered_map<nonneg int, const Variable*>& getVars() const {
3093
28.6k
        return varids;
3094
28.6k
    }
3095
3096
28.6k
    const std::unordered_map<nonneg int, const Variable*>& getAliasedVars() const {
3097
28.6k
        return aliases;
3098
28.6k
    }
3099
3100
34.2k
    const ValueFlow::Value* getValue(const Token* /*tok*/) const override {
3101
34.2k
        return &value;
3102
34.2k
    }
3103
981
    ValueFlow::Value* getValue(const Token* /*tok*/) override {
3104
981
        return &value;
3105
981
    }
3106
3107
442
    void makeConditional() override {
3108
442
        value.conditional = true;
3109
442
    }
3110
3111
    bool useSymbolicValues() const override
3112
28.0k
    {
3113
28.0k
        if (value.isUninitValue())
3114
0
            return false;
3115
28.0k
        if (value.isLifetimeValue())
3116
0
            return false;
3117
28.0k
        return true;
3118
28.0k
    }
3119
3120
62
    void addErrorPath(const Token* tok, const std::string& s) override {
3121
62
        value.errorPath.emplace_back(tok, s);
3122
62
    }
3123
3124
28.6k
    bool isAlias(const Token* tok, bool& inconclusive) const override {
3125
28.6k
        if (value.isLifetimeValue())
3126
0
            return false;
3127
28.6k
        for (const auto& m: {
3128
28.6k
            std::ref(getVars()), std::ref(getAliasedVars())
3129
56.7k
        }) {
3130
56.7k
            for (const auto& p:m.get()) {
3131
37.3k
                nonneg int const varid = p.first;
3132
37.3k
                const Variable* var = p.second;
3133
37.3k
                if (tok->varId() == varid)
3134
576
                    return true;
3135
36.8k
                if (isAliasOf(var, tok, varid, MakeSingleRange(value), &inconclusive))
3136
0
                    return true;
3137
36.8k
            }
3138
56.7k
        }
3139
28.0k
        return false;
3140
28.6k
    }
3141
3142
0
    bool isGlobal() const override {
3143
0
        const auto& vars = getVars();
3144
0
        return std::any_of(vars.cbegin(), vars.cend(), [] (const std::pair<nonneg int, const Variable*>& p) {
3145
0
            const Variable* var = p.second;
3146
0
            return !var->isLocal() && !var->isArgument() && !var->isConst();
3147
0
        });
3148
0
    }
3149
3150
803
    bool lowerToPossible() override {
3151
803
        if (value.isImpossible())
3152
237
            return false;
3153
566
        value.changeKnownToPossible();
3154
566
        return true;
3155
803
    }
3156
0
    bool lowerToInconclusive() override {
3157
0
        if (value.isImpossible())
3158
0
            return false;
3159
0
        value.setInconclusive();
3160
0
        return true;
3161
0
    }
3162
3163
857
    bool isConditional() const override {
3164
857
        if (value.conditional)
3165
80
            return true;
3166
777
        if (value.condition)
3167
605
            return !value.isKnown() && !value.isImpossible();
3168
172
        return false;
3169
777
    }
3170
3171
    bool stopOnCondition(const Token* condTok) const override
3172
794
    {
3173
794
        if (value.isNonValue())
3174
0
            return false;
3175
794
        if (value.isImpossible())
3176
302
            return false;
3177
492
        if (isConditional() && !value.isKnown() && !value.isImpossible())
3178
343
            return true;
3179
149
        if (value.isSymbolicValue())
3180
0
            return false;
3181
149
        ConditionState cs = analyzeCondition(condTok);
3182
149
        return cs.isUnknownDependent();
3183
149
    }
3184
3185
825
    bool updateScope(const Token* endBlock, bool /*modified*/) const override {
3186
825
        const Scope* scope = endBlock->scope();
3187
825
        if (!scope)
3188
0
            return false;
3189
825
        if (scope->type == Scope::eLambda)
3190
0
            return value.isLifetimeValue();
3191
825
        if (scope->type == Scope::eIf || scope->type == Scope::eElse || scope->type == Scope::eWhile ||
3192
825
            scope->type == Scope::eFor) {
3193
825
            if (value.isKnown() || value.isImpossible())
3194
563
                return true;
3195
262
            if (value.isLifetimeValue())
3196
0
                return true;
3197
262
            if (isConditional())
3198
248
                return false;
3199
14
            const Token* condTok = getCondTokFromEnd(endBlock);
3200
14
            std::set<nonneg int> varids2;
3201
14
            std::transform(getVars().cbegin(), getVars().cend(), std::inserter(varids2, varids2.begin()), SelectMapKeys{});
3202
14
            return bifurcate(condTok, varids2, getSettings());
3203
262
        }
3204
3205
0
        return false;
3206
825
    }
3207
3208
19
    ValuePtr<Analyzer> reanalyze(Token* tok, const std::string& msg) const override {
3209
19
        ValueFlow::Value newValue = value;
3210
19
        newValue.errorPath.emplace_back(tok, msg);
3211
19
        return makeAnalyzer(tok, std::move(newValue), tokenlist, settings);
3212
19
    }
3213
};
3214
3215
struct ExpressionAnalyzer : SingleValueFlowAnalyzer {
3216
    const Token* expr;
3217
    bool local = true;
3218
    bool unknown{};
3219
    bool dependOnThis{};
3220
    bool uniqueExprId{};
3221
3222
    ExpressionAnalyzer(const Token* e, ValueFlow::Value val, const TokenList& t, const Settings& s)
3223
        : SingleValueFlowAnalyzer(std::move(val), t, s),
3224
        expr(e)
3225
7.94k
    {
3226
3227
7.94k
        assert(e && e->exprId() != 0 && "Not a valid expression");
3228
0
        dependOnThis = exprDependsOnThis(expr);
3229
7.94k
        setupExprVarIds(expr);
3230
7.94k
        if (value.isSymbolicValue()) {
3231
4.72k
            dependOnThis |= exprDependsOnThis(value.tokvalue);
3232
4.72k
            setupExprVarIds(value.tokvalue);
3233
4.72k
        }
3234
7.94k
        uniqueExprId =
3235
7.94k
            expr->isUniqueExprId() && (Token::Match(expr, "%cop%") || !isVariableChanged(expr, 0, &s, t.isCPP()));
3236
7.94k
    }
3237
3238
10.7k
    static bool nonLocal(const Variable* var, bool deref) {
3239
10.7k
        return !var || (!var->isLocal() && !var->isArgument()) || (deref && var->isArgument() && var->isPointer()) ||
3240
10.7k
               var->isStatic() || var->isReference() || var->isExtern();
3241
10.7k
    }
3242
3243
12.6k
    void setupExprVarIds(const Token* start, int depth = 0) {
3244
12.6k
        constexpr int maxDepth = 4;
3245
12.6k
        if (depth > maxDepth)
3246
0
            return;
3247
26.2k
        visitAstNodes(start, [&](const Token* tok) {
3248
26.2k
            const bool top = depth == 0 && tok == start;
3249
26.2k
            const bool ispointer = astIsPointer(tok) || astIsSmartPointer(tok) || astIsIterator(tok);
3250
26.2k
            if (!top || !ispointer || value.indirect != 0) {
3251
26.2k
                for (const ValueFlow::Value& v : tok->values()) {
3252
6.94k
                    if (!(v.isLocalLifetimeValue() || (ispointer && v.isSymbolicValue() && v.isKnown())))
3253
6.94k
                        continue;
3254
0
                    if (!v.tokvalue)
3255
0
                        continue;
3256
0
                    if (v.tokvalue == tok)
3257
0
                        continue;
3258
0
                    setupExprVarIds(v.tokvalue, depth + 1);
3259
0
                }
3260
26.2k
            }
3261
26.2k
            if (depth == 0 && tok->isIncompleteVar()) {
3262
                // TODO: Treat incomplete var as global, but we need to update
3263
                // the alias variables to just expr ids instead of requiring
3264
                // Variable
3265
5.39k
                unknown = true;
3266
5.39k
                return ChildrenToVisit::none;
3267
5.39k
            }
3268
20.8k
            if (tok->varId() > 0) {
3269
10.7k
                varids[tok->varId()] = tok->variable();
3270
10.7k
                if (!Token::simpleMatch(tok->previous(), ".")) {
3271
10.7k
                    const Variable* var = tok->variable();
3272
10.7k
                    if (var && var->isReference() && var->isLocal() && Token::Match(var->nameToken(), "%var% [=(]") &&
3273
10.7k
                        !isGlobalData(var->nameToken()->next()->astOperand2(), isCPP()))
3274
0
                        return ChildrenToVisit::none;
3275
10.7k
                    const bool deref = tok->astParent() &&
3276
10.7k
                                       (tok->astParent()->isUnaryOp("*") ||
3277
10.7k
                                        (tok->astParent()->str() == "[" && tok == tok->astParent()->astOperand1()));
3278
10.7k
                    local &= !nonLocal(tok->variable(), deref);
3279
10.7k
                }
3280
10.7k
            }
3281
20.8k
            return ChildrenToVisit::op1_and_op2;
3282
20.8k
        });
3283
12.6k
    }
3284
3285
38.9k
    virtual bool skipUniqueExprIds() const {
3286
38.9k
        return true;
3287
38.9k
    }
3288
3289
38.9k
    bool invalid() const override {
3290
38.9k
        if (skipUniqueExprIds() && uniqueExprId)
3291
2.47k
            return true;
3292
36.5k
        return unknown;
3293
38.9k
    }
3294
3295
6.51k
    ProgramState getProgramState() const override {
3296
6.51k
        ProgramState ps;
3297
6.51k
        ps[expr] = value;
3298
6.51k
        return ps;
3299
6.51k
    }
3300
3301
31.1k
    bool match(const Token* tok) const override {
3302
31.1k
        return tok->exprId() == expr->exprId();
3303
31.1k
    }
3304
3305
57.1k
    bool dependsOnThis() const override {
3306
57.1k
        return dependOnThis;
3307
57.1k
    }
3308
3309
28.6k
    bool isGlobal() const override {
3310
28.6k
        return !local;
3311
28.6k
    }
3312
3313
0
    bool isVariable() const override {
3314
0
        return expr->varId() > 0;
3315
0
    }
3316
3317
576
    Action isAliasModified(const Token* tok, int indirect) const override {
3318
576
        if (value.isSymbolicValue() && tok->exprId() == value.tokvalue->exprId())
3319
354
            indirect = 0;
3320
576
        return SingleValueFlowAnalyzer::isAliasModified(tok, indirect);
3321
576
    }
3322
};
3323
3324
struct SameExpressionAnalyzer : ExpressionAnalyzer {
3325
    SameExpressionAnalyzer(const Token* e, ValueFlow::Value val, const TokenList& t, const Settings& s)
3326
        : ExpressionAnalyzer(e, std::move(val), t, s)
3327
0
    {}
3328
3329
0
    bool skipUniqueExprIds() const override {
3330
0
        return false;
3331
0
    }
3332
3333
    bool match(const Token* tok) const override
3334
0
    {
3335
0
        return isSameExpression(isCPP(), true, expr, tok, getSettings().library, true, true);
3336
0
    }
3337
};
3338
3339
struct OppositeExpressionAnalyzer : ExpressionAnalyzer {
3340
    bool isNot{};
3341
3342
    OppositeExpressionAnalyzer(bool pIsNot, const Token* e, ValueFlow::Value val, const TokenList& t, const Settings& s)
3343
        : ExpressionAnalyzer(e, std::move(val), t, s), isNot(pIsNot)
3344
0
    {}
3345
3346
0
    bool skipUniqueExprIds() const override {
3347
0
        return false;
3348
0
    }
3349
3350
0
    bool match(const Token* tok) const override {
3351
0
        return isOppositeCond(isNot, isCPP(), expr, tok, getSettings().library, true, true);
3352
0
    }
3353
};
3354
3355
struct SubExpressionAnalyzer : ExpressionAnalyzer {
3356
    using PartialReadContainer = std::vector<std::pair<Token *, ValueFlow::Value>>;
3357
    // A shared_ptr is used so partial reads can be captured even after forking
3358
    std::shared_ptr<PartialReadContainer> partialReads;
3359
3360
    SubExpressionAnalyzer(const Token* e, ValueFlow::Value val, const TokenList& t, const Settings& s)
3361
        : ExpressionAnalyzer(e, std::move(val), t, s), partialReads(std::make_shared<PartialReadContainer>())
3362
0
    {}
3363
3364
    virtual bool submatch(const Token* tok, bool exact = true) const = 0;
3365
3366
    bool isAlias(const Token* tok, bool& inconclusive) const override
3367
0
    {
3368
0
        if (tok->exprId() == expr->exprId() && tok->astParent() && submatch(tok->astParent(), false))
3369
0
            return false;
3370
0
        return ExpressionAnalyzer::isAlias(tok, inconclusive);
3371
0
    }
3372
3373
    bool match(const Token* tok) const override
3374
0
    {
3375
0
        return tok->astOperand1() && tok->astOperand1()->exprId() == expr->exprId() && submatch(tok);
3376
0
    }
3377
    bool internalMatch(const Token* tok) const override
3378
0
    {
3379
0
        return tok->exprId() == expr->exprId() && !(astIsLHS(tok) && submatch(tok->astParent(), false));
3380
0
    }
3381
    void internalUpdate(Token* tok, const ValueFlow::Value& v, Direction /*d*/) override
3382
0
    {
3383
0
        partialReads->emplace_back(tok, v);
3384
0
    }
3385
3386
    // No reanalysis for subexpression
3387
0
    ValuePtr<Analyzer> reanalyze(Token* /*tok*/, const std::string& /*msg*/) const override {
3388
0
        return {};
3389
0
    }
3390
};
3391
3392
struct MemberExpressionAnalyzer : SubExpressionAnalyzer {
3393
    std::string varname;
3394
3395
    MemberExpressionAnalyzer(std::string varname, const Token* e, ValueFlow::Value val, const TokenList& t, const Settings& s)
3396
        : SubExpressionAnalyzer(e, std::move(val), t, s), varname(std::move(varname))
3397
0
    {}
3398
3399
    bool submatch(const Token* tok, bool exact) const override
3400
0
    {
3401
0
        if (!Token::Match(tok, ". %var%"))
3402
0
            return false;
3403
0
        if (!exact)
3404
0
            return true;
3405
0
        return tok->next()->str() == varname;
3406
0
    }
3407
};
3408
3409
enum class LifetimeCapture { Undefined, ByValue, ByReference };
3410
3411
static std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
3412
0
{
3413
0
    std::string result;
3414
0
    if (!val)
3415
0
        return "object";
3416
0
    switch (val->lifetimeKind) {
3417
0
    case ValueFlow::Value::LifetimeKind::Lambda:
3418
0
        result = "lambda";
3419
0
        break;
3420
0
    case ValueFlow::Value::LifetimeKind::Iterator:
3421
0
        result = "iterator";
3422
0
        break;
3423
0
    case ValueFlow::Value::LifetimeKind::Object:
3424
0
    case ValueFlow::Value::LifetimeKind::SubObject:
3425
0
    case ValueFlow::Value::LifetimeKind::Address:
3426
0
        if (astIsPointer(tok))
3427
0
            result = "pointer";
3428
0
        else if (Token::simpleMatch(tok, "=") && astIsPointer(tok->astOperand2()))
3429
0
            result = "pointer";
3430
0
        else
3431
0
            result = "object";
3432
0
        break;
3433
0
    }
3434
0
    return result;
3435
0
}
3436
3437
std::string ValueFlow::lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ErrorPath &errorPath)
3438
0
{
3439
0
    const Token *tokvalue = val ? val->tokvalue : nullptr;
3440
0
    const Variable *tokvar = tokvalue ? tokvalue->variable() : nullptr;
3441
0
    const Token *vartok = tokvar ? tokvar->nameToken() : nullptr;
3442
0
    const bool classVar = tokvar ? (!tokvar->isLocal() && !tokvar->isArgument() && !tokvar->isGlobal()) : false;
3443
0
    std::string type = lifetimeType(tok, val);
3444
0
    std::string msg = type;
3445
0
    if (vartok) {
3446
0
        if (!classVar)
3447
0
            errorPath.emplace_back(vartok, "Variable created here.");
3448
0
        const Variable * var = vartok->variable();
3449
0
        if (var) {
3450
0
            std::string submessage;
3451
0
            switch (val->lifetimeKind) {
3452
0
            case ValueFlow::Value::LifetimeKind::SubObject:
3453
0
            case ValueFlow::Value::LifetimeKind::Object:
3454
0
            case ValueFlow::Value::LifetimeKind::Address:
3455
0
                if (type == "pointer")
3456
0
                    submessage = " to local variable";
3457
0
                else
3458
0
                    submessage = " that points to local variable";
3459
0
                break;
3460
0
            case ValueFlow::Value::LifetimeKind::Lambda:
3461
0
                submessage = " that captures local variable";
3462
0
                break;
3463
0
            case ValueFlow::Value::LifetimeKind::Iterator:
3464
0
                submessage = " to local container";
3465
0
                break;
3466
0
            }
3467
0
            if (classVar)
3468
0
                submessage.replace(submessage.find("local"), 5, "member");
3469
0
            msg += submessage + " '" + var->name() + "'";
3470
0
        }
3471
0
    }
3472
0
    return msg;
3473
0
}
3474
3475
std::vector<ValueFlow::Value> ValueFlow::getLifetimeObjValues(const Token* tok, bool inconclusive, MathLib::bigint path)
3476
4.75k
{
3477
4.75k
    std::vector<ValueFlow::Value> result;
3478
4.75k
    auto pred = [&](const ValueFlow::Value& v) {
3479
1.74k
        if (!v.isLocalLifetimeValue() && !(path != 0 && v.isSubFunctionLifetimeValue()))
3480
1.74k
            return false;
3481
0
        if (!inconclusive && v.isInconclusive())
3482
0
            return false;
3483
0
        if (!v.tokvalue)
3484
0
            return false;
3485
0
        if (path >= 0 && v.path != 0 && v.path != path)
3486
0
            return false;
3487
0
        return true;
3488
0
    };
3489
4.75k
    std::copy_if(tok->values().cbegin(), tok->values().cend(), std::back_inserter(result), pred);
3490
4.75k
    return result;
3491
4.75k
}
3492
3493
static bool hasUniqueOwnership(const Token* tok)
3494
0
{
3495
0
    if (!tok)
3496
0
        return false;
3497
0
    const Variable* var = tok->variable();
3498
0
    if (var && var->isArray() && !var->isArgument())
3499
0
        return true;
3500
0
    if (astIsPointer(tok))
3501
0
        return false;
3502
0
    if (astIsUniqueSmartPointer(tok))
3503
0
        return true;
3504
0
    if (astIsContainerOwned(tok))
3505
0
        return true;
3506
0
    return false;
3507
0
}
3508
3509
// Check if dereferencing an object that doesn't have unique ownership
3510
static bool derefShared(const Token* tok)
3511
0
{
3512
0
    if (!tok)
3513
0
        return false;
3514
0
    if (!tok->isUnaryOp("*") && tok->str() != "[" && tok->str() != ".")
3515
0
        return false;
3516
0
    if (tok->str() == "." && tok->originalName() != "->")
3517
0
        return false;
3518
0
    const Token* ptrTok = tok->astOperand1();
3519
0
    return !hasUniqueOwnership(ptrTok);
3520
0
}
3521
3522
ValueFlow::Value ValueFlow::getLifetimeObjValue(const Token *tok, bool inconclusive)
3523
308
{
3524
308
    std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(tok, inconclusive);
3525
    // There should only be one lifetime
3526
308
    if (values.size() != 1)
3527
308
        return ValueFlow::Value{};
3528
0
    return values.front();
3529
308
}
3530
3531
template<class Predicate>
3532
static std::vector<ValueFlow::LifetimeToken> getLifetimeTokens(const Token* tok,
3533
                                                               bool escape,
3534
                                                               ValueFlow::Value::ErrorPath errorPath,
3535
                                                               Predicate pred,
3536
                                                               int depth = 20)
3537
17.4k
{
3538
17.4k
    if (!tok)
3539
0
        return std::vector<ValueFlow::LifetimeToken> {};
3540
17.4k
    if (Token::simpleMatch(tok, "..."))
3541
0
        return std::vector<ValueFlow::LifetimeToken>{};
3542
17.4k
    const Variable *var = tok->variable();
3543
17.4k
    if (pred(tok))
3544
0
        return {{tok, std::move(errorPath)}};
3545
17.4k
    if (depth < 0)
3546
0
        return {{tok, std::move(errorPath)}};
3547
17.4k
    if (var && var->declarationId() == tok->varId()) {
3548
17.4k
        if (var->isReference() || var->isRValueReference()) {
3549
0
            const Token * const varDeclEndToken = var->declEndToken();
3550
0
            if (!varDeclEndToken)
3551
0
                return {{tok, true, std::move(errorPath)}};
3552
0
            if (var->isArgument()) {
3553
0
                errorPath.emplace_back(varDeclEndToken, "Passed to reference.");
3554
0
                return {{tok, true, std::move(errorPath)}};
3555
0
            }
3556
0
            if (Token::Match(varDeclEndToken, "=|{")) {
3557
0
                errorPath.emplace_back(varDeclEndToken, "Assigned to reference.");
3558
0
                const Token *vartok = varDeclEndToken->astOperand2();
3559
0
                const bool temporary = isTemporary(true, vartok, nullptr, true);
3560
0
                const bool nonlocal = var->isStatic() || var->isGlobal();
3561
0
                if (vartok == tok || (nonlocal && temporary) ||
3562
0
                    (!escape && (var->isConst() || var->isRValueReference()) && temporary))
3563
0
                    return {{tok, true, std::move(errorPath)}};
3564
0
                if (vartok)
3565
0
                    return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3566
0
            } else if (Token::simpleMatch(var->nameToken()->astParent(), ":") &&
3567
0
                       var->nameToken()->astParent()->astParent() &&
3568
0
                       Token::simpleMatch(var->nameToken()->astParent()->astParent()->previous(), "for (")) {
3569
0
                errorPath.emplace_back(var->nameToken(), "Assigned to reference.");
3570
0
                const Token* vartok = var->nameToken();
3571
0
                if (vartok == tok)
3572
0
                    return {{tok, true, std::move(errorPath)}};
3573
0
                const Token* contok = var->nameToken()->astParent()->astOperand2();
3574
0
                if (astIsContainer(contok))
3575
0
                    return getLifetimeTokens(contok, escape, std::move(errorPath), pred, depth - 1);
3576
0
                return std::vector<ValueFlow::LifetimeToken>{};
3577
0
            } else {
3578
0
                return std::vector<ValueFlow::LifetimeToken> {};
3579
0
            }
3580
0
        }
3581
17.4k
    } else if (Token::Match(tok->previous(), "%name% (")) {
3582
0
        const Function *f = tok->previous()->function();
3583
0
        if (f) {
3584
0
            if (!Function::returnsReference(f))
3585
0
                return {{tok, std::move(errorPath)}};
3586
0
            std::vector<ValueFlow::LifetimeToken> result;
3587
0
            std::vector<const Token*> returns = Function::findReturns(f);
3588
0
            for (const Token* returnTok : returns) {
3589
0
                if (returnTok == tok)
3590
0
                    continue;
3591
0
                for (ValueFlow::LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, depth - returns.size())) {
3592
0
                    const Token* argvarTok = lt.token;
3593
0
                    const Variable* argvar = argvarTok->variable();
3594
0
                    if (!argvar)
3595
0
                        continue;
3596
0
                    const Token* argTok = nullptr;
3597
0
                    if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
3598
0
                        const int n = getArgumentPos(argvar, f);
3599
0
                        if (n < 0)
3600
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3601
0
                        std::vector<const Token*> args = getArguments(tok->previous());
3602
                        // TODO: Track lifetimes of default parameters
3603
0
                        if (n >= args.size())
3604
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3605
0
                        argTok = args[n];
3606
0
                        lt.errorPath.emplace_back(returnTok, "Return reference.");
3607
0
                        lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
3608
0
                    } else if (Token::Match(tok->tokAt(-2), ". %name% (") && !derefShared(tok->tokAt(-2)) &&
3609
0
                               exprDependsOnThis(argvarTok)) {
3610
0
                        argTok = tok->tokAt(-2)->astOperand1();
3611
0
                        lt.errorPath.emplace_back(returnTok, "Return reference that depends on 'this'.");
3612
0
                        lt.errorPath.emplace_back(tok->previous(),
3613
0
                                                  "Calling member function on '" + argTok->expressionString() + "'.");
3614
0
                    }
3615
0
                    if (argTok) {
3616
0
                        std::vector<ValueFlow::LifetimeToken> arglts = ValueFlow::LifetimeToken::setInconclusive(
3617
0
                            getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, depth - returns.size()),
3618
0
                            returns.size() > 1);
3619
0
                        result.insert(result.end(), arglts.cbegin(), arglts.cend());
3620
0
                    }
3621
0
                }
3622
0
            }
3623
0
            return result;
3624
0
        }
3625
0
        if (Token::Match(tok->tokAt(-2), ". %name% (") && tok->tokAt(-2)->originalName() != "->" && astIsContainer(tok->tokAt(-2)->astOperand1())) {
3626
0
            const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1());
3627
0
            const Library::Container::Yield y = library->getYield(tok->previous()->str());
3628
0
            if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {
3629
0
                errorPath.emplace_back(tok->previous(), "Accessing container.");
3630
0
                return ValueFlow::LifetimeToken::setAddressOf(
3631
0
                    getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, depth - 1),
3632
0
                    false);
3633
0
            }
3634
0
        }
3635
0
    } else if (Token::Match(tok, ".|::|[") || tok->isUnaryOp("*")) {
3636
3637
0
        const Token *vartok = tok;
3638
0
        while (vartok) {
3639
0
            if (vartok->str() == "[" || vartok->originalName() == "->" || vartok->isUnaryOp("*"))
3640
0
                vartok = vartok->astOperand1();
3641
0
            else if (vartok->str() == "." || vartok->str() == "::")
3642
0
                vartok = vartok->astOperand2();
3643
0
            else
3644
0
                break;
3645
0
        }
3646
3647
0
        if (!vartok)
3648
0
            return {{tok, std::move(errorPath)}};
3649
0
        if (derefShared(vartok->astParent())) {
3650
0
            for (const ValueFlow::Value &v : vartok->values()) {
3651
0
                if (!v.isLocalLifetimeValue())
3652
0
                    continue;
3653
0
                if (v.tokvalue == tok)
3654
0
                    continue;
3655
0
                errorPath.insert(errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
3656
0
                return getLifetimeTokens(v.tokvalue, escape, std::move(errorPath), pred, depth - 1);
3657
0
            }
3658
0
        } else {
3659
0
            return ValueFlow::LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1),
3660
0
                                                          !(astIsContainer(vartok) && Token::simpleMatch(vartok->astParent(), "[")));
3661
0
        }
3662
0
    } else if (Token::simpleMatch(tok, "{") && getArgumentStart(tok) &&
3663
0
               !Token::simpleMatch(getArgumentStart(tok), ",") && getArgumentStart(tok)->valueType()) {
3664
0
        const Token* vartok = getArgumentStart(tok);
3665
0
        auto vts = getParentValueTypes(tok);
3666
0
        auto it = std::find_if(vts.cbegin(), vts.cend(), [&](const ValueType& vt) {
3667
0
            return vt.isTypeEqual(vartok->valueType());
3668
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> > > > >)::$_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::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> > > > >)::$_5, int)::{lambda(ValueType const&)#1}::operator()(ValueType const&) const
Unexecuted instantiation: valueflow.cpp:getLifetimeTokens<ValueFlow::hasLifetimeToken(Token const*, Token const*)::$_6>(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*)::$_6, int)::{lambda(ValueType const&)#1}::operator()(ValueType const&) const
3669
0
        if (it != vts.end())
3670
0
            return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3671
0
    }
3672
17.4k
    return {{tok, std::move(errorPath)}};
3673
17.4k
}
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> > > > >)::$_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::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> > > > >)::$_5, int)
Line
Count
Source
3537
17.4k
{
3538
17.4k
    if (!tok)
3539
0
        return std::vector<ValueFlow::LifetimeToken> {};
3540
17.4k
    if (Token::simpleMatch(tok, "..."))
3541
0
        return std::vector<ValueFlow::LifetimeToken>{};
3542
17.4k
    const Variable *var = tok->variable();
3543
17.4k
    if (pred(tok))
3544
0
        return {{tok, std::move(errorPath)}};
3545
17.4k
    if (depth < 0)
3546
0
        return {{tok, std::move(errorPath)}};
3547
17.4k
    if (var && var->declarationId() == tok->varId()) {
3548
17.4k
        if (var->isReference() || var->isRValueReference()) {
3549
0
            const Token * const varDeclEndToken = var->declEndToken();
3550
0
            if (!varDeclEndToken)
3551
0
                return {{tok, true, std::move(errorPath)}};
3552
0
            if (var->isArgument()) {
3553
0
                errorPath.emplace_back(varDeclEndToken, "Passed to reference.");
3554
0
                return {{tok, true, std::move(errorPath)}};
3555
0
            }
3556
0
            if (Token::Match(varDeclEndToken, "=|{")) {
3557
0
                errorPath.emplace_back(varDeclEndToken, "Assigned to reference.");
3558
0
                const Token *vartok = varDeclEndToken->astOperand2();
3559
0
                const bool temporary = isTemporary(true, vartok, nullptr, true);
3560
0
                const bool nonlocal = var->isStatic() || var->isGlobal();
3561
0
                if (vartok == tok || (nonlocal && temporary) ||
3562
0
                    (!escape && (var->isConst() || var->isRValueReference()) && temporary))
3563
0
                    return {{tok, true, std::move(errorPath)}};
3564
0
                if (vartok)
3565
0
                    return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3566
0
            } else if (Token::simpleMatch(var->nameToken()->astParent(), ":") &&
3567
0
                       var->nameToken()->astParent()->astParent() &&
3568
0
                       Token::simpleMatch(var->nameToken()->astParent()->astParent()->previous(), "for (")) {
3569
0
                errorPath.emplace_back(var->nameToken(), "Assigned to reference.");
3570
0
                const Token* vartok = var->nameToken();
3571
0
                if (vartok == tok)
3572
0
                    return {{tok, true, std::move(errorPath)}};
3573
0
                const Token* contok = var->nameToken()->astParent()->astOperand2();
3574
0
                if (astIsContainer(contok))
3575
0
                    return getLifetimeTokens(contok, escape, std::move(errorPath), pred, depth - 1);
3576
0
                return std::vector<ValueFlow::LifetimeToken>{};
3577
0
            } else {
3578
0
                return std::vector<ValueFlow::LifetimeToken> {};
3579
0
            }
3580
0
        }
3581
17.4k
    } else if (Token::Match(tok->previous(), "%name% (")) {
3582
0
        const Function *f = tok->previous()->function();
3583
0
        if (f) {
3584
0
            if (!Function::returnsReference(f))
3585
0
                return {{tok, std::move(errorPath)}};
3586
0
            std::vector<ValueFlow::LifetimeToken> result;
3587
0
            std::vector<const Token*> returns = Function::findReturns(f);
3588
0
            for (const Token* returnTok : returns) {
3589
0
                if (returnTok == tok)
3590
0
                    continue;
3591
0
                for (ValueFlow::LifetimeToken& lt : getLifetimeTokens(returnTok, escape, errorPath, pred, depth - returns.size())) {
3592
0
                    const Token* argvarTok = lt.token;
3593
0
                    const Variable* argvar = argvarTok->variable();
3594
0
                    if (!argvar)
3595
0
                        continue;
3596
0
                    const Token* argTok = nullptr;
3597
0
                    if (argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
3598
0
                        const int n = getArgumentPos(argvar, f);
3599
0
                        if (n < 0)
3600
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3601
0
                        std::vector<const Token*> args = getArguments(tok->previous());
3602
                        // TODO: Track lifetimes of default parameters
3603
0
                        if (n >= args.size())
3604
0
                            return std::vector<ValueFlow::LifetimeToken> {};
3605
0
                        argTok = args[n];
3606
0
                        lt.errorPath.emplace_back(returnTok, "Return reference.");
3607
0
                        lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
3608
0
                    } else if (Token::Match(tok->tokAt(-2), ". %name% (") && !derefShared(tok->tokAt(-2)) &&
3609
0
                               exprDependsOnThis(argvarTok)) {
3610
0
                        argTok = tok->tokAt(-2)->astOperand1();
3611
0
                        lt.errorPath.emplace_back(returnTok, "Return reference that depends on 'this'.");
3612
0
                        lt.errorPath.emplace_back(tok->previous(),
3613
0
                                                  "Calling member function on '" + argTok->expressionString() + "'.");
3614
0
                    }
3615
0
                    if (argTok) {
3616
0
                        std::vector<ValueFlow::LifetimeToken> arglts = ValueFlow::LifetimeToken::setInconclusive(
3617
0
                            getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, depth - returns.size()),
3618
0
                            returns.size() > 1);
3619
0
                        result.insert(result.end(), arglts.cbegin(), arglts.cend());
3620
0
                    }
3621
0
                }
3622
0
            }
3623
0
            return result;
3624
0
        }
3625
0
        if (Token::Match(tok->tokAt(-2), ". %name% (") && tok->tokAt(-2)->originalName() != "->" && astIsContainer(tok->tokAt(-2)->astOperand1())) {
3626
0
            const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1());
3627
0
            const Library::Container::Yield y = library->getYield(tok->previous()->str());
3628
0
            if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {
3629
0
                errorPath.emplace_back(tok->previous(), "Accessing container.");
3630
0
                return ValueFlow::LifetimeToken::setAddressOf(
3631
0
                    getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, depth - 1),
3632
0
                    false);
3633
0
            }
3634
0
        }
3635
0
    } else if (Token::Match(tok, ".|::|[") || tok->isUnaryOp("*")) {
3636
3637
0
        const Token *vartok = tok;
3638
0
        while (vartok) {
3639
0
            if (vartok->str() == "[" || vartok->originalName() == "->" || vartok->isUnaryOp("*"))
3640
0
                vartok = vartok->astOperand1();
3641
0
            else if (vartok->str() == "." || vartok->str() == "::")
3642
0
                vartok = vartok->astOperand2();
3643
0
            else
3644
0
                break;
3645
0
        }
3646
3647
0
        if (!vartok)
3648
0
            return {{tok, std::move(errorPath)}};
3649
0
        if (derefShared(vartok->astParent())) {
3650
0
            for (const ValueFlow::Value &v : vartok->values()) {
3651
0
                if (!v.isLocalLifetimeValue())
3652
0
                    continue;
3653
0
                if (v.tokvalue == tok)
3654
0
                    continue;
3655
0
                errorPath.insert(errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
3656
0
                return getLifetimeTokens(v.tokvalue, escape, std::move(errorPath), pred, depth - 1);
3657
0
            }
3658
0
        } else {
3659
0
            return ValueFlow::LifetimeToken::setAddressOf(getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1),
3660
0
                                                          !(astIsContainer(vartok) && Token::simpleMatch(vartok->astParent(), "[")));
3661
0
        }
3662
0
    } else if (Token::simpleMatch(tok, "{") && getArgumentStart(tok) &&
3663
0
               !Token::simpleMatch(getArgumentStart(tok), ",") && getArgumentStart(tok)->valueType()) {
3664
0
        const Token* vartok = getArgumentStart(tok);
3665
0
        auto vts = getParentValueTypes(tok);
3666
0
        auto it = std::find_if(vts.cbegin(), vts.cend(), [&](const ValueType& vt) {
3667
0
            return vt.isTypeEqual(vartok->valueType());
3668
0
        });
3669
0
        if (it != vts.end())
3670
0
            return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, depth - 1);
3671
0
    }
3672
17.4k
    return {{tok, std::move(errorPath)}};
3673
17.4k
}
Unexecuted instantiation: valueflow.cpp:std::__1::vector<ValueFlow::LifetimeToken, std::__1::allocator<ValueFlow::LifetimeToken> > getLifetimeTokens<ValueFlow::hasLifetimeToken(Token const*, Token const*)::$_6>(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*)::$_6, int)
3674
3675
std::vector<ValueFlow::LifetimeToken> ValueFlow::getLifetimeTokens(const Token* tok, bool escape, ValueFlow::Value::ErrorPath errorPath)
3676
17.4k
{
3677
17.4k
    return getLifetimeTokens(tok, escape, std::move(errorPath), [](const Token*) {
3678
17.4k
        return false;
3679
17.4k
    });
3680
17.4k
}
3681
3682
bool ValueFlow::hasLifetimeToken(const Token* tok, const Token* lifetime)
3683
0
{
3684
0
    bool result = false;
3685
0
    getLifetimeTokens(tok, false, ValueFlow::Value::ErrorPath{}, [&](const Token* tok2) {
3686
0
        result = tok2->exprId() == lifetime->exprId();
3687
0
        return result;
3688
0
    });
3689
0
    return result;
3690
0
}
3691
3692
static const Token* getLifetimeToken(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf = nullptr)
3693
17.4k
{
3694
17.4k
    std::vector<ValueFlow::LifetimeToken> lts = ValueFlow::getLifetimeTokens(tok);
3695
17.4k
    if (lts.size() != 1)
3696
0
        return nullptr;
3697
17.4k
    if (lts.front().inconclusive)
3698
0
        return nullptr;
3699
17.4k
    if (addressOf)
3700
0
        *addressOf = lts.front().addressOf;
3701
17.4k
    errorPath.insert(errorPath.end(), lts.front().errorPath.cbegin(), lts.front().errorPath.cend());
3702
17.4k
    return lts.front().token;
3703
17.4k
}
3704
3705
const Variable* ValueFlow::getLifetimeVariable(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf)
3706
17.4k
{
3707
17.4k
    const Token* tok2 = getLifetimeToken(tok, errorPath, addressOf);
3708
17.4k
    if (tok2 && tok2->variable())
3709
17.4k
        return tok2->variable();
3710
0
    return nullptr;
3711
17.4k
}
3712
3713
const Variable* ValueFlow::getLifetimeVariable(const Token* tok)
3714
0
{
3715
0
    ValueFlow::Value::ErrorPath errorPath;
3716
0
    return getLifetimeVariable(tok, errorPath, nullptr);
3717
0
}
3718
3719
static bool isNotLifetimeValue(const ValueFlow::Value& val)
3720
0
{
3721
0
    return !val.isLifetimeValue();
3722
0
}
3723
3724
static bool isLifetimeOwned(const ValueType* vtParent)
3725
0
{
3726
0
    if (vtParent->container)
3727
0
        return !vtParent->container->view;
3728
0
    return vtParent->type == ValueType::CONTAINER;
3729
0
}
3730
3731
static bool isLifetimeOwned(const ValueType *vt, const ValueType *vtParent)
3732
0
{
3733
0
    if (!vtParent)
3734
0
        return false;
3735
0
    if (isLifetimeOwned(vtParent))
3736
0
        return true;
3737
0
    if (!vt)
3738
0
        return false;
3739
    // If converted from iterator to pointer then the iterator is most likely a pointer
3740
0
    if (vtParent->pointer == 1 && vt->pointer == 0 && vt->type == ValueType::ITERATOR)
3741
0
        return false;
3742
0
    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE) {
3743
0
        if (vt->pointer != vtParent->pointer)
3744
0
            return true;
3745
0
        if (vt->type != vtParent->type) {
3746
0
            if (vtParent->type == ValueType::RECORD)
3747
0
                return true;
3748
0
            if (isLifetimeOwned(vtParent))
3749
0
                return true;
3750
0
        }
3751
0
    }
3752
3753
0
    return false;
3754
0
}
3755
3756
static bool isLifetimeBorrowed(const ValueType *vt, const ValueType *vtParent)
3757
0
{
3758
0
    if (!vtParent)
3759
0
        return false;
3760
0
    if (!vt)
3761
0
        return false;
3762
0
    if (vt->pointer > 0 && vt->pointer == vtParent->pointer)
3763
0
        return true;
3764
0
    if (vtParent->container && vtParent->container->view)
3765
0
        return true;
3766
0
    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE && vtParent->container == vt->container) {
3767
0
        if (vtParent->pointer > vt->pointer)
3768
0
            return true;
3769
0
        if (vtParent->pointer < vt->pointer && vtParent->isIntegral())
3770
0
            return true;
3771
0
        if (vtParent->str() == vt->str())
3772
0
            return true;
3773
0
    }
3774
3775
0
    return false;
3776
0
}
3777
3778
static const Token* skipCVRefs(const Token* tok, const Token* endTok)
3779
0
{
3780
0
    while (tok != endTok && Token::Match(tok, "const|volatile|auto|&|&&"))
3781
0
        tok = tok->next();
3782
0
    return tok;
3783
0
}
3784
3785
static bool isNotEqual(std::pair<const Token*, const Token*> x, std::pair<const Token*, const Token*> y)
3786
527
{
3787
527
    const Token* start1 = x.first;
3788
527
    const Token* start2 = y.first;
3789
527
    if (start1 == nullptr || start2 == nullptr)
3790
527
        return false;
3791
0
    while (start1 != x.second && start2 != y.second) {
3792
0
        const Token* tok1 = skipCVRefs(start1, x.second);
3793
0
        if (tok1 != start1) {
3794
0
            start1 = tok1;
3795
0
            continue;
3796
0
        }
3797
0
        const Token* tok2 = skipCVRefs(start2, y.second);
3798
0
        if (tok2 != start2) {
3799
0
            start2 = tok2;
3800
0
            continue;
3801
0
        }
3802
0
        if (start1->str() != start2->str())
3803
0
            return true;
3804
0
        start1 = start1->next();
3805
0
        start2 = start2->next();
3806
0
    }
3807
0
    start1 = skipCVRefs(start1, x.second);
3808
0
    start2 = skipCVRefs(start2, y.second);
3809
0
    return !(start1 == x.second && start2 == y.second);
3810
0
}
3811
static bool isNotEqual(std::pair<const Token*, const Token*> x, const std::string& y)
3812
0
{
3813
0
    TokenList tokenList(nullptr);
3814
0
    std::istringstream istr(y);
3815
0
    tokenList.createTokens(istr);
3816
0
    return isNotEqual(x, std::make_pair(tokenList.front(), tokenList.back()));
3817
0
}
3818
static bool isNotEqual(std::pair<const Token*, const Token*> x, const ValueType* y)
3819
1.05k
{
3820
1.05k
    if (y == nullptr)
3821
580
        return false;
3822
474
    if (y->originalTypeName.empty())
3823
474
        return false;
3824
0
    return isNotEqual(x, y->originalTypeName);
3825
474
}
3826
3827
static bool isDifferentType(const Token* src, const Token* dst)
3828
527
{
3829
527
    const Type* t = Token::typeOf(src);
3830
527
    const Type* parentT = Token::typeOf(dst);
3831
527
    if (t && parentT) {
3832
0
        if (t->classDef && parentT->classDef && t->classDef != parentT->classDef)
3833
0
            return true;
3834
527
    } else {
3835
527
        std::pair<const Token*, const Token*> decl = Token::typeDecl(src);
3836
527
        std::pair<const Token*, const Token*> parentdecl = Token::typeDecl(dst);
3837
527
        if (isNotEqual(decl, parentdecl))
3838
0
            return true;
3839
527
        if (isNotEqual(decl, dst->valueType()))
3840
0
            return true;
3841
527
        if (isNotEqual(parentdecl, src->valueType()))
3842
0
            return true;
3843
527
    }
3844
527
    return false;
3845
527
}
3846
3847
bool ValueFlow::isLifetimeBorrowed(const Token *tok, const Settings &settings)
3848
0
{
3849
0
    if (!tok)
3850
0
        return true;
3851
0
    if (tok->str() == ",")
3852
0
        return true;
3853
0
    if (!tok->astParent())
3854
0
        return true;
3855
0
    const Token* parent = nullptr;
3856
0
    const ValueType* vt = tok->valueType();
3857
0
    std::vector<ValueType> vtParents = getParentValueTypes(tok, &settings, &parent);
3858
0
    for (const ValueType& vtParent : vtParents) {
3859
0
        if (isLifetimeBorrowed(vt, &vtParent))
3860
0
            return true;
3861
0
        if (isLifetimeOwned(vt, &vtParent))
3862
0
            return false;
3863
0
    }
3864
0
    if (parent) {
3865
0
        if (isDifferentType(tok, parent))
3866
0
            return false;
3867
0
    }
3868
0
    return true;
3869
0
}
3870
3871
static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings);
3872
3873
static void valueFlowLifetimeConstructor(Token *tok,
3874
                                         TokenList &tokenlist,
3875
                                         ErrorLogger *errorLogger,
3876
                                         const Settings &settings);
3877
3878
static bool isRangeForScope(const Scope* scope)
3879
0
{
3880
0
    if (!scope)
3881
0
        return false;
3882
0
    if (scope->type != Scope::eFor)
3883
0
        return false;
3884
0
    if (!scope->bodyStart)
3885
0
        return false;
3886
0
    if (!Token::simpleMatch(scope->bodyStart->previous(), ") {"))
3887
0
        return false;
3888
0
    return Token::simpleMatch(scope->bodyStart->linkAt(-1)->astOperand2(), ":");
3889
0
}
3890
3891
static const Token* getEndOfVarScope(const Variable* var)
3892
0
{
3893
0
    if (!var)
3894
0
        return nullptr;
3895
0
    const Scope* innerScope = var->scope();
3896
0
    const Scope* outerScope = innerScope;
3897
0
    if (var->typeStartToken() && var->typeStartToken()->scope())
3898
0
        outerScope = var->typeStartToken()->scope();
3899
0
    if (!innerScope && outerScope)
3900
0
        innerScope = outerScope;
3901
0
    if (!innerScope || !outerScope)
3902
0
        return nullptr;
3903
0
    if (!innerScope->isExecutable())
3904
0
        return nullptr;
3905
    // If the variable is defined in a for/while initializer then we want to
3906
    // pick one token after the end so forward analysis can analyze the exit
3907
    // conditions
3908
0
    if (innerScope != outerScope && outerScope->isExecutable() && innerScope->isLoopScope() &&
3909
0
        !isRangeForScope(innerScope))
3910
0
        return innerScope->bodyEnd->next();
3911
0
    return innerScope->bodyEnd;
3912
0
}
3913
3914
const Token* ValueFlow::getEndOfExprScope(const Token* tok, const Scope* defaultScope, bool smallest)
3915
2.94k
{
3916
2.94k
    const Token* end = nullptr;
3917
2.94k
    bool local = false;
3918
3.19k
    visitAstNodes(tok, [&](const Token* child) {
3919
3.19k
        if (const Variable* var = child->variable()) {
3920
2.39k
            local |= var->isLocal();
3921
2.39k
            if (var->isLocal() || var->isArgument()) {
3922
0
                const Token* varEnd = getEndOfVarScope(var);
3923
0
                if (!end || (smallest ? precedes(varEnd, end) : succeeds(varEnd, end)))
3924
0
                    end = varEnd;
3925
3926
0
                const Token* top = var->nameToken()->astTop();
3927
0
                if (top && Token::simpleMatch(top->tokAt(-1), "if (")) { // variable declared in if (...)
3928
0
                    const Token* elseTok = top->link()->linkAt(1);
3929
0
                    if (Token::simpleMatch(elseTok, "} else {") && tok->scope()->isNestedIn(elseTok->tokAt(2)->scope()))
3930
0
                        end = tok->scope()->bodyEnd;
3931
0
                }
3932
0
            }
3933
2.39k
        }
3934
3.19k
        return ChildrenToVisit::op1_and_op2;
3935
3.19k
    });
3936
2.94k
    if (!end && defaultScope)
3937
2.28k
        end = defaultScope->bodyEnd;
3938
2.94k
    if (!end) {
3939
665
        const Scope* scope = tok->scope();
3940
665
        if (scope)
3941
665
            end = scope->bodyEnd;
3942
        // If there is no local variables then pick the function scope
3943
665
        if (!local) {
3944
1.22k
            while (scope && scope->isLocal())
3945
557
                scope = scope->nestedIn;
3946
665
            if (scope && scope->isExecutable())
3947
665
                end = scope->bodyEnd;
3948
665
        }
3949
665
    }
3950
2.94k
    return end;
3951
2.94k
}
3952
3953
static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings)
3954
245
{
3955
    // Forward lifetimes to constructed variable
3956
245
    if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) {
3957
0
        std::list<ValueFlow::Value> values = tok->values();
3958
0
        values.remove_if(&isNotLifetimeValue);
3959
0
        valueFlowForward(nextAfterAstRightmostLeaf(tok), ValueFlow::getEndOfExprScope(tok), tok->previous(), std::move(values), tokenlist, errorLogger, settings);
3960
0
        return;
3961
0
    }
3962
245
    Token *parent = tok->astParent();
3963
245
    while (parent && parent->str() == ",")
3964
0
        parent = parent->astParent();
3965
245
    if (!parent)
3966
245
        return;
3967
    // Assignment
3968
0
    if (parent->str() == "=" && (!parent->astParent() || Token::simpleMatch(parent->astParent(), ";"))) {
3969
        // Rhs values..
3970
0
        if (!parent->astOperand2() || parent->astOperand2()->values().empty())
3971
0
            return;
3972
3973
0
        if (!ValueFlow::isLifetimeBorrowed(parent->astOperand2(), settings))
3974
0
            return;
3975
3976
0
        const Token* expr = getLHSVariableToken(parent);
3977
0
        if (!expr)
3978
0
            return;
3979
3980
0
        if (expr->exprId() == 0)
3981
0
            return;
3982
3983
0
        const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
3984
3985
        // Only forward lifetime values
3986
0
        std::list<ValueFlow::Value> values = parent->astOperand2()->values();
3987
0
        values.remove_if(&isNotLifetimeValue);
3988
        // Dont forward lifetimes that overlap
3989
0
        values.remove_if([&](const ValueFlow::Value& value) {
3990
0
            return findAstNode(value.tokvalue, [&](const Token* child) {
3991
0
                return child->exprId() == expr->exprId();
3992
0
            });
3993
0
        });
3994
3995
        // Skip RHS
3996
0
        Token* nextExpression = nextAfterAstRightmostLeaf(parent);
3997
3998
0
        if (expr->exprId() > 0) {
3999
0
            valueFlowForward(nextExpression, endOfVarScope->next(), expr, values, tokenlist, errorLogger, settings);
4000
4001
0
            for (ValueFlow::Value& val : values) {
4002
0
                if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address)
4003
0
                    val.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject;
4004
0
            }
4005
            // TODO: handle `[`
4006
0
            if (Token::simpleMatch(parent->astOperand1(), ".")) {
4007
0
                const Token* parentLifetime =
4008
0
                    getParentLifetime(tokenlist.isCPP(), parent->astOperand1()->astOperand2(), &settings.library);
4009
0
                if (parentLifetime && parentLifetime->exprId() > 0) {
4010
0
                    valueFlowForward(nextExpression, endOfVarScope, parentLifetime, values, tokenlist, errorLogger, settings);
4011
0
                }
4012
0
            }
4013
0
        }
4014
        // Constructor
4015
0
    } else if (Token::simpleMatch(parent, "{") && !isScopeBracket(parent)) {
4016
0
        valueFlowLifetimeConstructor(parent, tokenlist, errorLogger, settings);
4017
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
4018
        // Function call
4019
0
    } else if (Token::Match(parent->previous(), "%name% (")) {
4020
0
        valueFlowLifetimeFunction(parent->previous(), tokenlist, errorLogger, settings);
4021
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
4022
        // Variable
4023
0
    } else if (tok->variable() && tok->variable()->scope()) {
4024
0
        const Variable *var = tok->variable();
4025
0
        const Token *endOfVarScope = var->scope()->bodyEnd;
4026
4027
0
        std::list<ValueFlow::Value> values = tok->values();
4028
0
        Token *nextExpression = nextAfterAstRightmostLeaf(parent);
4029
        // Only forward lifetime values
4030
0
        values.remove_if(&isNotLifetimeValue);
4031
0
        valueFlowForward(nextExpression, endOfVarScope, tok, std::move(values), tokenlist, errorLogger, settings);
4032
        // Cast
4033
0
    } else if (parent->isCast()) {
4034
0
        std::list<ValueFlow::Value> values = tok->values();
4035
        // Only forward lifetime values
4036
0
        values.remove_if(&isNotLifetimeValue);
4037
0
        for (ValueFlow::Value& value:values)
4038
0
            setTokenValue(parent, std::move(value), settings);
4039
0
        valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
4040
0
    }
4041
0
}
4042
4043
struct LifetimeStore {
4044
    const Token* argtok{};
4045
    std::string message;
4046
    ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object;
4047
    ErrorPath errorPath;
4048
    bool inconclusive{};
4049
    bool forward = true;
4050
4051
    struct Context {
4052
        Token* tok{};
4053
        TokenList* tokenlist{};
4054
        ErrorLogger* errorLogger{};
4055
        const Settings* settings{};
4056
    };
4057
4058
0
    LifetimeStore() = default;
4059
4060
    LifetimeStore(const Token* argtok,
4061
                  std::string message,
4062
                  ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object,
4063
                  bool inconclusive = false)
4064
        : argtok(argtok),
4065
        message(std::move(message)),
4066
        type(type),
4067
        inconclusive(inconclusive)
4068
0
    {}
4069
4070
    template<class F>
4071
    static void forEach(const std::vector<const Token*>& argtoks,
4072
                        const std::string& message,
4073
                        ValueFlow::Value::LifetimeKind type,
4074
0
                        F f) {
4075
0
        std::map<const Token*, Context> forwardToks;
4076
0
        for (const Token* arg : argtoks) {
4077
0
            LifetimeStore ls{arg, message, type};
4078
0
            Context c{};
4079
0
            ls.mContext = &c;
4080
0
            ls.forward = false;
4081
0
            f(ls);
4082
0
            if (c.tok)
4083
0
                forwardToks[c.tok] = c;
4084
0
        }
4085
0
        for (const auto& p : forwardToks) {
4086
0
            const Context& c = p.second;
4087
0
            valueFlowForwardLifetime(c.tok, *c.tokenlist, c.errorLogger, *c.settings);
4088
0
        }
4089
0
    }
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<valueFlowLifetimeConstructor(Token*, TokenList&, ErrorLogger*, Settings const&)::$_65>(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&)::$_65)
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<valueFlowLifetimeClassConstructor(Token*, Type const*, 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, valueFlowLifetimeClassConstructor(Token*, Type const*, TokenList&, ErrorLogger*, Settings const&)::$_62)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeUserConstructor(Token*, Function const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, TokenList&, 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*> > const&, TokenList&, ErrorLogger*, Settings const&)::$_59)
Unexecuted instantiation: valueflow.cpp:void LifetimeStore::forEach<valueFlowLifetimeUserConstructor(Token*, Function const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, TokenList&, 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, valueFlowLifetimeUserConstructor(Token*, Function const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<Token const*, std::__1::allocator<Token const*> > const&, TokenList&, ErrorLogger*, Settings const&)::$_60)
4090
4091
0
    static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, const TokenList &tokenlist, const Settings& settings, ErrorLogger *errorLogger) {
4092
0
        if (!var)
4093
0
            return LifetimeStore{};
4094
0
        if (!var->isArgument())
4095
0
            return LifetimeStore{};
4096
0
        const int n = getArgumentPos(var, f);
4097
0
        if (n < 0)
4098
0
            return LifetimeStore{};
4099
0
        std::vector<const Token *> args = getArguments(tok);
4100
0
        if (n >= args.size()) {
4101
0
            if (settings.debugwarnings)
4102
0
                bailout(tokenlist,
4103
0
                        errorLogger,
4104
0
                        tok,
4105
0
                        "Argument mismatch: Function '" + tok->str() + "' returning lifetime from argument index " +
4106
0
                        std::to_string(n) + " but only " + std::to_string(args.size()) +
4107
0
                        " arguments are available.");
4108
0
            return LifetimeStore{};
4109
0
        }
4110
0
        const Token *argtok2 = args[n];
4111
0
        return LifetimeStore{argtok2, "Passed to '" + tok->expressionString() + "'.", ValueFlow::Value::LifetimeKind::Object};
4112
0
    }
4113
4114
    template<class Predicate>
4115
    bool byRef(Token* tok,
4116
               TokenList& tokenlist,
4117
               ErrorLogger* errorLogger,
4118
               const Settings& settings,
4119
               Predicate pred,
4120
               SourceLocation loc = SourceLocation::current()) const
4121
0
    {
4122
0
        if (!argtok)
4123
0
            return false;
4124
0
        bool update = false;
4125
0
        for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok)) {
4126
0
            if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4127
0
                continue;
4128
0
            ErrorPath er = errorPath;
4129
0
            er.insert(er.end(), lt.errorPath.cbegin(), lt.errorPath.cend());
4130
0
            if (!lt.token)
4131
0
                return false;
4132
0
            if (!pred(lt.token))
4133
0
                return false;
4134
0
            er.emplace_back(argtok, message);
4135
4136
0
            ValueFlow::Value value;
4137
0
            value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4138
0
            value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4139
0
            value.tokvalue = lt.token;
4140
0
            value.errorPath = std::move(er);
4141
0
            value.lifetimeKind = type;
4142
0
            value.setInconclusive(lt.inconclusive || inconclusive);
4143
            // Don't add the value a second time
4144
0
            if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4145
0
                return false;
4146
0
            if (settings.debugnormal)
4147
0
                setSourceLocation(value, loc, tok);
4148
0
            setTokenValue(tok, std::move(value), settings);
4149
0
            update = true;
4150
0
        }
4151
0
        if (update && forward)
4152
0
            forwardLifetime(tok, tokenlist, errorLogger, settings);
4153
0
        return update;
4154
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
4155
4156
    bool byRef(Token* tok,
4157
               TokenList& tokenlist,
4158
               ErrorLogger* errorLogger,
4159
               const Settings& settings,
4160
               SourceLocation loc = SourceLocation::current()) const
4161
0
    {
4162
0
        return byRef(
4163
0
            tok,
4164
0
            tokenlist,
4165
0
            errorLogger,
4166
0
            settings,
4167
0
            [](const Token*) {
4168
0
            return true;
4169
0
        },
4170
0
            loc);
4171
0
    }
4172
4173
    template<class Predicate>
4174
    bool byVal(Token* tok,
4175
               TokenList& tokenlist,
4176
               ErrorLogger* errorLogger,
4177
               const Settings& settings,
4178
               Predicate pred,
4179
               SourceLocation loc = SourceLocation::current()) const
4180
0
    {
4181
0
        if (!argtok)
4182
0
            return false;
4183
0
        bool update = false;
4184
0
        if (argtok->values().empty()) {
4185
0
            ErrorPath er;
4186
0
            er.emplace_back(argtok, message);
4187
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(argtok)) {
4188
0
                if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4189
0
                    continue;
4190
0
                ValueFlow::Value value;
4191
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4192
0
                value.tokvalue = lt.token;
4193
0
                value.capturetok = argtok;
4194
0
                value.errorPath = er;
4195
0
                value.lifetimeKind = type;
4196
0
                value.setInconclusive(inconclusive || lt.inconclusive);
4197
0
                const Variable* var = lt.token->variable();
4198
0
                if (var && var->isArgument()) {
4199
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::Argument;
4200
0
                } else {
4201
0
                    continue;
4202
0
                }
4203
                // Don't add the value a second time
4204
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4205
0
                    continue;
4206
0
                if (settings.debugnormal)
4207
0
                    setSourceLocation(value, loc, tok);
4208
0
                setTokenValue(tok, std::move(value), settings);
4209
0
                update = true;
4210
0
            }
4211
0
        }
4212
0
        for (const ValueFlow::Value &v : argtok->values()) {
4213
0
            if (!v.isLifetimeValue())
4214
0
                continue;
4215
0
            const Token *tok3 = v.tokvalue;
4216
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok3)) {
4217
0
                if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4218
0
                    continue;
4219
0
                ErrorPath er = v.errorPath;
4220
0
                er.insert(er.end(), lt.errorPath.cbegin(), lt.errorPath.cend());
4221
0
                if (!lt.token)
4222
0
                    return false;
4223
0
                if (!pred(lt.token))
4224
0
                    return false;
4225
0
                er.emplace_back(argtok, message);
4226
0
                er.insert(er.end(), errorPath.cbegin(), errorPath.cend());
4227
4228
0
                ValueFlow::Value value;
4229
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4230
0
                value.lifetimeScope = v.lifetimeScope;
4231
0
                value.path = v.path;
4232
0
                value.tokvalue = lt.token;
4233
0
                value.capturetok = argtok;
4234
0
                value.errorPath = std::move(er);
4235
0
                value.lifetimeKind = type;
4236
0
                value.setInconclusive(lt.inconclusive || v.isInconclusive() || inconclusive);
4237
                // Don't add the value a second time
4238
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4239
0
                    continue;
4240
0
                if (settings.debugnormal)
4241
0
                    setSourceLocation(value, loc, tok);
4242
0
                setTokenValue(tok, std::move(value), settings);
4243
0
                update = true;
4244
0
            }
4245
0
        }
4246
0
        if (update && forward)
4247
0
            forwardLifetime(tok, tokenlist, errorLogger, settings);
4248
0
        return update;
4249
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
4250
4251
    bool byVal(Token* tok,
4252
               TokenList& tokenlist,
4253
               ErrorLogger* errorLogger,
4254
               const Settings& settings,
4255
               SourceLocation loc = SourceLocation::current()) const
4256
0
    {
4257
0
        return byVal(
4258
0
            tok,
4259
0
            tokenlist,
4260
0
            errorLogger,
4261
0
            settings,
4262
0
            [](const Token*) {
4263
0
            return true;
4264
0
        },
4265
0
            loc);
4266
0
    }
4267
4268
    template<class Predicate>
4269
    bool byDerefCopy(Token* tok,
4270
                     TokenList& tokenlist,
4271
                     ErrorLogger* errorLogger,
4272
                     const Settings& settings,
4273
                     Predicate pred,
4274
                     SourceLocation loc = SourceLocation::current()) const
4275
0
    {
4276
0
        bool update = false;
4277
0
        if (!settings.certainty.isEnabled(Certainty::inconclusive) && inconclusive)
4278
0
            return update;
4279
0
        if (!argtok)
4280
0
            return update;
4281
0
        if (!tok)
4282
0
            return update;
4283
0
        for (const ValueFlow::Value &v : argtok->values()) {
4284
0
            if (!v.isLifetimeValue())
4285
0
                continue;
4286
0
            const Token *tok2 = v.tokvalue;
4287
0
            ErrorPath er = v.errorPath;
4288
0
            const Variable *var = ValueFlow::getLifetimeVariable(tok2, er);
4289
            // TODO: the inserted data is never used
4290
0
            er.insert(er.end(), errorPath.cbegin(), errorPath.cend());
4291
0
            if (!var)
4292
0
                continue;
4293
0
            const Token * const varDeclEndToken = var->declEndToken();
4294
0
            for (const Token *tok3 = tok; tok3 && tok3 != varDeclEndToken; tok3 = tok3->previous()) {
4295
0
                if (tok3->varId() == var->declarationId()) {
4296
0
                    update |= LifetimeStore{tok3, message, type, inconclusive}
4297
0
                    .byVal(tok, tokenlist, errorLogger, settings, pred, loc);
4298
0
                    break;
4299
0
                }
4300
0
            }
4301
0
        }
4302
0
        return update;
4303
0
    }
4304
4305
    bool byDerefCopy(Token* tok,
4306
                     TokenList& tokenlist,
4307
                     ErrorLogger* errorLogger,
4308
                     const Settings& settings,
4309
                     SourceLocation loc = SourceLocation::current()) const
4310
0
    {
4311
0
        return byDerefCopy(
4312
0
            tok,
4313
0
            tokenlist,
4314
0
            errorLogger,
4315
0
            settings,
4316
0
            [](const Token*) {
4317
0
            return true;
4318
0
        },
4319
0
            loc);
4320
0
    }
4321
4322
private:
4323
    Context* mContext{};
4324
0
    void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings& settings) const {
4325
0
        if (mContext) {
4326
0
            mContext->tok = tok;
4327
0
            mContext->tokenlist = &tokenlist;
4328
0
            mContext->errorLogger = errorLogger;
4329
0
            mContext->settings = &settings;
4330
0
        }
4331
0
        valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4332
0
    }
4333
};
4334
4335
static bool hasBorrowingVariables(const std::list<Variable>& vars, const std::vector<const Token*>& args, int depth = 10)
4336
0
{
4337
0
    if (depth < 0)
4338
0
        return true;
4339
0
    return std::any_of(vars.cbegin(), vars.cend(), [&](const Variable& var) {
4340
0
        if (const ValueType* vt = var.valueType()) {
4341
0
            if (vt->pointer > 0 &&
4342
0
                std::none_of(args.begin(), args.end(), [vt](const Token* arg) {
4343
0
                return arg->valueType() && arg->valueType()->type == vt->type;
4344
0
            }))
4345
0
                return false;
4346
0
            if (vt->pointer > 0)
4347
0
                return true;
4348
0
            if (vt->reference != Reference::None)
4349
0
                return true;
4350
0
            if (vt->isPrimitive())
4351
0
                return false;
4352
0
            if (vt->isEnum())
4353
0
                return false;
4354
            // TODO: Check container inner type
4355
0
            if (vt->type == ValueType::CONTAINER && vt->container)
4356
0
                return vt->container->view;
4357
0
            if (vt->typeScope)
4358
0
                return hasBorrowingVariables(vt->typeScope->varlist, args, depth - 1);
4359
0
        }
4360
0
        return true;
4361
0
    });
4362
0
}
4363
4364
static void valueFlowLifetimeUserConstructor(Token* tok,
4365
                                             const Function* constructor,
4366
                                             const std::string& name,
4367
                                             const std::vector<const Token*>& args,
4368
                                             TokenList& tokenlist,
4369
                                             ErrorLogger* errorLogger,
4370
                                             const Settings& settings)
4371
0
{
4372
0
    if (!constructor)
4373
0
        return;
4374
0
    std::unordered_map<const Token*, const Variable*> argToParam;
4375
0
    for (std::size_t i = 0; i < args.size(); i++)
4376
0
        argToParam[args[i]] = constructor->getArgumentVar(i);
4377
0
    if (const Token* initList = constructor->constructorMemberInitialization()) {
4378
0
        std::unordered_map<const Variable*, LifetimeCapture> paramCapture;
4379
0
        for (const Token* tok2 : astFlatten(initList->astOperand2(), ",")) {
4380
0
            if (!Token::simpleMatch(tok2, "("))
4381
0
                continue;
4382
0
            if (!tok2->astOperand1())
4383
0
                continue;
4384
0
            if (!tok2->astOperand2())
4385
0
                continue;
4386
0
            const Variable* var = tok2->astOperand1()->variable();
4387
0
            const Token* expr = tok2->astOperand2();
4388
0
            if (!var)
4389
0
                continue;
4390
0
            if (!ValueFlow::isLifetimeBorrowed(expr, settings))
4391
0
                continue;
4392
0
            const Variable* argvar = ValueFlow::getLifetimeVariable(expr);
4393
0
            if (var->isReference() || var->isRValueReference()) {
4394
0
                if (argvar && argvar->isArgument() && (argvar->isReference() || argvar->isRValueReference())) {
4395
0
                    paramCapture[argvar] = LifetimeCapture::ByReference;
4396
0
                }
4397
0
            } else {
4398
0
                bool found = false;
4399
0
                for (const ValueFlow::Value& v : expr->values()) {
4400
0
                    if (!v.isLifetimeValue())
4401
0
                        continue;
4402
0
                    if (v.path > 0)
4403
0
                        continue;
4404
0
                    if (!v.tokvalue)
4405
0
                        continue;
4406
0
                    const Variable* lifeVar = v.tokvalue->variable();
4407
0
                    if (!lifeVar)
4408
0
                        continue;
4409
0
                    LifetimeCapture c = LifetimeCapture::Undefined;
4410
0
                    if (!v.isArgumentLifetimeValue() && (lifeVar->isReference() || lifeVar->isRValueReference()))
4411
0
                        c = LifetimeCapture::ByReference;
4412
0
                    else if (v.isArgumentLifetimeValue())
4413
0
                        c = LifetimeCapture::ByValue;
4414
0
                    if (c != LifetimeCapture::Undefined) {
4415
0
                        paramCapture[lifeVar] = c;
4416
0
                        found = true;
4417
0
                    }
4418
0
                }
4419
0
                if (!found && argvar && argvar->isArgument())
4420
0
                    paramCapture[argvar] = LifetimeCapture::ByValue;
4421
0
            }
4422
0
        }
4423
        // TODO: Use SubExpressionAnalyzer for members
4424
0
        LifetimeStore::forEach(args,
4425
0
                               "Passed to constructor of '" + name + "'.",
4426
0
                               ValueFlow::Value::LifetimeKind::SubObject,
4427
0
                               [&](const LifetimeStore& ls) {
4428
0
            const Variable* paramVar = argToParam.at(ls.argtok);
4429
0
            if (paramCapture.count(paramVar) == 0)
4430
0
                return;
4431
0
            const LifetimeCapture c = paramCapture.at(paramVar);
4432
0
            if (c == LifetimeCapture::ByReference)
4433
0
                ls.byRef(tok, tokenlist, errorLogger, settings);
4434
0
            else
4435
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
4436
0
        });
4437
0
    } else if (hasBorrowingVariables(constructor->nestedIn->varlist, args)) {
4438
0
        LifetimeStore::forEach(args,
4439
0
                               "Passed to constructor of '" + name + "'.",
4440
0
                               ValueFlow::Value::LifetimeKind::SubObject,
4441
0
                               [&](LifetimeStore& ls) {
4442
0
            ls.inconclusive = true;
4443
0
            const Variable* var = argToParam.at(ls.argtok);
4444
0
            if (var && !var->isConst() && var->isReference())
4445
0
                ls.byRef(tok, tokenlist, errorLogger, settings);
4446
0
            else
4447
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
4448
0
        });
4449
0
    }
4450
0
}
4451
4452
static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings)
4453
245
{
4454
245
    if (!Token::Match(tok, "%name% ("))
4455
0
        return;
4456
245
    Token* memtok = nullptr;
4457
245
    if (Token::Match(tok->astParent(), ". %name% (") && astIsRHS(tok))
4458
0
        memtok = tok->astParent()->astOperand1();
4459
245
    const int returnContainer = settings.library.returnValueContainer(tok);
4460
245
    if (returnContainer >= 0) {
4461
0
        std::vector<const Token *> args = getArguments(tok);
4462
0
        for (int argnr = 1; argnr <= args.size(); ++argnr) {
4463
0
            const Library::ArgumentChecks::IteratorInfo *i = settings.library.getArgIteratorInfo(tok, argnr);
4464
0
            if (!i)
4465
0
                continue;
4466
0
            if (i->container != returnContainer)
4467
0
                continue;
4468
0
            const Token * const argTok = args[argnr - 1];
4469
0
            bool forward = false;
4470
0
            for (ValueFlow::Value val : argTok->values()) {
4471
0
                if (!val.isLifetimeValue())
4472
0
                    continue;
4473
0
                val.errorPath.emplace_back(argTok, "Passed to '" + tok->str() + "'.");
4474
0
                setTokenValue(tok->next(), std::move(val), settings);
4475
0
                forward = true;
4476
0
            }
4477
            // Check if lifetime is available to avoid adding the lifetime twice
4478
0
            if (forward) {
4479
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4480
0
                break;
4481
0
            }
4482
0
        }
4483
245
    } else if (Token::Match(tok->tokAt(-2), "std :: ref|cref|tie|front_inserter|back_inserter")) {
4484
0
        for (const Token *argtok : getArguments(tok)) {
4485
0
            LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byRef(
4486
0
                tok->next(), tokenlist, errorLogger, settings);
4487
0
        }
4488
245
    } else if (Token::Match(tok->tokAt(-2), "std :: make_tuple|tuple_cat|make_pair|make_reverse_iterator|next|prev|move|bind")) {
4489
0
        for (const Token *argtok : getArguments(tok)) {
4490
0
            LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byVal(
4491
0
                tok->next(), tokenlist, errorLogger, settings);
4492
0
        }
4493
245
    } else if (memtok && Token::Match(tok->astParent(), ". push_back|push_front|insert|push|assign") &&
4494
245
               astIsContainer(memtok)) {
4495
0
        std::vector<const Token *> args = getArguments(tok);
4496
0
        const std::size_t n = args.size();
4497
0
        if (n > 1 && Token::typeStr(args[n - 2]) == Token::typeStr(args[n - 1]) &&
4498
0
            (((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) ||
4499
0
              (astIsPointer(args[n - 2]) && astIsPointer(args[n - 1]))))) {
4500
0
            LifetimeStore{
4501
0
                args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
4502
0
            .byDerefCopy(memtok, tokenlist, errorLogger, settings);
4503
0
        } else if (!args.empty() && ValueFlow::isLifetimeBorrowed(args.back(), settings)) {
4504
0
            LifetimeStore{
4505
0
                args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
4506
0
            .byVal(memtok, tokenlist, errorLogger, settings);
4507
0
        }
4508
245
    } else if (tok->function()) {
4509
0
        const Function *f = tok->function();
4510
0
        if (f->isConstructor()) {
4511
0
            valueFlowLifetimeUserConstructor(tok->next(), f, tok->str(), getArguments(tok), tokenlist, errorLogger, settings);
4512
0
            return;
4513
0
        }
4514
0
        if (Function::returnsReference(f))
4515
0
            return;
4516
0
        std::vector<const Token*> returns = Function::findReturns(f);
4517
0
        const bool inconclusive = returns.size() > 1;
4518
0
        bool update = false;
4519
0
        for (const Token* returnTok : returns) {
4520
0
            if (returnTok == tok)
4521
0
                continue;
4522
0
            const Variable *returnVar = ValueFlow::getLifetimeVariable(returnTok);
4523
0
            if (returnVar && returnVar->isArgument() && (returnVar->isConst() || !isVariableChanged(returnVar, &settings, tokenlist.isCPP()))) {
4524
0
                LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, tokenlist, settings, errorLogger);
4525
0
                ls.inconclusive = inconclusive;
4526
0
                ls.forward = false;
4527
0
                update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
4528
0
            }
4529
0
            for (const ValueFlow::Value &v : returnTok->values()) {
4530
0
                if (!v.isLifetimeValue())
4531
0
                    continue;
4532
0
                if (!v.tokvalue)
4533
0
                    continue;
4534
0
                if (memtok &&
4535
0
                    (contains({ValueFlow::Value::LifetimeScope::ThisPointer, ValueFlow::Value::LifetimeScope::ThisValue},
4536
0
                              v.lifetimeScope) ||
4537
0
                     exprDependsOnThis(v.tokvalue))) {
4538
0
                    LifetimeStore ls = LifetimeStore{memtok,
4539
0
                                                     "Passed to member function '" + tok->expressionString() + "'.",
4540
0
                                                     ValueFlow::Value::LifetimeKind::Object};
4541
0
                    ls.inconclusive = inconclusive;
4542
0
                    ls.forward = false;
4543
0
                    ls.errorPath = v.errorPath;
4544
0
                    ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
4545
0
                    int thisIndirect = v.lifetimeScope == ValueFlow::Value::LifetimeScope::ThisValue ? 0 : 1;
4546
0
                    if (derefShared(memtok->astParent()))
4547
0
                        thisIndirect--;
4548
0
                    if (thisIndirect == -1)
4549
0
                        update |= ls.byDerefCopy(tok->next(), tokenlist, errorLogger, settings);
4550
0
                    else if (thisIndirect == 0)
4551
0
                        update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
4552
0
                    else if (thisIndirect == 1)
4553
0
                        update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings);
4554
0
                    continue;
4555
0
                }
4556
0
                const Variable *var = v.tokvalue->variable();
4557
0
                LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, var, tokenlist, settings, errorLogger);
4558
0
                if (!ls.argtok)
4559
0
                    continue;
4560
0
                ls.forward = false;
4561
0
                ls.inconclusive = inconclusive;
4562
0
                ls.errorPath = v.errorPath;
4563
0
                ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
4564
0
                if (!v.isArgumentLifetimeValue() && (var->isReference() || var->isRValueReference())) {
4565
0
                    update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings);
4566
0
                } else if (v.isArgumentLifetimeValue()) {
4567
0
                    update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
4568
0
                }
4569
0
            }
4570
0
        }
4571
0
        if (update)
4572
0
            valueFlowForwardLifetime(tok->next(), tokenlist, errorLogger, settings);
4573
245
    } else if (tok->valueType()) {
4574
        // TODO: Propagate lifetimes with library functions
4575
245
        if (settings.library.getFunction(tok->previous()))
4576
0
            return;
4577
        // Assume constructing the valueType
4578
245
        valueFlowLifetimeConstructor(tok->next(), tokenlist, errorLogger, settings);
4579
245
        valueFlowForwardLifetime(tok->next(), tokenlist, errorLogger, settings);
4580
245
    } else {
4581
0
        const std::string& retVal = settings.library.returnValue(tok);
4582
0
        if (startsWith(retVal, "arg")) {
4583
0
            std::size_t iArg{};
4584
0
            try {
4585
0
                iArg = strToInt<std::size_t>(retVal.substr(3));
4586
0
            } catch (...) {
4587
0
                return;
4588
0
            }
4589
0
            std::vector<const Token*> args = getArguments(tok);
4590
0
            if (iArg > 0 && iArg <= args.size()) {
4591
0
                const Token* varTok = args[iArg - 1];
4592
0
                if (varTok->variable() && varTok->variable()->isLocal())
4593
0
                    LifetimeStore{ varTok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Address }.byRef(
4594
0
                    tok->next(), tokenlist, errorLogger, settings);
4595
0
            }
4596
0
        }
4597
0
    }
4598
245
}
4599
4600
static bool isScope(const Token* tok)
4601
1.81k
{
4602
1.81k
    if (!tok)
4603
0
        return false;
4604
1.81k
    if (!Token::simpleMatch(tok, "{"))
4605
245
        return false;
4606
1.57k
    const Scope* scope = tok->scope();
4607
1.57k
    if (!scope)
4608
0
        return false;
4609
1.57k
    if (!scope->bodyStart)
4610
0
        return false;
4611
1.57k
    return scope->bodyStart == tok;
4612
1.57k
}
4613
4614
static const Function* findConstructor(const Scope* scope, const Token* tok, const std::vector<const Token*>& args)
4615
0
{
4616
0
    if (!tok)
4617
0
        return nullptr;
4618
0
    const Function* f = tok->function();
4619
0
    if (!f && tok->astOperand1())
4620
0
        f = tok->astOperand1()->function();
4621
    // Search for a constructor
4622
0
    if (!f || !f->isConstructor()) {
4623
0
        f = nullptr;
4624
0
        std::vector<const Function*> candidates;
4625
0
        for (const Function& function : scope->functionList) {
4626
0
            if (function.minArgCount() > args.size())
4627
0
                continue;
4628
0
            if (!function.isConstructor())
4629
0
                continue;
4630
0
            candidates.push_back(&function);
4631
0
        }
4632
        // TODO: Narrow the candidates
4633
0
        if (candidates.size() == 1)
4634
0
            f = candidates.front();
4635
0
    }
4636
0
    if (!f)
4637
0
        return nullptr;
4638
0
    return f;
4639
0
}
4640
4641
static void valueFlowLifetimeClassConstructor(Token* tok,
4642
                                              const Type* t,
4643
                                              TokenList& tokenlist,
4644
                                              ErrorLogger* errorLogger,
4645
                                              const Settings& settings)
4646
0
{
4647
0
    if (!Token::Match(tok, "(|{"))
4648
0
        return;
4649
0
    if (isScope(tok))
4650
0
        return;
4651
0
    if (!t) {
4652
0
        if (tok->valueType() && tok->valueType()->type != ValueType::RECORD)
4653
0
            return;
4654
0
        if (tok->str() != "{" && !Token::Match(tok->previous(), "%var% (") && !isVariableDecl(tok->previous()))
4655
0
            return;
4656
        // If the type is unknown then assume it captures by value in the
4657
        // constructor, but make each lifetime inconclusive
4658
0
        std::vector<const Token*> args = getArguments(tok);
4659
0
        LifetimeStore::forEach(args,
4660
0
                               "Passed to initializer list.",
4661
0
                               ValueFlow::Value::LifetimeKind::SubObject,
4662
0
                               [&](LifetimeStore& ls) {
4663
0
            ls.inconclusive = true;
4664
0
            ls.byVal(tok, tokenlist, errorLogger, settings);
4665
0
        });
4666
0
        return;
4667
0
    }
4668
0
    const Scope* scope = t->classScope;
4669
0
    if (!scope)
4670
0
        return;
4671
    // Aggregate constructor
4672
0
    if (t->derivedFrom.empty() && (t->isClassType() || t->isStructType())) {
4673
0
        std::vector<const Token*> args = getArguments(tok);
4674
0
        if (scope->numConstructors == 0) {
4675
0
            auto it = scope->varlist.cbegin();
4676
0
            LifetimeStore::forEach(
4677
0
                args,
4678
0
                "Passed to constructor of '" + t->name() + "'.",
4679
0
                ValueFlow::Value::LifetimeKind::SubObject,
4680
0
                [&](const LifetimeStore& ls) {
4681
                // Skip static variable
4682
0
                it = std::find_if(it, scope->varlist.cend(), [](const Variable& var) {
4683
0
                    return !var.isStatic();
4684
0
                });
4685
0
                if (it == scope->varlist.cend())
4686
0
                    return;
4687
0
                const Variable& var = *it;
4688
0
                if (var.isReference() || var.isRValueReference()) {
4689
0
                    ls.byRef(tok, tokenlist, errorLogger, settings);
4690
0
                } else if (ValueFlow::isLifetimeBorrowed(ls.argtok, settings)) {
4691
0
                    ls.byVal(tok, tokenlist, errorLogger, settings);
4692
0
                }
4693
0
                it++;
4694
0
            });
4695
0
        } else {
4696
0
            const Function* constructor = findConstructor(scope, tok, args);
4697
0
            valueFlowLifetimeUserConstructor(tok, constructor, t->name(), args, tokenlist, errorLogger, settings);
4698
0
        }
4699
0
    }
4700
0
}
4701
4702
static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings& settings)
4703
245
{
4704
245
    if (!Token::Match(tok, "(|{"))
4705
0
        return;
4706
245
    if (isScope(tok))
4707
0
        return;
4708
245
    std::vector<ValueType> vts;
4709
245
    if (tok->valueType()) {
4710
0
        vts = {*tok->valueType()};
4711
245
    } else if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous()) &&
4712
245
               tok->previous()->valueType()) {
4713
0
        vts = {*tok->previous()->valueType()};
4714
245
    } else if (Token::simpleMatch(tok, "{") && !Token::Match(tok->previous(), "%name%")) {
4715
0
        vts = getParentValueTypes(tok, &settings);
4716
0
    }
4717
4718
245
    for (const ValueType& vt : vts) {
4719
0
        if (vt.pointer > 0) {
4720
0
            std::vector<const Token*> args = getArguments(tok);
4721
0
            LifetimeStore::forEach(args,
4722
0
                                   "Passed to initializer list.",
4723
0
                                   ValueFlow::Value::LifetimeKind::SubObject,
4724
0
                                   [&](const LifetimeStore& ls) {
4725
0
                ls.byVal(tok, tokenlist, errorLogger, settings);
4726
0
            });
4727
0
        } else if (vt.container && vt.type == ValueType::CONTAINER) {
4728
0
            std::vector<const Token*> args = getArguments(tok);
4729
0
            if (args.size() == 1 && vt.container->view && astIsContainerOwned(args.front())) {
4730
0
                LifetimeStore{args.front(), "Passed to container view.", ValueFlow::Value::LifetimeKind::SubObject}
4731
0
                .byRef(tok, tokenlist, errorLogger, settings);
4732
0
            } else if (args.size() == 2 && astIsIterator(args[0]) && astIsIterator(args[1])) {
4733
0
                LifetimeStore::forEach(
4734
0
                    args,
4735
0
                    "Passed to initializer list.",
4736
0
                    ValueFlow::Value::LifetimeKind::SubObject,
4737
0
                    [&](const LifetimeStore& ls) {
4738
0
                    ls.byDerefCopy(tok, tokenlist, errorLogger, settings);
4739
0
                });
4740
0
            } else if (vt.container->hasInitializerListConstructor) {
4741
0
                LifetimeStore::forEach(args,
4742
0
                                       "Passed to initializer list.",
4743
0
                                       ValueFlow::Value::LifetimeKind::SubObject,
4744
0
                                       [&](const LifetimeStore& ls) {
4745
0
                    ls.byVal(tok, tokenlist, errorLogger, settings);
4746
0
                });
4747
0
            }
4748
0
        } else {
4749
0
            const Type* t = nullptr;
4750
0
            if (vt.typeScope && vt.typeScope->definedType)
4751
0
                t = vt.typeScope->definedType;
4752
0
            else
4753
0
                t = Token::typeOf(tok->previous());
4754
0
            valueFlowLifetimeClassConstructor(tok, t, tokenlist, errorLogger, settings);
4755
0
        }
4756
0
    }
4757
245
}
4758
4759
struct Lambda {
4760
    explicit Lambda(const Token* tok)
4761
107k
    {
4762
107k
        if (!Token::simpleMatch(tok, "[") || !tok->link())
4763
107k
            return;
4764
0
        capture = tok;
4765
4766
0
        if (Token::simpleMatch(capture->link(), "] (")) {
4767
0
            arguments = capture->link()->next();
4768
0
        }
4769
0
        const Token * afterArguments = arguments ? arguments->link()->next() : capture->link()->next();
4770
0
        if (afterArguments && afterArguments->originalName() == "->") {
4771
0
            returnTok = afterArguments->next();
4772
0
            bodyTok = Token::findsimplematch(returnTok, "{");
4773
0
        } else if (Token::simpleMatch(afterArguments, "{")) {
4774
0
            bodyTok = afterArguments;
4775
0
        }
4776
0
        for (const Token* c:getCaptures()) {
4777
0
            if (Token::Match(c, "this !!.")) {
4778
0
                explicitCaptures[c->variable()] = std::make_pair(c, LifetimeCapture::ByReference);
4779
0
            } else if (Token::simpleMatch(c, "* this")) {
4780
0
                explicitCaptures[c->next()->variable()] = std::make_pair(c->next(), LifetimeCapture::ByValue);
4781
0
            } else if (c->variable()) {
4782
0
                explicitCaptures[c->variable()] = std::make_pair(c, LifetimeCapture::ByValue);
4783
0
            } else if (c->isUnaryOp("&") && Token::Match(c->astOperand1(), "%var%")) {
4784
0
                explicitCaptures[c->astOperand1()->variable()] =
4785
0
                    std::make_pair(c->astOperand1(), LifetimeCapture::ByReference);
4786
0
            } else {
4787
0
                const std::string& s = c->expressionString();
4788
0
                if (s == "=")
4789
0
                    implicitCapture = LifetimeCapture::ByValue;
4790
0
                else if (s == "&")
4791
0
                    implicitCapture = LifetimeCapture::ByReference;
4792
0
            }
4793
0
        }
4794
0
    }
4795
4796
    const Token* capture{};
4797
    const Token* arguments{};
4798
    const Token* returnTok{};
4799
    const Token* bodyTok{};
4800
    std::unordered_map<const Variable*, std::pair<const Token*, LifetimeCapture>> explicitCaptures;
4801
    LifetimeCapture implicitCapture = LifetimeCapture::Undefined;
4802
4803
0
    std::vector<const Token*> getCaptures() const {
4804
0
        return getArguments(capture);
4805
0
    }
4806
4807
107k
    bool isLambda() const {
4808
107k
        return capture && bodyTok;
4809
107k
    }
4810
};
4811
4812
static bool isDecayedPointer(const Token *tok)
4813
0
{
4814
0
    if (!tok)
4815
0
        return false;
4816
0
    if (!tok->astParent())
4817
0
        return false;
4818
0
    if (astIsPointer(tok->astParent()) && !Token::simpleMatch(tok->astParent(), "return"))
4819
0
        return true;
4820
0
    if (tok->astParent()->isConstOp())
4821
0
        return true;
4822
0
    if (!Token::simpleMatch(tok->astParent(), "return"))
4823
0
        return false;
4824
0
    return astIsPointer(tok->astParent());
4825
0
}
4826
4827
static bool isConvertedToView(const Token* tok, const Settings& settings)
4828
0
{
4829
0
    std::vector<ValueType> vtParents = getParentValueTypes(tok, &settings);
4830
0
    return std::any_of(vtParents.cbegin(), vtParents.cend(), [&](const ValueType& vt) {
4831
0
        if (!vt.container)
4832
0
            return false;
4833
0
        return vt.container->view;
4834
0
    });
4835
0
}
4836
4837
static bool isContainerOfPointers(const Token* tok, const Settings& settings)
4838
0
{
4839
0
    if (!tok)
4840
0
    {
4841
0
        return true;
4842
0
    }
4843
4844
0
    ValueType vt = ValueType::parseDecl(tok, settings);
4845
0
    return vt.pointer > 0;
4846
0
}
4847
4848
static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings)
4849
3.57k
{
4850
255k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
4851
251k
        if (!tok->scope())
4852
0
            continue;
4853
251k
        if (tok->scope()->type == Scope::eGlobal)
4854
143k
            continue;
4855
107k
        Lambda lam(tok);
4856
        // Lambdas
4857
107k
        if (lam.isLambda()) {
4858
0
            const Scope * bodyScope = lam.bodyTok->scope();
4859
4860
0
            std::set<const Scope *> scopes;
4861
            // Avoid capturing a variable twice
4862
0
            std::set<nonneg int> varids;
4863
0
            bool capturedThis = false;
4864
4865
0
            auto isImplicitCapturingVariable = [&](const Token *varTok) {
4866
0
                const Variable *var = varTok->variable();
4867
0
                if (!var)
4868
0
                    return false;
4869
0
                if (varids.count(var->declarationId()) > 0)
4870
0
                    return false;
4871
0
                if (!var->isLocal() && !var->isArgument())
4872
0
                    return false;
4873
0
                const Scope *scope = var->scope();
4874
0
                if (!scope)
4875
0
                    return false;
4876
0
                if (scopes.count(scope) > 0)
4877
0
                    return false;
4878
0
                if (scope->isNestedIn(bodyScope))
4879
0
                    return false;
4880
0
                scopes.insert(scope);
4881
0
                varids.insert(var->declarationId());
4882
0
                return true;
4883
0
            };
4884
4885
0
            bool update = false;
4886
0
            auto captureVariable = [&](const Token* tok2, LifetimeCapture c, const std::function<bool(const Token*)> &pred) {
4887
0
                if (varids.count(tok->varId()) > 0)
4888
0
                    return;
4889
0
                if (c == LifetimeCapture::ByReference) {
4890
0
                    LifetimeStore ls{
4891
0
                        tok2, "Lambda captures variable by reference here.", ValueFlow::Value::LifetimeKind::Lambda};
4892
0
                    ls.forward = false;
4893
0
                    update |= ls.byRef(tok, tokenlist, errorLogger, settings, pred);
4894
0
                } else if (c == LifetimeCapture::ByValue) {
4895
0
                    LifetimeStore ls{
4896
0
                        tok2, "Lambda captures variable by value here.", ValueFlow::Value::LifetimeKind::Lambda};
4897
0
                    ls.forward = false;
4898
0
                    update |= ls.byVal(tok, tokenlist, errorLogger, settings, pred);
4899
0
                    pred(tok2);
4900
0
                }
4901
0
            };
4902
4903
0
            auto captureThisVariable = [&](const Token* tok2, LifetimeCapture c) {
4904
0
                ValueFlow::Value value;
4905
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4906
0
                if (c == LifetimeCapture::ByReference)
4907
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::ThisPointer;
4908
0
                else if (c == LifetimeCapture::ByValue)
4909
0
                    value.lifetimeScope = ValueFlow::Value::LifetimeScope::ThisValue;
4910
0
                value.tokvalue = tok2;
4911
0
                value.errorPath.emplace_back(tok2, "Lambda captures the 'this' variable here.");
4912
0
                value.lifetimeKind = ValueFlow::Value::LifetimeKind::Lambda;
4913
0
                capturedThis = true;
4914
                // Don't add the value a second time
4915
0
                if (std::find(tok->values().cbegin(), tok->values().cend(), value) != tok->values().cend())
4916
0
                    return;
4917
0
                setTokenValue(tok, std::move(value), settings);
4918
0
                update |= true;
4919
0
            };
4920
4921
            // Handle explicit capture
4922
0
            for (const auto& p:lam.explicitCaptures) {
4923
0
                const Variable* var = p.first;
4924
0
                const Token* tok2 = p.second.first;
4925
0
                const LifetimeCapture c = p.second.second;
4926
0
                if (Token::Match(tok2, "this !!.")) {
4927
0
                    captureThisVariable(tok2, c);
4928
0
                } else if (var) {
4929
0
                    captureVariable(tok2, c, [](const Token*) {
4930
0
                        return true;
4931
0
                    });
4932
0
                    varids.insert(var->declarationId());
4933
0
                }
4934
0
            }
4935
4936
0
            auto isImplicitCapturingThis = [&](const Token* tok2) {
4937
0
                if (capturedThis)
4938
0
                    return false;
4939
0
                if (Token::simpleMatch(tok2, "this"))
4940
0
                    return true;
4941
0
                if (tok2->variable()) {
4942
0
                    if (Token::simpleMatch(tok2->previous(), "."))
4943
0
                        return false;
4944
0
                    const Variable* var = tok2->variable();
4945
0
                    if (var->isLocal())
4946
0
                        return false;
4947
0
                    if (var->isArgument())
4948
0
                        return false;
4949
0
                    return exprDependsOnThis(tok2);
4950
0
                }
4951
0
                if (Token::simpleMatch(tok2, "("))
4952
0
                    return exprDependsOnThis(tok2);
4953
0
                return false;
4954
0
            };
4955
4956
0
            for (const Token * tok2 = lam.bodyTok; tok2 != lam.bodyTok->link(); tok2 = tok2->next()) {
4957
0
                if (isImplicitCapturingThis(tok2)) {
4958
0
                    captureThisVariable(tok2, LifetimeCapture::ByReference);
4959
0
                } else if (tok2->variable()) {
4960
0
                    captureVariable(tok2, lam.implicitCapture, isImplicitCapturingVariable);
4961
0
                }
4962
0
            }
4963
0
            if (update)
4964
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4965
0
        }
4966
        // address of
4967
107k
        else if (tok->isUnaryOp("&")) {
4968
0
            for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1())) {
4969
0
                if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive)
4970
0
                    continue;
4971
0
                ErrorPath errorPath = lt.errorPath;
4972
0
                errorPath.emplace_back(tok, "Address of variable taken here.");
4973
4974
0
                ValueFlow::Value value;
4975
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
4976
0
                value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
4977
0
                value.tokvalue = lt.token;
4978
0
                value.errorPath = std::move(errorPath);
4979
0
                if (lt.addressOf || astIsPointer(lt.token) || !Token::Match(lt.token->astParent(), ".|["))
4980
0
                    value.lifetimeKind = ValueFlow::Value::LifetimeKind::Address;
4981
0
                value.setInconclusive(lt.inconclusive);
4982
0
                setTokenValue(tok, std::move(value), settings);
4983
4984
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4985
0
            }
4986
0
        }
4987
        // Converting to container view
4988
107k
        else if (astIsContainerOwned(tok) && isConvertedToView(tok, settings)) {
4989
0
            LifetimeStore ls =
4990
0
                LifetimeStore{tok, "Converted to container view", ValueFlow::Value::LifetimeKind::SubObject};
4991
0
            ls.byRef(tok, tokenlist, errorLogger, settings);
4992
0
            valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
4993
0
        }
4994
        // container lifetimes
4995
107k
        else if (astIsContainer(tok)) {
4996
0
            Token * parent = astParentSkipParens(tok);
4997
0
            if (!parent)
4998
0
                continue;
4999
0
            if (!Token::Match(parent, ". %name% (") && !Token::Match(parent->previous(), "%name% ("))
5000
0
                continue;
5001
5002
            // Skip if its a free function that doesnt yield an iterator to the container
5003
0
            if (Token::Match(parent->previous(), "%name% (") &&
5004
0
                !contains({Library::Container::Yield::START_ITERATOR, Library::Container::Yield::END_ITERATOR},
5005
0
                          astFunctionYield(parent->previous(), &settings)))
5006
0
                continue;
5007
5008
0
            ValueFlow::Value master;
5009
0
            master.valueType = ValueFlow::Value::ValueType::LIFETIME;
5010
0
            master.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
5011
5012
0
            if (astIsIterator(parent->tokAt(2))) {
5013
0
                master.errorPath.emplace_back(parent->tokAt(2), "Iterator to container is created here.");
5014
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator;
5015
0
            } else if (astIsIterator(parent) && Token::Match(parent->previous(), "%name% (") &&
5016
0
                       contains({Library::Container::Yield::START_ITERATOR, Library::Container::Yield::END_ITERATOR},
5017
0
                                astFunctionYield(parent->previous(), &settings))) {
5018
0
                master.errorPath.emplace_back(parent, "Iterator to container is created here.");
5019
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator;
5020
0
            } else if ((astIsPointer(parent->tokAt(2)) &&
5021
0
                        !isContainerOfPointers(tok->valueType()->containerTypeToken, settings)) ||
5022
0
                       Token::Match(parent->next(), "data|c_str")) {
5023
0
                master.errorPath.emplace_back(parent->tokAt(2), "Pointer to container is created here.");
5024
0
                master.lifetimeKind = ValueFlow::Value::LifetimeKind::Object;
5025
0
            } else {
5026
0
                continue;
5027
0
            }
5028
5029
0
            std::vector<const Token*> toks;
5030
0
            if (tok->isUnaryOp("*") || parent->originalName() == "->") {
5031
0
                for (const ValueFlow::Value& v : tok->values()) {
5032
0
                    if (!v.isLocalLifetimeValue())
5033
0
                        continue;
5034
0
                    if (v.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
5035
0
                        continue;
5036
0
                    if (!v.tokvalue)
5037
0
                        continue;
5038
0
                    toks.push_back(v.tokvalue);
5039
0
                }
5040
0
            } else if (astIsContainerView(tok)) {
5041
0
                for (const ValueFlow::Value& v : tok->values()) {
5042
0
                    if (!v.isLocalLifetimeValue())
5043
0
                        continue;
5044
0
                    if (!v.tokvalue)
5045
0
                        continue;
5046
0
                    if (!astIsContainerOwned(v.tokvalue))
5047
0
                        continue;
5048
0
                    toks.push_back(v.tokvalue);
5049
0
                }
5050
0
            } else {
5051
0
                toks = {tok};
5052
0
            }
5053
5054
0
            for (const Token* tok2 : toks) {
5055
0
                for (const ReferenceToken& rt : followAllReferences(tok2, false)) {
5056
0
                    ValueFlow::Value value = master;
5057
0
                    value.tokvalue = rt.token;
5058
0
                    value.errorPath.insert(value.errorPath.begin(), rt.errors.cbegin(), rt.errors.cend());
5059
0
                    if (Token::simpleMatch(parent, "("))
5060
0
                        setTokenValue(parent, std::move(value), settings);
5061
0
                    else
5062
0
                        setTokenValue(parent->tokAt(2), std::move(value), settings);
5063
5064
0
                    if (!rt.token->variable()) {
5065
0
                        LifetimeStore ls = LifetimeStore{
5066
0
                            rt.token, master.errorPath.back().second, ValueFlow::Value::LifetimeKind::Object};
5067
0
                        ls.byRef(parent->tokAt(2), tokenlist, errorLogger, settings);
5068
0
                    }
5069
0
                }
5070
0
            }
5071
0
            valueFlowForwardLifetime(parent->tokAt(2), tokenlist, errorLogger, settings);
5072
0
        }
5073
        // Check constructors
5074
107k
        else if (Token::Match(tok, "=|return|%name%|{|,|> {") && !isScope(tok->next())) {
5075
0
            valueFlowLifetimeConstructor(tok->next(), tokenlist, errorLogger, settings);
5076
0
        }
5077
        // Check function calls
5078
107k
        else if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->next()->link(), ") {")) {
5079
245
            valueFlowLifetimeFunction(tok, tokenlist, errorLogger, settings);
5080
245
        }
5081
        // Unique pointer lifetimes
5082
107k
        else if (astIsUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
5083
0
            Token* ptok = tok->astParent()->tokAt(2);
5084
0
            ErrorPath errorPath = {{ptok, "Raw pointer to smart pointer created here."}};
5085
0
            ValueFlow::Value value;
5086
0
            value.valueType = ValueFlow::Value::ValueType::LIFETIME;
5087
0
            value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
5088
0
            value.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject;
5089
0
            value.tokvalue = tok;
5090
0
            value.errorPath = std::move(errorPath);
5091
0
            setTokenValue(ptok, std::move(value), settings);
5092
0
            valueFlowForwardLifetime(ptok, tokenlist, errorLogger, settings);
5093
0
        }
5094
        // Check variables
5095
107k
        else if (tok->variable()) {
5096
17.4k
            ErrorPath errorPath;
5097
17.4k
            const Variable * var = ValueFlow::getLifetimeVariable(tok, errorPath);
5098
17.4k
            if (!var)
5099
0
                continue;
5100
17.4k
            if (var->nameToken() == tok)
5101
0
                continue;
5102
17.4k
            if (var->isArray() && !var->isStlType() && !var->isArgument() && isDecayedPointer(tok)) {
5103
0
                errorPath.emplace_back(tok, "Array decayed to pointer here.");
5104
5105
0
                ValueFlow::Value value;
5106
0
                value.valueType = ValueFlow::Value::ValueType::LIFETIME;
5107
0
                value.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
5108
0
                value.tokvalue = var->nameToken();
5109
0
                value.errorPath = std::move(errorPath);
5110
0
                setTokenValue(tok, std::move(value), settings);
5111
5112
0
                valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
5113
0
            }
5114
17.4k
        }
5115
        // Forward any lifetimes
5116
90.1k
        else if (std::any_of(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
5117
0
            valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
5118
0
        }
5119
107k
    }
5120
3.57k
}
5121
5122
static bool isStdMoveOrStdForwarded(Token * tok, ValueFlow::Value::MoveKind * moveKind, Token ** varTok = nullptr)
5123
67.0k
{
5124
67.0k
    if (tok->str() != "std")
5125
67.0k
        return false;
5126
0
    ValueFlow::Value::MoveKind kind = ValueFlow::Value::MoveKind::NonMovedVariable;
5127
0
    Token * variableToken = nullptr;
5128
0
    if (Token::Match(tok, "std :: move ( %var% )")) {
5129
0
        variableToken = tok->tokAt(4);
5130
0
        kind = ValueFlow::Value::MoveKind::MovedVariable;
5131
0
    } else if (Token::simpleMatch(tok, "std :: forward <")) {
5132
0
        Token * const leftAngle = tok->tokAt(3);
5133
0
        Token * rightAngle = leftAngle->link();
5134
0
        if (Token::Match(rightAngle, "> ( %var% )")) {
5135
0
            variableToken = rightAngle->tokAt(2);
5136
0
            kind = ValueFlow::Value::MoveKind::ForwardedVariable;
5137
0
        }
5138
0
    }
5139
0
    if (!variableToken)
5140
0
        return false;
5141
0
    if (variableToken->strAt(2) == ".") // Only partially moved
5142
0
        return false;
5143
0
    if (variableToken->valueType() && variableToken->valueType()->type >= ValueType::Type::VOID)
5144
0
        return false;
5145
0
    if (moveKind != nullptr)
5146
0
        *moveKind = kind;
5147
0
    if (varTok != nullptr)
5148
0
        *varTok = variableToken;
5149
0
    return true;
5150
0
}
5151
5152
static bool isOpenParenthesisMemberFunctionCallOfVarId(const Token * openParenthesisToken, nonneg int varId)
5153
0
{
5154
0
    const Token * varTok = openParenthesisToken->tokAt(-3);
5155
0
    return Token::Match(varTok, "%varid% . %name% (", varId) &&
5156
0
           varTok->next()->originalName().empty();
5157
0
}
5158
5159
static Token* findOpenParentesisOfMove(Token* moveVarTok)
5160
0
{
5161
0
    Token* tok = moveVarTok;
5162
0
    while (tok && tok->str() != "(")
5163
0
        tok = tok->previous();
5164
0
    return tok;
5165
0
}
5166
5167
static Token* findEndOfFunctionCallForParameter(Token* parameterToken)
5168
0
{
5169
0
    if (!parameterToken)
5170
0
        return nullptr;
5171
0
    Token* parent = parameterToken->astParent();
5172
0
    while (parent && !parent->isOp() && !Token::Match(parent, "[({]"))
5173
0
        parent = parent->astParent();
5174
0
    if (!parent)
5175
0
        return nullptr;
5176
0
    return nextAfterAstRightmostLeaf(parent);
5177
0
}
5178
5179
static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings)
5180
2.23k
{
5181
2.23k
    if (!tokenlist.isCPP() || settings.standards.cpp < Standards::CPP11)
5182
0
        return;
5183
2.92k
    for (const Scope * scope : symboldatabase.functionScopes) {
5184
2.92k
        if (!scope)
5185
0
            continue;
5186
2.92k
        const Token * start = scope->bodyStart;
5187
2.92k
        if (scope->function) {
5188
2.92k
            const Token * memberInitializationTok = scope->function->constructorMemberInitialization();
5189
2.92k
            if (memberInitializationTok)
5190
0
                start = memberInitializationTok;
5191
2.92k
        }
5192
5193
69.9k
        for (auto* tok = const_cast<Token*>(start); tok != scope->bodyEnd; tok = tok->next()) {
5194
67.0k
            Token * varTok;
5195
67.0k
            if (Token::Match(tok, "%var% . reset|clear (") && tok->next()->originalName().empty()) {
5196
0
                varTok = tok;
5197
5198
0
                const Variable *var = tok->variable();
5199
0
                if (!var || (!var->isLocal() && !var->isArgument()))
5200
0
                    continue;
5201
5202
0
                ValueFlow::Value value;
5203
0
                value.valueType = ValueFlow::Value::ValueType::MOVED;
5204
0
                value.moveKind = ValueFlow::Value::MoveKind::NonMovedVariable;
5205
0
                value.errorPath.emplace_back(tok, "Calling " + tok->next()->expressionString() + " makes " + tok->str() + " 'non-moved'");
5206
0
                value.setKnown();
5207
5208
0
                setTokenValue(tok, value, settings);
5209
0
                if (var->scope()) {
5210
0
                    const Token* const endOfVarScope = var->scope()->bodyEnd;
5211
0
                    valueFlowForward(tok->next(), endOfVarScope, tok, std::move(value), tokenlist, errorLogger, settings);
5212
0
                }
5213
0
                continue;
5214
0
            }
5215
67.0k
            ValueFlow::Value::MoveKind moveKind;
5216
67.0k
            if (!isStdMoveOrStdForwarded(tok, &moveKind, &varTok))
5217
67.0k
                continue;
5218
0
            const nonneg int varId = varTok->varId();
5219
            // x is not MOVED after assignment if code is:  x = ... std::move(x) .. ;
5220
0
            const Token *parent = tok->astParent();
5221
0
            while (parent && parent->str() != "=" && parent->str() != "return" &&
5222
0
                   !(parent->str() == "(" && isOpenParenthesisMemberFunctionCallOfVarId(parent, varId)))
5223
0
                parent = parent->astParent();
5224
0
            if (parent &&
5225
0
                (parent->str() == "return" || // MOVED in return statement
5226
0
                 parent->str() == "(")) // MOVED in self assignment, isOpenParenthesisMemberFunctionCallOfVarId == true
5227
0
                continue;
5228
0
            if (parent && parent->astOperand1() && parent->astOperand1()->varId() == varId)
5229
0
                continue;
5230
0
            const Token* const endOfVarScope = ValueFlow::getEndOfExprScope(varTok);
5231
5232
0
            Token* openParentesisOfMove = findOpenParentesisOfMove(varTok);
5233
0
            Token* endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
5234
0
            if (endOfFunctionCall) {
5235
0
                ValueFlow::Value value;
5236
0
                value.valueType = ValueFlow::Value::ValueType::MOVED;
5237
0
                value.moveKind = moveKind;
5238
0
                if (moveKind == ValueFlow::Value::MoveKind::MovedVariable)
5239
0
                    value.errorPath.emplace_back(tok, "Calling std::move(" + varTok->str() + ")");
5240
0
                else // if (moveKind == ValueFlow::Value::ForwardedVariable)
5241
0
                    value.errorPath.emplace_back(tok, "Calling std::forward(" + varTok->str() + ")");
5242
0
                value.setKnown();
5243
5244
0
                valueFlowForward(endOfFunctionCall, endOfVarScope, varTok, std::move(value), tokenlist, errorLogger, settings);
5245
0
            }
5246
0
        }
5247
2.92k
    }
5248
2.23k
}
5249
5250
static const Token* findIncompleteVar(const Token* start, const Token* end)
5251
0
{
5252
0
    for (const Token* tok = start; tok != end; tok = tok->next()) {
5253
0
        if (tok->isIncompleteVar())
5254
0
            return tok;
5255
0
    }
5256
0
    return nullptr;
5257
0
}
5258
5259
static ValueFlow::Value makeConditionValue(long long val,
5260
                                           const Token* condTok,
5261
                                           bool assume,
5262
                                           bool impossible = false,
5263
                                           const Settings* settings = nullptr,
5264
                                           SourceLocation loc = SourceLocation::current())
5265
0
{
5266
0
    ValueFlow::Value v(val);
5267
0
    v.setKnown();
5268
0
    if (impossible) {
5269
0
        v.intvalue = !v.intvalue;
5270
0
        v.setImpossible();
5271
0
    }
5272
0
    v.condition = condTok;
5273
0
    if (assume)
5274
0
        v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is true");
5275
0
    else
5276
0
        v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is false");
5277
0
    if (settings && settings->debugnormal)
5278
0
        setSourceLocation(v, loc, condTok);
5279
0
    return v;
5280
0
}
5281
5282
static std::vector<const Token*> getConditions(const Token* tok, const char* op)
5283
0
{
5284
0
    std::vector<const Token*> conds = {tok};
5285
0
    if (tok->str() == op) {
5286
0
        std::vector<const Token*> args = astFlatten(tok, op);
5287
0
        std::copy_if(args.cbegin(), args.cend(), std::back_inserter(conds), [&](const Token* tok2) {
5288
0
            if (tok2->exprId() == 0)
5289
0
                return false;
5290
0
            if (tok2->hasKnownIntValue())
5291
0
                return false;
5292
0
            if (Token::Match(tok2, "%var%|.") && !astIsBool(tok2))
5293
0
                return false;
5294
0
            return true;
5295
0
        });
5296
0
    }
5297
0
    return conds;
5298
0
}
5299
5300
static bool isBreakOrContinueScope(const Token* endToken)
5301
200
{
5302
200
    if (!Token::simpleMatch(endToken, "}"))
5303
0
        return false;
5304
200
    return Token::Match(endToken->tokAt(-2), "break|continue ;");
5305
200
}
5306
5307
static const Scope* getLoopScope(const Token* tok)
5308
0
{
5309
0
    if (!tok)
5310
0
        return nullptr;
5311
0
    const Scope* scope = tok->scope();
5312
0
    while (scope && scope->type != Scope::eWhile && scope->type != Scope::eFor && scope->type != Scope::eDo)
5313
0
        scope = scope->nestedIn;
5314
0
    return scope;
5315
0
}
5316
5317
//
5318
static void valueFlowConditionExpressions(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings)
5319
1.34k
{
5320
1.34k
    if (settings.checkLevel == Settings::CheckLevel::normal)
5321
1.34k
        return;
5322
5323
0
    for (const Scope * scope : symboldatabase.functionScopes) {
5324
0
        if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) {
5325
0
            if (settings.debugwarnings)
5326
0
                bailoutIncompleteVar(tokenlist, errorLogger, incompleteTok, "Skipping function due to incomplete variable " + incompleteTok->str());
5327
0
            break;
5328
0
        }
5329
5330
0
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5331
0
            if (!Token::simpleMatch(tok, "if ("))
5332
0
                continue;
5333
0
            Token* parenTok = tok->next();
5334
0
            if (!Token::simpleMatch(parenTok->link(), ") {"))
5335
0
                continue;
5336
0
            Token * blockTok = parenTok->link()->tokAt(1);
5337
0
            const Token* condTok = parenTok->astOperand2();
5338
0
            if (condTok->exprId() == 0)
5339
0
                continue;
5340
0
            if (condTok->hasKnownIntValue())
5341
0
                continue;
5342
0
            if (!isConstExpression(condTok, settings.library, tokenlist.isCPP()))
5343
0
                continue;
5344
0
            const bool is1 = (condTok->isComparisonOp() || condTok->tokType() == Token::eLogicalOp || astIsBool(condTok));
5345
5346
0
            Token* startTok = blockTok;
5347
            // Inner condition
5348
0
            {
5349
0
                for (const Token* condTok2 : getConditions(condTok, "&&")) {
5350
0
                    if (is1) {
5351
0
                        const bool isBool = astIsBool(condTok2) || Token::Match(condTok2, "%comp%|%oror%|&&");
5352
0
                        SameExpressionAnalyzer a1(condTok2, makeConditionValue(1, condTok2, /*assume*/ true, !isBool), tokenlist, settings); // don't set '1' for non-boolean expressions
5353
0
                        valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings);
5354
0
                    }
5355
5356
0
                    OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(0, condTok2, true), tokenlist, settings);
5357
0
                    valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings);
5358
0
                }
5359
0
            }
5360
5361
0
            std::vector<const Token*> conds = getConditions(condTok, "||");
5362
5363
            // Check else block
5364
0
            if (Token::simpleMatch(startTok->link(), "} else {")) {
5365
0
                startTok = startTok->link()->tokAt(2);
5366
0
                for (const Token* condTok2:conds) {
5367
0
                    SameExpressionAnalyzer a1(condTok2, makeConditionValue(0, condTok2, false), tokenlist, settings);
5368
0
                    valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings);
5369
5370
0
                    if (is1) {
5371
0
                        OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(1, condTok2, false), tokenlist, settings);
5372
0
                        valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings);
5373
0
                    }
5374
0
                }
5375
0
            }
5376
5377
            // Check if the block terminates early
5378
0
            if (isEscapeScope(blockTok, settings)) {
5379
0
                const Scope* scope2 = scope;
5380
                // If escaping a loop then only use the loop scope
5381
0
                if (isBreakOrContinueScope(blockTok->link())) {
5382
0
                    scope2 = getLoopScope(blockTok->link());
5383
0
                    if (!scope2)
5384
0
                        continue;
5385
0
                }
5386
0
                for (const Token* condTok2:conds) {
5387
0
                    SameExpressionAnalyzer a1(condTok2, makeConditionValue(0, condTok2, false), tokenlist, settings);
5388
0
                    valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a1, tokenlist, errorLogger, settings);
5389
5390
0
                    if (is1) {
5391
0
                        OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(1, condTok2, false), tokenlist, settings);
5392
0
                        valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a2, tokenlist, errorLogger, settings);
5393
0
                    }
5394
0
                }
5395
0
            }
5396
0
        }
5397
0
    }
5398
0
}
5399
5400
static bool isTruncated(const ValueType* src, const ValueType* dst, const Settings& settings)
5401
287
{
5402
287
    if (src->pointer > 0 || dst->pointer > 0)
5403
0
        return src->pointer != dst->pointer;
5404
287
    if (src->smartPointer && dst->smartPointer)
5405
0
        return false;
5406
287
    if ((src->isIntegral() && dst->isIntegral()) || (src->isFloat() && dst->isFloat())) {
5407
287
        const size_t srcSize = ValueFlow::getSizeOf(*src, settings);
5408
287
        const size_t dstSize = ValueFlow::getSizeOf(*dst, settings);
5409
287
        if (srcSize > dstSize)
5410
0
            return true;
5411
287
        if (srcSize == dstSize && src->sign != dst->sign)
5412
0
            return true;
5413
287
    } else if (src->type == dst->type) {
5414
0
        if (src->type == ValueType::Type::RECORD)
5415
0
            return src->typeScope != dst->typeScope;
5416
0
    } else {
5417
0
        return true;
5418
0
    }
5419
287
    return false;
5420
287
}
5421
5422
static void setSymbolic(ValueFlow::Value& value, const Token* tok)
5423
8.18k
{
5424
8.18k
    assert(tok && tok->exprId() > 0 && "Missing expr id for symbolic value");
5425
0
    value.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
5426
8.18k
    value.tokvalue = tok;
5427
8.18k
}
5428
5429
static ValueFlow::Value makeSymbolic(const Token* tok, MathLib::bigint delta = 0)
5430
85
{
5431
85
    ValueFlow::Value value;
5432
85
    value.setKnown();
5433
85
    setSymbolic(value, tok);
5434
85
    value.intvalue = delta;
5435
85
    return value;
5436
85
}
5437
5438
static std::set<nonneg int> getVarIds(const Token* tok)
5439
814
{
5440
814
    std::set<nonneg int> result;
5441
1.81k
    visitAstNodes(tok, [&](const Token* child) {
5442
1.81k
        if (child->varId() > 0)
5443
733
            result.insert(child->varId());
5444
1.81k
        return ChildrenToVisit::op1_and_op2;
5445
1.81k
    });
5446
814
    return result;
5447
814
}
5448
5449
static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings)
5450
1.34k
{
5451
1.75k
    for (const Scope* scope : symboldatabase.functionScopes) {
5452
37.8k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5453
36.0k
            if (!Token::simpleMatch(tok, "="))
5454
34.1k
                continue;
5455
1.91k
            if (tok->astParent())
5456
424
                continue;
5457
1.48k
            if (!tok->astOperand1())
5458
1
                continue;
5459
1.48k
            if (!tok->astOperand2())
5460
0
                continue;
5461
1.48k
            if (tok->astOperand1()->hasKnownIntValue())
5462
0
                continue;
5463
1.48k
            if (tok->astOperand2()->hasKnownIntValue())
5464
181
                continue;
5465
1.30k
            if (tok->astOperand1()->exprId() == 0)
5466
0
                continue;
5467
1.30k
            if (tok->astOperand2()->exprId() == 0)
5468
8
                continue;
5469
1.29k
            if (!isConstExpression(tok->astOperand2(), settings.library, tokenlist.isCPP()))
5470
482
                continue;
5471
814
            if (tok->astOperand1()->valueType() && tok->astOperand2()->valueType()) {
5472
287
                if (isTruncated(
5473
287
                        tok->astOperand2()->valueType(), tok->astOperand1()->valueType(), settings))
5474
0
                    continue;
5475
527
            } else if (isDifferentType(tok->astOperand2(), tok->astOperand1())) {
5476
0
                continue;
5477
0
            }
5478
814
            const std::set<nonneg int> rhsVarIds = getVarIds(tok->astOperand2());
5479
814
            const std::vector<const Variable*> vars = getLHSVariables(tok);
5480
814
            if (std::any_of(vars.cbegin(), vars.cend(), [&](const Variable* var) {
5481
509
                if (rhsVarIds.count(var->declarationId()) > 0)
5482
79
                    return true;
5483
430
                if (var->isLocal())
5484
0
                    return var->isStatic();
5485
430
                return !var->isArgument();
5486
430
            }))
5487
509
                continue;
5488
5489
610
            if (findAstNode(tok, [](const Token* child) {
5490
610
                return child->isIncompleteVar();
5491
610
            }))
5492
305
                continue;
5493
5494
0
            Token* start = nextAfterAstRightmostLeaf(tok);
5495
0
            const Token* end = ValueFlow::getEndOfExprScope(tok->astOperand1(), scope);
5496
5497
0
            ValueFlow::Value rhs = makeSymbolic(tok->astOperand2());
5498
0
            rhs.errorPath.emplace_back(tok,
5499
0
                                       tok->astOperand1()->expressionString() + " is assigned '" +
5500
0
                                       tok->astOperand2()->expressionString() + "' here.");
5501
0
            valueFlowForward(start, end, tok->astOperand1(), std::move(rhs), tokenlist, errorLogger, settings);
5502
5503
0
            ValueFlow::Value lhs = makeSymbolic(tok->astOperand1());
5504
0
            lhs.errorPath.emplace_back(tok,
5505
0
                                       tok->astOperand1()->expressionString() + " is assigned '" +
5506
0
                                       tok->astOperand2()->expressionString() + "' here.");
5507
0
            valueFlowForward(start, end, tok->astOperand2(), std::move(lhs), tokenlist, errorLogger, settings);
5508
0
        }
5509
1.75k
    }
5510
1.34k
}
5511
5512
static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth = 10)
5513
0
{
5514
0
    if (depth < 0)
5515
0
        return nullptr;
5516
0
    if (!tok)
5517
0
        return nullptr;
5518
0
    if (!expr)
5519
0
        return nullptr;
5520
0
    if (expr->exprId() == 0)
5521
0
        return nullptr;
5522
0
    if (Token::simpleMatch(tok->previous(), "strlen (")) {
5523
0
        if (tok->astOperand2()->exprId() == expr->exprId())
5524
0
            return tok;
5525
0
    } else {
5526
0
        for (const ValueFlow::Value& v : tok->values()) {
5527
0
            if (!v.isSymbolicValue())
5528
0
                continue;
5529
0
            if (!v.isKnown())
5530
0
                continue;
5531
0
            if (v.intvalue != 0)
5532
0
                continue;
5533
0
            if (const Token* next = isStrlenOf(v.tokvalue, expr, depth - 1))
5534
0
                return next;
5535
0
        }
5536
0
    }
5537
0
    return nullptr;
5538
0
}
5539
5540
static ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val);
5541
5542
static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, const Settings& settings)
5543
2.23k
{
5544
2.92k
    for (const Scope* scope : symboldatabase.functionScopes) {
5545
69.9k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5546
67.0k
            if (tok->hasKnownIntValue())
5547
6.86k
                continue;
5548
5549
60.1k
            if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) {
5550
0
                const Token* arg = tok->next()->astOperand2();
5551
0
                if (!arg)
5552
0
                    continue;
5553
0
                if (arg->exprId() == 0)
5554
0
                    continue;
5555
0
                ValueFlow::Value c = inferCondition(">=", arg, 0);
5556
0
                if (!c.isKnown())
5557
0
                    continue;
5558
5559
0
                ValueFlow::Value v = makeSymbolic(arg);
5560
0
                v.errorPath = c.errorPath;
5561
0
                v.errorPath.emplace_back(tok, "Passed to " + tok->str());
5562
0
                if (c.intvalue == 0)
5563
0
                    v.setImpossible();
5564
0
                else
5565
0
                    v.setKnown();
5566
0
                setTokenValue(tok->next(), std::move(v), settings);
5567
60.1k
            } else if (Token::Match(tok, "*|/|<<|>>|^|+|-|%or%")) {
5568
2.58k
                if (!tok->astOperand1())
5569
2
                    continue;
5570
2.58k
                if (!tok->astOperand2())
5571
0
                    continue;
5572
2.58k
                if (!astIsIntegral(tok->astOperand1(), false) && !astIsIntegral(tok->astOperand2(), false))
5573
194
                    continue;
5574
2.38k
                const ValueFlow::Value* constant = nullptr;
5575
2.38k
                const Token* vartok = nullptr;
5576
2.38k
                if (tok->astOperand1()->hasKnownIntValue()) {
5577
440
                    constant = &tok->astOperand1()->values().front();
5578
440
                    vartok = tok->astOperand2();
5579
440
                }
5580
2.38k
                if (tok->astOperand2()->hasKnownIntValue()) {
5581
426
                    constant = &tok->astOperand2()->values().front();
5582
426
                    vartok = tok->astOperand1();
5583
426
                }
5584
2.38k
                if (!constant)
5585
1.52k
                    continue;
5586
866
                if (!vartok)
5587
0
                    continue;
5588
866
                if (vartok->exprId() == 0)
5589
3
                    continue;
5590
863
                if (Token::Match(tok, "<<|>>|/") && !astIsLHS(vartok))
5591
86
                    continue;
5592
777
                if (Token::Match(tok, "<<|>>|^|+|-|%or%") && constant->intvalue != 0)
5593
441
                    continue;
5594
336
                if (Token::Match(tok, "*|/") && constant->intvalue != 1)
5595
251
                    continue;
5596
85
                std::vector<ValueFlow::Value> values = {makeSymbolic(vartok)};
5597
85
                std::unordered_set<nonneg int> ids = {vartok->exprId()};
5598
85
                std::copy_if(vartok->values().cbegin(),
5599
85
                             vartok->values().cend(),
5600
85
                             std::back_inserter(values),
5601
85
                             [&](const ValueFlow::Value& v) {
5602
44
                    if (!v.isSymbolicValue())
5603
44
                        return false;
5604
0
                    if (!v.tokvalue)
5605
0
                        return false;
5606
0
                    return ids.insert(v.tokvalue->exprId()).second;
5607
0
                });
5608
85
                for (ValueFlow::Value& v : values)
5609
85
                    setTokenValue(tok, std::move(v), settings);
5610
57.5k
            } else if (Token::simpleMatch(tok, "[")) {
5611
0
                const Token* arrayTok = tok->astOperand1();
5612
0
                const Token* indexTok = tok->astOperand2();
5613
0
                if (!arrayTok)
5614
0
                    continue;
5615
0
                if (!indexTok)
5616
0
                    continue;
5617
0
                for (const ValueFlow::Value& value : indexTok->values()) {
5618
0
                    if (!value.isSymbolicValue())
5619
0
                        continue;
5620
0
                    if (value.intvalue != 0)
5621
0
                        continue;
5622
0
                    const Token* strlenTok = isStrlenOf(value.tokvalue, arrayTok);
5623
0
                    if (!strlenTok)
5624
0
                        continue;
5625
0
                    ValueFlow::Value v = value;
5626
0
                    v.bound = ValueFlow::Value::Bound::Point;
5627
0
                    v.valueType = ValueFlow::Value::ValueType::INT;
5628
0
                    v.errorPath.emplace_back(strlenTok, "Return index of first '\\0' character in string");
5629
0
                    setTokenValue(tok, std::move(v), settings);
5630
0
                }
5631
0
            }
5632
60.1k
        }
5633
2.92k
    }
5634
2.23k
}
5635
5636
struct SymbolicInferModel : InferModel {
5637
    const Token* expr;
5638
5.12k
    explicit SymbolicInferModel(const Token* tok) : expr(tok) {
5639
5.12k
        assert(expr->exprId() != 0);
5640
5.12k
    }
5641
    bool match(const ValueFlow::Value& value) const override
5642
6.06k
    {
5643
6.06k
        return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId();
5644
6.06k
    }
5645
    ValueFlow::Value yield(MathLib::bigint value) const override
5646
5.12k
    {
5647
5.12k
        ValueFlow::Value result(value);
5648
5.12k
        result.valueType = ValueFlow::Value::ValueType::SYMBOLIC;
5649
5.12k
        result.tokvalue = expr;
5650
5.12k
        result.setKnown();
5651
5.12k
        return result;
5652
5.12k
    }
5653
};
5654
5655
static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings)
5656
2.23k
{
5657
2.92k
    for (const Scope* scope : symboldatabase.functionScopes) {
5658
69.9k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
5659
67.0k
            if (!Token::Match(tok, "-|%comp%"))
5660
62.6k
                continue;
5661
4.35k
            if (tok->hasKnownIntValue())
5662
600
                continue;
5663
3.75k
            if (!tok->astOperand1())
5664
0
                continue;
5665
3.75k
            if (!tok->astOperand2())
5666
0
                continue;
5667
3.75k
            if (tok->astOperand1()->exprId() == 0)
5668
442
                continue;
5669
3.31k
            if (tok->astOperand2()->exprId() == 0)
5670
401
                continue;
5671
2.90k
            if (tok->astOperand1()->hasKnownIntValue())
5672
201
                continue;
5673
2.70k
            if (tok->astOperand2()->hasKnownIntValue())
5674
148
                continue;
5675
2.56k
            if (astIsFloat(tok->astOperand1(), false))
5676
0
                continue;
5677
2.56k
            if (astIsFloat(tok->astOperand2(), false))
5678
0
                continue;
5679
5680
2.56k
            SymbolicInferModel leftModel{tok->astOperand1()};
5681
2.56k
            std::vector<ValueFlow::Value> values = infer(leftModel, tok->str(), 0, tok->astOperand2()->values());
5682
2.56k
            if (values.empty()) {
5683
2.56k
                SymbolicInferModel rightModel{tok->astOperand2()};
5684
2.56k
                values = infer(rightModel, tok->str(), tok->astOperand1()->values(), 0);
5685
2.56k
            }
5686
2.56k
            for (ValueFlow::Value& value : values) {
5687
3
                setTokenValue(tok, std::move(value), settings);
5688
3
            }
5689
2.56k
        }
5690
2.92k
    }
5691
2.23k
}
5692
5693
template<class ContainerOfValue>
5694
static void valueFlowForwardConst(Token* start,
5695
                                  const Token* end,
5696
                                  const Variable* var,
5697
                                  const ContainerOfValue& values,
5698
                                  const Settings& settings,
5699
                                  int /*unused*/ = 0)
5700
0
{
5701
0
    if (!precedes(start, end))
5702
0
        throw InternalError(var->nameToken(), "valueFlowForwardConst: start token does not precede the end token.");
5703
0
    for (Token* tok = start; tok != end; tok = tok->next()) {
5704
0
        if (tok->varId() == var->declarationId()) {
5705
0
            for (const ValueFlow::Value& value : values)
5706
0
                setTokenValue(tok, value, settings);
5707
0
        } else {
5708
0
            [&] {
5709
                // Follow references
5710
0
                auto refs = followAllReferences(tok);
5711
0
                auto it = std::find_if(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
5712
0
                    return ref.token->varId() == var->declarationId();
5713
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
5714
0
                if (it != refs.end()) {
5715
0
                    for (ValueFlow::Value value : values) {
5716
0
                        if (refs.size() > 1)
5717
0
                            value.setInconclusive();
5718
0
                        value.errorPath.insert(value.errorPath.end(), it->errors.cbegin(), it->errors.cend());
5719
0
                        setTokenValue(tok, std::move(value), settings);
5720
0
                    }
5721
0
                    return;
5722
0
                }
5723
                // Follow symbolic values
5724
0
                for (const ValueFlow::Value& v : tok->values()) {
5725
0
                    if (!v.isSymbolicValue())
5726
0
                        continue;
5727
0
                    if (!v.tokvalue)
5728
0
                        continue;
5729
0
                    if (v.tokvalue->varId() != var->declarationId())
5730
0
                        continue;
5731
0
                    for (ValueFlow::Value value : values) {
5732
0
                        if (!v.isKnown() && value.isImpossible())
5733
0
                            continue;
5734
0
                        if (v.intvalue != 0) {
5735
0
                            if (!value.isIntValue())
5736
0
                                continue;
5737
0
                            value.intvalue += v.intvalue;
5738
0
                        }
5739
0
                        if (!value.isImpossible())
5740
0
                            value.valueKind = v.valueKind;
5741
0
                        value.bound = v.bound;
5742
0
                        value.errorPath.insert(value.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend());
5743
0
                        setTokenValue(tok, std::move(value), settings);
5744
0
                    }
5745
0
                }
5746
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
5747
0
        }
5748
0
    }
5749
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)
5750
5751
static void valueFlowForwardConst(Token* start,
5752
                                  const Token* end,
5753
                                  const Variable* var,
5754
                                  const std::initializer_list<ValueFlow::Value>& values,
5755
                                  const Settings& settings)
5756
0
{
5757
0
    valueFlowForwardConst(start, end, var, values, settings, 0);
5758
0
}
5759
5760
static ValueFlow::Value::Bound findVarBound(const Variable* var,
5761
                                            const Token* start,
5762
                                            const Token* end,
5763
                                            const Settings* settings)
5764
0
{
5765
0
    ValueFlow::Value::Bound result = ValueFlow::Value::Bound::Point;
5766
0
    const Token* next = start;
5767
0
    while ((next = findExpressionChangedSkipDeadCode(
5768
0
                var->nameToken(), next->next(), end, settings, true, &evaluateKnownValues))) {
5769
0
        ValueFlow::Value::Bound b = ValueFlow::Value::Bound::Point;
5770
0
        if (next->varId() != var->declarationId())
5771
0
            return ValueFlow::Value::Bound::Point;
5772
0
        if (Token::simpleMatch(next->astParent(), "++"))
5773
0
            b = ValueFlow::Value::Bound::Lower;
5774
0
        else if (Token::simpleMatch(next->astParent(), "--"))
5775
0
            b = ValueFlow::Value::Bound::Upper;
5776
0
        else
5777
0
            return ValueFlow::Value::Bound::Point;
5778
0
        if (result == ValueFlow::Value::Bound::Point)
5779
0
            result = b;
5780
0
        else if (result != b)
5781
0
            return ValueFlow::Value::Bound::Point;
5782
0
    }
5783
0
    return result;
5784
0
}
5785
5786
static bool isInitialVarAssign(const Token* tok)
5787
665
{
5788
665
    if (!tok)
5789
0
        return false;
5790
665
    if (!tok->variable())
5791
153
        return false;
5792
512
    if (tok->variable()->nameToken() == tok)
5793
0
        return true;
5794
512
    const Token* prev = tok->tokAt(2);
5795
512
    if (!Token::Match(prev, "%var% ; %var%"))
5796
512
        return false;
5797
0
    return tok->varId() == prev->varId() && tok->variable()->nameToken() == prev;
5798
512
}
5799
5800
static void valueFlowForwardAssign(Token* const tok,
5801
                                   const Token* expr,
5802
                                   std::vector<const Variable*> vars,
5803
                                   std::list<ValueFlow::Value> values,
5804
                                   const bool init,
5805
                                   TokenList& tokenlist,
5806
                                   ErrorLogger* const errorLogger,
5807
                                   const Settings& settings)
5808
665
{
5809
665
    if (Token::simpleMatch(tok->astParent(), "return"))
5810
0
        return;
5811
665
    const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
5812
665
    if (std::any_of(values.cbegin(), values.cend(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
5813
0
        valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
5814
0
        values.remove_if(std::mem_fn(&ValueFlow::Value::isLifetimeValue));
5815
0
    }
5816
665
    if (std::all_of(
5817
665
            vars.cbegin(), vars.cend(), [&](const Variable* var) {
5818
512
        return !var->isPointer() && !var->isSmartPointer();
5819
512
    }))
5820
665
        values.remove_if(std::mem_fn(&ValueFlow::Value::isTokValue));
5821
665
    if (tok->astParent()) {
5822
872
        for (ValueFlow::Value& value : values) {
5823
872
            std::string valueKind;
5824
872
            if (value.valueKind == ValueFlow::Value::ValueKind::Impossible) {
5825
442
                if (value.bound == ValueFlow::Value::Bound::Point)
5826
7
                    valueKind = "never ";
5827
435
                else if (value.bound == ValueFlow::Value::Bound::Lower)
5828
233
                    valueKind = "less than ";
5829
202
                else if (value.bound == ValueFlow::Value::Bound::Upper)
5830
202
                    valueKind = "greater than ";
5831
442
            }
5832
872
            std::string info = "Assignment '" + tok->astParent()->expressionString() + "', assigned value is " + valueKind + value.infoString();
5833
872
            value.errorPath.emplace_back(tok, std::move(info));
5834
872
        }
5835
665
    }
5836
5837
665
    if (tokenlist.isCPP() && vars.size() == 1 && Token::Match(vars.front()->typeStartToken(), "bool|_Bool")) {
5838
0
        for (ValueFlow::Value& value : values) {
5839
0
            if (value.isImpossible())
5840
0
                continue;
5841
0
            if (value.isIntValue())
5842
0
                value.intvalue = (value.intvalue != 0);
5843
0
            if (value.isTokValue())
5844
0
                value.intvalue = (value.tokvalue != nullptr);
5845
0
        }
5846
0
    }
5847
5848
    // Static variable initialisation?
5849
665
    if (vars.size() == 1 && vars.front()->isStatic() && init)
5850
0
        lowerToPossible(values);
5851
5852
    // is volatile
5853
665
    if (std::any_of(vars.cbegin(), vars.cend(), [&](const Variable* var) {
5854
512
        return var->isVolatile();
5855
512
    }))
5856
0
        lowerToPossible(values);
5857
5858
    // Skip RHS
5859
665
    Token* nextExpression = tok->astParent() ? nextAfterAstRightmostLeaf(tok->astParent()) : tok->next();
5860
665
    if (!nextExpression)
5861
0
        return;
5862
5863
872
    for (ValueFlow::Value& value : values) {
5864
872
        if (value.isSymbolicValue())
5865
42
            continue;
5866
830
        if (value.isTokValue())
5867
0
            continue;
5868
830
        value.tokvalue = tok;
5869
830
    }
5870
    // Const variable
5871
665
    if (expr->variable() && expr->variable()->isConst() && !expr->variable()->isReference()) {
5872
0
        auto it = std::remove_if(values.begin(), values.end(), [](const ValueFlow::Value& value) {
5873
0
            if (!value.isKnown())
5874
0
                return false;
5875
0
            if (value.isIntValue())
5876
0
                return true;
5877
0
            if (value.isFloatValue())
5878
0
                return true;
5879
0
            if (value.isContainerSizeValue())
5880
0
                return true;
5881
0
            if (value.isIteratorValue())
5882
0
                return true;
5883
0
            return false;
5884
0
        });
5885
0
        std::list<ValueFlow::Value> constValues;
5886
0
        constValues.splice(constValues.end(), values, it, values.end());
5887
0
        valueFlowForwardConst(nextExpression, endOfVarScope, expr->variable(), constValues, settings);
5888
0
    }
5889
665
    if (isInitialVarAssign(expr)) {
5890
        // Check if variable is only incremented or decremented
5891
0
        ValueFlow::Value::Bound b = findVarBound(expr->variable(), nextExpression, endOfVarScope, &settings);
5892
0
        if (b != ValueFlow::Value::Bound::Point) {
5893
0
            auto knownValueIt = std::find_if(values.begin(), values.end(), [](const ValueFlow::Value& value) {
5894
0
                if (!value.isKnown())
5895
0
                    return false;
5896
0
                return value.isIntValue();
5897
0
            });
5898
0
            if (knownValueIt != values.end()) {
5899
0
                ValueFlow::Value value = *knownValueIt;
5900
0
                value.bound = b;
5901
0
                value.invertRange();
5902
0
                value.setImpossible();
5903
0
                valueFlowForwardConst(nextExpression, endOfVarScope, expr->variable(), {std::move(value)}, settings);
5904
0
            }
5905
0
        }
5906
0
    }
5907
665
    valueFlowForward(nextExpression, endOfVarScope, expr, std::move(values), tokenlist, errorLogger, settings);
5908
665
}
5909
5910
static void valueFlowForwardAssign(Token* const tok,
5911
                                   const Variable* const var,
5912
                                   const std::list<ValueFlow::Value>& values,
5913
                                   const bool /*unused*/,
5914
                                   const bool init,
5915
                                   TokenList& tokenlist,
5916
                                   ErrorLogger* const errorLogger,
5917
                                   const Settings& settings)
5918
0
{
5919
0
    valueFlowForwardAssign(tok, var->nameToken(), {var}, values, init, tokenlist, errorLogger, settings);
5920
0
}
5921
5922
static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> values,
5923
                                                  const ValueType* dst,
5924
                                                  const ValueType* src,
5925
                                                  const Settings& settings)
5926
671
{
5927
671
    if (!dst || !dst->isIntegral())
5928
153
        return values;
5929
5930
518
    const size_t sz = ValueFlow::getSizeOf(*dst, settings);
5931
5932
518
    if (src) {
5933
513
        const size_t osz = ValueFlow::getSizeOf(*src, settings);
5934
513
        if (osz >= sz && dst->sign == ValueType::Sign::SIGNED && src->sign == ValueType::Sign::UNSIGNED) {
5935
0
            values.remove_if([&](const ValueFlow::Value& value) {
5936
0
                if (!value.isIntValue())
5937
0
                    return false;
5938
0
                if (!value.isImpossible())
5939
0
                    return false;
5940
0
                if (value.bound != ValueFlow::Value::Bound::Upper)
5941
0
                    return false;
5942
0
                if (osz == sz && value.intvalue < 0)
5943
0
                    return true;
5944
0
                if (osz > sz)
5945
0
                    return true;
5946
0
                return false;
5947
0
            });
5948
0
        }
5949
513
    }
5950
5951
681
    for (ValueFlow::Value &value : values) {
5952
        // Don't truncate impossible values since those can be outside of the valid range
5953
681
        if (value.isImpossible())
5954
346
            continue;
5955
335
        if (value.isFloatValue()) {
5956
0
            value.intvalue = value.floatValue;
5957
0
            value.valueType = ValueFlow::Value::ValueType::INT;
5958
0
        }
5959
5960
335
        if (value.isIntValue() && sz > 0 && sz < 8) {
5961
313
            const MathLib::biguint unsignedMaxValue = (1ULL << (sz * 8)) - 1ULL;
5962
313
            const MathLib::biguint signBit = 1ULL << (sz * 8 - 1);
5963
313
            value.intvalue &= unsignedMaxValue;
5964
313
            if (dst->sign == ValueType::Sign::SIGNED && (value.intvalue & signBit))
5965
21
                value.intvalue |= ~unsignedMaxValue;
5966
313
        }
5967
335
    }
5968
518
    return values;
5969
671
}
5970
5971
static bool isVariableInit(const Token *tok)
5972
63.5k
{
5973
63.5k
    return (tok->str() == "(" || tok->str() == "{") &&
5974
63.5k
           (tok->isBinaryOp() || (tok->astOperand1() && tok->link() == tok->next())) &&
5975
63.5k
           tok->astOperand1()->variable() &&
5976
63.5k
           tok->astOperand1()->variable()->nameToken() == tok->astOperand1() &&
5977
63.5k
           tok->astOperand1()->variable()->valueType() &&
5978
63.5k
           tok->astOperand1()->variable()->valueType()->type >= ValueType::Type::VOID &&
5979
63.5k
           !Token::simpleMatch(tok->astOperand2(), ",");
5980
63.5k
}
5981
5982
// Return true if two associative containers intersect
5983
template<class C1, class C2>
5984
static bool intersects(const C1& c1, const C2& c2)
5985
42
{
5986
42
    if (c1.size() > c2.size())
5987
0
        return intersects(c2, c1);
5988
    // NOLINTNEXTLINE(readability-use-anyofallof) - TODO: fix if possible / also Cppcheck false negative
5989
42
    for (auto&& x : c1) {
5990
4
        if (c2.find(x) != c2.end())
5991
4
            return true;
5992
4
    }
5993
38
    return false;
5994
42
}
5995
5996
static void valueFlowAfterAssign(TokenList &tokenlist,
5997
                                 const SymbolDatabase& symboldatabase,
5998
                                 ErrorLogger *errorLogger,
5999
                                 const Settings &settings,
6000
                                 const std::set<const Scope*>& skippedFunctions)
6001
2.23k
{
6002
2.92k
    for (const Scope * scope : symboldatabase.functionScopes) {
6003
2.92k
        if (skippedFunctions.count(scope))
6004
0
            continue;
6005
2.92k
        std::unordered_map<nonneg int, std::unordered_set<nonneg int>> backAssigns;
6006
69.9k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
6007
            // Assignment
6008
67.0k
            bool isInit = false;
6009
67.0k
            if (tok->str() != "=" && !(isInit = isVariableInit(tok)))
6010
63.5k
                continue;
6011
6012
3.45k
            if (tok->astParent() && !((tok->astParent()->str() == ";" && astIsLHS(tok)) || tok->astParent()->str() == "*"))
6013
754
                continue;
6014
6015
            // Lhs should be a variable
6016
2.69k
            if (!tok->astOperand1() || !tok->astOperand1()->exprId())
6017
1
                continue;
6018
2.69k
            std::vector<const Variable*> vars = getLHSVariables(tok);
6019
6020
            // Rhs values..
6021
2.69k
            Token* rhs = tok->astOperand2();
6022
2.69k
            if (!rhs && isInit)
6023
0
                rhs = tok;
6024
2.69k
            if (!rhs || rhs->values().empty())
6025
2.02k
                continue;
6026
6027
671
            std::list<ValueFlow::Value> values = truncateValues(
6028
671
                rhs->values(), tok->astOperand1()->valueType(), rhs->valueType(), settings);
6029
            // Remove known values
6030
671
            std::set<ValueFlow::Value::ValueType> types;
6031
671
            if (tok->astOperand1()->hasKnownValue()) {
6032
0
                for (const ValueFlow::Value& value:tok->astOperand1()->values()) {
6033
0
                    if (value.isKnown() && !value.isSymbolicValue())
6034
0
                        types.insert(value.valueType);
6035
0
                }
6036
0
            }
6037
880
            values.remove_if([&](const ValueFlow::Value& value) {
6038
880
                return types.count(value.valueType) > 0;
6039
880
            });
6040
            // Remove container size if its not a container
6041
671
            if (!astIsContainer(tok->astOperand2()))
6042
880
                values.remove_if([&](const ValueFlow::Value& value) {
6043
880
                    return value.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE;
6044
880
                });
6045
            // Remove symbolic values that are the same as the LHS
6046
880
            values.remove_if([&](const ValueFlow::Value& value) {
6047
880
                if (value.isSymbolicValue() && value.tokvalue)
6048
50
                    return value.tokvalue->exprId() == tok->astOperand1()->exprId();
6049
830
                return false;
6050
880
            });
6051
            // Find references to LHS in RHS
6052
713
            auto isIncremental = [&](const Token* tok2) -> bool {
6053
713
                return findAstNode(tok2,
6054
2.01k
                                   [&](const Token* child) {
6055
2.01k
                    return child->exprId() == tok->astOperand1()->exprId();
6056
2.01k
                });
6057
713
            };
6058
            // Check symbolic values as well
6059
671
            const bool incremental = isIncremental(tok->astOperand2()) ||
6060
748
                                     std::any_of(values.cbegin(), values.cend(), [&](const ValueFlow::Value& value) {
6061
748
                if (!value.isSymbolicValue())
6062
706
                    return false;
6063
42
                return isIncremental(value.tokvalue);
6064
748
            });
6065
            // Remove values from the same assignment if it is incremental
6066
671
            if (incremental) {
6067
124
                values.remove_if([&](const ValueFlow::Value& value) {
6068
124
                    if (value.tokvalue)
6069
6
                        return value.tokvalue == tok->astOperand2();
6070
118
                    return false;
6071
124
                });
6072
75
            }
6073
            // If assignment copy by value, remove Uninit values..
6074
671
            if ((tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->pointer == 0) ||
6075
671
                (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isReference() && tok->astOperand1()->variable()->nameToken() == tok->astOperand1()))
6076
673
                values.remove_if([&](const ValueFlow::Value& value) {
6077
673
                    return value.isUninitValue();
6078
673
                });
6079
671
            if (values.empty())
6080
6
                continue;
6081
665
            const bool init = vars.size() == 1 && (vars.front()->nameToken() == tok->astOperand1() || tok->isSplittedVarDeclEq());
6082
665
            valueFlowForwardAssign(
6083
665
                rhs, tok->astOperand1(), std::move(vars), values, init, tokenlist, errorLogger, settings);
6084
            // Back propagate symbolic values
6085
665
            if (tok->astOperand1()->exprId() > 0) {
6086
665
                Token* start = nextAfterAstRightmostLeaf(tok);
6087
665
                const Token* end = scope->bodyEnd;
6088
                // Collect symbolic ids
6089
665
                std::unordered_set<nonneg int> ids;
6090
872
                for (const ValueFlow::Value& value : values) {
6091
872
                    if (!value.isSymbolicValue())
6092
830
                        continue;
6093
42
                    if (!value.tokvalue)
6094
0
                        continue;
6095
42
                    if (value.tokvalue->exprId() == 0)
6096
0
                        continue;
6097
42
                    ids.insert(value.tokvalue->exprId());
6098
42
                }
6099
872
                for (ValueFlow::Value value : values) {
6100
872
                    if (!value.isSymbolicValue())
6101
830
                        continue;
6102
42
                    const Token* expr = value.tokvalue;
6103
42
                    value.intvalue = -value.intvalue;
6104
42
                    value.tokvalue = tok->astOperand1();
6105
6106
                    // Skip if it intersects with an already assigned symbol
6107
42
                    auto& s = backAssigns[value.tokvalue->exprId()];
6108
42
                    if (intersects(s, ids))
6109
4
                        continue;
6110
38
                    s.insert(expr->exprId());
6111
6112
38
                    value.errorPath.emplace_back(tok,
6113
38
                                                 tok->astOperand1()->expressionString() + " is assigned '" +
6114
38
                                                 tok->astOperand2()->expressionString() + "' here.");
6115
38
                    valueFlowForward(start, end, expr, std::move(value), tokenlist, errorLogger, settings);
6116
38
                }
6117
665
            }
6118
665
        }
6119
2.92k
    }
6120
2.23k
}
6121
6122
static std::vector<const Variable*> getVariables(const Token* tok)
6123
0
{
6124
0
    std::vector<const Variable*> result;
6125
0
    visitAstNodes(tok, [&](const Token* child) {
6126
0
        if (child->variable())
6127
0
            result.push_back(child->variable());
6128
0
        return ChildrenToVisit::op1_and_op2;
6129
0
    });
6130
0
    return result;
6131
0
}
6132
6133
static void valueFlowAfterSwap(TokenList& tokenlist,
6134
                               const SymbolDatabase& symboldatabase,
6135
                               ErrorLogger* errorLogger,
6136
                               const Settings& settings)
6137
2.23k
{
6138
2.92k
    for (const Scope* scope : symboldatabase.functionScopes) {
6139
69.9k
        for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
6140
67.0k
            if (!Token::simpleMatch(tok, "swap ("))
6141
67.0k
                continue;
6142
0
            if (!Token::simpleMatch(tok->next()->astOperand2(), ","))
6143
0
                continue;
6144
0
            std::vector<Token*> args = astFlatten(tok->next()->astOperand2(), ",");
6145
0
            if (args.size() != 2)
6146
0
                continue;
6147
0
            if (args[0]->exprId() == 0)
6148
0
                continue;
6149
0
            if (args[1]->exprId() == 0)
6150
0
                continue;
6151
0
            for (int i = 0; i < 2; i++) {
6152
0
                std::vector<const Variable*> vars = getVariables(args[0]);
6153
0
                const std::list<ValueFlow::Value>& values = args[0]->values();
6154
0
                valueFlowForwardAssign(args[0], args[1], std::move(vars), values, false, tokenlist, errorLogger, settings);
6155
0
                std::swap(args[0], args[1]);
6156
0
            }
6157
0
        }
6158
2.92k
    }
6159
2.23k
}
6160
6161
static void valueFlowSetConditionToKnown(const Token* tok, std::list<ValueFlow::Value>& values, bool then)
6162
3.16k
{
6163
3.16k
    if (values.empty())
6164
0
        return;
6165
3.16k
    if (then && !Token::Match(tok, "==|!|("))
6166
1.88k
        return;
6167
1.28k
    if (!then && !Token::Match(tok, "!=|%var%|("))
6168
878
        return;
6169
403
    if (isConditionKnown(tok, then))
6170
403
        changePossibleToKnown(values);
6171
403
}
6172
6173
static bool isBreakScope(const Token* const endToken)
6174
250
{
6175
250
    if (!Token::simpleMatch(endToken, "}"))
6176
0
        return false;
6177
250
    if (!Token::simpleMatch(endToken->link(), "{"))
6178
0
        return false;
6179
250
    return Token::findmatch(endToken->link(), "break|goto", endToken);
6180
250
}
6181
6182
ValueFlow::Value ValueFlow::asImpossible(ValueFlow::Value v)
6183
3.00k
{
6184
3.00k
    v.invertRange();
6185
3.00k
    v.setImpossible();
6186
3.00k
    return v;
6187
3.00k
}
6188
6189
static void insertImpossible(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
6190
2.91k
{
6191
2.91k
    std::transform(input.cbegin(), input.cend(), std::back_inserter(values), &ValueFlow::asImpossible);
6192
2.91k
}
6193
6194
static void insertNegateKnown(std::list<ValueFlow::Value>& values, const std::list<ValueFlow::Value>& input)
6195
155
{
6196
155
    for (ValueFlow::Value value:input) {
6197
155
        if (!value.isIntValue() && !value.isContainerSizeValue())
6198
99
            continue;
6199
56
        value.intvalue = !value.intvalue;
6200
56
        value.setKnown();
6201
56
        values.push_back(std::move(value));
6202
56
    }
6203
155
}
6204
6205
struct ConditionHandler {
6206
    struct Condition {
6207
        const Token* vartok{};
6208
        std::list<ValueFlow::Value> true_values;
6209
        std::list<ValueFlow::Value> false_values;
6210
        bool inverted = false;
6211
        // Whether to insert impossible values for the condition or only use possible values
6212
        bool impossible = true;
6213
6214
1.64k
        bool isBool() const {
6215
1.64k
            return astIsBool(vartok);
6216
1.64k
        }
6217
6218
        static MathLib::bigint findPath(const std::list<ValueFlow::Value>& values)
6219
24.7k
        {
6220
24.7k
            auto it = std::find_if(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) {
6221
24.7k
                return v.path > 0;
6222
24.7k
            });
6223
24.7k
            if (it == values.end())
6224
24.7k
                return 0;
6225
0
            assert(std::all_of(it, values.end(), [&](const ValueFlow::Value& v) {
6226
0
                return v.path == 0 || v.path == it->path;
6227
0
            }));
6228
0
            return it->path;
6229
24.7k
        }
6230
6231
        MathLib::bigint getPath() const
6232
6.18k
        {
6233
6.18k
            assert(std::abs(findPath(true_values) - findPath(false_values)) == 0);
6234
0
            return findPath(true_values) | findPath(false_values);
6235
6.18k
        }
6236
6237
        Token* getContextAndValues(Token* condTok,
6238
                                   std::list<ValueFlow::Value>& thenValues,
6239
                                   std::list<ValueFlow::Value>& elseValues,
6240
                                   bool known = false) const
6241
3.09k
        {
6242
3.09k
            const MathLib::bigint path = getPath();
6243
3.09k
            const bool allowKnown = path == 0;
6244
3.09k
            const bool allowImpossible = impossible && allowKnown;
6245
6246
3.09k
            bool inverted2 = inverted;
6247
3.09k
            Token* ctx = skipNotAndCasts(condTok, &inverted2);
6248
3.09k
            bool then = !inverted || !inverted2;
6249
6250
3.09k
            if (!Token::Match(condTok, "!=|=|(|.") && condTok != vartok) {
6251
2.36k
                thenValues.insert(thenValues.end(), true_values.cbegin(), true_values.cend());
6252
2.36k
                if (allowImpossible && (known || isConditionKnown(ctx, !then)))
6253
1.27k
                    insertImpossible(elseValues, false_values);
6254
2.36k
            }
6255
3.09k
            if (!Token::Match(condTok, "==|!")) {
6256
2.73k
                elseValues.insert(elseValues.end(), false_values.cbegin(), false_values.cend());
6257
2.73k
                if (allowImpossible && (known || isConditionKnown(ctx, then))) {
6258
1.64k
                    insertImpossible(thenValues, true_values);
6259
1.64k
                    if (isBool())
6260
155
                        insertNegateKnown(thenValues, true_values);
6261
1.64k
                }
6262
2.73k
            }
6263
6264
3.09k
            if (inverted2)
6265
18
                std::swap(thenValues, elseValues);
6266
6267
3.09k
            return ctx;
6268
3.09k
        }
6269
    };
6270
6271
    virtual std::vector<Condition> parse(const Token* tok, const Settings& settings) const = 0;
6272
6273
    virtual Analyzer::Result forward(Token* start,
6274
                                     const Token* stop,
6275
                                     const Token* exprTok,
6276
                                     const std::list<ValueFlow::Value>& values,
6277
                                     TokenList& tokenlist,
6278
                                     ErrorLogger* errorLogger,
6279
                                     const Settings& settings,
6280
                                     SourceLocation loc = SourceLocation::current()) const
6281
3.23k
    {
6282
3.23k
        return valueFlowForward(start->next(), stop, exprTok, values, tokenlist, errorLogger, settings, loc);
6283
3.23k
    }
6284
6285
    virtual Analyzer::Result forward(Token* top,
6286
                                     const Token* exprTok,
6287
                                     const std::list<ValueFlow::Value>& values,
6288
                                     TokenList& tokenlist,
6289
                                     ErrorLogger* errorLogger,
6290
                                     const Settings& settings,
6291
                                     SourceLocation loc = SourceLocation::current()) const
6292
0
    {
6293
0
        return valueFlowForwardRecursive(top, exprTok, values, tokenlist, errorLogger, settings, loc);
6294
0
    }
6295
6296
    virtual void reverse(Token* start,
6297
                         const Token* endToken,
6298
                         const Token* exprTok,
6299
                         const std::list<ValueFlow::Value>& values,
6300
                         TokenList& tokenlist,
6301
                         ErrorLogger* errorLogger,
6302
                         const Settings& settings,
6303
                         SourceLocation loc = SourceLocation::current()) const
6304
1.42k
    {
6305
1.42k
        valueFlowReverse(start, endToken, exprTok, values, tokenlist, errorLogger, settings, loc);
6306
1.42k
    }
6307
6308
    void traverseCondition(const TokenList& tokenlist,
6309
                           const SymbolDatabase& symboldatabase,
6310
                           const Settings& settings,
6311
                           const std::set<const Scope*>& skippedFunctions,
6312
                           const std::function<void(const Condition& cond, Token* tok, const Scope* scope)>& f) const
6313
17.8k
    {
6314
23.3k
        for (const Scope *scope : symboldatabase.functionScopes) {
6315
23.3k
            if (skippedFunctions.count(scope))
6316
0
                continue;
6317
559k
            for (auto *tok = const_cast<Token *>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
6318
536k
                if (Token::Match(tok, "if|while|for ("))
6319
21.9k
                    continue;
6320
514k
                if (Token::Match(tok, ":|;|,"))
6321
48.2k
                    continue;
6322
6323
465k
                const Token* top = tok->astTop();
6324
465k
                if (!top)
6325
0
                    continue;
6326
6327
465k
                if (!Token::Match(top->previous(), "if|while|for (") && !Token::Match(tok->astParent(), "&&|%oror%|?|!"))
6328
307k
                    continue;
6329
158k
                for (const Condition& cond : parse(tok, settings)) {
6330
47.0k
                    if (!cond.vartok)
6331
39.6k
                        continue;
6332
7.43k
                    if (cond.vartok->exprId() == 0)
6333
28
                        continue;
6334
7.40k
                    if (cond.vartok->hasKnownIntValue())
6335
75
                        continue;
6336
7.33k
                    if (cond.true_values.empty() || cond.false_values.empty())
6337
0
                        continue;
6338
7.33k
                    if (!isConstExpression(cond.vartok, settings.library, tokenlist.isCPP()))
6339
1.14k
                        continue;
6340
6.18k
                    f(cond, tok, scope);
6341
6.18k
                }
6342
158k
            }
6343
23.3k
        }
6344
17.8k
    }
6345
6346
    void beforeCondition(TokenList& tokenlist,
6347
                         const SymbolDatabase& symboldatabase,
6348
                         ErrorLogger* errorLogger,
6349
                         const Settings& settings,
6350
8.92k
                         const std::set<const Scope*>& skippedFunctions) const {
6351
8.92k
        traverseCondition(tokenlist, symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* tok, const Scope*) {
6352
3.09k
            if (cond.vartok->exprId() == 0)
6353
0
                return;
6354
6355
            // If condition is known then don't propagate value
6356
3.09k
            if (tok->hasKnownIntValue())
6357
77
                return;
6358
6359
3.01k
            Token* top = tok->astTop();
6360
6361
3.01k
            if (Token::Match(top, "%assign%"))
6362
0
                return;
6363
3.01k
            if (Token::Match(cond.vartok->astParent(), "%assign%|++|--"))
6364
165
                return;
6365
6366
2.85k
            if (Token::simpleMatch(tok->astParent(), "?") && tok->astParent()->isExpandedMacro()) {
6367
0
                if (settings.debugwarnings)
6368
0
                    bailout(tokenlist,
6369
0
                            errorLogger,
6370
0
                            tok,
6371
0
                            "variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
6372
0
                return;
6373
0
            }
6374
6375
            // if,macro => bailout
6376
2.85k
            if (Token::simpleMatch(top->previous(), "if (") && top->previous()->isExpandedMacro()) {
6377
0
                if (settings.debugwarnings)
6378
0
                    bailout(tokenlist,
6379
0
                            errorLogger,
6380
0
                            tok,
6381
0
                            "variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
6382
0
                return;
6383
0
            }
6384
6385
2.85k
            std::list<ValueFlow::Value> values = cond.true_values;
6386
2.85k
            if (cond.true_values != cond.false_values)
6387
1.97k
                values.insert(values.end(), cond.false_values.cbegin(), cond.false_values.cend());
6388
6389
            // extra logic for unsigned variables 'i>=1' => possible value can also be 0
6390
2.85k
            if (Token::Match(tok, "<|>|<=|>=")) {
6391
3.95k
                values.remove_if([](const ValueFlow::Value& v) {
6392
3.95k
                    if (v.isIntValue())
6393
854
                        return v.intvalue != 0;
6394
3.10k
                    return false;
6395
3.95k
                });
6396
1.97k
                if (cond.vartok->valueType() && cond.vartok->valueType()->sign != ValueType::Sign::UNSIGNED)
6397
1.25k
                    return;
6398
1.97k
            }
6399
1.59k
            if (values.empty())
6400
113
                return;
6401
6402
            // bailout: for/while-condition, variable is changed in while loop
6403
1.48k
            if (Token::Match(top->previous(), "for|while (") && Token::simpleMatch(top->link(), ") {")) {
6404
6405
                // Variable changed in 3rd for-expression
6406
566
                if (Token::simpleMatch(top->previous(), "for (")) {
6407
0
                    if (top->astOperand2() && top->astOperand2()->astOperand2() &&
6408
0
                        findExpressionChanged(
6409
0
                            cond.vartok, top->astOperand2()->astOperand2(), top->link(), &settings, tokenlist.isCPP())) {
6410
0
                        if (settings.debugwarnings)
6411
0
                            bailout(tokenlist,
6412
0
                                    errorLogger,
6413
0
                                    tok,
6414
0
                                    "variable '" + cond.vartok->expressionString() + "' used in loop");
6415
0
                        return;
6416
0
                    }
6417
0
                }
6418
6419
                // Variable changed in loop code
6420
566
                const Token* const start = top;
6421
566
                const Token* const block = top->link()->next();
6422
566
                const Token* const end = block->link();
6423
6424
566
                if (findExpressionChanged(cond.vartok, start, end, &settings, tokenlist.isCPP())) {
6425
                    // If its reassigned in loop then analyze from the end
6426
73
                    if (!Token::Match(tok, "%assign%|++|--") &&
6427
147
                        findExpression(cond.vartok->exprId(), start, end, [&](const Token* tok2) {
6428
147
                        return Token::Match(tok2->astParent(), "%assign%") && astIsLHS(tok2);
6429
147
                    })) {
6430
                        // Start at the end of the loop body
6431
14
                        Token* bodyTok = top->link()->next();
6432
14
                        reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist, errorLogger, settings);
6433
14
                    }
6434
73
                    if (settings.debugwarnings)
6435
73
                        bailout(tokenlist,
6436
73
                                errorLogger,
6437
73
                                tok,
6438
73
                                "variable '" + cond.vartok->expressionString() + "' used in loop");
6439
73
                    return;
6440
73
                }
6441
566
            }
6442
6443
1.40k
            Token* startTok = nullptr;
6444
1.40k
            if (astIsRHS(tok))
6445
1.07k
                startTok = tok->astParent();
6446
338
            else if (astIsLHS(tok))
6447
338
                startTok = previousBeforeAstLeftmostLeaf(tok->astParent());
6448
1.40k
            if (!startTok)
6449
0
                startTok = tok->previous();
6450
6451
1.40k
            reverse(startTok, nullptr, cond.vartok, values, tokenlist, errorLogger, settings);
6452
1.40k
        });
6453
8.92k
    }
6454
6455
    static Token* skipNotAndCasts(Token* tok, bool* inverted = nullptr)
6456
3.09k
    {
6457
3.11k
        for (; tok->astParent(); tok = tok->astParent()) {
6458
3.11k
            if (Token::simpleMatch(tok->astParent(), "!")) {
6459
0
                if (inverted)
6460
0
                    *inverted ^= true;
6461
0
                continue;
6462
0
            }
6463
3.11k
            if (Token::Match(tok->astParent(), "==|!=")) {
6464
98
                const Token* sibling = tok->astSibling();
6465
98
                if (sibling->hasKnownIntValue() && (astIsBool(tok) || astIsBool(sibling))) {
6466
26
                    const bool value = sibling->values().front().intvalue;
6467
26
                    if (inverted)
6468
26
                        *inverted ^= value == Token::simpleMatch(tok->astParent(), "!=");
6469
26
                    continue;
6470
26
                }
6471
98
            }
6472
3.09k
            if (tok->astParent()->isCast() && astIsBool(tok->astParent()))
6473
0
                continue;
6474
3.09k
            return tok;
6475
3.09k
        }
6476
0
        return tok;
6477
3.09k
    }
6478
6479
    static void fillFromPath(ProgramMemory& pm, const Token* top, MathLib::bigint path)
6480
0
    {
6481
0
        if (path < 1)
6482
0
            return;
6483
0
        visitAstNodes(top, [&](const Token* tok) {
6484
0
            const ValueFlow::Value* v = ValueFlow::findValue(tok->values(), nullptr, [&](const ValueFlow::Value& v) {
6485
0
                return v.path == path && isNonConditionalPossibleIntValue(v);
6486
0
            });
6487
0
            if (v == nullptr)
6488
0
                return ChildrenToVisit::op1_and_op2;
6489
0
            pm.setValue(tok, *v);
6490
0
            return ChildrenToVisit::op1_and_op2;
6491
0
        });
6492
0
    }
6493
6494
    void afterCondition(TokenList& tokenlist,
6495
                        const SymbolDatabase& symboldatabase,
6496
                        ErrorLogger* errorLogger,
6497
                        const Settings& settings,
6498
8.92k
                        const std::set<const Scope*>& skippedFunctions) const {
6499
8.92k
        traverseCondition(tokenlist, symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* condTok, const Scope* scope) {
6500
3.09k
            Token* top = condTok->astTop();
6501
6502
3.09k
            const MathLib::bigint path = cond.getPath();
6503
3.09k
            const bool allowKnown = path == 0;
6504
6505
3.09k
            std::list<ValueFlow::Value> thenValues;
6506
3.09k
            std::list<ValueFlow::Value> elseValues;
6507
6508
3.09k
            Token* ctx = cond.getContextAndValues(condTok, thenValues, elseValues);
6509
6510
3.09k
            if (Token::Match(ctx->astParent(), "%oror%|&&")) {
6511
0
                Token* parent = ctx->astParent();
6512
0
                if (astIsRHS(ctx) && astIsLHS(parent) && parent->astParent() &&
6513
0
                    parent->str() == parent->astParent()->str())
6514
0
                    parent = parent->astParent();
6515
0
                else if (!astIsLHS(ctx)) {
6516
0
                    parent = nullptr;
6517
0
                }
6518
0
                if (parent) {
6519
0
                    std::vector<Token*> nextExprs = {parent->astOperand2()};
6520
0
                    if (astIsLHS(parent) && parent->astParent() && parent->astParent()->str() == parent->str()) {
6521
0
                        nextExprs.push_back(parent->astParent()->astOperand2());
6522
0
                    }
6523
0
                    std::list<ValueFlow::Value> andValues;
6524
0
                    std::list<ValueFlow::Value> orValues;
6525
0
                    cond.getContextAndValues(condTok, andValues, orValues, true);
6526
6527
0
                    const std::string& op(parent->str());
6528
0
                    std::list<ValueFlow::Value> values;
6529
0
                    if (op == "&&")
6530
0
                        values = std::move(andValues);
6531
0
                    else if (op == "||")
6532
0
                        values = std::move(orValues);
6533
0
                    if (allowKnown && (Token::Match(condTok, "==|!=") || cond.isBool()))
6534
0
                        changePossibleToKnown(values);
6535
0
                    if (astIsFloat(cond.vartok, false) ||
6536
0
                        (!cond.vartok->valueType() &&
6537
0
                         std::all_of(values.cbegin(), values.cend(), [](const ValueFlow::Value& v) {
6538
0
                        return v.isIntValue() || v.isFloatValue();
6539
0
                    })))
6540
0
                        values.remove_if([&](const ValueFlow::Value& v) {
6541
0
                            return v.isImpossible();
6542
0
                        });
6543
0
                    for (Token* start:nextExprs) {
6544
0
                        Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, errorLogger, settings);
6545
0
                        if (r.terminate != Analyzer::Terminate::None || r.action.isModified())
6546
0
                            return;
6547
0
                    }
6548
0
                }
6549
0
            }
6550
6551
3.09k
            {
6552
3.09k
                const Token* tok2 = condTok;
6553
3.09k
                std::string op;
6554
3.09k
                bool mixedOperators = false;
6555
7.84k
                while (tok2->astParent()) {
6556
4.74k
                    const Token* parent = tok2->astParent();
6557
4.74k
                    if (Token::Match(parent, "%oror%|&&")) {
6558
0
                        if (op.empty()) {
6559
0
                            op = parent->str();
6560
0
                        } else if (op != parent->str()) {
6561
0
                            mixedOperators = true;
6562
0
                            break;
6563
0
                        }
6564
0
                    }
6565
4.74k
                    if (parent->str() == "!") {
6566
0
                        op = (op == "&&" ? "||" : "&&");
6567
0
                    }
6568
4.74k
                    tok2 = parent;
6569
4.74k
                }
6570
6571
3.09k
                if (mixedOperators) {
6572
0
                    return;
6573
0
                }
6574
3.09k
            }
6575
6576
3.09k
            if (!top)
6577
0
                return;
6578
6579
3.09k
            if (top->previous()->isExpandedMacro()) {
6580
0
                for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
6581
0
                    for (ValueFlow::Value& v : *values)
6582
0
                        v.macro = true;
6583
0
                }
6584
0
            }
6585
6586
3.09k
            Token* condTop = ctx->astParent();
6587
3.09k
            {
6588
3.09k
                bool inverted2 = false;
6589
3.09k
                while (Token::Match(condTop, "%oror%|&&")) {
6590
0
                    Token* parent = skipNotAndCasts(condTop, &inverted2)->astParent();
6591
0
                    if (!parent)
6592
0
                        break;
6593
0
                    condTop = parent;
6594
0
                }
6595
3.09k
                if (inverted2)
6596
0
                    std::swap(thenValues, elseValues);
6597
3.09k
            }
6598
6599
3.09k
            if (!condTop)
6600
0
                return;
6601
6602
3.09k
            if (Token::simpleMatch(condTop, "?")) {
6603
0
                Token* colon = condTop->astOperand2();
6604
0
                forward(colon->astOperand1(), cond.vartok, thenValues, tokenlist, errorLogger, settings);
6605
0
                forward(colon->astOperand2(), cond.vartok, elseValues, tokenlist, errorLogger, settings);
6606
                // TODO: Handle after condition
6607
0
                return;
6608
0
            }
6609
6610
3.09k
            if (condTop != top && condTop->str() != ";")
6611
1.17k
                return;
6612
6613
1.91k
            if (!Token::Match(top->previous(), "if|while|for ("))
6614
0
                return;
6615
6616
1.91k
            if (top->previous()->str() == "for") {
6617
0
                if (!Token::Match(condTok, "%comp%"))
6618
0
                    return;
6619
0
                if (!Token::simpleMatch(condTok->astParent(), ";"))
6620
0
                    return;
6621
0
                const Token* stepTok = getStepTok(top);
6622
0
                if (cond.vartok->varId() == 0)
6623
0
                    return;
6624
0
                if (!cond.vartok->variable())
6625
0
                    return;
6626
0
                if (!Token::Match(stepTok, "++|--"))
6627
0
                    return;
6628
0
                std::set<ValueFlow::Value::Bound> bounds;
6629
0
                for (const ValueFlow::Value& v : thenValues) {
6630
0
                    if (v.bound != ValueFlow::Value::Bound::Point && v.isImpossible())
6631
0
                        continue;
6632
0
                    bounds.insert(v.bound);
6633
0
                }
6634
0
                if (Token::simpleMatch(stepTok, "++") && bounds.count(ValueFlow::Value::Bound::Lower) > 0)
6635
0
                    return;
6636
0
                if (Token::simpleMatch(stepTok, "--") && bounds.count(ValueFlow::Value::Bound::Upper) > 0)
6637
0
                    return;
6638
0
                const Token* childTok = condTok->astOperand1();
6639
0
                if (!childTok)
6640
0
                    childTok = condTok->astOperand2();
6641
0
                if (!childTok)
6642
0
                    return;
6643
0
                if (childTok->varId() != cond.vartok->varId())
6644
0
                    return;
6645
0
                const Token* startBlock = top->link()->next();
6646
0
                if (isVariableChanged(startBlock,
6647
0
                                      startBlock->link(),
6648
0
                                      cond.vartok->varId(),
6649
0
                                      cond.vartok->variable()->isGlobal(),
6650
0
                                      &settings,
6651
0
                                      tokenlist.isCPP()))
6652
0
                    return;
6653
                // Check if condition in for loop is always false
6654
0
                const Token* initTok = getInitTok(top);
6655
0
                ProgramMemory pm;
6656
0
                fillFromPath(pm, initTok, path);
6657
0
                fillFromPath(pm, condTok, path);
6658
0
                execute(initTok, pm, nullptr, nullptr);
6659
0
                MathLib::bigint result = 1;
6660
0
                execute(condTok, pm, &result, nullptr);
6661
0
                if (result == 0)
6662
0
                    return;
6663
                // Remove condition since for condition is not redundant
6664
0
                for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
6665
0
                    for (ValueFlow::Value& v : *values) {
6666
0
                        v.condition = nullptr;
6667
0
                        v.conditional = true;
6668
0
                    }
6669
0
                }
6670
0
            }
6671
6672
1.91k
            bool deadBranch[] = {false, false};
6673
            // start token of conditional code
6674
1.91k
            Token* startTokens[] = {nullptr, nullptr};
6675
            // determine startToken(s)
6676
1.91k
            if (Token::simpleMatch(top->link(), ") {"))
6677
1.91k
                startTokens[0] = top->link()->next();
6678
1.91k
            if (Token::simpleMatch(top->link()->linkAt(1), "} else {"))
6679
685
                startTokens[1] = top->link()->linkAt(1)->tokAt(2);
6680
6681
1.91k
            int changeBlock = -1;
6682
1.91k
            int bailBlock = -1;
6683
6684
5.75k
            for (int i = 0; i < 2; i++) {
6685
3.83k
                const Token* const startToken = startTokens[i];
6686
3.83k
                if (!startToken)
6687
1.23k
                    continue;
6688
2.60k
                std::list<ValueFlow::Value>& values = (i == 0 ? thenValues : elseValues);
6689
2.60k
                if (allowKnown)
6690
2.60k
                    valueFlowSetConditionToKnown(condTok, values, i == 0);
6691
6692
2.60k
                Analyzer::Result r = forward(startTokens[i], startTokens[i]->link(), cond.vartok, values, tokenlist, errorLogger, settings);
6693
2.60k
                deadBranch[i] = r.terminate == Analyzer::Terminate::Escape;
6694
2.60k
                if (r.action.isModified() && !deadBranch[i])
6695
174
                    changeBlock = i;
6696
2.60k
                if (r.terminate != Analyzer::Terminate::None && r.terminate != Analyzer::Terminate::Escape &&
6697
2.60k
                    r.terminate != Analyzer::Terminate::Modified)
6698
1.61k
                    bailBlock = i;
6699
2.60k
                changeKnownToPossible(values);
6700
2.60k
            }
6701
1.91k
            if (changeBlock >= 0 && !Token::simpleMatch(top->previous(), "while (")) {
6702
82
                if (settings.debugwarnings)
6703
82
                    bailout(tokenlist,
6704
82
                            errorLogger,
6705
82
                            startTokens[changeBlock]->link(),
6706
82
                            "valueFlowAfterCondition: " + cond.vartok->expressionString() +
6707
82
                            " is changed in conditional block");
6708
82
                return;
6709
82
            }
6710
1.83k
            if (bailBlock >= 0) {
6711
1.20k
                if (settings.debugwarnings)
6712
1.20k
                    bailout(tokenlist,
6713
1.20k
                            errorLogger,
6714
1.20k
                            startTokens[bailBlock]->link(),
6715
1.20k
                            "valueFlowAfterCondition: bailing in conditional block");
6716
1.20k
                return;
6717
1.20k
            }
6718
6719
            // After conditional code..
6720
633
            if (Token::simpleMatch(top->link(), ") {")) {
6721
633
                Token* after = top->link()->linkAt(1);
6722
633
                bool dead_if = deadBranch[0];
6723
633
                bool dead_else = deadBranch[1];
6724
633
                const Token* unknownFunction = nullptr;
6725
633
                if (condTok->astParent() && Token::Match(top->previous(), "while|for ("))
6726
250
                    dead_if = !isBreakScope(after);
6727
383
                else if (!dead_if)
6728
351
                    dead_if = isReturnScope(after, &settings.library, &unknownFunction);
6729
6730
633
                if (!dead_if && unknownFunction) {
6731
0
                    if (settings.debugwarnings)
6732
0
                        bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
6733
0
                    return;
6734
0
                }
6735
6736
633
                if (Token::simpleMatch(after, "} else {")) {
6737
237
                    after = after->linkAt(2);
6738
237
                    unknownFunction = nullptr;
6739
237
                    if (!dead_else)
6740
237
                        dead_else = isReturnScope(after, &settings.library, &unknownFunction);
6741
237
                    if (!dead_else && unknownFunction) {
6742
0
                        if (settings.debugwarnings)
6743
0
                            bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
6744
0
                        return;
6745
0
                    }
6746
237
                }
6747
6748
633
                if (dead_if && dead_else)
6749
0
                    return;
6750
6751
633
                std::list<ValueFlow::Value> values;
6752
633
                if (dead_if) {
6753
282
                    values = std::move(elseValues);
6754
351
                } else if (dead_else) {
6755
0
                    values = std::move(thenValues);
6756
351
                } else {
6757
351
                    std::copy_if(thenValues.cbegin(),
6758
351
                                 thenValues.cend(),
6759
351
                                 std::back_inserter(values),
6760
351
                                 std::mem_fn(&ValueFlow::Value::isPossible));
6761
351
                    std::copy_if(elseValues.cbegin(),
6762
351
                                 elseValues.cend(),
6763
351
                                 std::back_inserter(values),
6764
351
                                 std::mem_fn(&ValueFlow::Value::isPossible));
6765
351
                }
6766
6767
633
                if (values.empty())
6768
0
                    return;
6769
6770
633
                if (dead_if || dead_else) {
6771
282
                    const Token* parent = condTok->astParent();
6772
                    // Skip the not operator
6773
282
                    while (Token::simpleMatch(parent, "!"))
6774
0
                        parent = parent->astParent();
6775
282
                    bool possible = false;
6776
282
                    if (Token::Match(parent, "&&|%oror%")) {
6777
0
                        const std::string& op(parent->str());
6778
0
                        while (parent && parent->str() == op)
6779
0
                            parent = parent->astParent();
6780
0
                        if (Token::simpleMatch(parent, "!") || Token::simpleMatch(parent, "== false"))
6781
0
                            possible = op == "||";
6782
0
                        else
6783
0
                            possible = op == "&&";
6784
0
                    }
6785
282
                    if (possible) {
6786
0
                        values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible));
6787
0
                        changeKnownToPossible(values);
6788
282
                    } else if (allowKnown) {
6789
282
                        valueFlowSetConditionToKnown(condTok, values, true);
6790
282
                        valueFlowSetConditionToKnown(condTok, values, false);
6791
282
                    }
6792
282
                }
6793
633
                if (values.empty())
6794
0
                    return;
6795
824
                const bool isKnown = std::any_of(values.cbegin(), values.cend(), [&](const ValueFlow::Value& v) {
6796
824
                    return v.isKnown() || v.isImpossible();
6797
824
                });
6798
633
                if (isKnown && isBreakOrContinueScope(after)) {
6799
0
                    const Scope* loopScope = getLoopScope(cond.vartok);
6800
0
                    if (loopScope) {
6801
0
                        Analyzer::Result r = forward(after, loopScope->bodyEnd, cond.vartok, values, tokenlist, errorLogger, settings);
6802
0
                        if (r.terminate != Analyzer::Terminate::None)
6803
0
                            return;
6804
0
                        if (r.action.isModified())
6805
0
                            return;
6806
0
                        auto* start = const_cast<Token*>(loopScope->bodyEnd);
6807
0
                        if (Token::simpleMatch(start, "} while (")) {
6808
0
                            start = start->tokAt(2);
6809
0
                            forward(start, start->link(), cond.vartok, values, tokenlist, errorLogger, settings);
6810
0
                            start = start->link();
6811
0
                        }
6812
0
                        values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible));
6813
0
                        changeKnownToPossible(values);
6814
0
                    }
6815
0
                }
6816
633
                forward(after, ValueFlow::getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, errorLogger, settings);
6817
633
            }
6818
633
        });
6819
8.92k
    }
6820
17.8k
    virtual ~ConditionHandler() = default;
6821
8.92k
    ConditionHandler(const ConditionHandler&) = default;
6822
protected:
6823
8.92k
    ConditionHandler() = default;
6824
};
6825
6826
static void valueFlowCondition(const ValuePtr<ConditionHandler>& handler,
6827
                               TokenList& tokenlist,
6828
                               SymbolDatabase& symboldatabase,
6829
                               ErrorLogger* errorLogger,
6830
                               const Settings& settings,
6831
                               const std::set<const Scope*>& skippedFunctions)
6832
8.92k
{
6833
8.92k
    handler->beforeCondition(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
6834
8.92k
    handler->afterCondition(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
6835
8.92k
}
6836
6837
struct SimpleConditionHandler : ConditionHandler {
6838
39.6k
    std::vector<Condition> parse(const Token* tok, const Settings& /*settings*/) const override {
6839
6840
39.6k
        std::vector<Condition> conds;
6841
39.6k
        parseCompareEachInt(tok, [&](const Token* vartok, ValueFlow::Value true_value, ValueFlow::Value false_value) {
6842
1.79k
            if (vartok->hasKnownIntValue())
6843
0
                return;
6844
1.79k
            if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
6845
28
                vartok = vartok->astOperand1();
6846
1.79k
            Condition cond;
6847
1.79k
            cond.true_values.push_back(std::move(true_value));
6848
1.79k
            cond.false_values.push_back(std::move(false_value));
6849
1.79k
            cond.vartok = vartok;
6850
1.79k
            conds.push_back(std::move(cond));
6851
1.79k
        });
6852
39.6k
        if (!conds.empty())
6853
1.79k
            return conds;
6854
6855
37.8k
        const Token* vartok = nullptr;
6856
6857
37.8k
        if (tok->str() == "!") {
6858
0
            vartok = tok->astOperand1();
6859
6860
37.8k
        } else if (tok->astParent() && (Token::Match(tok->astParent(), "%oror%|&&|?") ||
6861
32.3k
                                        Token::Match(tok->astParent()->previous(), "if|while ("))) {
6862
4.43k
            if (Token::simpleMatch(tok, "="))
6863
506
                vartok = tok->astOperand1();
6864
3.92k
            else if (!Token::Match(tok, "%comp%|%assign%"))
6865
1.08k
                vartok = tok;
6866
4.43k
        }
6867
6868
37.8k
        if (!vartok)
6869
36.2k
            return {};
6870
1.59k
        Condition cond;
6871
1.59k
        cond.true_values.emplace_back(tok, 0LL);
6872
1.59k
        cond.false_values.emplace_back(tok, 0LL);
6873
1.59k
        cond.vartok = vartok;
6874
6875
1.59k
        return {std::move(cond)};
6876
37.8k
    }
6877
};
6878
6879
struct IntegralInferModel : InferModel {
6880
19.4k
    bool match(const ValueFlow::Value& value) const override {
6881
19.4k
        return value.isIntValue();
6882
19.4k
    }
6883
    ValueFlow::Value yield(MathLib::bigint value) const override
6884
3.44k
    {
6885
3.44k
        ValueFlow::Value result(value);
6886
3.44k
        result.valueType = ValueFlow::Value::ValueType::INT;
6887
3.44k
        result.setKnown();
6888
3.44k
        return result;
6889
3.44k
    }
6890
};
6891
6892
11.8k
ValuePtr<InferModel> ValueFlow::makeIntegralInferModel() {
6893
11.8k
    return IntegralInferModel{};
6894
11.8k
}
6895
6896
static ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val)
6897
0
{
6898
0
    if (!varTok)
6899
0
        return ValueFlow::Value{};
6900
0
    if (varTok->hasKnownIntValue())
6901
0
        return ValueFlow::Value{};
6902
0
    std::vector<ValueFlow::Value> r = infer(IntegralInferModel{}, op, varTok->values(), val);
6903
0
    if (r.size() == 1 && r.front().isKnown())
6904
0
        return r.front();
6905
0
    return ValueFlow::Value{};
6906
0
}
6907
6908
struct IteratorInferModel : InferModel {
6909
    virtual ValueFlow::Value::ValueType getType() const = 0;
6910
0
    bool match(const ValueFlow::Value& value) const override {
6911
0
        return value.valueType == getType();
6912
0
    }
6913
    ValueFlow::Value yield(MathLib::bigint value) const override
6914
0
    {
6915
0
        ValueFlow::Value result(value);
6916
0
        result.valueType = getType();
6917
0
        result.setKnown();
6918
0
        return result;
6919
0
    }
6920
};
6921
6922
struct EndIteratorInferModel : IteratorInferModel {
6923
0
    ValueFlow::Value::ValueType getType() const override {
6924
0
        return ValueFlow::Value::ValueType::ITERATOR_END;
6925
0
    }
6926
};
6927
6928
struct StartIteratorInferModel : IteratorInferModel {
6929
0
    ValueFlow::Value::ValueType getType() const override {
6930
0
        return ValueFlow::Value::ValueType::ITERATOR_END;
6931
0
    }
6932
};
6933
6934
3.56k
static bool isIntegralOnlyOperator(const Token* tok) {
6935
3.56k
    return Token::Match(tok, "%|<<|>>|&|^|~|%or%");
6936
3.56k
}
6937
6938
static bool isIntegralOrPointer(const Token* tok)
6939
7.33k
{
6940
7.33k
    if (!tok)
6941
0
        return false;
6942
7.33k
    if (astIsIntegral(tok, false))
6943
5.41k
        return true;
6944
1.91k
    if (astIsPointer(tok))
6945
0
        return true;
6946
1.91k
    if (Token::Match(tok, "NULL|nullptr"))
6947
0
        return true;
6948
1.91k
    if (tok->valueType())
6949
0
        return false;
6950
    // These operators only work on integers
6951
1.91k
    if (isIntegralOnlyOperator(tok))
6952
276
        return true;
6953
1.64k
    if (isIntegralOnlyOperator(tok->astParent()))
6954
0
        return true;
6955
1.64k
    if (Token::Match(tok, "+|-|*|/") && tok->isBinaryOp())
6956
369
        return isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2());
6957
1.27k
    return false;
6958
1.64k
}
6959
6960
static void valueFlowInferCondition(TokenList& tokenlist,
6961
                                    const Settings& settings)
6962
2.23k
{
6963
161k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
6964
159k
        if (!tok->astParent())
6965
102k
            continue;
6966
57.5k
        if (tok->hasKnownIntValue())
6967
17.7k
            continue;
6968
39.8k
        if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) {
6969
3.74k
            if (astIsIterator(tok->astOperand1()) || astIsIterator(tok->astOperand2())) {
6970
0
                static const std::array<ValuePtr<InferModel>, 2> iteratorModels = {EndIteratorInferModel{},
6971
0
                                                                                   StartIteratorInferModel{}};
6972
0
                for (const ValuePtr<InferModel>& model : iteratorModels) {
6973
0
                    std::vector<ValueFlow::Value> result =
6974
0
                        infer(model, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
6975
0
                    for (ValueFlow::Value value : result) {
6976
0
                        value.valueType = ValueFlow::Value::ValueType::INT;
6977
0
                        setTokenValue(tok, std::move(value), settings);
6978
0
                    }
6979
0
                }
6980
3.74k
            } else if (isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2())) {
6981
2.47k
                std::vector<ValueFlow::Value> result =
6982
2.47k
                    infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
6983
2.47k
                for (ValueFlow::Value& value : result) {
6984
67
                    setTokenValue(tok, std::move(value), settings);
6985
67
                }
6986
2.47k
            }
6987
36.0k
        } else if (Token::Match(tok->astParent(), "?|&&|!|%oror%") ||
6988
36.0k
                   Token::Match(tok->astParent()->previous(), "if|while (") ||
6989
36.0k
                   (astIsPointer(tok) && isUsedAsBool(tok, &settings))) {
6990
3.44k
            std::vector<ValueFlow::Value> result = infer(IntegralInferModel{}, "!=", tok->values(), 0);
6991
3.44k
            if (result.size() != 1)
6992
3.44k
                continue;
6993
0
            ValueFlow::Value value = result.front();
6994
0
            setTokenValue(tok, std::move(value), settings);
6995
0
        }
6996
39.8k
    }
6997
2.23k
}
6998
6999
struct SymbolicConditionHandler : SimpleConditionHandler {
7000
7001
    static bool isNegatedBool(const Token* tok)
7002
952
    {
7003
952
        if (!Token::simpleMatch(tok, "!"))
7004
952
            return false;
7005
0
        return (astIsBool(tok->astOperand1()));
7006
952
    }
7007
7008
    static const Token* skipNot(const Token* tok)
7009
0
    {
7010
0
        if (!Token::simpleMatch(tok, "!"))
7011
0
            return tok;
7012
0
        return tok->astOperand1();
7013
0
    }
7014
7015
    std::vector<Condition> parse(const Token* tok, const Settings& settings) const override
7016
39.6k
    {
7017
39.6k
        if (!Token::Match(tok, "%comp%"))
7018
32.8k
            return {};
7019
6.79k
        if (tok->hasKnownIntValue())
7020
900
            return {};
7021
5.89k
        if (!tok->astOperand1() || tok->astOperand1()->hasKnownIntValue() || tok->astOperand1()->isLiteral())
7022
922
            return {};
7023
4.96k
        if (!tok->astOperand2() || tok->astOperand2()->hasKnownIntValue() || tok->astOperand2()->isLiteral())
7024
760
            return {};
7025
4.20k
        if (!isConstExpression(tok, settings.library, true))
7026
2.18k
            return {};
7027
7028
2.02k
        std::vector<Condition> result;
7029
2.02k
        auto addCond = [&](const Token* lhsTok, const Token* rhsTok, bool inverted) {
7030
6.08k
            for (int i = 0; i < 2; i++) {
7031
4.05k
                const bool lhs = i == 0;
7032
4.05k
                const Token* vartok = lhs ? lhsTok : rhsTok;
7033
4.05k
                const Token* valuetok = lhs ? rhsTok : lhsTok;
7034
4.05k
                if (valuetok->exprId() == 0)
7035
0
                    continue;
7036
4.05k
                if (valuetok->hasKnownSymbolicValue(vartok))
7037
4
                    continue;
7038
4.05k
                if (vartok->hasKnownSymbolicValue(valuetok))
7039
4
                    continue;
7040
4.04k
                ValueFlow::Value true_value;
7041
4.04k
                ValueFlow::Value false_value;
7042
4.04k
                setConditionalValues(tok, !lhs, 0, true_value, false_value);
7043
4.04k
                setSymbolic(true_value, valuetok);
7044
4.04k
                setSymbolic(false_value, valuetok);
7045
7046
4.04k
                Condition cond;
7047
4.04k
                cond.true_values = {std::move(true_value)};
7048
4.04k
                cond.false_values = {std::move(false_value)};
7049
4.04k
                cond.vartok = vartok;
7050
4.04k
                cond.inverted = inverted;
7051
4.04k
                result.push_back(std::move(cond));
7052
4.04k
            }
7053
2.02k
        };
7054
2.02k
        addCond(tok->astOperand1(), tok->astOperand2(), false);
7055
2.02k
        if (Token::Match(tok, "==|!=") && (isNegatedBool(tok->astOperand1()) || isNegatedBool(tok->astOperand2()))) {
7056
0
            const Token* lhsTok = skipNot(tok->astOperand1());
7057
0
            const Token* rhsTok = skipNot(tok->astOperand2());
7058
0
            addCond(lhsTok, rhsTok, !(isNegatedBool(tok->astOperand1()) && isNegatedBool(tok->astOperand2())));
7059
0
        }
7060
2.02k
        return result;
7061
4.20k
    }
7062
};
7063
7064
static bool valueFlowForLoop2(const Token *tok,
7065
                              ProgramMemory *memory1,
7066
                              ProgramMemory *memory2,
7067
                              ProgramMemory *memoryAfter)
7068
0
{
7069
    // for ( firstExpression ; secondExpression ; thirdExpression )
7070
0
    const Token *firstExpression  = tok->next()->astOperand2()->astOperand1();
7071
0
    const Token *secondExpression = tok->next()->astOperand2()->astOperand2()->astOperand1();
7072
0
    const Token *thirdExpression = tok->next()->astOperand2()->astOperand2()->astOperand2();
7073
7074
0
    ProgramMemory programMemory;
7075
0
    MathLib::bigint result(0);
7076
0
    bool error = false;
7077
0
    execute(firstExpression, programMemory, &result, &error);
7078
0
    if (error)
7079
0
        return false;
7080
0
    execute(secondExpression, programMemory, &result, &error);
7081
0
    if (result == 0) // 2nd expression is false => no looping
7082
0
        return false;
7083
0
    if (error) {
7084
        // If a variable is reassigned in second expression, return false
7085
0
        bool reassign = false;
7086
0
        visitAstNodes(secondExpression,
7087
0
                      [&](const Token *t) {
7088
0
            if (t->str() == "=" && t->astOperand1() && programMemory.hasValue(t->astOperand1()->varId()))
7089
                // TODO: investigate what variable is assigned.
7090
0
                reassign = true;
7091
0
            return reassign ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
7092
0
        });
7093
0
        if (reassign)
7094
0
            return false;
7095
0
    }
7096
7097
0
    ProgramMemory startMemory(programMemory);
7098
0
    ProgramMemory endMemory;
7099
7100
0
    int maxcount = 10000;
7101
0
    while (result != 0 && !error && --maxcount > 0) {
7102
0
        endMemory = programMemory;
7103
0
        execute(thirdExpression, programMemory, &result, &error);
7104
0
        if (!error)
7105
0
            execute(secondExpression, programMemory, &result, &error);
7106
0
    }
7107
7108
0
    if (memory1)
7109
0
        memory1->swap(startMemory);
7110
0
    if (!error) {
7111
0
        if (memory2)
7112
0
            memory2->swap(endMemory);
7113
0
        if (memoryAfter)
7114
0
            memoryAfter->swap(programMemory);
7115
0
    }
7116
7117
0
    return true;
7118
0
}
7119
7120
static void valueFlowForLoopSimplify(Token* const bodyStart,
7121
                                     const Token* expr,
7122
                                     bool globalvar,
7123
                                     const MathLib::bigint value,
7124
                                     const TokenList& tokenlist,
7125
                                     ErrorLogger* errorLogger,
7126
                                     const Settings& settings)
7127
0
{
7128
    // TODO: Refactor this to use arbitrary expressions
7129
0
    assert(expr->varId() > 0);
7130
0
    const Token * const bodyEnd = bodyStart->link();
7131
7132
    // Is variable modified inside for loop
7133
0
    if (isVariableChanged(bodyStart, bodyEnd, expr->varId(), globalvar, &settings, tokenlist.isCPP()))
7134
0
        return;
7135
7136
0
    for (Token *tok2 = bodyStart->next(); tok2 != bodyEnd; tok2 = tok2->next()) {
7137
0
        if (tok2->varId() == expr->varId()) {
7138
0
            const Token * parent = tok2->astParent();
7139
0
            while (parent) {
7140
0
                const Token * const p = parent;
7141
0
                parent = parent->astParent();
7142
0
                if (!parent || parent->str() == ":")
7143
0
                    break;
7144
0
                if (parent->str() == "?") {
7145
0
                    if (parent->astOperand2() != p)
7146
0
                        parent = nullptr;
7147
0
                    break;
7148
0
                }
7149
0
            }
7150
0
            if (parent) {
7151
0
                if (settings.debugwarnings)
7152
0
                    bailout(tokenlist, errorLogger, tok2, "For loop variable " + tok2->str() + " stopping on ?");
7153
0
                continue;
7154
0
            }
7155
7156
0
            ValueFlow::Value value1(value);
7157
0
            value1.varId = tok2->varId();
7158
0
            setTokenValue(tok2, std::move(value1), settings);
7159
0
        }
7160
7161
0
        if (Token::Match(tok2, "%oror%|&&")) {
7162
0
            const ProgramMemory programMemory(getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), &settings));
7163
0
            if ((tok2->str() == "&&" && !conditionIsTrue(tok2->astOperand1(), programMemory, &settings)) ||
7164
0
                (tok2->str() == "||" && !conditionIsFalse(tok2->astOperand1(), programMemory, &settings))) {
7165
                // Skip second expression..
7166
0
                Token *parent = tok2;
7167
0
                while (parent && parent->str() == tok2->str())
7168
0
                    parent = parent->astParent();
7169
                // Jump to end of condition
7170
0
                if (parent && parent->str() == "(") {
7171
0
                    tok2 = parent->link();
7172
                    // cast
7173
0
                    if (Token::simpleMatch(tok2, ") ("))
7174
0
                        tok2 = tok2->linkAt(1);
7175
0
                }
7176
0
            }
7177
0
        }
7178
0
        const Token* vartok = expr;
7179
0
        const Token* rml = nextAfterAstRightmostLeaf(vartok);
7180
0
        if (rml)
7181
0
            vartok = rml->str() == "]" ? rml : rml->previous();
7182
0
        if (vartok->str() == "]" && vartok->link()->previous())
7183
0
            vartok = vartok->link()->previous();
7184
7185
0
        if ((tok2->str() == "&&" &&
7186
0
             conditionIsFalse(tok2->astOperand1(),
7187
0
                              getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), &settings),
7188
0
                              &settings)) ||
7189
0
            (tok2->str() == "||" &&
7190
0
             conditionIsTrue(tok2->astOperand1(),
7191
0
                             getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), &settings),
7192
0
                             &settings)))
7193
0
            break;
7194
7195
0
        if (Token::simpleMatch(tok2, ") {")) {
7196
0
            if (vartok->varId() && Token::findmatch(tok2->link(), "%varid%", tok2, vartok->varId())) {
7197
0
                if (Token::findmatch(tok2, "continue|break|return", tok2->linkAt(1), vartok->varId())) {
7198
0
                    if (settings.debugwarnings)
7199
0
                        bailout(tokenlist, errorLogger, tok2, "For loop variable bailout on conditional continue|break|return");
7200
0
                    break;
7201
0
                }
7202
0
                if (settings.debugwarnings)
7203
0
                    bailout(tokenlist, errorLogger, tok2, "For loop variable skipping conditional scope");
7204
0
                tok2 = tok2->next()->link();
7205
0
                if (Token::simpleMatch(tok2, "} else {")) {
7206
0
                    if (Token::findmatch(tok2, "continue|break|return", tok2->linkAt(2), vartok->varId())) {
7207
0
                        if (settings.debugwarnings)
7208
0
                            bailout(tokenlist, errorLogger, tok2, "For loop variable bailout on conditional continue|break|return");
7209
0
                        break;
7210
0
                    }
7211
0
                    tok2 = tok2->linkAt(2);
7212
0
                }
7213
0
            }
7214
0
            else {
7215
0
                if (settings.debugwarnings)
7216
0
                    bailout(tokenlist, errorLogger, tok2, "For loop skipping {} code");
7217
0
                tok2 = tok2->linkAt(1);
7218
0
                if (Token::simpleMatch(tok2, "} else {"))
7219
0
                    tok2 = tok2->linkAt(2);
7220
0
            }
7221
0
        }
7222
0
    }
7223
0
}
7224
7225
static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, ErrorLogger * const errorLogger, const Settings& settings)
7226
0
{
7227
0
    const Token *vartok = nullptr;
7228
0
    for (const Token *tok = fortok; tok; tok = tok->next()) {
7229
0
        if (tok->varId() == varid) {
7230
0
            vartok = tok;
7231
0
            break;
7232
0
        }
7233
0
    }
7234
0
    if (!vartok || !vartok->variable())
7235
0
        return;
7236
7237
0
    const Variable *var = vartok->variable();
7238
0
    const Token *endToken = nullptr;
7239
0
    if (var->isLocal())
7240
0
        endToken = var->scope()->bodyEnd;
7241
0
    else
7242
0
        endToken = fortok->scope()->bodyEnd;
7243
7244
0
    Token* blockTok = fortok->linkAt(1)->linkAt(1);
7245
0
    if (blockTok != endToken) {
7246
0
        ValueFlow::Value v{num};
7247
0
        v.errorPath.emplace_back(fortok,"After for loop, " + var->name() + " has value " + v.infoString());
7248
7249
0
        valueFlowForward(blockTok->next(), endToken, vartok, std::move(v), tokenlist, errorLogger, settings);
7250
0
    }
7251
0
}
7252
7253
static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings)
7254
2.23k
{
7255
8.93k
    for (const Scope &scope : symboldatabase.scopeList) {
7256
8.93k
        if (scope.type != Scope::eFor)
7257
8.93k
            continue;
7258
7259
0
        auto* tok = const_cast<Token*>(scope.classDef);
7260
0
        auto* const bodyStart = const_cast<Token*>(scope.bodyStart);
7261
7262
0
        if (!Token::simpleMatch(tok->next()->astOperand2(), ";") ||
7263
0
            !Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";"))
7264
0
            continue;
7265
7266
0
        nonneg int varid;
7267
0
        bool knownInitValue, partialCond;
7268
0
        MathLib::bigint initValue, stepValue, lastValue;
7269
7270
0
        if (extractForLoopValues(tok, varid, knownInitValue, initValue, partialCond, stepValue, lastValue)) {
7271
0
            const bool executeBody = !knownInitValue || initValue <= lastValue;
7272
0
            const Token* vartok = Token::findmatch(tok, "%varid%", bodyStart, varid);
7273
0
            if (executeBody && vartok) {
7274
0
                std::list<ValueFlow::Value> initValues;
7275
0
                initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower);
7276
0
                initValues.push_back(ValueFlow::asImpossible(initValues.back()));
7277
0
                Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, std::move(initValues), tokenlist, errorLogger, settings);
7278
7279
0
                if (!result.action.isModified()) {
7280
0
                    std::list<ValueFlow::Value> lastValues;
7281
0
                    lastValues.emplace_back(lastValue, ValueFlow::Value::Bound::Upper);
7282
0
                    lastValues.back().conditional = true;
7283
0
                    lastValues.push_back(ValueFlow::asImpossible(lastValues.back()));
7284
0
                    if (stepValue != 1)
7285
0
                        lastValues.pop_front();
7286
0
                    valueFlowForward(bodyStart, bodyStart->link(), vartok, std::move(lastValues), tokenlist, errorLogger, settings);
7287
0
                }
7288
0
            }
7289
0
            const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue;
7290
0
            valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, errorLogger, settings);
7291
0
        } else {
7292
0
            ProgramMemory mem1, mem2, memAfter;
7293
0
            if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) {
7294
0
                for (const auto& p : mem1) {
7295
0
                    if (!p.second.isIntValue())
7296
0
                        continue;
7297
0
                    if (p.second.isImpossible())
7298
0
                        continue;
7299
0
                    if (p.first.tok->varId() == 0)
7300
0
                        continue;
7301
0
                    valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
7302
0
                }
7303
0
                for (const auto& p : mem2) {
7304
0
                    if (!p.second.isIntValue())
7305
0
                        continue;
7306
0
                    if (p.second.isImpossible())
7307
0
                        continue;
7308
0
                    if (p.first.tok->varId() == 0)
7309
0
                        continue;
7310
0
                    valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
7311
0
                }
7312
0
                for (const auto& p : memAfter) {
7313
0
                    if (!p.second.isIntValue())
7314
0
                        continue;
7315
0
                    if (p.second.isImpossible())
7316
0
                        continue;
7317
0
                    if (p.first.tok->varId() == 0)
7318
0
                        continue;
7319
0
                    valueFlowForLoopSimplifyAfter(tok, p.first.getExpressionId(), p.second.intvalue, tokenlist, errorLogger, settings);
7320
0
                }
7321
0
            }
7322
0
        }
7323
0
    }
7324
2.23k
}
7325
7326
struct MultiValueFlowAnalyzer : ValueFlowAnalyzer {
7327
    std::unordered_map<nonneg int, ValueFlow::Value> values;
7328
    std::unordered_map<nonneg int, const Variable*> vars;
7329
7330
    MultiValueFlowAnalyzer(const std::unordered_map<const Variable*, ValueFlow::Value>& args, const TokenList& t, const Settings& set)
7331
0
        : ValueFlowAnalyzer(t, set) {
7332
0
        for (const auto& p:args) {
7333
0
            values[p.first->declarationId()] = p.second;
7334
0
            vars[p.first->declarationId()] = p.first;
7335
0
        }
7336
0
    }
7337
7338
0
    virtual const std::unordered_map<nonneg int, const Variable*>& getVars() const {
7339
0
        return vars;
7340
0
    }
7341
7342
0
    const ValueFlow::Value* getValue(const Token* tok) const override {
7343
0
        if (tok->varId() == 0)
7344
0
            return nullptr;
7345
0
        auto it = values.find(tok->varId());
7346
0
        if (it == values.end())
7347
0
            return nullptr;
7348
0
        return &it->second;
7349
0
    }
7350
0
    ValueFlow::Value* getValue(const Token* tok) override {
7351
0
        if (tok->varId() == 0)
7352
0
            return nullptr;
7353
0
        auto it = values.find(tok->varId());
7354
0
        if (it == values.end())
7355
0
            return nullptr;
7356
0
        return &it->second;
7357
0
    }
7358
7359
0
    void makeConditional() override {
7360
0
        for (auto&& p:values) {
7361
0
            p.second.conditional = true;
7362
0
        }
7363
0
    }
7364
7365
0
    void addErrorPath(const Token* tok, const std::string& s) override {
7366
0
        for (auto&& p:values) {
7367
0
            p.second.errorPath.emplace_back(tok, s);
7368
0
        }
7369
0
    }
7370
7371
0
    bool isAlias(const Token* tok, bool& inconclusive) const override {
7372
0
        const auto range = SelectValueFromVarIdMapRange(&values);
7373
7374
0
        for (const auto& p:getVars()) {
7375
0
            nonneg int const varid = p.first;
7376
0
            const Variable* var = p.second;
7377
0
            if (tok->varId() == varid)
7378
0
                return true;
7379
0
            if (isAliasOf(var, tok, varid, range, &inconclusive))
7380
0
                return true;
7381
0
        }
7382
0
        return false;
7383
0
    }
7384
7385
0
    bool lowerToPossible() override {
7386
0
        for (auto&& p:values) {
7387
0
            if (p.second.isImpossible())
7388
0
                return false;
7389
0
            p.second.changeKnownToPossible();
7390
0
        }
7391
0
        return true;
7392
0
    }
7393
0
    bool lowerToInconclusive() override {
7394
0
        for (auto&& p:values) {
7395
0
            if (p.second.isImpossible())
7396
0
                return false;
7397
0
            p.second.setInconclusive();
7398
0
        }
7399
0
        return true;
7400
0
    }
7401
7402
0
    bool isConditional() const override {
7403
0
        for (auto&& p:values) {
7404
0
            if (p.second.conditional)
7405
0
                return true;
7406
0
            if (p.second.condition)
7407
0
                return !p.second.isImpossible();
7408
0
        }
7409
0
        return false;
7410
0
    }
7411
7412
0
    bool stopOnCondition(const Token* condTok) const override {
7413
0
        if (isConditional())
7414
0
            return true;
7415
0
        if (!condTok->hasKnownIntValue() && values.count(condTok->varId()) == 0) {
7416
0
            const auto& values_ = condTok->values();
7417
0
            return std::any_of(values_.cbegin(), values_.cend(), [](const ValueFlow::Value& v) {
7418
0
                return v.isSymbolicValue() && Token::Match(v.tokvalue, "%oror%|&&");
7419
0
            });
7420
0
        }
7421
0
        return false;
7422
0
    }
7423
7424
0
    bool updateScope(const Token* endBlock, bool /*modified*/) const override {
7425
0
        const Scope* scope = endBlock->scope();
7426
0
        if (!scope)
7427
0
            return false;
7428
0
        if (scope->type == Scope::eLambda) {
7429
0
            return std::all_of(values.cbegin(), values.cend(), [](const std::pair<nonneg int, ValueFlow::Value>& p) {
7430
0
                return p.second.isLifetimeValue();
7431
0
            });
7432
0
        }
7433
0
        if (scope->type == Scope::eIf || scope->type == Scope::eElse || scope->type == Scope::eWhile ||
7434
0
            scope->type == Scope::eFor) {
7435
0
            auto pred = [](const ValueFlow::Value& value) {
7436
0
                if (value.isKnown())
7437
0
                    return true;
7438
0
                if (value.isImpossible())
7439
0
                    return true;
7440
0
                if (value.isLifetimeValue())
7441
0
                    return true;
7442
0
                return false;
7443
0
            };
7444
0
            if (std::all_of(values.cbegin(), values.cend(), std::bind(pred, std::bind(SelectMapValues{}, std::placeholders::_1))))
7445
0
                return true;
7446
0
            if (isConditional())
7447
0
                return false;
7448
0
            const Token* condTok = getCondTokFromEnd(endBlock);
7449
0
            std::set<nonneg int> varids;
7450
0
            std::transform(getVars().cbegin(), getVars().cend(), std::inserter(varids, varids.begin()), SelectMapKeys{});
7451
0
            return bifurcate(condTok, varids, getSettings());
7452
0
        }
7453
7454
0
        return false;
7455
0
    }
7456
7457
0
    bool match(const Token* tok) const override {
7458
0
        return values.count(tok->varId()) > 0;
7459
0
    }
7460
7461
0
    ProgramState getProgramState() const override {
7462
0
        ProgramState ps;
7463
0
        for (const auto& p : values) {
7464
0
            const Variable* var = vars.at(p.first);
7465
0
            if (!var)
7466
0
                continue;
7467
0
            ps[var->nameToken()] = p.second;
7468
0
        }
7469
0
        return ps;
7470
0
    }
7471
};
7472
7473
template<class Key, class F>
7474
static bool productParams(const Settings& settings, const std::unordered_map<Key, std::list<ValueFlow::Value>>& vars, F f)
7475
0
{
7476
0
    using Args = std::vector<std::unordered_map<Key, ValueFlow::Value>>;
7477
0
    Args args(1);
7478
    // Compute cartesian product of all arguments
7479
0
    for (const auto& p:vars) {
7480
0
        if (p.second.empty())
7481
0
            continue;
7482
0
        args.back()[p.first] = p.second.front();
7483
0
    }
7484
0
    bool bail = false;
7485
0
    int max = settings.performanceValueFlowMaxSubFunctionArgs;
7486
0
    for (const auto& p:vars) {
7487
0
        if (args.size() > max) {
7488
0
            bail = true;
7489
0
            break;
7490
0
        }
7491
0
        if (p.second.empty())
7492
0
            continue;
7493
0
        std::for_each(std::next(p.second.begin()), p.second.end(), [&](const ValueFlow::Value& value) {
7494
0
            Args new_args;
7495
0
            for (auto arg:args) {
7496
0
                if (value.path != 0) {
7497
0
                    for (const auto& q:arg) {
7498
0
                        if (q.first == p.first)
7499
0
                            continue;
7500
0
                        if (q.second.path == 0)
7501
0
                            continue;
7502
0
                        if (q.second.path != value.path)
7503
0
                            return;
7504
0
                    }
7505
0
                }
7506
0
                arg[p.first] = value;
7507
0
                new_args.push_back(std::move(arg));
7508
0
            }
7509
0
            std::copy(new_args.cbegin(), new_args.cend(), std::back_inserter(args));
7510
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&)::$_89>(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&)::$_89)::{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&)::$_88>(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&)::$_88)::{lambda(ValueFlow::Value const&)#1}::operator()(ValueFlow::Value const&) const
7511
0
    }
7512
7513
0
    if (args.size() > max) {
7514
0
        bail = true;
7515
0
        args.resize(max);
7516
0
    }
7517
7518
0
    for (const auto& arg:args) {
7519
0
        if (arg.empty())
7520
0
            continue;
7521
        // Make sure all arguments are the same path
7522
0
        const MathLib::bigint path = arg.cbegin()->second.path;
7523
0
        if (std::any_of(arg.cbegin(), arg.cend(), [&](const std::pair<Key, ValueFlow::Value>& p) {
7524
0
            return p.second.path != path;
7525
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&)::$_89>(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&)::$_89)::{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&)::$_88>(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&)::$_88)::{lambda(std::__1::pair<Variable const*, ValueFlow::Value> const&)#1}::operator()(std::__1::pair<Variable const*, ValueFlow::Value> const&) const
7526
0
            continue;
7527
0
        f(arg);
7528
0
    }
7529
0
    return !bail;
7530
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&)::$_89>(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&)::$_89)
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&)::$_88>(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&)::$_88)
7531
7532
static void valueFlowInjectParameter(TokenList& tokenlist,
7533
                                     ErrorLogger* errorLogger,
7534
                                     const Settings& settings,
7535
                                     const Scope* functionScope,
7536
                                     const std::unordered_map<const Variable*, std::list<ValueFlow::Value>>& vars)
7537
0
{
7538
0
    const bool r = productParams(settings, vars, [&](const std::unordered_map<const Variable*, ValueFlow::Value>& arg) {
7539
0
        MultiValueFlowAnalyzer a(arg, tokenlist, settings);
7540
0
        valueFlowGenericForward(const_cast<Token*>(functionScope->bodyStart), functionScope->bodyEnd, a, tokenlist, errorLogger, settings);
7541
0
    });
7542
0
    if (!r) {
7543
0
        std::string fname = "<unknown>";
7544
0
        if (const Function* f = functionScope->function)
7545
0
            fname = f->name();
7546
0
        if (settings.debugwarnings)
7547
0
            bailout(tokenlist, errorLogger, functionScope->bodyStart, "Too many argument passed to " + fname);
7548
0
    }
7549
0
}
7550
7551
static void valueFlowInjectParameter(const TokenList& tokenlist,
7552
                                     ErrorLogger* const errorLogger,
7553
                                     const Settings& settings,
7554
                                     const Variable* arg,
7555
                                     const Scope* functionScope,
7556
                                     const std::list<ValueFlow::Value>& argvalues)
7557
0
{
7558
    // Is argument passed by value or const reference, and is it a known non-class type?
7559
0
    if (arg->isReference() && !arg->isConst() && !arg->isClass())
7560
0
        return;
7561
7562
    // Set value in function scope..
7563
0
    const nonneg int varid2 = arg->declarationId();
7564
0
    if (!varid2)
7565
0
        return;
7566
7567
0
    valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
7568
0
                     functionScope->bodyEnd,
7569
0
                     arg->nameToken(),
7570
0
                     argvalues,
7571
0
                     tokenlist,
7572
0
                     errorLogger,
7573
0
                     settings);
7574
0
}
7575
7576
static void valueFlowSwitchVariable(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings)
7577
2.23k
{
7578
8.93k
    for (const Scope &scope : symboldatabase.scopeList) {
7579
8.93k
        if (scope.type != Scope::ScopeType::eSwitch)
7580
8.93k
            continue;
7581
0
        if (!Token::Match(scope.classDef, "switch ( %var% ) {"))
7582
0
            continue;
7583
0
        const Token *vartok = scope.classDef->tokAt(2);
7584
0
        const Variable *var = vartok->variable();
7585
0
        if (!var)
7586
0
            continue;
7587
7588
        // bailout: global non-const variables
7589
0
        if (!(var->isLocal() || var->isArgument()) && !var->isConst()) {
7590
0
            if (settings.debugwarnings)
7591
0
                bailout(tokenlist, errorLogger, vartok, "switch variable " + var->name() + " is global");
7592
0
            continue;
7593
0
        }
7594
7595
0
        for (const Token *tok = scope.bodyStart->next(); tok != scope.bodyEnd; tok = tok->next()) {
7596
0
            if (tok->str() == "{") {
7597
0
                tok = tok->link();
7598
0
                continue;
7599
0
            }
7600
0
            if (Token::Match(tok, "case %num% :")) {
7601
0
                std::list<ValueFlow::Value> values;
7602
0
                values.emplace_back(MathLib::toBigNumber(tok->next()->str()));
7603
0
                values.back().condition = tok;
7604
0
                values.back().errorPath.emplace_back(tok, "case " + tok->next()->str() + ": " + vartok->str() + " is " + tok->next()->str() + " here.");
7605
0
                bool known = false;
7606
0
                if ((Token::simpleMatch(tok->previous(), "{") || Token::simpleMatch(tok->tokAt(-2), "break ;")) && !Token::Match(tok->tokAt(3), ";| case"))
7607
0
                    known = true;
7608
0
                while (Token::Match(tok->tokAt(3), ";| case %num% :")) {
7609
0
                    known = false;
7610
0
                    tok = tok->tokAt(3);
7611
0
                    if (!tok->isName())
7612
0
                        tok = tok->next();
7613
0
                    values.emplace_back(MathLib::toBigNumber(tok->next()->str()));
7614
0
                    values.back().condition = tok;
7615
0
                    values.back().errorPath.emplace_back(tok, "case " + tok->next()->str() + ": " + vartok->str() + " is " + tok->next()->str() + " here.");
7616
0
                }
7617
0
                for (std::list<ValueFlow::Value>::const_iterator val = values.cbegin(); val != values.cend(); ++val) {
7618
0
                    valueFlowReverse(tokenlist,
7619
0
                                     const_cast<Token*>(scope.classDef),
7620
0
                                     vartok,
7621
0
                                     *val,
7622
0
                                     ValueFlow::Value(),
7623
0
                                     errorLogger,
7624
0
                                     settings);
7625
0
                }
7626
0
                if (vartok->variable()->scope()) {
7627
0
                    if (known)
7628
0
                        values.back().setKnown();
7629
7630
                    // FIXME We must check if there is a return. See #9276
7631
                    /*
7632
                       valueFlowForwardVariable(tok->tokAt(3),
7633
                                             vartok->variable()->scope()->bodyEnd,
7634
                                             vartok->variable(),
7635
                                             vartok->varId(),
7636
                                             values,
7637
                                             values.back().isKnown(),
7638
                                             false,
7639
                                             tokenlist,
7640
                                             errorLogger,
7641
                                             settings);
7642
                     */
7643
0
                }
7644
0
            }
7645
0
        }
7646
0
    }
7647
2.23k
}
7648
7649
static std::list<ValueFlow::Value> getFunctionArgumentValues(const Token *argtok)
7650
0
{
7651
0
    std::list<ValueFlow::Value> argvalues(argtok->values());
7652
0
    removeImpossible(argvalues);
7653
0
    if (argvalues.empty() && Token::Match(argtok, "%comp%|%oror%|&&|!")) {
7654
0
        argvalues.emplace_back(0);
7655
0
        argvalues.emplace_back(1);
7656
0
    }
7657
0
    return argvalues;
7658
0
}
7659
7660
static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue, const Settings &settings)
7661
0
{
7662
0
    std::unordered_map<nonneg int, std::list<ValueFlow::Value>> argValues;
7663
0
    int argn = 1;
7664
0
    for (const Token *argtok : getArguments(tok->previous())) {
7665
0
        argValues[argn] = getFunctionArgumentValues(argtok);
7666
0
        argn++;
7667
0
    }
7668
0
    if (returnValue.find("arg") != std::string::npos && argValues.empty())
7669
0
        return;
7670
0
    productParams(settings, argValues, [&](const std::unordered_map<nonneg int, ValueFlow::Value>& arg) {
7671
0
        ValueFlow::Value value = evaluateLibraryFunction(arg, returnValue, &settings);
7672
0
        if (value.isUninitValue())
7673
0
            return;
7674
0
        ValueFlow::Value::ValueKind kind = ValueFlow::Value::ValueKind::Known;
7675
0
        for (auto&& p : arg) {
7676
0
            if (p.second.isPossible())
7677
0
                kind = p.second.valueKind;
7678
0
            if (p.second.isInconclusive()) {
7679
0
                kind = p.second.valueKind;
7680
0
                break;
7681
0
            }
7682
0
        }
7683
0
        if (value.isImpossible() && kind != ValueFlow::Value::ValueKind::Known)
7684
0
            return;
7685
0
        if (!value.isImpossible())
7686
0
            value.valueKind = kind;
7687
0
        setTokenValue(tok, std::move(value), settings);
7688
0
    });
7689
0
}
7690
7691
template<class Iterator>
7692
struct IteratorRange
7693
{
7694
    Iterator mBegin;
7695
    Iterator mEnd;
7696
7697
2.23k
    Iterator begin() const {
7698
2.23k
        return mBegin;
7699
2.23k
    }
7700
7701
2.23k
    Iterator end() const {
7702
2.23k
        return mEnd;
7703
2.23k
    }
7704
};
7705
7706
template<class Iterator>
7707
static IteratorRange<Iterator> MakeIteratorRange(Iterator start, Iterator last)
7708
2.23k
{
7709
2.23k
    return {start, last};
7710
2.23k
}
7711
7712
static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase& symboldatabase,  ErrorLogger* errorLogger, const Settings& settings)
7713
2.23k
{
7714
2.23k
    int id = 0;
7715
2.92k
    for (const Scope* scope : MakeIteratorRange(symboldatabase.functionScopes.crbegin(), symboldatabase.functionScopes.crend())) {
7716
2.92k
        const Function* function = scope->function;
7717
2.92k
        if (!function)
7718
0
            continue;
7719
69.9k
        for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
7720
67.0k
            if (tok->isKeyword() || !Token::Match(tok, "%name% ("))
7721
67.0k
                continue;
7722
7723
0
            const Function * const calledFunction = tok->function();
7724
0
            if (!calledFunction) {
7725
                // library function?
7726
0
                const std::string& returnValue(settings.library.returnValue(tok));
7727
0
                if (!returnValue.empty())
7728
0
                    valueFlowLibraryFunction(tok->next(), returnValue, settings);
7729
0
                continue;
7730
0
            }
7731
7732
0
            const Scope * const calledFunctionScope = calledFunction->functionScope;
7733
0
            if (!calledFunctionScope)
7734
0
                continue;
7735
7736
0
            id++;
7737
0
            std::unordered_map<const Variable*, std::list<ValueFlow::Value>> argvars;
7738
            // TODO: Rewrite this. It does not work well to inject 1 argument at a time.
7739
0
            const std::vector<const Token *> &callArguments = getArguments(tok);
7740
0
            for (int argnr = 0U; argnr < callArguments.size(); ++argnr) {
7741
0
                const Token *argtok = callArguments[argnr];
7742
                // Get function argument
7743
0
                const Variable * const argvar = calledFunction->getArgumentVar(argnr);
7744
0
                if (!argvar)
7745
0
                    break;
7746
7747
                // passing value(s) to function
7748
0
                std::list<ValueFlow::Value> argvalues(getFunctionArgumentValues(argtok));
7749
7750
                // Remove non-local lifetimes
7751
0
                argvalues.remove_if([](const ValueFlow::Value& v) {
7752
0
                    if (v.isLifetimeValue())
7753
0
                        return !v.isLocalLifetimeValue() && !v.isSubFunctionLifetimeValue();
7754
0
                    return false;
7755
0
                });
7756
                // Remove uninit values if argument is passed by value
7757
0
                if (argtok->variable() && !argtok->variable()->isPointer() && argvalues.size() == 1 && argvalues.front().isUninitValue()) {
7758
0
                    if (CheckUninitVar::isVariableUsage(argtok, settings.library, false, CheckUninitVar::Alloc::NO_ALLOC, 0))
7759
0
                        continue;
7760
0
                }
7761
7762
0
                if (argvalues.empty())
7763
0
                    continue;
7764
7765
                // Error path..
7766
0
                for (ValueFlow::Value &v : argvalues) {
7767
0
                    const std::string nr = std::to_string(argnr + 1) + getOrdinalText(argnr + 1);
7768
7769
0
                    v.errorPath.emplace_back(argtok,
7770
0
                                             "Calling function '" +
7771
0
                                             calledFunction->name() +
7772
0
                                             "', " +
7773
0
                                             nr +
7774
0
                                             " argument '" +
7775
0
                                             argtok->expressionString() +
7776
0
                                             "' value is " +
7777
0
                                             v.infoString());
7778
0
                    v.path = 256 * v.path + id % 256;
7779
                    // Change scope of lifetime values
7780
0
                    if (v.isLifetimeValue())
7781
0
                        v.lifetimeScope = ValueFlow::Value::LifetimeScope::SubFunction;
7782
0
                }
7783
7784
                // passed values are not "known"..
7785
0
                lowerToPossible(argvalues);
7786
7787
0
                argvars[argvar] = std::move(argvalues);
7788
0
            }
7789
0
            valueFlowInjectParameter(tokenlist, errorLogger, settings, calledFunctionScope, argvars);
7790
0
        }
7791
2.92k
    }
7792
2.23k
}
7793
7794
static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings)
7795
2.23k
{
7796
2.23k
    if (!tokenlist.isCPP())
7797
0
        return;
7798
7799
2.92k
    for (const Scope* scope : symboldatabase.functionScopes) {
7800
2.92k
        const Function* function = scope->function;
7801
2.92k
        if (!function)
7802
0
            continue;
7803
2.92k
        for (std::size_t arg = function->minArgCount(); arg < function->argCount(); arg++) {
7804
0
            const Variable* var = function->getArgumentVar(arg);
7805
0
            if (var && var->hasDefault() && Token::Match(var->nameToken(), "%var% = %num%|%str% [,)]")) {
7806
0
                const std::list<ValueFlow::Value> &values = var->nameToken()->tokAt(2)->values();
7807
0
                std::list<ValueFlow::Value> argvalues;
7808
0
                for (const ValueFlow::Value &value : values) {
7809
0
                    ValueFlow::Value v(value);
7810
0
                    v.defaultArg = true;
7811
0
                    v.changeKnownToPossible();
7812
0
                    if (v.isPossible())
7813
0
                        argvalues.push_back(std::move(v));
7814
0
                }
7815
0
                if (!argvalues.empty())
7816
0
                    valueFlowInjectParameter(tokenlist, errorLogger, settings, var, scope, argvalues);
7817
0
            }
7818
0
        }
7819
2.92k
    }
7820
2.23k
}
7821
7822
static const ValueFlow::Value* getKnownValueFromToken(const Token* tok)
7823
0
{
7824
0
    if (!tok)
7825
0
        return nullptr;
7826
0
    auto it = std::find_if(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) {
7827
0
        return (v.isIntValue() || v.isContainerSizeValue() || v.isFloatValue()) && v.isKnown();
7828
0
    });
7829
0
    if (it == tok->values().end())
7830
0
        return nullptr;
7831
0
    return std::addressof(*it);
7832
0
}
7833
7834
static const ValueFlow::Value* getKnownValueFromTokens(const std::vector<const Token*>& toks)
7835
0
{
7836
0
    if (toks.empty())
7837
0
        return nullptr;
7838
0
    const ValueFlow::Value* result = getKnownValueFromToken(toks.front());
7839
0
    if (!result)
7840
0
        return nullptr;
7841
0
    if (!std::all_of(std::next(toks.begin()), toks.end(), [&](const Token* tok) {
7842
0
        return std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) {
7843
0
            return v.equalValue(*result) && v.valueKind == result->valueKind;
7844
0
        });
7845
0
    }))
7846
0
        return nullptr;
7847
0
    return result;
7848
0
}
7849
7850
static void setFunctionReturnValue(const Function* f, Token* tok, ValueFlow::Value v, const Settings& settings)
7851
0
{
7852
0
    if (f->hasVirtualSpecifier()) {
7853
0
        if (v.isImpossible())
7854
0
            return;
7855
0
        v.setPossible();
7856
0
    } else if (!v.isImpossible()) {
7857
0
        v.setKnown();
7858
0
    }
7859
0
    v.errorPath.emplace_back(tok, "Calling function '" + f->name() + "' returns " + v.toString());
7860
0
    setTokenValue(tok, std::move(v), settings);
7861
0
}
7862
7863
static void valueFlowFunctionReturn(TokenList &tokenlist, ErrorLogger *errorLogger, const Settings& settings)
7864
2.23k
{
7865
161k
    for (Token *tok = tokenlist.back(); tok; tok = tok->previous()) {
7866
159k
        if (tok->str() != "(" || !tok->astOperand1() || tok->isCast())
7867
157k
            continue;
7868
7869
2.74k
        const Function* function = nullptr;
7870
2.74k
        if (Token::Match(tok->previous(), "%name% ("))
7871
2.74k
            function = tok->previous()->function();
7872
6
        else
7873
6
            function = tok->astOperand1()->function();
7874
2.74k
        if (!function)
7875
2.74k
            continue;
7876
        // TODO: Check if member variable is a pointer or reference
7877
0
        if (function->isImplicitlyVirtual() && !function->hasFinalSpecifier())
7878
0
            continue;
7879
7880
0
        if (tok->hasKnownValue())
7881
0
            continue;
7882
7883
0
        std::vector<const Token*> returns = Function::findReturns(function);
7884
0
        if (returns.empty())
7885
0
            continue;
7886
7887
0
        if (const ValueFlow::Value* v = getKnownValueFromTokens(returns)) {
7888
0
            setFunctionReturnValue(function, tok, *v, settings);
7889
0
            continue;
7890
0
        }
7891
7892
        // Arguments..
7893
0
        std::vector<const Token*> arguments = getArguments(tok);
7894
7895
0
        ProgramMemory programMemory;
7896
0
        for (std::size_t i = 0; i < arguments.size(); ++i) {
7897
0
            const Variable * const arg = function->getArgumentVar(i);
7898
0
            if (!arg) {
7899
0
                if (settings.debugwarnings)
7900
0
                    bailout(tokenlist, errorLogger, tok, "function return; unhandled argument type");
7901
0
                programMemory.clear();
7902
0
                break;
7903
0
            }
7904
0
            const ValueFlow::Value* v = getKnownValueFromToken(arguments[i]);
7905
0
            if (!v)
7906
0
                continue;
7907
0
            programMemory.setValue(arg->nameToken(), *v);
7908
0
        }
7909
0
        if (programMemory.empty() && !arguments.empty())
7910
0
            continue;
7911
0
        std::vector<ValueFlow::Value> values = execute(function->functionScope, programMemory, &settings);
7912
0
        for (const ValueFlow::Value& v : values) {
7913
0
            if (v.isUninitValue())
7914
0
                continue;
7915
0
            setFunctionReturnValue(function, tok, v, settings);
7916
0
        }
7917
0
    }
7918
2.23k
}
7919
7920
static bool needsInitialization(const Variable* var, bool cpp)
7921
0
{
7922
0
    if (!var)
7923
0
        return false;
7924
0
    if (var->hasDefault())
7925
0
        return false;
7926
0
    if (var->isPointer())
7927
0
        return true;
7928
0
    if (var->type() && var->type()->isUnionType())
7929
0
        return false;
7930
0
    if (!cpp)
7931
0
        return true;
7932
0
    if (var->type() && var->type()->needInitialization == Type::NeedInitialization::True)
7933
0
        return true;
7934
0
    if (var->valueType()) {
7935
0
        if (var->valueType()->isPrimitive())
7936
0
            return true;
7937
0
        if (var->valueType()->type == ValueType::Type::POD)
7938
0
            return true;
7939
0
        if (var->valueType()->type == ValueType::Type::ITERATOR)
7940
0
            return true;
7941
0
    }
7942
0
    return false;
7943
0
}
7944
7945
static void addToErrorPath(ValueFlow::Value& value, const ValueFlow::Value& from)
7946
0
{
7947
0
    std::unordered_set<const Token*> locations;
7948
0
    std::transform(value.errorPath.cbegin(),
7949
0
                   value.errorPath.cend(),
7950
0
                   std::inserter(locations, locations.begin()),
7951
0
                   [](const ErrorPathItem& e) {
7952
0
        return e.first;
7953
0
    });
7954
0
    if (from.condition && !value.condition)
7955
0
        value.condition = from.condition;
7956
0
    std::copy_if(from.errorPath.cbegin(),
7957
0
                 from.errorPath.cend(),
7958
0
                 std::back_inserter(value.errorPath),
7959
0
                 [&](const ErrorPathItem& e) {
7960
0
        return locations.insert(e.first).second;
7961
0
    });
7962
0
}
7963
7964
static std::vector<Token*> findAllUsages(const Variable* var,
7965
                                         Token* start, // cppcheck-suppress constParameterPointer // FP
7966
                                         const Library* library)
7967
0
{
7968
    // std::vector<Token*> result;
7969
0
    const Scope* scope = var->scope();
7970
0
    if (!scope)
7971
0
        return {};
7972
0
    return findTokensSkipDeadCode(library, start, scope->bodyEnd, [&](const Token* tok) {
7973
0
        return tok->varId() == var->declarationId();
7974
0
    });
7975
0
}
7976
7977
static Token* findStartToken(const Variable* var, Token* start, const Library* library)
7978
0
{
7979
0
    std::vector<Token*> uses = findAllUsages(var, start, library);
7980
0
    if (uses.empty())
7981
0
        return start;
7982
0
    Token* first = uses.front();
7983
0
    if (Token::findmatch(start, "goto|asm|setjmp|longjmp", first))
7984
0
        return start;
7985
0
    if (first != var->nameToken()) {
7986
        // if this is lhs in assignment then set first to the first token in LHS expression
7987
0
        Token* temp = first;
7988
0
        while (Token::Match(temp->astParent(), "[&*(]") && precedes(temp->astParent(), temp))
7989
0
            temp = temp->astParent();
7990
0
        if (Token::simpleMatch(temp->astParent(), "=") && precedes(temp, temp->astParent()))
7991
0
            first = temp;
7992
0
    }
7993
    // If there is only one usage
7994
0
    if (uses.size() == 1)
7995
0
        return first->previous();
7996
0
    const Scope* scope = first->scope();
7997
    // If first usage is in variable scope
7998
0
    if (scope == var->scope()) {
7999
0
        bool isLoopExpression = false;
8000
0
        for (const Token* parent = first; parent; parent = parent->astParent()) {
8001
0
            if (Token::simpleMatch(parent->astParent(), ";") &&
8002
0
                Token::simpleMatch(parent->astParent()->astParent(), ";") &&
8003
0
                Token::simpleMatch(parent->astParent()->astParent()->astParent(), "(") &&
8004
0
                Token::simpleMatch(parent->astParent()->astParent()->astParent()->astOperand1(), "for (") &&
8005
0
                parent == parent->astParent()->astParent()->astParent()->astOperand2()->astOperand2()->astOperand2()) {
8006
0
                isLoopExpression = true;
8007
0
            }
8008
0
        }
8009
0
        return isLoopExpression ? start : first->previous();
8010
0
    }
8011
    // If all uses are in the same scope
8012
0
    if (std::all_of(uses.begin() + 1, uses.end(), [&](const Token* tok) {
8013
0
        return tok->scope() == scope;
8014
0
    }))
8015
0
        return first->previous();
8016
    // Compute the outer scope
8017
0
    while (scope && scope->nestedIn != var->scope())
8018
0
        scope = scope->nestedIn;
8019
0
    if (!scope)
8020
0
        return start;
8021
0
    Token* tok = const_cast<Token*>(scope->bodyStart);
8022
0
    if (!tok)
8023
0
        return start;
8024
0
    if (Token::simpleMatch(tok->tokAt(-2), "} else {"))
8025
0
        tok = tok->linkAt(-2);
8026
0
    if (Token::simpleMatch(tok->previous(), ") {"))
8027
0
        return tok->linkAt(-1)->previous();
8028
0
    return tok;
8029
0
}
8030
8031
static void valueFlowUninit(TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings)
8032
2.23k
{
8033
161k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
8034
159k
        if (!tok->scope()->isExecutable())
8035
89.8k
            continue;
8036
69.9k
        if (!Token::Match(tok, "%var% ;|["))
8037
67.6k
            continue;
8038
2.27k
        const Variable* var = tok->variable();
8039
2.27k
        if (!var)
8040
0
            continue;
8041
2.27k
        if (var->nameToken() != tok || var->isInit())
8042
2.27k
            continue;
8043
0
        if (!needsInitialization(var, tokenlist.isCPP()))
8044
0
            continue;
8045
0
        if (!var->isLocal() || var->isStatic() || var->isExtern() || var->isReference() || var->isThrow())
8046
0
            continue;
8047
8048
0
        ValueFlow::Value uninitValue;
8049
0
        uninitValue.setKnown();
8050
0
        uninitValue.valueType = ValueFlow::Value::ValueType::UNINIT;
8051
0
        uninitValue.tokvalue = tok;
8052
0
        if (var->isArray())
8053
0
            uninitValue.indirect = var->dimensions().size();
8054
8055
0
        bool partial = false;
8056
8057
0
        Token* start = findStartToken(var, tok->next(), &settings.library);
8058
8059
0
        std::map<Token*, ValueFlow::Value> partialReads;
8060
0
        if (const Scope* scope = var->typeScope()) {
8061
0
            if (Token::findsimplematch(scope->bodyStart, "union", scope->bodyEnd))
8062
0
                continue;
8063
0
            for (const Variable& memVar : scope->varlist) {
8064
0
                if (!memVar.isPublic())
8065
0
                    continue;
8066
                // Skip array since we can't track partial initialization from nested subexpressions
8067
0
                if (memVar.isArray())
8068
0
                    continue;
8069
0
                if (!needsInitialization(&memVar, tokenlist.isCPP())) {
8070
0
                    partial = true;
8071
0
                    continue;
8072
0
                }
8073
0
                MemberExpressionAnalyzer analyzer(memVar.nameToken()->str(), tok, uninitValue, tokenlist, settings);
8074
0
                valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, tokenlist, errorLogger, settings);
8075
8076
0
                for (auto&& p : *analyzer.partialReads) {
8077
0
                    Token* tok2 = p.first;
8078
0
                    const ValueFlow::Value& v = p.second;
8079
                    // Try to insert into map
8080
0
                    auto pp = partialReads.insert(std::make_pair(tok2, v));
8081
0
                    ValueFlow::Value& v2 = pp.first->second;
8082
0
                    const bool inserted = pp.second;
8083
                    // Merge the two values if it is already in map
8084
0
                    if (!inserted) {
8085
0
                        if (v.valueType != v2.valueType)
8086
0
                            continue;
8087
0
                        addToErrorPath(v2, v);
8088
0
                    }
8089
0
                    v2.subexpressions.push_back(memVar.nameToken()->str());
8090
0
                }
8091
0
            }
8092
0
        }
8093
8094
0
        for (auto&& p : partialReads) {
8095
0
            Token* tok2 = p.first;
8096
0
            ValueFlow::Value& v = p.second;
8097
8098
0
            setTokenValue(tok2, std::move(v), settings);
8099
0
        }
8100
8101
0
        if (partial)
8102
0
            continue;
8103
8104
0
        valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), std::move(uninitValue), tokenlist, errorLogger, settings);
8105
0
    }
8106
2.23k
}
8107
8108
static bool isContainerSizeChanged(const Token* expr,
8109
                                   const Token* start,
8110
                                   const Token* end,
8111
                                   int indirect,
8112
                                   const Settings& settings,
8113
                                   int depth = 20);
8114
8115
static bool isContainerSizeChangedByFunction(const Token* tok,
8116
                                             int indirect,
8117
                                             const Settings& settings,
8118
                                             int depth = 20)
8119
0
{
8120
0
    if (!tok->valueType())
8121
0
        return false;
8122
0
    if (!astIsContainer(tok))
8123
0
        return false;
8124
    // If we are accessing an element then we are not changing the container size
8125
0
    if (Token::Match(tok, "%name% . %name% (")) {
8126
0
        const Library::Container::Yield yield = getLibraryContainer(tok)->getYield(tok->strAt(2));
8127
0
        if (yield != Library::Container::Yield::NO_YIELD)
8128
0
            return false;
8129
0
    }
8130
0
    if (Token::simpleMatch(tok->astParent(), "["))
8131
0
        return false;
8132
8133
    // address of variable
8134
0
    const bool addressOf = tok->valueType()->pointer || (tok->astParent() && tok->astParent()->isUnaryOp("&"));
8135
8136
0
    int narg;
8137
0
    const Token * ftok = getTokenArgumentFunction(tok, narg);
8138
0
    if (!ftok)
8139
0
        return false; // not a function => variable not changed
8140
0
    const Function * fun = ftok->function();
8141
0
    if (fun && !fun->isImplicitlyVirtual()) {
8142
0
        const Variable *arg = fun->getArgumentVar(narg);
8143
0
        if (arg) {
8144
0
            const bool isPointer = addressOf || indirect > 0;
8145
0
            if (!arg->isReference() && !isPointer)
8146
0
                return false;
8147
0
            if (!isPointer && arg->isConst())
8148
0
                return false;
8149
0
            if (arg->valueType() && arg->valueType()->constness == 1)
8150
0
                return false;
8151
0
            const Scope * scope = fun->functionScope;
8152
0
            if (scope) {
8153
                // Argument not used
8154
0
                if (!arg->nameToken())
8155
0
                    return false;
8156
0
                if (depth > 0)
8157
0
                    return isContainerSizeChanged(arg->nameToken(),
8158
0
                                                  scope->bodyStart,
8159
0
                                                  scope->bodyEnd,
8160
0
                                                  addressOf ? indirect + 1 : indirect,
8161
0
                                                  settings,
8162
0
                                                  depth - 1);
8163
0
            }
8164
            // Don't know => Safe guess
8165
0
            return true;
8166
0
        }
8167
0
    }
8168
8169
0
    bool inconclusive = false;
8170
0
    const bool isChanged = isVariableChangedByFunctionCall(tok, indirect, &settings, &inconclusive);
8171
0
    return (isChanged || inconclusive);
8172
0
}
8173
8174
struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
8175
    ContainerExpressionAnalyzer(const Token* expr, ValueFlow::Value val, const TokenList& t, const Settings& s)
8176
        : ExpressionAnalyzer(expr, std::move(val), t, s)
8177
0
    {}
8178
8179
0
    bool match(const Token* tok) const override {
8180
0
        return tok->exprId() == expr->exprId() || (astIsIterator(tok) && isAliasOf(tok, expr->exprId()));
8181
0
    }
8182
8183
    Action isWritable(const Token* tok, Direction /*d*/) const override
8184
0
    {
8185
0
        if (astIsIterator(tok))
8186
0
            return Action::None;
8187
0
        if (!getValue(tok))
8188
0
            return Action::None;
8189
0
        if (!tok->valueType())
8190
0
            return Action::None;
8191
0
        if (!astIsContainer(tok))
8192
0
            return Action::None;
8193
0
        const Token* parent = tok->astParent();
8194
0
        const Library::Container* container = getLibraryContainer(tok);
8195
8196
0
        if (container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) {
8197
0
            const Token* rhs = parent->astOperand2();
8198
0
            if (rhs->tokType() == Token::eString)
8199
0
                return Action::Read | Action::Write | Action::Incremental;
8200
0
            const Library::Container* rhsContainer = getLibraryContainer(rhs);
8201
0
            if (rhsContainer && rhsContainer->stdStringLike) {
8202
0
                if (std::any_of(rhs->values().cbegin(), rhs->values().cend(), [&](const ValueFlow::Value &rhsval) {
8203
0
                    return rhsval.isKnown() && rhsval.isContainerSizeValue();
8204
0
                }))
8205
0
                    return Action::Read | Action::Write | Action::Incremental;
8206
0
            }
8207
0
        } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
8208
0
            const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
8209
0
            if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) {
8210
0
                std::vector<const Token*> args = getArguments(tok->tokAt(3));
8211
0
                if (args.size() < 2)
8212
0
                    return Action::Read | Action::Write | Action::Incremental;
8213
0
            }
8214
0
        }
8215
0
        return Action::None;
8216
0
    }
8217
8218
0
    void writeValue(ValueFlow::Value* val, const Token* tok, Direction d) const override {
8219
0
        if (!val)
8220
0
            return;
8221
0
        if (!tok->astParent())
8222
0
            return;
8223
0
        if (!tok->valueType())
8224
0
            return;
8225
0
        if (!astIsContainer(tok))
8226
0
            return;
8227
0
        const Token* parent = tok->astParent();
8228
0
        const Library::Container* container = getLibraryContainer(tok);
8229
0
        int n = 0;
8230
8231
0
        if (container->stdStringLike && Token::simpleMatch(parent, "+=") && parent->astOperand2()) {
8232
0
            const Token* rhs = parent->astOperand2();
8233
0
            const Library::Container* rhsContainer = getLibraryContainer(rhs);
8234
0
            if (rhs->tokType() == Token::eString)
8235
0
                n = Token::getStrLength(rhs);
8236
0
            else if (rhsContainer && rhsContainer->stdStringLike) {
8237
0
                auto it = std::find_if(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value& rhsval) {
8238
0
                    return rhsval.isKnown() && rhsval.isContainerSizeValue();
8239
0
                });
8240
0
                if (it != rhs->values().end())
8241
0
                    n = it->intvalue;
8242
0
            }
8243
0
        } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
8244
0
            const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
8245
0
            if (action == Library::Container::Action::PUSH)
8246
0
                n = 1;
8247
0
            if (action == Library::Container::Action::POP)
8248
0
                n = -1;
8249
0
        }
8250
0
        if (d == Direction::Reverse)
8251
0
            val->intvalue -= n;
8252
0
        else
8253
0
            val->intvalue += n;
8254
0
    }
8255
8256
    int getIndirect(const Token* tok) const override
8257
0
    {
8258
0
        if (tok->valueType()) {
8259
0
            return tok->valueType()->pointer;
8260
0
        }
8261
0
        return ValueFlowAnalyzer::getIndirect(tok);
8262
0
    }
8263
8264
0
    Action isModified(const Token* tok) const override {
8265
0
        Action read = Action::Read;
8266
        // An iterator won't change the container size
8267
0
        if (astIsIterator(tok))
8268
0
            return read;
8269
0
        if (Token::Match(tok->astParent(), "%assign%") && astIsLHS(tok))
8270
0
            return Action::Invalid;
8271
0
        if (isLikelyStreamRead(isCPP(), tok->astParent()))
8272
0
            return Action::Invalid;
8273
0
        if (astIsContainer(tok) && ValueFlow::isContainerSizeChanged(tok, getIndirect(tok), getSettings()))
8274
0
            return read | Action::Invalid;
8275
0
        return read;
8276
0
    }
8277
};
8278
8279
static const Token* parseBinaryIntOp(const Token* expr,
8280
                                     const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
8281
                                     MathLib::bigint& known)
8282
15.2k
{
8283
15.2k
    if (!expr)
8284
0
        return nullptr;
8285
15.2k
    if (!expr->astOperand1() || !expr->astOperand2())
8286
13.8k
        return nullptr;
8287
1.42k
    if (expr->astOperand1()->exprId() == 0 && expr->astOperand2()->exprId() == 0)
8288
0
        return nullptr;
8289
1.42k
    std::vector<MathLib::bigint> x1 = eval(expr->astOperand1());
8290
1.42k
    std::vector<MathLib::bigint> x2 = eval(expr->astOperand2());
8291
1.42k
    if (expr->astOperand1()->exprId() == 0 && x1.empty())
8292
2
        return nullptr;
8293
1.42k
    if (expr->astOperand2()->exprId() == 0 && x2.empty())
8294
0
        return nullptr;
8295
1.42k
    const Token* varTok = nullptr;
8296
1.42k
    if (!x1.empty() && x2.empty()) {
8297
270
        varTok = expr->astOperand2();
8298
270
        known = x1.front();
8299
1.15k
    } else if (x1.empty() && !x2.empty()) {
8300
233
        varTok = expr->astOperand1();
8301
233
        known = x2.front();
8302
233
    }
8303
1.42k
    return varTok;
8304
1.42k
}
8305
8306
const Token* ValueFlow::solveExprValue(const Token* expr,
8307
                                       const std::function<std::vector<MathLib::bigint>(const Token*)>& eval,
8308
                                       ValueFlow::Value& value)
8309
24.0k
{
8310
24.0k
    if (!value.isIntValue() && !value.isIteratorValue() && !value.isSymbolicValue())
8311
548
        return expr;
8312
23.5k
    if (value.isSymbolicValue() && !Token::Match(expr, "+|-"))
8313
8.31k
        return expr;
8314
15.2k
    MathLib::bigint intval;
8315
15.2k
    const Token* binaryTok = parseBinaryIntOp(expr, eval, intval);
8316
15.2k
    const bool rhs = astIsRHS(binaryTok);
8317
    // If its on the rhs, then -1 multiplication is needed, which is not possible with simple delta analysis used currently for symbolic values
8318
15.2k
    if (value.isSymbolicValue() && rhs && Token::simpleMatch(expr, "-"))
8319
16
        return expr;
8320
15.2k
    if (binaryTok && expr->str().size() == 1) {
8321
399
        switch (expr->str()[0]) {
8322
70
        case '+': {
8323
70
            value.intvalue -= intval;
8324
70
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8325
0
        }
8326
32
        case '-': {
8327
32
            if (rhs)
8328
28
                value.intvalue = intval - value.intvalue;
8329
4
            else
8330
4
                value.intvalue += intval;
8331
32
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8332
0
        }
8333
8
        case '*': {
8334
8
            if (intval == 0)
8335
0
                break;
8336
8
            value.intvalue /= intval;
8337
8
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8338
8
        }
8339
105
        case '^': {
8340
105
            value.intvalue ^= intval;
8341
105
            return ValueFlow::solveExprValue(binaryTok, eval, value);
8342
8
        }
8343
399
        }
8344
399
    }
8345
15.0k
    return expr;
8346
15.2k
}
8347
8348
static const Token* solveExprValue(const Token* expr, ValueFlow::Value& value)
8349
5.93k
{
8350
5.93k
    return ValueFlow::solveExprValue(
8351
5.93k
        expr,
8352
5.93k
        [](const Token* tok) -> std::vector<MathLib::bigint> {
8353
1.52k
        if (tok->hasKnownIntValue())
8354
342
            return {tok->values().front().intvalue};
8355
1.17k
        return {};
8356
1.52k
    },
8357
5.93k
        value);
8358
5.93k
}
8359
8360
static ValuePtr<Analyzer> makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings& settings)
8361
5.93k
{
8362
5.93k
    if (value.isContainerSizeValue())
8363
0
        return ContainerExpressionAnalyzer(exprTok, std::move(value), tokenlist, settings);
8364
5.93k
    const Token* expr = solveExprValue(exprTok, value);
8365
5.93k
    return ExpressionAnalyzer(expr, std::move(value), tokenlist, settings);
8366
5.93k
}
8367
8368
static ValuePtr<Analyzer> makeReverseAnalyzer(const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, const Settings& settings)
8369
2.01k
{
8370
2.01k
    if (value.isContainerSizeValue())
8371
0
        return ContainerExpressionAnalyzer(exprTok, std::move(value), tokenlist, settings);
8372
2.01k
    return ExpressionAnalyzer(exprTok, std::move(value), tokenlist, settings);
8373
2.01k
}
8374
8375
bool ValueFlow::isContainerSizeChanged(const Token* tok, int indirect, const Settings& settings, int depth)
8376
0
{
8377
0
    if (!tok)
8378
0
        return false;
8379
0
    if (!tok->valueType() || !tok->valueType()->container)
8380
0
        return true;
8381
0
    if (astIsLHS(tok) && Token::Match(tok->astParent(), "%assign%|<<"))
8382
0
        return true;
8383
0
    const Library::Container* container = tok->valueType()->container;
8384
0
    if (astIsLHS(tok) && Token::simpleMatch(tok->astParent(), "["))
8385
0
        return container->stdAssociativeLike;
8386
0
    const Library::Container::Action action = astContainerAction(tok);
8387
0
    switch (action) {
8388
0
    case Library::Container::Action::RESIZE:
8389
0
    case Library::Container::Action::CLEAR:
8390
0
    case Library::Container::Action::PUSH:
8391
0
    case Library::Container::Action::POP:
8392
0
    case Library::Container::Action::CHANGE:
8393
0
    case Library::Container::Action::INSERT:
8394
0
    case Library::Container::Action::ERASE:
8395
0
        return true;
8396
0
    case Library::Container::Action::NO_ACTION:
8397
        // Is this an unknown member function call?
8398
0
        if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
8399
0
            const Library::Container::Yield yield = astContainerYield(tok);
8400
0
            return yield == Library::Container::Yield::NO_YIELD;
8401
0
        }
8402
0
        break;
8403
0
    case Library::Container::Action::FIND:
8404
0
    case Library::Container::Action::FIND_CONST:
8405
0
    case Library::Container::Action::CHANGE_CONTENT:
8406
0
    case Library::Container::Action::CHANGE_INTERNAL:
8407
0
        break;
8408
0
    }
8409
0
    return isContainerSizeChangedByFunction(tok, indirect, settings, depth);
8410
0
}
8411
8412
static bool isContainerSizeChanged(const Token* expr,
8413
                                   const Token* start,
8414
                                   const Token* end,
8415
                                   int indirect,
8416
                                   const Settings& settings,
8417
                                   int depth)
8418
0
{
8419
0
    for (const Token *tok = start; tok != end; tok = tok->next()) {
8420
0
        if (tok->exprId() != expr->exprId() && !isAliasOf(tok, expr))
8421
0
            continue;
8422
0
        if (ValueFlow::isContainerSizeChanged(tok, indirect, settings, depth))
8423
0
            return true;
8424
0
    }
8425
0
    return false;
8426
0
}
8427
8428
static void valueFlowSmartPointer(TokenList &tokenlist, ErrorLogger * errorLogger, const Settings &settings)
8429
2.23k
{
8430
161k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
8431
159k
        if (!tok->scope())
8432
0
            continue;
8433
159k
        if (!tok->scope()->isExecutable())
8434
89.8k
            continue;
8435
69.9k
        if (!astIsSmartPointer(tok))
8436
69.9k
            continue;
8437
0
        if (tok->variable() && Token::Match(tok, "%var% (|{|;")) {
8438
0
            const Variable* var = tok->variable();
8439
0
            if (!var->isSmartPointer())
8440
0
                continue;
8441
0
            if (var->nameToken() == tok) {
8442
0
                if (Token::Match(tok, "%var% (|{") && tok->next()->astOperand2() &&
8443
0
                    tok->next()->astOperand2()->str() != ",") {
8444
0
                    Token* inTok = tok->next()->astOperand2();
8445
0
                    const std::list<ValueFlow::Value>& values = inTok->values();
8446
0
                    const bool constValue = inTok->isNumber();
8447
0
                    valueFlowForwardAssign(inTok, var, values, constValue, true, tokenlist, errorLogger, settings);
8448
8449
0
                } else if (Token::Match(tok, "%var% ;")) {
8450
0
                    ValueFlow::Value v(0);
8451
0
                    v.setKnown();
8452
0
                    valueFlowForwardAssign(tok, var, {std::move(v)}, false, true, tokenlist, errorLogger, settings);
8453
0
                }
8454
0
            }
8455
0
        } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (") &&
8456
0
                   tok->astParent()->originalName() != "->") {
8457
0
            std::vector<const Variable*> vars = getVariables(tok);
8458
0
            Token* ftok = tok->astParent()->tokAt(2);
8459
0
            if (Token::simpleMatch(tok->astParent(), ". reset (")) {
8460
0
                if (Token::simpleMatch(ftok, "( )")) {
8461
0
                    ValueFlow::Value v(0);
8462
0
                    v.setKnown();
8463
0
                    valueFlowForwardAssign(ftok, tok, vars, {std::move(v)}, false, tokenlist, errorLogger, settings);
8464
0
                } else {
8465
0
                    tok->removeValues(std::mem_fn(&ValueFlow::Value::isIntValue));
8466
0
                    Token* inTok = ftok->astOperand2();
8467
0
                    if (!inTok)
8468
0
                        continue;
8469
0
                    const std::list<ValueFlow::Value>& values = inTok->values();
8470
0
                    valueFlowForwardAssign(inTok, tok, std::move(vars), values, false, tokenlist, errorLogger, settings);
8471
0
                }
8472
0
            } else if (Token::simpleMatch(tok->astParent(), ". release ( )")) {
8473
0
                const Token* parent = ftok->astParent();
8474
0
                bool hasParentReset = false;
8475
0
                while (parent) {
8476
0
                    if (Token::Match(parent->tokAt(-2), ". release|reset (") &&
8477
0
                        parent->tokAt(-2)->astOperand1()->exprId() == tok->exprId()) {
8478
0
                        hasParentReset = true;
8479
0
                        break;
8480
0
                    }
8481
0
                    parent = parent->astParent();
8482
0
                }
8483
0
                if (hasParentReset)
8484
0
                    continue;
8485
0
                ValueFlow::Value v(0);
8486
0
                v.setKnown();
8487
0
                valueFlowForwardAssign(ftok, tok, std::move(vars), {std::move(v)}, false, tokenlist, errorLogger, settings);
8488
0
            } else if (Token::simpleMatch(tok->astParent(), ". get ( )")) {
8489
0
                ValueFlow::Value v = makeSymbolic(tok);
8490
0
                setTokenValue(tok->astParent()->tokAt(2), std::move(v), settings);
8491
0
            }
8492
0
        } else if (Token::Match(tok->previous(), "%name%|> (|{") && astIsSmartPointer(tok) &&
8493
0
                   astIsSmartPointer(tok->astOperand1())) {
8494
0
            std::vector<const Token*> args = getArguments(tok);
8495
0
            if (args.empty())
8496
0
                continue;
8497
0
            for (const ValueFlow::Value& v : args.front()->values())
8498
0
                setTokenValue(tok, v, settings);
8499
0
        }
8500
0
    }
8501
2.23k
}
8502
8503
static Library::Container::Yield findIteratorYield(Token* tok, const Token** ftok, const Settings &settings)
8504
0
{
8505
0
    auto yield = astContainerYield(tok, ftok);
8506
0
    if (*ftok)
8507
0
        return yield;
8508
8509
0
    if (!tok->astParent())
8510
0
        return yield;
8511
8512
    //begin/end free functions
8513
0
    return astFunctionYield(tok->astParent()->previous(), &settings, ftok);
8514
0
}
8515
8516
static void valueFlowIterators(TokenList &tokenlist, const Settings &settings)
8517
2.23k
{
8518
161k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
8519
159k
        if (!tok->scope())
8520
0
            continue;
8521
159k
        if (!tok->scope()->isExecutable())
8522
89.8k
            continue;
8523
69.9k
        if (!astIsContainer(tok))
8524
69.9k
            continue;
8525
0
        Token* ftok = nullptr;
8526
0
        const Library::Container::Yield yield = findIteratorYield(tok, const_cast<const Token**>(&ftok), settings);
8527
0
        if (ftok) {
8528
0
            ValueFlow::Value v(0);
8529
0
            v.setKnown();
8530
0
            if (yield == Library::Container::Yield::START_ITERATOR) {
8531
0
                v.valueType = ValueFlow::Value::ValueType::ITERATOR_START;
8532
0
                setTokenValue(ftok->next(), std::move(v), settings);
8533
0
            } else if (yield == Library::Container::Yield::END_ITERATOR) {
8534
0
                v.valueType = ValueFlow::Value::ValueType::ITERATOR_END;
8535
0
                setTokenValue(ftok->next(), std::move(v), settings);
8536
0
            }
8537
0
        }
8538
0
    }
8539
2.23k
}
8540
8541
static std::list<ValueFlow::Value> getIteratorValues(std::list<ValueFlow::Value> values, const ValueFlow::Value::ValueKind* kind = nullptr)
8542
73.8k
{
8543
73.8k
    values.remove_if([&](const ValueFlow::Value& v) {
8544
16.8k
        if (kind && v.valueKind != *kind)
8545
576
            return true;
8546
16.2k
        return !v.isIteratorValue();
8547
16.8k
    });
8548
73.8k
    return values;
8549
73.8k
}
8550
8551
struct IteratorConditionHandler : SimpleConditionHandler {
8552
39.6k
    std::vector<Condition> parse(const Token* tok, const Settings& /*settings*/) const override {
8553
39.6k
        Condition cond;
8554
8555
39.6k
        if (Token::Match(tok, "==|!=")) {
8556
1.96k
            if (!tok->astOperand1() || !tok->astOperand2())
8557
0
                return {};
8558
8559
1.96k
            constexpr ValueFlow::Value::ValueKind kind = ValueFlow::Value::ValueKind::Known;
8560
1.96k
            std::list<ValueFlow::Value> values = getIteratorValues(tok->astOperand1()->values(), &kind);
8561
1.96k
            if (!values.empty()) {
8562
0
                cond.vartok = tok->astOperand2();
8563
1.96k
            } else {
8564
1.96k
                values = getIteratorValues(tok->astOperand2()->values(), &kind);
8565
1.96k
                if (!values.empty())
8566
0
                    cond.vartok = tok->astOperand1();
8567
1.96k
            }
8568
1.96k
            for (ValueFlow::Value& v:values) {
8569
0
                v.setPossible();
8570
0
                v.assumeCondition(tok);
8571
0
            }
8572
1.96k
            cond.true_values = values;
8573
1.96k
            cond.false_values = std::move(values);
8574
1.96k
        }
8575
8576
39.6k
        return {std::move(cond)};
8577
39.6k
    }
8578
};
8579
8580
static void valueFlowIteratorInfer(TokenList &tokenlist, const Settings &settings)
8581
2.23k
{
8582
161k
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
8583
159k
        if (!tok->scope())
8584
0
            continue;
8585
159k
        if (!tok->scope()->isExecutable())
8586
89.8k
            continue;
8587
69.9k
        std::list<ValueFlow::Value> values = getIteratorValues(tok->values());
8588
69.9k
        values.remove_if([&](const ValueFlow::Value& v) {
8589
0
            if (!v.isImpossible())
8590
0
                return true;
8591
0
            if (!v.condition)
8592
0
                return true;
8593
0
            if (v.bound != ValueFlow::Value::Bound::Point)
8594
0
                return true;
8595
0
            if (v.isIteratorEndValue() && v.intvalue <= 0)
8596
0
                return true;
8597
0
            if (v.isIteratorStartValue() && v.intvalue >= 0)
8598
0
                return true;
8599
0
            return false;
8600
0
        });
8601
69.9k
        for (ValueFlow::Value& v:values) {
8602
0
            v.setPossible();
8603
0
            if (v.isIteratorStartValue())
8604
0
                v.intvalue++;
8605
0
            if (v.isIteratorEndValue())
8606
0
                v.intvalue--;
8607
0
            setTokenValue(tok, std::move(v), settings);
8608
0
        }
8609
69.9k
    }
8610
2.23k
}
8611
8612
static std::vector<ValueFlow::Value> getContainerValues(const Token* tok)
8613
0
{
8614
0
    std::vector<ValueFlow::Value> values;
8615
0
    if (tok) {
8616
0
        std::copy_if(tok->values().cbegin(),
8617
0
                     tok->values().cend(),
8618
0
                     std::back_inserter(values),
8619
0
                     std::mem_fn(&ValueFlow::Value::isContainerSizeValue));
8620
0
    }
8621
0
    return values;
8622
0
}
8623
8624
static ValueFlow::Value makeContainerSizeValue(std::size_t s, bool known = true)
8625
0
{
8626
0
    ValueFlow::Value value(s);
8627
0
    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8628
0
    if (known)
8629
0
        value.setKnown();
8630
0
    return value;
8631
0
}
8632
8633
static std::vector<ValueFlow::Value> makeContainerSizeValue(const Token* tok, bool known = true)
8634
0
{
8635
0
    if (tok->hasKnownIntValue())
8636
0
        return {makeContainerSizeValue(tok->values().front().intvalue, known)};
8637
0
    return {};
8638
0
}
8639
8640
static std::vector<ValueFlow::Value> getContainerSizeFromConstructorArgs(const std::vector<const Token*>& args,
8641
                                                                         const Library::Container* container,
8642
                                                                         bool known)
8643
0
{
8644
0
    if (astIsIntegral(args[0], false)) { // { count, i } or { count }
8645
0
        if (args.size() == 1 || (args.size() > 1 && !astIsIntegral(args[1], false)))
8646
0
            return {makeContainerSizeValue(args[0], known)};
8647
0
    } else if (astIsContainer(args[0]) && args.size() == 1) { // copy constructor
8648
0
        return getContainerValues(args[0]);
8649
0
    } else if (isIteratorPair(args)) {
8650
0
        std::vector<ValueFlow::Value> result = getContainerValues(args[0]);
8651
0
        if (!result.empty())
8652
0
            return result;
8653
        // (ptr, ptr + size)
8654
0
        if (astIsPointer(args[0]) && args[0]->exprId() != 0) {
8655
            // (ptr, ptr) is empty
8656
            // TODO: Use lifetime values to check if it points to the same address
8657
0
            if (args[0]->exprId() == args[1]->exprId())
8658
0
                return {makeContainerSizeValue(std::size_t{0}, known)};
8659
            // TODO: Insert iterator positions for pointers
8660
0
            if (Token::simpleMatch(args[1], "+")) {
8661
0
                nonneg int const eid = args[0]->exprId();
8662
0
                const Token* vartok = args[1]->astOperand1();
8663
0
                const Token* sizetok = args[1]->astOperand2();
8664
0
                if (sizetok->exprId() == eid)
8665
0
                    std::swap(vartok, sizetok);
8666
0
                if (vartok->exprId() == eid && sizetok->hasKnownIntValue())
8667
0
                    return {makeContainerSizeValue(sizetok, known)};
8668
0
            }
8669
0
        }
8670
0
    } else if (container->stdStringLike) {
8671
0
        if (astIsPointer(args[0])) {
8672
            // TODO: Try to read size of string literal { "abc" }
8673
0
            if (args.size() == 2 && astIsIntegral(args[1], false)) // { char*, count }
8674
0
                return {makeContainerSizeValue(args[1], known)};
8675
0
        } else if (astIsContainer(args[0])) {
8676
0
            if (args.size() == 1) // copy constructor { str }
8677
0
                return getContainerValues(args[0]);
8678
0
            if (args.size() == 3) // { str, pos, count }
8679
0
                return {makeContainerSizeValue(args[2], known)};
8680
            // TODO: { str, pos }, { ..., alloc }
8681
0
        }
8682
0
    }
8683
0
    return {};
8684
0
}
8685
8686
static bool valueFlowIsSameContainerType(const ValueType& contType, const Token* tok, const Settings& settings)
8687
0
{
8688
0
    if (!tok || !tok->valueType() || !tok->valueType()->containerTypeToken)
8689
0
        return true;
8690
8691
0
    const ValueType tokType = ValueType::parseDecl(tok->valueType()->containerTypeToken, settings);
8692
0
    return contType.isTypeEqual(&tokType) || tokType.type == ValueType::Type::UNKNOWN_TYPE;
8693
0
}
8694
8695
static std::vector<ValueFlow::Value> getInitListSize(const Token* tok,
8696
                                                     const ValueType* valueType,
8697
                                                     const Settings& settings,
8698
                                                     bool known = true)
8699
0
{
8700
0
    std::vector<const Token*> args = getArguments(tok);
8701
0
    if (args.empty())
8702
0
        return {makeContainerSizeValue(std::size_t{0}, known)};
8703
0
    bool initList = true;
8704
    // Try to disambiguate init list from constructor
8705
0
    if (args.size() < 4) {
8706
0
        initList = !isIteratorPair(args) && !(args.size() < 3 && astIsIntegral(args[0], false));
8707
0
        const Token* containerTypeToken = valueType->containerTypeToken;
8708
0
        if (valueType->container->stdStringLike) {
8709
0
            initList = astIsGenericChar(args[0]) && !astIsPointer(args[0]);
8710
0
        } else if (containerTypeToken) {
8711
0
            ValueType vt = ValueType::parseDecl(containerTypeToken, settings);
8712
0
            if (vt.pointer > 0 && astIsPointer(args[0]))
8713
0
                initList = true;
8714
0
            else if (vt.type == ValueType::ITERATOR && astIsIterator(args[0]))
8715
0
                initList = true;
8716
0
            else if (vt.isIntegral() && astIsIntegral(args[0], false))
8717
0
                initList = true;
8718
0
            else if (args.size() == 1 && valueFlowIsSameContainerType(vt, tok->astOperand2(), settings))
8719
0
                initList = false; // copy ctor
8720
0
        }
8721
0
    }
8722
0
    if (!initList)
8723
0
        return getContainerSizeFromConstructorArgs(args, valueType->container, known);
8724
0
    return {makeContainerSizeValue(args.size(), known)};
8725
0
}
8726
8727
static std::vector<ValueFlow::Value> getContainerSizeFromConstructor(const Token* tok,
8728
                                                                     const ValueType* valueType,
8729
                                                                     const Settings& settings,
8730
                                                                     bool known = true)
8731
0
{
8732
0
    std::vector<const Token*> args = getArguments(tok);
8733
0
    if (args.empty())
8734
0
        return {makeContainerSizeValue(std::size_t{0}, known)};
8735
    // Init list in constructor
8736
0
    if (args.size() == 1 && Token::simpleMatch(args[0], "{"))
8737
0
        return getInitListSize(args[0], valueType, settings, known);
8738
0
    return getContainerSizeFromConstructorArgs(args, valueType->container, known);
8739
0
}
8740
8741
static void valueFlowContainerSetTokValue(TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings, const Token* tok, Token* initList)
8742
0
{
8743
0
    ValueFlow::Value value;
8744
0
    value.valueType = ValueFlow::Value::ValueType::TOK;
8745
0
    value.tokvalue = initList;
8746
0
    if (astIsContainerString(tok) && Token::simpleMatch(initList, "{") && Token::Match(initList->astOperand2(), "%str%")) {
8747
0
        value.tokvalue = initList->astOperand2();
8748
0
    }
8749
0
    value.setKnown();
8750
0
    Token* start = initList->link() ? initList->link() : initList->next();
8751
0
    if (tok->variable() && tok->variable()->isConst()) {
8752
0
        valueFlowForwardConst(start, tok->variable()->scope()->bodyEnd, tok->variable(), {std::move(value)}, settings);
8753
0
    } else {
8754
0
        valueFlowForward(start, tok, std::move(value), tokenlist, errorLogger, settings);
8755
0
    }
8756
0
}
8757
8758
0
static const Scope* getFunctionScope(const Scope* scope) {
8759
0
    while (scope && scope->type != Scope::ScopeType::eFunction)
8760
0
        scope = scope->nestedIn;
8761
0
    return scope;
8762
0
}
8763
8764
static MathLib::bigint valueFlowGetStrLength(const Token* tok)
8765
0
{
8766
0
    if (tok->tokType() == Token::eString)
8767
0
        return Token::getStrLength(tok);
8768
0
    if (astIsGenericChar(tok) || tok->tokType() == Token::eChar)
8769
0
        return 1;
8770
0
    if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE))
8771
0
        return v->intvalue;
8772
0
    if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::TOK)) {
8773
0
        if (v->tokvalue != tok)
8774
0
            return valueFlowGetStrLength(v->tokvalue);
8775
0
    }
8776
0
    return 0;
8777
0
}
8778
8779
static void valueFlowContainerSize(TokenList& tokenlist,
8780
                                   const SymbolDatabase& symboldatabase,
8781
                                   ErrorLogger* const errorLogger,
8782
                                   const Settings& settings,
8783
                                   const std::set<const Scope*>& skippedFunctions)
8784
2.23k
{
8785
    // declaration
8786
13.3k
    for (const Variable *var : symboldatabase.variableList()) {
8787
13.3k
        if (!var)
8788
2.23k
            continue;
8789
11.1k
        if (!var->scope() || !var->scope()->bodyEnd || !var->scope()->bodyStart)
8790
11.1k
            continue;
8791
0
        if (!var->valueType() || !var->valueType()->container)
8792
0
            continue;
8793
0
        if (!astIsContainer(var->nameToken()))
8794
0
            continue;
8795
0
        if (skippedFunctions.count(getFunctionScope(var->scope())))
8796
0
            continue;
8797
8798
0
        bool known = true;
8799
0
        int size = 0;
8800
0
        const bool nonLocal = !var->isLocal() || var->isPointer() || var->isReference() || var->isStatic();
8801
0
        bool constSize = var->isConst() && !nonLocal;
8802
0
        bool staticSize = false;
8803
0
        if (var->valueType()->container->size_templateArgNo >= 0) {
8804
0
            staticSize = true;
8805
0
            constSize = true;
8806
0
            size = -1;
8807
0
            if (var->dimensions().size() == 1) {
8808
0
                const Dimension& dim = var->dimensions().front();
8809
0
                if (dim.known) {
8810
0
                    size = dim.num;
8811
0
                } else if (dim.tok && dim.tok->hasKnownIntValue()) {
8812
0
                    size = dim.tok->values().front().intvalue;
8813
0
                }
8814
0
            }
8815
0
            if (size < 0)
8816
0
                continue;
8817
0
        }
8818
0
        if (!staticSize && nonLocal)
8819
0
            continue;
8820
0
        Token* nameToken = const_cast<Token*>(var->nameToken());
8821
0
        if (nameToken->hasKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE))
8822
0
            continue;
8823
0
        if (!staticSize) {
8824
0
            if (!Token::Match(nameToken, "%name% ;") &&
8825
0
                !(Token::Match(nameToken, "%name% {") && Token::simpleMatch(nameToken->next()->link(), "} ;")) &&
8826
0
                !Token::Match(nameToken, "%name% ("))
8827
0
                continue;
8828
0
        }
8829
0
        if (nameToken->astTop() && Token::Match(nameToken->astTop()->previous(), "for|while"))
8830
0
            known = !isVariableChanged(var, &settings, true);
8831
0
        std::vector<ValueFlow::Value> values{ValueFlow::Value{size}};
8832
0
        values.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8833
0
        if (known)
8834
0
            values.back().setKnown();
8835
0
        if (!staticSize) {
8836
0
            if (Token::simpleMatch(nameToken->next(), "{")) {
8837
0
                Token* initList = nameToken->next();
8838
0
                valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, nameToken, initList);
8839
0
                values = getInitListSize(initList, var->valueType(), settings, known);
8840
0
            } else if (Token::simpleMatch(nameToken->next(), "(")) {
8841
0
                const Token* constructorArgs = nameToken->next();
8842
0
                values = getContainerSizeFromConstructor(constructorArgs, var->valueType(), settings, known);
8843
0
            }
8844
0
        }
8845
8846
0
        if (constSize) {
8847
0
            valueFlowForwardConst(nameToken->next(), var->scope()->bodyEnd, var, values, settings);
8848
0
            continue;
8849
0
        }
8850
8851
0
        for (const ValueFlow::Value& value : values) {
8852
0
            valueFlowForward(nameToken->next(), var->nameToken(), value, tokenlist, errorLogger, settings);
8853
0
        }
8854
0
    }
8855
8856
    // after assignment
8857
2.92k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
8858
69.9k
        for (auto* tok = const_cast<Token*>(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) {
8859
67.0k
            if (Token::Match(tok, "%name%|;|{|} %var% = %str% ;")) {
8860
0
                Token* containerTok = tok->next();
8861
0
                if (containerTok->exprId() == 0)
8862
0
                    continue;
8863
0
                if (containerTok->valueType() && containerTok->valueType()->container &&
8864
0
                    containerTok->valueType()->container->stdStringLike) {
8865
0
                    valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, containerTok, containerTok->tokAt(2));
8866
0
                    ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2)));
8867
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8868
0
                    value.setKnown();
8869
0
                    valueFlowForward(containerTok->next(), containerTok, value, tokenlist, errorLogger, settings);
8870
0
                }
8871
67.0k
            } else if (Token::Match(tok->previous(), ">|return (|{") && astIsContainer(tok) && getLibraryContainer(tok)->size_templateArgNo < 0) {
8872
0
                std::vector<ValueFlow::Value> values;
8873
0
                if (Token::simpleMatch(tok, "{")) {
8874
0
                    values = getInitListSize(tok, tok->valueType(), settings, true);
8875
0
                    ValueFlow::Value value;
8876
0
                    value.valueType = ValueFlow::Value::ValueType::TOK;
8877
0
                    value.tokvalue = tok;
8878
0
                    value.setKnown();
8879
0
                    values.push_back(value);
8880
0
                } else if (Token::simpleMatch(tok, "(")) {
8881
0
                    const Token* constructorArgs = tok;
8882
0
                    values = getContainerSizeFromConstructor(constructorArgs, tok->valueType(), settings, true);
8883
0
                }
8884
0
                for (const ValueFlow::Value& value : values)
8885
0
                    setTokenValue(tok, value, settings);
8886
67.0k
            } else if (Token::Match(tok, "%name%|;|{|}|> %var% = {") && Token::simpleMatch(tok->linkAt(3), "} ;")) {
8887
0
                Token* containerTok = tok->next();
8888
0
                if (containerTok->exprId() == 0)
8889
0
                    continue;
8890
0
                if (astIsContainer(containerTok) && containerTok->valueType()->container->size_templateArgNo < 0) {
8891
0
                    std::vector<ValueFlow::Value> values =
8892
0
                        getInitListSize(tok->tokAt(3), containerTok->valueType(), settings);
8893
0
                    valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, containerTok, tok->tokAt(3));
8894
0
                    for (const ValueFlow::Value& value : values)
8895
0
                        valueFlowForward(containerTok->next(), containerTok, value, tokenlist, errorLogger, settings);
8896
0
                }
8897
67.0k
            } else if (Token::Match(tok, ". %name% (") && tok->astOperand1() && tok->astOperand1()->valueType() &&
8898
67.0k
                       tok->astOperand1()->valueType()->container) {
8899
0
                const Token* containerTok = tok->astOperand1();
8900
0
                if (containerTok->exprId() == 0)
8901
0
                    continue;
8902
0
                const Library::Container::Action action = containerTok->valueType()->container->getAction(tok->strAt(1));
8903
0
                if (action == Library::Container::Action::CLEAR) {
8904
0
                    ValueFlow::Value value(0);
8905
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8906
0
                    value.setKnown();
8907
0
                    valueFlowForward(tok->next(), containerTok, std::move(value), tokenlist, errorLogger, settings);
8908
0
                } else if (action == Library::Container::Action::RESIZE && tok->tokAt(2)->astOperand2() &&
8909
0
                           tok->tokAt(2)->astOperand2()->hasKnownIntValue()) {
8910
0
                    ValueFlow::Value value(tok->tokAt(2)->astOperand2()->values().front());
8911
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8912
0
                    value.setKnown();
8913
0
                    valueFlowForward(tok->linkAt(2), containerTok, std::move(value), tokenlist, errorLogger, settings);
8914
0
                } else if (action == Library::Container::Action::PUSH && !isIteratorPair(getArguments(tok->tokAt(2)))) {
8915
0
                    ValueFlow::Value value(0);
8916
0
                    value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8917
0
                    value.setImpossible();
8918
0
                    valueFlowForward(tok->linkAt(2), containerTok, value, tokenlist, errorLogger, settings);
8919
0
                }
8920
67.0k
            } else if (Token::simpleMatch(tok, "+=") && astIsContainer(tok->astOperand1())) {
8921
0
                const Token* containerTok = tok->astOperand1();
8922
0
                const Token* valueTok = tok->astOperand2();
8923
0
                MathLib::bigint size = valueFlowGetStrLength(valueTok);
8924
0
                if (size == 0)
8925
0
                    continue;
8926
0
                ValueFlow::Value value(size - 1);
8927
0
                value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8928
0
                value.bound = ValueFlow::Value::Bound::Upper;
8929
0
                value.setImpossible();
8930
0
                Token* next = nextAfterAstRightmostLeaf(tok);
8931
0
                if (!next)
8932
0
                    next = tok->next();
8933
0
                valueFlowForward(next, containerTok, value, tokenlist, errorLogger, settings);
8934
0
            }
8935
67.0k
        }
8936
2.92k
    }
8937
2.23k
}
8938
8939
struct ContainerConditionHandler : ConditionHandler {
8940
    std::vector<Condition> parse(const Token* tok, const Settings& settings) const override
8941
39.6k
    {
8942
39.6k
        std::vector<Condition> conds;
8943
39.6k
        parseCompareEachInt(tok, [&](const Token* vartok, ValueFlow::Value true_value, ValueFlow::Value false_value) {
8944
1.80k
            vartok = settings.library.getContainerFromYield(vartok, Library::Container::Yield::SIZE);
8945
1.80k
            if (!vartok)
8946
1.80k
                return;
8947
0
            true_value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8948
0
            false_value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8949
0
            Condition cond;
8950
0
            cond.true_values.push_back(std::move(true_value));
8951
0
            cond.false_values.push_back(std::move(false_value));
8952
0
            cond.vartok = vartok;
8953
0
            conds.push_back(std::move(cond));
8954
0
        });
8955
39.6k
        if (!conds.empty())
8956
0
            return conds;
8957
8958
39.6k
        const Token* vartok = nullptr;
8959
8960
        // Empty check
8961
39.6k
        if (tok->str() == "(") {
8962
5.49k
            vartok = settings.library.getContainerFromYield(tok, Library::Container::Yield::EMPTY);
8963
            // TODO: Handle .size()
8964
5.49k
            if (!vartok)
8965
5.49k
                return {};
8966
0
            const Token *parent = tok->astParent();
8967
0
            while (parent) {
8968
0
                if (Token::Match(parent, "%comp%"))
8969
0
                    return {};
8970
0
                parent = parent->astParent();
8971
0
            }
8972
0
            ValueFlow::Value value(tok, 0LL);
8973
0
            value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8974
0
            Condition cond;
8975
0
            cond.true_values.emplace_back(value);
8976
0
            cond.false_values.emplace_back(std::move(value));
8977
0
            cond.vartok = vartok;
8978
0
            cond.inverted = true;
8979
0
            return {std::move(cond)};
8980
0
        }
8981
        // String compare
8982
34.1k
        if (Token::Match(tok, "==|!=")) {
8983
1.96k
            const Token *strtok = nullptr;
8984
1.96k
            if (Token::Match(tok->astOperand1(), "%str%")) {
8985
0
                strtok = tok->astOperand1();
8986
0
                vartok = tok->astOperand2();
8987
1.96k
            } else if (Token::Match(tok->astOperand2(), "%str%")) {
8988
0
                strtok = tok->astOperand2();
8989
0
                vartok = tok->astOperand1();
8990
0
            }
8991
1.96k
            if (!strtok)
8992
1.96k
                return {};
8993
0
            if (!astIsContainer(vartok))
8994
0
                return {};
8995
0
            ValueFlow::Value value(tok, Token::getStrLength(strtok));
8996
0
            value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
8997
0
            Condition cond;
8998
0
            cond.false_values.emplace_back(value);
8999
0
            cond.true_values.emplace_back(std::move(value));
9000
0
            cond.vartok = vartok;
9001
0
            cond.impossible = false;
9002
0
            return {std::move(cond)};
9003
0
        }
9004
32.1k
        return {};
9005
34.1k
    }
9006
};
9007
9008
static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings)
9009
1.34k
{
9010
1.34k
    auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint {
9011
0
        MathLib::bigint sizeValue = -1;
9012
0
        const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(funcTok);
9013
0
        if (!allocFunc)
9014
0
            allocFunc = settings.library.getReallocFuncInfo(funcTok);
9015
0
        if (!allocFunc || allocFunc->bufferSize == Library::AllocFunc::BufferSize::none)
9016
0
            return sizeValue;
9017
9018
0
        const std::vector<const Token*> args = getArguments(funcTok);
9019
9020
0
        const Token* const arg1 = (args.size() >= allocFunc->bufferSizeArg1) ? args[allocFunc->bufferSizeArg1 - 1] : nullptr;
9021
0
        const Token* const arg2 = (args.size() >= allocFunc->bufferSizeArg2) ? args[allocFunc->bufferSizeArg2 - 1] : nullptr;
9022
9023
0
        switch (allocFunc->bufferSize) {
9024
0
        case Library::AllocFunc::BufferSize::none:
9025
0
            break;
9026
0
        case Library::AllocFunc::BufferSize::malloc:
9027
0
            if (arg1 && arg1->hasKnownIntValue())
9028
0
                sizeValue = arg1->getKnownIntValue();
9029
0
            break;
9030
0
        case Library::AllocFunc::BufferSize::calloc:
9031
0
            if (arg1 && arg2 && arg1->hasKnownIntValue() && arg2->hasKnownIntValue())
9032
0
                sizeValue = arg1->getKnownIntValue() * arg2->getKnownIntValue();
9033
0
            break;
9034
0
        case Library::AllocFunc::BufferSize::strdup:
9035
0
            if (arg1 && arg1->hasKnownValue()) {
9036
0
                const ValueFlow::Value& value = arg1->values().back();
9037
0
                if (value.isTokValue() && value.tokvalue->tokType() == Token::eString)
9038
0
                    sizeValue = Token::getStrLength(value.tokvalue) + 1; // Add one for the null terminator
9039
0
            }
9040
0
            break;
9041
0
        }
9042
0
        return sizeValue;
9043
0
    };
9044
9045
1.34k
    auto getBufferSizeFromNew = [&](const Token* newTok) -> MathLib::bigint {
9046
0
        MathLib::bigint sizeValue = -1, numElem = -1;
9047
9048
0
        if (newTok && newTok->astOperand1()) { // number of elements
9049
0
            const Token* bracTok = nullptr, *typeTok = nullptr;
9050
0
            if (newTok->astOperand1()->str() == "[")
9051
0
                bracTok = newTok->astOperand1();
9052
0
            else if (Token::Match(newTok->astOperand1(), "(|{")) {
9053
0
                if (newTok->astOperand1()->astOperand1() && newTok->astOperand1()->astOperand1()->str() == "[")
9054
0
                    bracTok = newTok->astOperand1()->astOperand1();
9055
0
                else
9056
0
                    typeTok = newTok->astOperand1()->astOperand1();
9057
0
            }
9058
0
            else
9059
0
                typeTok = newTok->astOperand1();
9060
0
            if (bracTok && bracTok->astOperand2() && bracTok->astOperand2()->hasKnownIntValue())
9061
0
                numElem = bracTok->astOperand2()->getKnownIntValue();
9062
0
            else if (Token::Match(typeTok, "%type%"))
9063
0
                numElem = 1;
9064
0
        }
9065
9066
0
        if (numElem >= 0 && newTok->astParent() && newTok->astParent()->isAssignmentOp()) { // size of the allocated type
9067
0
            const Token* typeTok = newTok->astParent()->astOperand1(); // TODO: implement fallback for e.g. "auto p = new Type;"
9068
0
            if (!typeTok || !typeTok->varId())
9069
0
                typeTok = newTok->astParent()->previous(); // hack for "int** z = ..."
9070
0
            if (typeTok && typeTok->valueType()) {
9071
0
                const MathLib::bigint typeSize = typeTok->valueType()->typeSize(settings.platform, typeTok->valueType()->pointer > 1);
9072
0
                if (typeSize >= 0)
9073
0
                    sizeValue = numElem * typeSize;
9074
0
            }
9075
0
        }
9076
0
        return sizeValue;
9077
0
    };
9078
9079
1.75k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
9080
37.8k
        for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) {
9081
36.0k
            if (!Token::Match(tok, "[;{}] %var% ="))
9082
35.0k
                continue;
9083
9084
1.04k
            if (!tok->next()->variable())
9085
0
                continue;
9086
9087
1.04k
            const Token *rhs = tok->tokAt(2)->astOperand2();
9088
1.04k
            while (rhs && rhs->isCast())
9089
0
                rhs = rhs->astOperand2() ? rhs->astOperand2() : rhs->astOperand1();
9090
1.04k
            if (!rhs)
9091
0
                continue;
9092
9093
1.04k
            const bool isNew = symboldatabase.isCPP() && rhs->str() == "new";
9094
1.04k
            if (!isNew && !Token::Match(rhs->previous(), "%name% ("))
9095
1.04k
                continue;
9096
9097
0
            const MathLib::bigint sizeValue = isNew ? getBufferSizeFromNew(rhs) : getBufferSizeFromAllocFunc(rhs->previous());
9098
0
            if (sizeValue < 0)
9099
0
                continue;
9100
9101
0
            ValueFlow::Value value(sizeValue);
9102
0
            value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + std::to_string(sizeValue));
9103
0
            value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
9104
0
            value.setKnown();
9105
0
            valueFlowForward(const_cast<Token*>(rhs), functionScope->bodyEnd, tok->next(), std::move(value), tokenlist, errorLogger, settings);
9106
0
        }
9107
1.75k
    }
9108
1.34k
}
9109
9110
static bool getMinMaxValues(const ValueType *vt, const Platform &platform, MathLib::bigint &minValue, MathLib::bigint &maxValue)
9111
0
{
9112
0
    if (!vt || !vt->isIntegral() || vt->pointer)
9113
0
        return false;
9114
9115
0
    int bits;
9116
0
    switch (vt->type) {
9117
0
    case ValueType::Type::BOOL:
9118
0
        bits = 1;
9119
0
        break;
9120
0
    case ValueType::Type::CHAR:
9121
0
        bits = platform.char_bit;
9122
0
        break;
9123
0
    case ValueType::Type::SHORT:
9124
0
        bits = platform.short_bit;
9125
0
        break;
9126
0
    case ValueType::Type::INT:
9127
0
        bits = platform.int_bit;
9128
0
        break;
9129
0
    case ValueType::Type::LONG:
9130
0
        bits = platform.long_bit;
9131
0
        break;
9132
0
    case ValueType::Type::LONGLONG:
9133
0
        bits = platform.long_long_bit;
9134
0
        break;
9135
0
    default:
9136
0
        return false;
9137
0
    }
9138
9139
0
    if (bits == 1) {
9140
0
        minValue = 0;
9141
0
        maxValue = 1;
9142
0
    } else if (bits < 62) {
9143
0
        if (vt->sign == ValueType::Sign::UNSIGNED) {
9144
0
            minValue = 0;
9145
0
            maxValue = (1LL << bits) - 1;
9146
0
        } else {
9147
0
            minValue = -(1LL << (bits - 1));
9148
0
            maxValue = (1LL << (bits - 1)) - 1;
9149
0
        }
9150
0
    } else if (bits == 64) {
9151
0
        if (vt->sign == ValueType::Sign::UNSIGNED) {
9152
0
            minValue = 0;
9153
0
            maxValue = LLONG_MAX; // todo max unsigned value
9154
0
        } else {
9155
0
            minValue = LLONG_MIN;
9156
0
            maxValue = LLONG_MAX;
9157
0
        }
9158
0
    } else {
9159
0
        return false;
9160
0
    }
9161
9162
0
    return true;
9163
0
}
9164
9165
static bool getMinMaxValues(const std::string &typestr, const Settings &settings, MathLib::bigint &minvalue, MathLib::bigint &maxvalue)
9166
0
{
9167
0
    TokenList typeTokens(&settings);
9168
0
    std::istringstream istr(typestr+";");
9169
0
    if (!typeTokens.createTokens(istr))
9170
0
        return false;
9171
0
    typeTokens.simplifyPlatformTypes();
9172
0
    typeTokens.simplifyStdType();
9173
0
    const ValueType &vt = ValueType::parseDecl(typeTokens.front(), settings);
9174
0
    return getMinMaxValues(&vt, settings.platform, minvalue, maxvalue);
9175
0
}
9176
9177
static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings)
9178
2.23k
{
9179
2.92k
    for (const Scope *functionScope : symboldatabase.functionScopes) {
9180
2.92k
        if (!functionScope->bodyStart)
9181
0
            continue;
9182
2.92k
        const Function *function = functionScope->function;
9183
2.92k
        if (!function)
9184
0
            continue;
9185
9186
2.92k
        const bool safe = function->isSafe(settings);
9187
2.92k
        const bool all = safe && settings.platform.type != Platform::Type::Unspecified;
9188
9189
2.92k
        for (const Variable &arg : function->argumentList) {
9190
0
            if (!arg.nameToken() || !arg.valueType())
9191
0
                continue;
9192
9193
0
            if (arg.valueType()->type == ValueType::Type::CONTAINER) {
9194
0
                if (!safe)
9195
0
                    continue;
9196
0
                std::list<ValueFlow::Value> argValues;
9197
0
                argValues.emplace_back(0);
9198
0
                argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
9199
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " is empty");
9200
0
                argValues.back().safe = true;
9201
0
                argValues.emplace_back(1000000);
9202
0
                argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
9203
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000");
9204
0
                argValues.back().safe = true;
9205
0
                for (const ValueFlow::Value &value : argValues)
9206
0
                    valueFlowForward(const_cast<Token*>(functionScope->bodyStart), arg.nameToken(), value, tokenlist, errorLogger, settings);
9207
0
                continue;
9208
0
            }
9209
9210
0
            MathLib::bigint low, high;
9211
0
            bool isLow = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, low);
9212
0
            bool isHigh = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, high);
9213
9214
0
            if (!isLow && !isHigh && !all)
9215
0
                continue;
9216
9217
0
            const bool safeLow = !isLow;
9218
0
            const bool safeHigh = !isHigh;
9219
9220
0
            if ((!isLow || !isHigh) && all) {
9221
0
                MathLib::bigint minValue, maxValue;
9222
0
                if (getMinMaxValues(arg.valueType(), settings.platform, minValue, maxValue)) {
9223
0
                    if (!isLow)
9224
0
                        low = minValue;
9225
0
                    if (!isHigh)
9226
0
                        high = maxValue;
9227
0
                    isLow = isHigh = true;
9228
0
                } else if (arg.valueType()->type == ValueType::Type::FLOAT || arg.valueType()->type == ValueType::Type::DOUBLE || arg.valueType()->type == ValueType::Type::LONGDOUBLE) {
9229
0
                    std::list<ValueFlow::Value> argValues;
9230
0
                    argValues.emplace_back(0);
9231
0
                    argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
9232
0
                    argValues.back().floatValue = isLow ? low : -1E25;
9233
0
                    argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
9234
0
                    argValues.back().safe = true;
9235
0
                    argValues.emplace_back(0);
9236
0
                    argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
9237
0
                    argValues.back().floatValue = isHigh ? high : 1E25;
9238
0
                    argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
9239
0
                    argValues.back().safe = true;
9240
0
                    valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
9241
0
                                     functionScope->bodyEnd,
9242
0
                                     arg.nameToken(),
9243
0
                                     std::move(argValues),
9244
0
                                     tokenlist,
9245
0
                                     errorLogger,
9246
0
                                     settings);
9247
0
                    continue;
9248
0
                }
9249
0
            }
9250
9251
0
            std::list<ValueFlow::Value> argValues;
9252
0
            if (isLow) {
9253
0
                argValues.emplace_back(low);
9254
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeLow ? "Safe checks: " : "") + "Assuming argument has value " + std::to_string(low));
9255
0
                argValues.back().safe = safeLow;
9256
0
            }
9257
0
            if (isHigh) {
9258
0
                argValues.emplace_back(high);
9259
0
                argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeHigh ? "Safe checks: " : "") + "Assuming argument has value " + std::to_string(high));
9260
0
                argValues.back().safe = safeHigh;
9261
0
            }
9262
9263
0
            if (!argValues.empty())
9264
0
                valueFlowForward(const_cast<Token*>(functionScope->bodyStart->next()),
9265
0
                                 functionScope->bodyEnd,
9266
0
                                 arg.nameToken(),
9267
0
                                 std::move(argValues),
9268
0
                                 tokenlist,
9269
0
                                 errorLogger,
9270
0
                                 settings);
9271
0
        }
9272
2.92k
    }
9273
2.23k
}
9274
9275
static void valueFlowUnknownFunctionReturn(TokenList &tokenlist, const Settings &settings)
9276
1.34k
{
9277
1.34k
    if (settings.checkUnknownFunctionReturn.empty())
9278
1.34k
        return;
9279
0
    for (Token *tok = tokenlist.front(); tok; tok = tok->next()) {
9280
0
        if (!tok->astParent() || tok->str() != "(" || !tok->previous()->isName())
9281
0
            continue;
9282
0
        if (settings.checkUnknownFunctionReturn.find(tok->previous()->str()) == settings.checkUnknownFunctionReturn.end())
9283
0
            continue;
9284
0
        std::vector<MathLib::bigint> unknownValues = settings.library.unknownReturnValues(tok->astOperand1());
9285
0
        if (unknownValues.empty())
9286
0
            continue;
9287
9288
        // Get min/max values for return type
9289
0
        const std::string &typestr = settings.library.returnValueType(tok->previous());
9290
0
        MathLib::bigint minvalue, maxvalue;
9291
0
        if (!getMinMaxValues(typestr, settings, minvalue, maxvalue))
9292
0
            continue;
9293
9294
0
        for (MathLib::bigint value : unknownValues) {
9295
0
            if (value < minvalue)
9296
0
                value = minvalue;
9297
0
            else if (value > maxvalue)
9298
0
                value = maxvalue;
9299
0
            setTokenValue(tok, ValueFlow::Value(value), settings);
9300
0
        }
9301
0
    }
9302
0
}
9303
9304
static void valueFlowDebug(TokenList& tokenlist, ErrorLogger* errorLogger, const Settings& settings)
9305
1.34k
{
9306
1.34k
    if (!settings.debugnormal && !settings.debugwarnings)
9307
1.34k
        return;
9308
0
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
9309
0
        if (tok->getTokenDebug() != TokenDebug::ValueFlow)
9310
0
            continue;
9311
0
        if (tok->astParent() && tok->astParent()->getTokenDebug() == TokenDebug::ValueFlow)
9312
0
            continue;
9313
0
        for (const ValueFlow::Value& v : tok->values()) {
9314
0
            std::string msg = "The value is " + debugString(v);
9315
0
            ErrorPath errorPath = v.errorPath;
9316
0
            errorPath.insert(errorPath.end(), v.debugPath.cbegin(), v.debugPath.cend());
9317
0
            errorPath.emplace_back(tok, "");
9318
0
            errorLogger->reportErr({errorPath, &tokenlist, Severity::debug, "valueFlow", msg, CWE{0}, Certainty::normal});
9319
0
        }
9320
0
    }
9321
0
}
9322
9323
const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(Token *expr, const Settings &settings)
9324
0
{
9325
0
    if (expr && expr->values().empty()) {
9326
0
        valueFlowConstantFoldAST(expr->astOperand1(), settings);
9327
0
        valueFlowConstantFoldAST(expr->astOperand2(), settings);
9328
0
        valueFlowSetConstantValue(expr, settings, true /* TODO: this is a guess */);
9329
0
    }
9330
0
    return expr && expr->hasKnownValue() ? &expr->values().front() : nullptr;
9331
0
}
9332
9333
struct ValueFlowState {
9334
    explicit ValueFlowState(TokenList& tokenlist,
9335
                            SymbolDatabase& symboldatabase,
9336
                            ErrorLogger* errorLogger,
9337
                            const Settings& settings)
9338
        : tokenlist(tokenlist), symboldatabase(symboldatabase), errorLogger(errorLogger), settings(settings)
9339
1.34k
    {}
9340
9341
    TokenList& tokenlist;
9342
    SymbolDatabase& symboldatabase;
9343
    ErrorLogger* errorLogger = nullptr;
9344
    const Settings& settings;
9345
    std::set<const Scope*> skippedFunctions;
9346
};
9347
9348
struct ValueFlowPass {
9349
56.4k
    ValueFlowPass() = default;
9350
56.4k
    ValueFlowPass(const ValueFlowPass&) = default;
9351
    // Name of pass
9352
    virtual const char* name() const = 0;
9353
    // Run the pass
9354
    virtual void run(const ValueFlowState& state) const = 0;
9355
    // Returns true if pass needs C++
9356
    virtual bool cpp() const = 0;
9357
112k
    virtual ~ValueFlowPass() noexcept = default;
9358
};
9359
9360
struct ValueFlowPassRunner {
9361
    using Clock = std::chrono::steady_clock;
9362
    using TimePoint = std::chrono::time_point<Clock>;
9363
    explicit ValueFlowPassRunner(ValueFlowState state, TimerResultsIntf* timerResults = nullptr)
9364
        : state(std::move(state)), stop(TimePoint::max()), timerResults(timerResults)
9365
1.34k
    {
9366
1.34k
        setSkippedFunctions();
9367
1.34k
        setStopTime();
9368
1.34k
    }
9369
9370
    bool run_once(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
9371
2.68k
    {
9372
21.5k
        return std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
9373
21.5k
            return run(pass);
9374
21.5k
        });
9375
2.68k
    }
9376
9377
    bool run(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
9378
1.34k
    {
9379
1.34k
        std::size_t values = 0;
9380
1.34k
        std::size_t n = state.settings.valueFlowMaxIterations;
9381
3.57k
        while (n > 0 && values != getTotalValues()) {
9382
2.23k
            values = getTotalValues();
9383
58.0k
            if (std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
9384
58.0k
                return run(pass);
9385
58.0k
            }))
9386
0
                return true;
9387
2.23k
            --n;
9388
2.23k
        }
9389
1.34k
        if (state.settings.debugwarnings) {
9390
0
            if (n == 0 && values != getTotalValues()) {
9391
0
                ErrorMessage::FileLocation loc;
9392
0
                loc.setfile(state.tokenlist.getFiles()[0]);
9393
0
                ErrorMessage errmsg({std::move(loc)},
9394
0
                                    emptyString,
9395
0
                                    Severity::debug,
9396
0
                                    "ValueFlow maximum iterations exceeded",
9397
0
                                    "valueFlowMaxIterations",
9398
0
                                    Certainty::normal);
9399
0
                state.errorLogger->reportErr(errmsg);
9400
0
            }
9401
0
        }
9402
1.34k
        return false;
9403
1.34k
    }
9404
9405
    bool run(const ValuePtr<ValueFlowPass>& pass) const
9406
79.5k
    {
9407
79.5k
        auto start = Clock::now();
9408
79.5k
        if (start > stop)
9409
0
            return true;
9410
79.5k
        if (!state.tokenlist.isCPP() && pass->cpp())
9411
0
            return false;
9412
79.5k
        if (timerResults) {
9413
0
            Timer t(pass->name(), state.settings.showtime, timerResults);
9414
0
            pass->run(state);
9415
79.5k
        } else {
9416
79.5k
            pass->run(state);
9417
79.5k
        }
9418
79.5k
        return false;
9419
79.5k
    }
9420
9421
    std::size_t getTotalValues() const
9422
5.80k
    {
9423
5.80k
        std::size_t n = 1;
9424
417k
        for (Token* tok = state.tokenlist.front(); tok; tok = tok->next())
9425
411k
            n += tok->values().size();
9426
5.80k
        return n;
9427
5.80k
    }
9428
9429
    void setSkippedFunctions()
9430
1.34k
    {
9431
1.34k
        if (state.settings.performanceValueFlowMaxIfCount > 0) {
9432
1.75k
            for (const Scope* functionScope : state.symboldatabase.functionScopes) {
9433
1.75k
                int countIfScopes = 0;
9434
1.75k
                std::vector<const Scope*> scopes{functionScope};
9435
5.45k
                while (!scopes.empty()) {
9436
3.69k
                    const Scope* s = scopes.back();
9437
3.69k
                    scopes.pop_back();
9438
3.69k
                    for (const Scope* s2 : s->nestedList) {
9439
1.93k
                        scopes.emplace_back(s2);
9440
1.93k
                        if (s2->type == Scope::ScopeType::eIf)
9441
944
                            ++countIfScopes;
9442
1.93k
                    }
9443
3.69k
                }
9444
1.75k
                if (countIfScopes > state.settings.performanceValueFlowMaxIfCount) {
9445
0
                    state.skippedFunctions.emplace(functionScope);
9446
9447
0
                    if (state.settings.severity.isEnabled(Severity::information)) {
9448
0
                        const std::string& functionName = functionScope->className;
9449
0
                        const std::list<ErrorMessage::FileLocation> callstack(
9450
0
                            1,
9451
0
                            ErrorMessage::FileLocation(functionScope->bodyStart, &state.tokenlist));
9452
0
                        const ErrorMessage errmsg(callstack,
9453
0
                                                  state.tokenlist.getSourceFilePath(),
9454
0
                                                  Severity::information,
9455
0
                                                  "Limiting ValueFlow analysis in function '" + functionName + "' since it is too complex. "
9456
0
                                                  "Please specify --check-level=exhaustive to perform full analysis.",
9457
0
                                                  "checkLevelNormal",
9458
0
                                                  Certainty::normal);
9459
0
                        state.errorLogger->reportErr(errmsg);
9460
0
                    }
9461
0
                }
9462
1.75k
            }
9463
1.34k
        }
9464
1.34k
    }
9465
9466
    void setStopTime()
9467
1.34k
    {
9468
1.34k
        if (state.settings.performanceValueFlowMaxTime >= 0)
9469
0
            stop = Clock::now() + std::chrono::seconds{state.settings.performanceValueFlowMaxTime};
9470
1.34k
    }
9471
9472
    ValueFlowState state;
9473
    TimePoint stop;
9474
    TimerResultsIntf* timerResults;
9475
};
9476
9477
template<class F>
9478
struct ValueFlowPassAdaptor : ValueFlowPass {
9479
    const char* mName = nullptr;
9480
    bool mCPP = false;
9481
    F mRun;
9482
56.4k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_8>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_8)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_9>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_9)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_10>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_10)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_11>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_11)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_12>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_12)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_13>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_13)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_14>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_14)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_15>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_15)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_16>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_16)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_17>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_17)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_18>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_18)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_19>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_19)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_20>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_20)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_21>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_21)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_22>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_22)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_23>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_23)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_24>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_24)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_25>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_25)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_26>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_26)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_27>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_27)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_28>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_28)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_29>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_29)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_30>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_30)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_31>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_31)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_32>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_32)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_33>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_33)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_34>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_34)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_35>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_35)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_36>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_36)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_37>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_37)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_38>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_38)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_39>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_39)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_40>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_40)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_41>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_41)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_42>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_42)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_43>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_43)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_44>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_44)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_45>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_45)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_46>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_46)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_47>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_47)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_48>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_48)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_49>::ValueFlowPassAdaptor(char const*, bool, ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_49)
Line
Count
Source
9482
1.34k
    ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : ValueFlowPass(), mName(pname), mCPP(pcpp), mRun(prun) {}
9483
0
    const char* name() const override {
9484
0
        return mName;
9485
0
    }
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
9486
    void run(const ValueFlowState& state) const override
9487
79.5k
    {
9488
79.5k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
79.5k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_8>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_9>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_10>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_11>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_12>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_13>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_14>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_15>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_16>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_17>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_18>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_19>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_20>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_21>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_22>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_23>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_24>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_25>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_26>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_27>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_28>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_29>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_30>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_31>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_32>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_33>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_34>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_35>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_36>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_37>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_38>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_39>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_40>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_41>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_42>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_43>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_44>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_45>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_46>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_47>::run(ValueFlowState const&) const
Line
Count
Source
9487
2.23k
    {
9488
2.23k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
2.23k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_48>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
valueflow.cpp:ValueFlowPassAdaptor<ValueFlow::setValues(TokenList&, SymbolDatabase&, ErrorLogger*, Settings const&, TimerResultsIntf*)::$_49>::run(ValueFlowState const&) const
Line
Count
Source
9487
1.34k
    {
9488
1.34k
        mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
9489
1.34k
    }
9490
0
    bool cpp() const override {
9491
0
        return mCPP;
9492
0
    }
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
9493
};
9494
9495
template<class F>
9496
static ValueFlowPassAdaptor<F> makeValueFlowPassAdaptor(const char* name, bool cpp, F run)
9497
56.4k
{
9498
56.4k
    return {name, cpp, run};
9499
56.4k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
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
9497
1.34k
{
9498
1.34k
    return {name, cpp, run};
9499
1.34k
}
9500
9501
#define VALUEFLOW_ADAPTOR(cpp, ...)                                                                                    \
9502
56.4k
    makeValueFlowPassAdaptor(#__VA_ARGS__,                                                                             \
9503
56.4k
                             (cpp),                                                                                      \
9504
56.4k
                             [](TokenList& tokenlist,                                                                  \
9505
56.4k
                                SymbolDatabase& symboldatabase,                                                        \
9506
56.4k
                                ErrorLogger* errorLogger,                                                              \
9507
56.4k
                                const Settings& settings,                                                              \
9508
79.5k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
79.5k
        (void)tokenlist;                                                                      \
9510
79.5k
        (void)symboldatabase;                                                                 \
9511
79.5k
        (void)errorLogger;                                                                    \
9512
79.5k
        (void)settings;                                                                       \
9513
79.5k
        (void)skippedFunctions;                                                               \
9514
79.5k
        __VA_ARGS__;                                                                          \
9515
79.5k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
2.23k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
2.23k
        (void)tokenlist;                                                                      \
9510
2.23k
        (void)symboldatabase;                                                                 \
9511
2.23k
        (void)errorLogger;                                                                    \
9512
2.23k
        (void)settings;                                                                       \
9513
2.23k
        (void)skippedFunctions;                                                               \
9514
2.23k
        __VA_ARGS__;                                                                          \
9515
2.23k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
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
9508
1.34k
                                const std::set<const Scope*>& skippedFunctions) {                                      \
9509
1.34k
        (void)tokenlist;                                                                      \
9510
1.34k
        (void)symboldatabase;                                                                 \
9511
1.34k
        (void)errorLogger;                                                                    \
9512
1.34k
        (void)settings;                                                                       \
9513
1.34k
        (void)skippedFunctions;                                                               \
9514
1.34k
        __VA_ARGS__;                                                                          \
9515
1.34k
    })
9516
9517
45.6k
#define VFA(...) VALUEFLOW_ADAPTOR(false, __VA_ARGS__)
9518
10.7k
#define VFA_CPP(...) VALUEFLOW_ADAPTOR(true, __VA_ARGS__)
9519
9520
void ValueFlow::setValues(TokenList& tokenlist,
9521
                          SymbolDatabase& symboldatabase,
9522
                          ErrorLogger* errorLogger,
9523
                          const Settings& settings,
9524
                          TimerResultsIntf* timerResults)
9525
1.34k
{
9526
93.2k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next())
9527
91.8k
        tok->clearValueFlow();
9528
9529
    // commas in init..
9530
93.2k
    for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
9531
91.8k
        if (tok->str() != "{" || !tok->astOperand1())
9532
91.8k
            continue;
9533
0
        for (Token* tok2 = tok->next(); tok2 != tok->link(); tok2 = tok2->next()) {
9534
0
            if (tok2->link() && Token::Match(tok2, "[{[(<]"))
9535
0
                tok2 = tok2->link();
9536
0
            else if (tok2->str() == ",")
9537
0
                tok2->isInitComma(true);
9538
0
        }
9539
0
    }
9540
9541
1.34k
    ValueFlowPassRunner runner{ValueFlowState{tokenlist, symboldatabase, errorLogger, settings}, timerResults};
9542
1.34k
    runner.run_once({
9543
1.34k
        VFA(valueFlowEnumValue(symboldatabase, settings)),
9544
1.34k
        VFA(valueFlowNumber(tokenlist, settings)),
9545
1.34k
        VFA(valueFlowString(tokenlist, settings)),
9546
1.34k
        VFA(valueFlowArray(tokenlist, settings)),
9547
1.34k
        VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)),
9548
1.34k
        VFA(valueFlowGlobalConstVar(tokenlist, settings)),
9549
1.34k
        VFA(valueFlowEnumValue(symboldatabase, settings)),
9550
1.34k
        VFA(valueFlowGlobalStaticVar(tokenlist, settings)),
9551
1.34k
        VFA(valueFlowPointerAlias(tokenlist, settings)),
9552
1.34k
        VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
9553
1.34k
        VFA(valueFlowSymbolic(tokenlist, symboldatabase, errorLogger, settings)),
9554
1.34k
        VFA(valueFlowBitAnd(tokenlist, settings)),
9555
1.34k
        VFA(valueFlowSameExpressions(tokenlist, settings)),
9556
1.34k
        VFA(valueFlowConditionExpressions(tokenlist, symboldatabase, errorLogger, settings)),
9557
1.34k
    });
9558
9559
1.34k
    runner.run({
9560
1.34k
        VFA(valueFlowImpossibleValues(tokenlist, settings)),
9561
1.34k
        VFA(valueFlowSymbolicOperators(symboldatabase, settings)),
9562
1.34k
        VFA(valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9563
1.34k
        VFA(valueFlowSymbolicInfer(symboldatabase, settings)),
9564
1.34k
        VFA(valueFlowArrayBool(tokenlist, settings)),
9565
1.34k
        VFA(valueFlowArrayElement(tokenlist, settings)),
9566
1.34k
        VFA(valueFlowRightShift(tokenlist, settings)),
9567
1.34k
        VFA(valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9568
1.34k
        VFA_CPP(valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings)),
9569
1.34k
        VFA(valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9570
1.34k
        VFA(valueFlowInferCondition(tokenlist, settings)),
9571
1.34k
        VFA(valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings)),
9572
1.34k
        VFA(valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings)),
9573
1.34k
        VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings)),
9574
1.34k
        VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)),
9575
1.34k
        VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
9576
1.34k
        VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings)),
9577
1.34k
        VFA(valueFlowUninit(tokenlist, errorLogger, settings)),
9578
1.34k
        VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, errorLogger, settings)),
9579
1.34k
        VFA_CPP(valueFlowSmartPointer(tokenlist, errorLogger, settings)),
9580
1.34k
        VFA_CPP(valueFlowIterators(tokenlist, settings)),
9581
1.34k
        VFA_CPP(
9582
1.34k
            valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9583
1.34k
        VFA_CPP(valueFlowIteratorInfer(tokenlist, settings)),
9584
1.34k
        VFA_CPP(valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9585
1.34k
        VFA_CPP(
9586
1.34k
            valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
9587
1.34k
        VFA(valueFlowSafeFunctions(tokenlist, symboldatabase, errorLogger, settings)),
9588
1.34k
    });
9589
9590
1.34k
    runner.run_once({
9591
1.34k
        VFA(valueFlowDynamicBufferSize(tokenlist, symboldatabase, errorLogger, settings)),
9592
1.34k
        VFA(valueFlowDebug(tokenlist, errorLogger, settings)),
9593
1.34k
    });
9594
1.34k
}
9595
9596
std::string ValueFlow::eitherTheConditionIsRedundant(const Token *condition)
9597
1
{
9598
1
    if (!condition)
9599
0
        return "Either the condition is redundant";
9600
1
    if (condition->str() == "case") {
9601
0
        std::string expr;
9602
0
        for (const Token *tok = condition; tok && tok->str() != ":"; tok = tok->next()) {
9603
0
            expr += tok->str();
9604
0
            if (Token::Match(tok, "%name%|%num% %name%|%num%"))
9605
0
                expr += ' ';
9606
0
        }
9607
0
        return "Either the switch case '" + expr + "' is redundant";
9608
0
    }
9609
1
    return "Either the condition '" + condition->expressionString() + "' is redundant";
9610
1
}
9611
9612
const ValueFlow::Value* ValueFlow::findValue(const std::list<ValueFlow::Value>& values,
9613
                                             const Settings* settings,
9614
                                             const std::function<bool(const ValueFlow::Value&)> &pred)
9615
481
{
9616
481
    const ValueFlow::Value* ret = nullptr;
9617
485
    for (const ValueFlow::Value& v : values) {
9618
485
        if (pred(v)) {
9619
56
            if (!ret || ret->isInconclusive() || (ret->condition && !v.isInconclusive()))
9620
56
                ret = &v;
9621
56
            if (!ret->isInconclusive() && !ret->condition)
9622
54
                break;
9623
56
        }
9624
485
    }
9625
481
    if (settings && ret) {
9626
56
        if (ret->isInconclusive() && !settings->certainty.isEnabled(Certainty::inconclusive))
9627
0
            return nullptr;
9628
56
        if (ret->condition && !settings->severity.isEnabled(Severity::warning))
9629
0
            return nullptr;
9630
56
    }
9631
481
    return ret;
9632
481
}
9633
9634
// TODO: returns a single value at most - no need for std::vector
9635
static std::vector<ValueFlow::Value> isOutOfBoundsImpl(const ValueFlow::Value& size,
9636
                                                       const Token* indexTok,
9637
                                                       bool condition)
9638
0
{
9639
0
    if (!indexTok)
9640
0
        return {};
9641
0
    const ValueFlow::Value* indexValue = indexTok->getMaxValue(condition, size.path);
9642
0
    if (!indexValue)
9643
0
        return {};
9644
0
    if (indexValue->intvalue >= size.intvalue)
9645
0
        return {*indexValue};
9646
0
    if (!condition)
9647
0
        return {};
9648
    // TODO: Use a better way to decide if the variable in unconstrained
9649
0
    if (!indexTok->variable() || !indexTok->variable()->isArgument())
9650
0
        return {};
9651
0
    if (std::any_of(indexTok->values().cbegin(), indexTok->values().cend(), [&](const ValueFlow::Value& v) {
9652
0
        return v.isSymbolicValue() && v.isPossible() && v.bound == ValueFlow::Value::Bound::Upper;
9653
0
    }))
9654
0
        return {};
9655
0
    if (indexValue->bound != ValueFlow::Value::Bound::Lower)
9656
0
        return {};
9657
0
    if (size.bound == ValueFlow::Value::Bound::Lower)
9658
0
        return {};
9659
    // Checking for underflow doesn't mean it could be out of bounds
9660
0
    if (indexValue->intvalue == 0)
9661
0
        return {};
9662
0
    ValueFlow::Value value = inferCondition(">=", indexTok, indexValue->intvalue);
9663
0
    if (!value.isKnown())
9664
0
        return {};
9665
0
    if (value.intvalue == 0)
9666
0
        return {};
9667
0
    value.intvalue = size.intvalue;
9668
0
    value.bound = ValueFlow::Value::Bound::Lower;
9669
0
    return {std::move(value)};
9670
0
}
9671
9672
// TODO: return single value at most - no need for std::vector
9673
std::vector<ValueFlow::Value> ValueFlow::isOutOfBounds(const Value& size, const Token* indexTok, bool possible)
9674
0
{
9675
0
    ValueFlow::Value inBoundsValue = inferCondition("<", indexTok, size.intvalue);
9676
0
    if (inBoundsValue.isKnown() && inBoundsValue.intvalue != 0)
9677
0
        return {};
9678
0
    std::vector<ValueFlow::Value> result = isOutOfBoundsImpl(size, indexTok, false);
9679
0
    if (!result.empty())
9680
0
        return result;
9681
0
    if (!possible)
9682
0
        return result;
9683
0
    return isOutOfBoundsImpl(size, indexTok, true);
9684
0
}