Coverage Report

Created: 2025-01-24 06:31

/src/cppcheck/oss-fuzz/build/vf_settokenvalue.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "matchcompiler.h"
2
#include <string>
3
#include <cstring>
4
#include "errorlogger.h"
5
#include "token.h"
6
// pattern: . %name% (
7
0
static inline bool match1(const Token* tok) {
8
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
9
0
        return false;
10
0
    tok = tok->next();
11
0
    if (!tok || !tok->isName())
12
0
        return false;
13
0
    tok = tok->next();
14
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
15
0
        return false;
16
0
    return true;
17
0
}
18
// pattern: %name% (
19
0
static inline bool match2(const Token* tok) {
20
0
    if (!tok || !tok->isName())
21
0
        return false;
22
0
    tok = tok->next();
23
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
24
0
        return false;
25
0
    return true;
26
0
}
27
// pattern: {|(
28
2.63k
static inline bool match3(const Token* tok) {
29
2.63k
    if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))))
30
1.58k
        return false;
31
1.05k
    return true;
32
2.63k
}
33
// pattern: %type% (|{
34
1.05k
static inline bool match4(const Token* tok) {
35
1.05k
    if (!tok || !(tok->isName() && tok->varId() == 0U))
36
0
        return false;
37
1.05k
    tok = tok->next();
38
1.05k
    if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))))
39
0
        return false;
40
1.05k
    return true;
41
1.05k
}
42
// pattern: ( %name%|::
43
0
static inline bool match5(const Token* tok) {
44
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
45
0
        return false;
46
0
    tok = tok->next();
47
0
    if (!tok || !(tok->isName() || (tok->str() == MatchCompiler::makeConstString("::"))))
48
0
        return false;
49
0
    return true;
50
0
}
51
// pattern: ::
52
0
static inline bool match6(const Token* tok) {
53
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("::")))
54
0
        return false;
55
0
    return true;
56
0
}
57
// pattern: %name% ::
58
0
static inline bool match7(const Token* tok) {
59
0
    if (!tok || !tok->isName())
60
0
        return false;
61
0
    tok = tok->next();
62
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("::")))
63
0
        return false;
64
0
    return true;
65
0
}
66
// pattern: const_cast|dynamic_cast|reinterpret_cast|static_cast <
67
1.05k
static inline bool match8(const Token* tok) {
68
1.05k
    if (!tok || !((tok->str() == MatchCompiler::makeConstString("const_cast")) || (tok->str() == MatchCompiler::makeConstString("dynamic_cast")) || (tok->str() == MatchCompiler::makeConstString("reinterpret_cast")) || (tok->str() == MatchCompiler::makeConstString("static_cast"))))
69
1.05k
        return false;
70
0
    tok = tok->next();
71
0
    if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))
72
0
        return false;
73
0
    return true;
74
0
}
75
// pattern: +|-
76
805
static inline bool match9(const Token* tok) {
77
805
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-"))))
78
760
        return false;
79
45
    return true;
80
805
}
81
// pattern: {|%str%
82
0
static inline bool match10(const Token* tok) {
83
0
    if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || (tok->tokType() == Token::eString)))
84
0
        return false;
85
0
    return true;
86
0
}
87
// pattern: ,
88
6.95k
static inline bool match11(const Token* tok) {
89
6.95k
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")))
90
6.95k
        return false;
91
0
    return true;
92
6.95k
}
93
// pattern: %name%|> (
94
0
static inline bool match12(const Token* tok) {
95
0
    if (!tok || !(tok->isName() || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))))
96
0
        return false;
97
0
    tok = tok->next();
98
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
99
0
        return false;
100
0
    return true;
101
0
}
102
// pattern: {
103
0
static inline bool match13(const Token* tok) {
104
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
105
0
        return false;
106
0
    return true;
107
0
}
108
// pattern: ( %name%
109
0
static inline bool match14(const Token* tok) {
110
0
    if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))
111
0
        return false;
112
0
    tok = tok->next();
113
0
    if (!tok || !tok->isName())
114
0
        return false;
115
0
    return true;
116
0
}
117
// pattern: %name%|(
118
0
static inline bool match15(const Token* tok) {
119
0
    if (!tok || !(tok->isName() || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))))
120
0
        return false;
121
0
    return true;
122
0
}
123
// pattern: *
124
0
static inline bool match16(const Token* tok) {
125
0
    if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")))
126
0
        return false;
127
0
    return true;
128
0
}
129
// pattern: =
130
6.95k
static inline bool match17(const Token* tok) {
131
6.95k
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
132
2.60k
        return false;
133
4.35k
    return true;
134
6.95k
}
135
// pattern: +|==|!=
136
0
static inline bool match18(const Token* tok) {
137
0
    if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!="))))
138
0
        return false;
139
0
    return true;
140
0
}
141
// pattern: %comp%
142
4
static inline bool match19(const Token* tok) {
143
4
    if (!tok || !tok->isComparisonOp())
144
2
        return false;
145
2
    return true;
146
4
}
147
// pattern: ==
148
0
static inline bool match20(const Token* tok) {
149
0
    if (!tok || !((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")))
150
0
        return false;
151
0
    return true;
152
0
}
153
// pattern: !=
154
0
static inline bool match21(const Token* tok) {
155
0
    if (!tok || !((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!=")))
156
0
        return false;
157
0
    return true;
158
0
}
159
// pattern: . %var%
160
0
static inline bool match22(const Token* tok) {
161
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(".")))
162
0
        return false;
163
0
    tok = tok->next();
164
0
    if (!tok || !(tok->varId() != 0))
165
0
        return false;
166
0
    return true;
167
0
}
168
// pattern: dynamic_cast
169
0
static inline bool match23(const Token* tok) {
170
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("dynamic_cast")))
171
0
        return false;
172
0
    return true;
173
0
}
174
// pattern: %name%
175
0
static inline bool match24(const Token* tok) {
176
0
    if (!tok || !tok->isName())
177
0
        return false;
178
0
    return true;
179
0
}
180
// pattern: [&*]
181
238
static inline bool match25(const Token* tok) {
182
238
    if (!tok || tok->str().size() != 1U || !strchr("&*", tok->str()[0]))
183
198
        return false;
184
40
    return true;
185
238
}
186
// pattern: &&
187
219
static inline bool match26(const Token* tok) {
188
219
    if (!tok || !((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")))
189
219
        return false;
190
0
    return true;
191
219
}
192
// pattern: ||
193
219
static inline bool match27(const Token* tok) {
194
219
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("||")))
195
219
        return false;
196
0
    return true;
197
219
}
198
// pattern: &|^|%|<<|>>|==|!=|%or%
199
0
static inline bool match28(const Token* tok) {
200
0
    if (!tok || !(((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("^")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("%")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!=")) || (tok->tokType() == Token::eBitOp && tok->str() == MatchCompiler::makeConstString("|") )))
201
0
        return false;
202
0
    return true;
203
0
}
204
// pattern: ==|!=
205
7
static inline bool match29(const Token* tok) {
206
7
    if (!tok || !(((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("==")) || ((tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("!="))))
207
4
        return false;
208
3
    return true;
209
7
}
210
// pattern: %str%
211
0
static inline bool match30(const Token* tok) {
212
0
    if (!tok || !(tok->tokType() == Token::eString))
213
0
        return false;
214
0
    return true;
215
0
}
216
// pattern: %op%
217
4
static inline bool match31(const Token* tok) {
218
4
    if (!tok || !tok->isOp())
219
0
        return false;
220
4
    return true;
221
4
}
222
// pattern: -
223
4
static inline bool match32(const Token* tok) {
224
4
    if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")))
225
4
        return false;
226
0
    return true;
227
4
}
228
// pattern: = {
229
0
static inline bool match33(const Token* tok) {
230
0
    if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))
231
0
        return false;
232
0
    tok = tok->next();
233
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))
234
0
        return false;
235
0
    return true;
236
0
}
237
// pattern: } ;
238
0
static inline bool match34(const Token* tok) {
239
0
    if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")))
240
0
        return false;
241
0
    tok = tok->next();
242
0
    if (!tok || !(tok->str() == MatchCompiler::makeConstString(";")))
243
0
        return false;
244
0
    return true;
245
0
}
246
// pattern: :: %name%
247
1.94k
static inline bool match35(const Token* tok) {
248
1.94k
    if (!tok || !(tok->str() == MatchCompiler::makeConstString("::")))
249
1.94k
        return false;
250
0
    tok = tok->next();
251
0
    if (!tok || !tok->isName())
252
0
        return false;
253
0
    return true;
254
0
}
255
/*
256
 * Cppcheck - A tool for static C/C++ code analysis
257
 * Copyright (C) 2007-2024 Cppcheck team.
258
 *
259
 * This program is free software: you can redistribute it and/or modify
260
 * it under the terms of the GNU General Public License as published by
261
 * the Free Software Foundation, either version 3 of the License, or
262
 * (at your option) any later version.
263
 *
264
 * This program is distributed in the hope that it will be useful,
265
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
266
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
267
 * GNU General Public License for more details.
268
 *
269
 * You should have received a copy of the GNU General Public License
270
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
271
 */
272
273
#include "vf_settokenvalue.h"
274
275
#include "astutils.h"
276
#include "calculate.h"
277
#include "config.h"
278
#include "library.h"
279
#include "mathlib.h"
280
#include "platform.h"
281
#include "settings.h"
282
#include "symboldatabase.h"
283
#include "token.h"
284
#include "utils.h"
285
#include "valueflow.h"
286
#include "vfvalue.h"
287
288
#include "vf_common.h"
289
290
#include <algorithm>
291
#include <climits>
292
#include <cstddef>
293
#include <functional>
294
#include <list>
295
#include <string>
296
#include <unordered_map>
297
#include <unordered_set>
298
#include <utility>
299
#include <vector>
300
301
namespace ValueFlow
302
{
303
    static Library::Container::Yield getContainerYield(Token* tok, const Settings& settings, Token*& parent)
304
0
    {
305
0
        if (match1(tok) && tok->astParent() == tok->tokAt(2) && tok->astOperand1() &&
306
0
            tok->astOperand1()->valueType()) {
307
0
            const Library::Container* c = getLibraryContainer(tok->astOperand1());
308
0
            parent = tok->astParent();
309
0
            return c ? c->getYield(tok->strAt(1)) : Library::Container::Yield::NO_YIELD;
310
0
        }
311
0
        if (match2(tok->previous())) {
312
0
            parent = tok;
313
0
            if (const Library::Function* f = settings.library.getFunction(tok->previous())) {
314
0
                return f->containerYield;
315
0
            }
316
0
        }
317
0
        return Library::Container::Yield::NO_YIELD;
318
0
    }
319
320
    static Value truncateImplicitConversion(Token* parent, const Value& value, const Settings& settings)
321
9.18k
    {
322
9.18k
        if (!value.isIntValue() && !value.isFloatValue())
323
0
            return value;
324
9.18k
        if (!parent)
325
3.96k
            return value;
326
5.22k
        if (!parent->isBinaryOp())
327
812
            return value;
328
4.41k
        if (!parent->isConstOp())
329
4.24k
            return value;
330
172
        if (!astIsIntegral(parent->astOperand1(), false))
331
28
            return value;
332
144
        if (!astIsIntegral(parent->astOperand2(), false))
333
14
            return value;
334
130
        const ValueType* vt1 = parent->astOperand1()->valueType();
335
130
        const ValueType* vt2 = parent->astOperand2()->valueType();
336
        // If the sign is the same there is no truncation
337
130
        if (vt1->sign == vt2->sign)
338
71
            return value;
339
59
        const size_t n1 = getSizeOf(*vt1, settings);
340
59
        const size_t n2 = getSizeOf(*vt2, settings);
341
59
        ValueType::Sign sign = ValueType::Sign::UNSIGNED;
342
59
        if (n1 < n2)
343
38
            sign = vt2->sign;
344
21
        else if (n1 > n2)
345
21
            sign = vt1->sign;
346
59
        Value v = castValue(value, sign, std::max(n1, n2) * 8);
347
59
        v.wideintvalue = value.intvalue;
348
59
        return v;
349
130
    }
350
351
    static const Token *getCastTypeStartToken(const Token *parent, const Settings& settings)
352
2.63k
    {
353
        // TODO: This might be a generic utility function?
354
2.63k
        if (!match3(parent))
355
1.58k
            return nullptr;
356
        // Functional cast
357
1.05k
        if (parent->isBinaryOp() && match4(parent->astOperand1()) &&
358
1.05k
            parent->astOperand1()->tokType() == Token::eType && astIsPrimitive(parent))
359
0
            return parent->astOperand1();
360
1.05k
        if (parent->str() != MatchCompiler::makeConstString("("))
361
0
            return nullptr;
362
1.05k
        if (!parent->astOperand2() && match5(parent)) {
363
0
            const Token* ftok = parent->next();
364
0
            if (ftok->isStandardType())
365
0
                return ftok;
366
0
            if (match6(ftok))
367
0
                ftok = ftok->next();
368
0
            while (match7(ftok))
369
0
                ftok = ftok->tokAt(2);
370
0
            if (settings.library.isNotLibraryFunction(ftok))
371
0
                return parent->next();
372
0
        }
373
1.05k
        if (parent->astOperand2() && match8(parent->astOperand1()))
374
0
            return parent->astOperand1()->tokAt(2);
375
1.05k
        return nullptr;
376
1.05k
    }
377
378
0
    static bool isNumeric(const Value& value) {
379
0
        return value.isIntValue() || value.isFloatValue();
380
0
    }
381
382
    static void setTokenValueCast(Token *parent, const ValueType &valueType, const Value &value, const Settings &settings)
383
0
    {
384
0
        if (valueType.pointer || value.isImpossible())
385
0
            setTokenValue(parent,value,settings);
386
0
        else if (valueType.type == ValueType::Type::CHAR)
387
0
            setTokenValue(parent, castValue(value, valueType.sign, settings.platform.char_bit), settings);
388
0
        else if (valueType.type == ValueType::Type::SHORT)
389
0
            setTokenValue(parent, castValue(value, valueType.sign, settings.platform.short_bit), settings);
390
0
        else if (valueType.type == ValueType::Type::INT)
391
0
            setTokenValue(parent, castValue(value, valueType.sign, settings.platform.int_bit), settings);
392
0
        else if (valueType.type == ValueType::Type::LONG)
393
0
            setTokenValue(parent, castValue(value, valueType.sign, settings.platform.long_bit), settings);
394
0
        else if (valueType.type == ValueType::Type::LONGLONG)
395
0
            setTokenValue(parent, castValue(value, valueType.sign, settings.platform.long_long_bit), settings);
396
0
        else if (valueType.isFloat() && isNumeric(value)) {
397
0
            Value floatValue = value;
398
0
            floatValue.valueType = Value::ValueType::FLOAT;
399
0
            if (value.isIntValue())
400
0
                floatValue.floatValue = static_cast<double>(value.intvalue);
401
0
            setTokenValue(parent, std::move(floatValue), settings);
402
0
        } else if (value.isIntValue()) {
403
0
            const long long charMax = settings.platform.signedCharMax();
404
0
            const long long charMin = settings.platform.signedCharMin();
405
0
            if (charMin <= value.intvalue && value.intvalue <= charMax) {
406
                // unknown type, but value is small so there should be no truncation etc
407
0
                setTokenValue(parent,value,settings);
408
0
            }
409
0
        }
410
0
    }
411
412
    // does the operation cause a loss of information?
413
    static bool isNonInvertibleOperation(const Token* tok)
414
801
    {
415
801
        return !match9(tok);
416
801
    }
417
418
    static bool isComputableValue(const Token* parent, const Value& value)
419
162
    {
420
162
        const bool noninvertible = isNonInvertibleOperation(parent);
421
162
        if (noninvertible && value.isImpossible())
422
19
            return false;
423
143
        if (!value.isIntValue() && !value.isFloatValue() && !value.isTokValue() && !value.isIteratorValue())
424
46
            return false;
425
97
        if (value.isIteratorValue() && !match9(parent))
426
0
            return false;
427
97
        if (value.isTokValue() && (!parent->isComparisonOp() || !match10(value.tokvalue)))
428
0
            return false;
429
97
        return true;
430
97
    }
431
432
    /** Set token value for cast */
433
    static bool isCompatibleValueTypes(Value::ValueType x, Value::ValueType y)
434
7
    {
435
7
        static const std::unordered_map<Value::ValueType,
436
7
                                        std::unordered_set<Value::ValueType, EnumClassHash>,
437
7
                                        EnumClassHash>
438
7
        compatibleTypes = {
439
7
            {Value::ValueType::INT,
440
7
             {Value::ValueType::FLOAT,
441
7
              Value::ValueType::SYMBOLIC,
442
7
              Value::ValueType::TOK}},
443
7
            {Value::ValueType::FLOAT, {Value::ValueType::INT}},
444
7
            {Value::ValueType::TOK, {Value::ValueType::INT}},
445
7
            {Value::ValueType::ITERATOR_START, {Value::ValueType::INT}},
446
7
            {Value::ValueType::ITERATOR_END, {Value::ValueType::INT}},
447
7
        };
448
7
        if (x == y)
449
7
            return true;
450
0
        auto it = compatibleTypes.find(x);
451
0
        if (it == compatibleTypes.end())
452
0
            return false;
453
0
        return it->second.count(y) > 0;
454
0
    }
455
456
    static bool isCompatibleValues(const Value& value1, const Value& value2)
457
7
    {
458
7
        if (value1.isSymbolicValue() && value2.isSymbolicValue() && value1.tokvalue->exprId() != value2.tokvalue->exprId())
459
0
            return false;
460
7
        if (!isCompatibleValueTypes(value1.valueType, value2.valueType))
461
0
            return false;
462
7
        if (value1.isKnown() || value2.isKnown())
463
2
            return true;
464
5
        if (value1.isImpossible() || value2.isImpossible())
465
0
            return false;
466
5
        if (value1.varId == 0 || value2.varId == 0)
467
1
            return true;
468
4
        if (value1.varId == value2.varId && value1.varvalue == value2.varvalue && value1.isIntValue() && value2.isIntValue())
469
4
            return true;
470
0
        return false;
471
4
    }
472
473
    /** set ValueFlow value and perform calculations if possible */
474
    void setTokenValue(Token* tok,
475
                       Value value,
476
                       const Settings& settings,
477
                       SourceLocation loc)
478
12.9k
    {
479
        // Skip setting values that are too big since its ambiguous
480
12.9k
        if (!value.isImpossible() && value.isIntValue() && value.intvalue < 0 && astIsUnsigned(tok) &&
481
12.9k
            getSizeOf(*tok->valueType(), settings) >= sizeof(MathLib::bigint))
482
0
            return;
483
484
12.9k
        if (!value.isImpossible() && value.isIntValue())
485
9.18k
            value = truncateImplicitConversion(tok->astParent(), value, settings);
486
487
12.9k
        if (settings.debugnormal)
488
0
            setSourceLocation(value, loc, tok);
489
490
12.9k
        if (!tok->addValue(value))
491
1.79k
            return;
492
493
11.1k
        if (value.path < 0)
494
0
            return;
495
496
11.1k
        Token *parent = tok->astParent();
497
11.1k
        if (!parent)
498
4.18k
            return;
499
500
6.95k
        if (match11(parent) && !parent->isInitComma() && astIsRHS(tok)) {
501
0
            const Token* callParent = findParent(parent, [](const Token* p) {
502
0
                return !match11(p);
503
0
            });
504
            // Ensure that the comma isn't a function call
505
0
            if (!callParent || (!match12(callParent->previous()) && !match13(callParent) &&
506
0
                                (!match14(callParent) || settings.library.isNotLibraryFunction(callParent->next())) &&
507
0
                                !(callParent->str() == MatchCompiler::makeConstString("(") && (match16(callParent->astOperand1()) || match15(callParent->astOperand1()))))) {
508
0
                setTokenValue(parent, std::move(value), settings);
509
0
                return;
510
0
            }
511
0
        }
512
513
6.95k
        if (match17(parent) && astIsRHS(tok)) {
514
4.31k
            setTokenValue(parent, value, settings);
515
4.31k
            if (!value.isUninitValue())
516
4.31k
                return;
517
4.31k
        }
518
519
2.64k
        if (value.isContainerSizeValue() && astIsContainer(tok)) {
520
            // .empty, .size, +"abc", +'a'
521
0
            if (match18(parent) && parent->astOperand1() && parent->astOperand2()) {
522
0
                for (const Value &value1 : parent->astOperand1()->values()) {
523
0
                    if (value1.isImpossible())
524
0
                        continue;
525
0
                    for (const Value &value2 : parent->astOperand2()->values()) {
526
0
                        if (value2.isImpossible())
527
0
                            continue;
528
0
                        if (value1.path != value2.path)
529
0
                            continue;
530
0
                        Value result;
531
0
                        if (match19(parent))
532
0
                            result.valueType = Value::ValueType::INT;
533
0
                        else
534
0
                            result.valueType = Value::ValueType::CONTAINER_SIZE;
535
536
0
                        if (value1.isContainerSizeValue() && value2.isContainerSizeValue())
537
0
                            result.intvalue = calculate(parent->str(), value1.intvalue, value2.intvalue);
538
0
                        else if (value1.isContainerSizeValue() && value2.isTokValue() && value2.tokvalue->tokType() == Token::eString)
539
0
                            result.intvalue = calculate(parent->str(), value1.intvalue, MathLib::bigint(Token::getStrLength(value2.tokvalue)));
540
0
                        else if (value2.isContainerSizeValue() && value1.isTokValue() && value1.tokvalue->tokType() == Token::eString)
541
0
                            result.intvalue = calculate(parent->str(), MathLib::bigint(Token::getStrLength(value1.tokvalue)), value2.intvalue);
542
0
                        else
543
0
                            continue;
544
545
0
                        combineValueProperties(value1, value2, result);
546
547
0
                        if (match20(parent) && result.intvalue)
548
0
                            continue;
549
0
                        if (match21(parent) && !result.intvalue)
550
0
                            continue;
551
552
0
                        setTokenValue(parent, std::move(result), settings);
553
0
                    }
554
0
                }
555
0
            }
556
0
            Token* next = nullptr;
557
0
            const Library::Container::Yield yields = getContainerYield(parent, settings, next);
558
0
            if (yields == Library::Container::Yield::SIZE) {
559
0
                Value v(value);
560
0
                v.valueType = Value::ValueType::INT;
561
0
                setTokenValue(next, std::move(v), settings);
562
0
            } else if (yields == Library::Container::Yield::EMPTY) {
563
0
                Value v(value);
564
0
                v.valueType = Value::ValueType::INT;
565
0
                v.bound = Value::Bound::Point;
566
0
                if (value.isImpossible()) {
567
0
                    if (value.intvalue == 0)
568
0
                        v.setKnown();
569
0
                    else if ((value.bound == Value::Bound::Upper && value.intvalue > 0) ||
570
0
                             (value.bound == Value::Bound::Lower && value.intvalue < 0)) {
571
0
                        v.intvalue = 0;
572
0
                        v.setKnown();
573
0
                    } else
574
0
                        v.setPossible();
575
0
                } else {
576
0
                    v.intvalue = !v.intvalue;
577
0
                }
578
0
                setTokenValue(next, std::move(v), settings);
579
0
            }
580
0
            return;
581
0
        }
582
583
2.64k
        if (value.isLifetimeValue()) {
584
6
            if (!isLifetimeBorrowed(parent, settings))
585
0
                return;
586
6
            if (value.lifetimeKind == Value::LifetimeKind::Iterator && astIsIterator(parent)) {
587
0
                setTokenValue(parent,std::move(value),settings);
588
6
            } else if (astIsPointer(tok) && astIsPointer(parent) && !parent->isUnaryOp("*") &&
589
6
                       (parent->isArithmeticalOp() || parent->isCast())) {
590
2
                setTokenValue(parent,std::move(value),settings);
591
2
            }
592
6
            return;
593
6
        }
594
595
2.63k
        if (value.isUninitValue()) {
596
0
            if (match22(tok))
597
0
                setTokenValue(tok->next(), value, settings);
598
0
            if (parent->isCast()) {
599
0
                setTokenValue(parent, std::move(value), settings);
600
0
                return;
601
0
            }
602
0
            Value pvalue = value;
603
0
            if (!value.subexpressions.empty() && match22(parent)) {
604
0
                if (contains(value.subexpressions, parent->strAt(1)))
605
0
                    pvalue.subexpressions.clear();
606
0
                else
607
0
                    return;
608
0
            }
609
0
            if (parent->isUnaryOp("&")) {
610
0
                pvalue.indirect++;
611
0
                setTokenValue(parent, std::move(pvalue), settings);
612
0
            } else if (match22(parent) && parent->astOperand1() == tok && parent->astOperand2()) {
613
0
                if (parent->originalName() == MatchCompiler::makeConstString("->") && pvalue.indirect > 0)
614
0
                    pvalue.indirect--;
615
0
                setTokenValue(parent->astOperand2(), std::move(pvalue), settings);
616
0
            } else if (match22(parent->astParent()) && parent->astParent()->astOperand1() == parent) {
617
0
                if (parent->astParent()->originalName() == MatchCompiler::makeConstString("->") && pvalue.indirect > 0)
618
0
                    pvalue.indirect--;
619
0
                setTokenValue(parent->astParent()->astOperand2(), std::move(pvalue), settings);
620
0
            } else if (parent->isUnaryOp("*") && pvalue.indirect > 0) {
621
0
                pvalue.indirect--;
622
0
                setTokenValue(parent, std::move(pvalue), settings);
623
0
            }
624
0
            return;
625
0
        }
626
627
        // cast..
628
2.63k
        if (const Token *castType = getCastTypeStartToken(parent, settings)) {
629
0
            if (contains({Value::ValueType::INT, Value::ValueType::SYMBOLIC}, value.valueType) &&
630
0
                match23(parent->astOperand1()))
631
0
                return;
632
0
            const ValueType &valueType = ValueType::parseDecl(castType, settings);
633
0
            if (value.isImpossible() && value.isIntValue() && value.intvalue < 0 && astIsUnsigned(tok) &&
634
0
                valueType.sign == ValueType::SIGNED && tok->valueType() &&
635
0
                getSizeOf(*tok->valueType(), settings) >= getSizeOf(valueType, settings))
636
0
                return;
637
0
            setTokenValueCast(parent, valueType, value, settings);
638
0
        }
639
640
2.63k
        else if (parent->str() == MatchCompiler::makeConstString(":")) {
641
0
            setTokenValue(parent,std::move(value),settings);
642
0
        }
643
644
2.63k
        else if (parent->str() == MatchCompiler::makeConstString("?") && tok->str() == MatchCompiler::makeConstString(":") && tok == parent->astOperand2() && parent->astOperand1()) {
645
            // is condition always true/false?
646
0
            if (parent->astOperand1()->hasKnownValue()) {
647
0
                const Value &condvalue = parent->astOperand1()->values().front();
648
0
                const bool cond(condvalue.isTokValue() || (condvalue.isIntValue() && condvalue.intvalue != 0));
649
0
                if (cond && !tok->astOperand1()) { // true condition, no second operator
650
0
                    setTokenValue(parent, condvalue, settings);
651
0
                } else {
652
0
                    const Token *op = cond ? tok->astOperand1() : tok->astOperand2();
653
0
                    if (!op) // #7769 segmentation fault at setTokenValue()
654
0
                        return;
655
0
                    const std::list<Value> &values = op->values();
656
0
                    if (std::find(values.cbegin(), values.cend(), value) != values.cend())
657
0
                        setTokenValue(parent, std::move(value), settings);
658
0
                }
659
0
            } else if (!value.isImpossible()) {
660
                // is condition only depending on 1 variable?
661
                // cppcheck-suppress[variableScope] #8541
662
0
                nonneg int varId = 0;
663
0
                bool ret = false;
664
0
                visitAstNodes(parent->astOperand1(),
665
0
                              [&](const Token *t) {
666
0
                    if (t->varId()) {
667
0
                        if (varId > 0 || value.varId != 0)
668
0
                            ret = true;
669
0
                        varId = t->varId();
670
0
                    } else if (t->str() == MatchCompiler::makeConstString("(") && match24(t->previous()))
671
0
                        ret = true; // function call
672
0
                    return ret ? ChildrenToVisit::done : ChildrenToVisit::op1_and_op2;
673
0
                });
674
0
                if (ret)
675
0
                    return;
676
677
0
                Value v(std::move(value));
678
0
                v.conditional = true;
679
0
                v.changeKnownToPossible();
680
681
0
                setTokenValue(parent, std::move(v), settings);
682
0
            }
683
0
        }
684
685
2.63k
        else if (parent->str() == MatchCompiler::makeConstString("?") && value.isIntValue() && tok == parent->astOperand1() && value.isKnown() &&
686
2.63k
                 parent->astOperand2() && parent->astOperand2()->astOperand1() && parent->astOperand2()->astOperand2()) {
687
0
            const std::list<Value> &values = (value.intvalue == 0
688
0
                ? parent->astOperand2()->astOperand2()->values()
689
0
                : parent->astOperand2()->astOperand1()->values());
690
691
0
            for (const Value &v : values)
692
0
                setTokenValue(parent, v, settings);
693
0
        }
694
695
        // Offset of non null pointer is not null also
696
2.63k
        else if (astIsPointer(tok) && match9(parent) &&
697
2.63k
                 (parent->astOperand2() == nullptr || !astIsPointer(parent->astOperand2())) &&
698
2.63k
                 value.isIntValue() && value.isImpossible() && value.intvalue == 0) {
699
0
            setTokenValue(parent, std::move(value), settings);
700
0
        }
701
702
        // Calculations..
703
2.63k
        else if ((parent->isArithmeticalOp() || parent->isComparisonOp() || (parent->tokType() == Token::eBitOp) ||
704
2.63k
                  (parent->tokType() == Token::eLogicalOp)) &&
705
2.63k
                 parent->astOperand1() && parent->astOperand2()) {
706
707
639
            const bool noninvertible = isNonInvertibleOperation(parent);
708
709
            // Skip operators with impossible values that are not invertible
710
639
            if (noninvertible && value.isImpossible())
711
401
                return;
712
713
            // known result when a operand is 0.
714
238
            if (match25(parent) && astIsIntegral(parent, true) && value.isKnown() && value.isIntValue() &&
715
238
                value.intvalue == 0) {
716
19
                setTokenValue(parent, std::move(value), settings);
717
19
                return;
718
19
            }
719
720
            // known result when a operand is true.
721
219
            if (match26(parent) && value.isKnown() && value.isIntValue() && value.intvalue==0) {
722
0
                setTokenValue(parent, std::move(value), settings);
723
0
                return;
724
0
            }
725
726
            // known result when a operand is false.
727
219
            if (match27(parent) && value.isKnown() && value.isIntValue() && value.intvalue!=0) {
728
0
                setTokenValue(parent, std::move(value), settings);
729
0
                return;
730
0
            }
731
732
219
            for (const Value &value1 : parent->astOperand1()->values()) {
733
153
                if (!isComputableValue(parent, value1))
734
63
                    continue;
735
90
                for (const Value &value2 : parent->astOperand2()->values()) {
736
9
                    if (value1.path != value2.path && value1.path != 0 && value2.path != 0)
737
0
                        continue;
738
9
                    if (!isComputableValue(parent, value2))
739
2
                        continue;
740
7
                    if (value1.isIteratorValue() && value2.isIteratorValue())
741
0
                        continue;
742
7
                    if (!isCompatibleValues(value1, value2))
743
0
                        continue;
744
7
                    Value result(0);
745
7
                    combineValueProperties(value1, value2, result);
746
7
                    if (astIsFloat(parent, false)) {
747
0
                        if (!result.isIntValue() && !result.isFloatValue())
748
0
                            continue;
749
0
                        result.valueType = Value::ValueType::FLOAT;
750
0
                    }
751
7
                    const double floatValue1 = value1.isFloatValue() ? value1.floatValue : static_cast<double>(value1.intvalue);
752
7
                    const double floatValue2 = value2.isFloatValue() ? value2.floatValue : static_cast<double>(value2.intvalue);
753
7
                    const bool isFloat = value1.isFloatValue() || value2.isFloatValue();
754
7
                    const auto intValue1 = [&]() -> MathLib::bigint {
755
7
                        return value1.isFloatValue() ? static_cast<MathLib::bigint>(value1.floatValue) : value1.intvalue;
756
7
                    };
757
7
                    const auto intValue2 = [&]() -> MathLib::bigint {
758
7
                        return value2.isFloatValue() ? static_cast<MathLib::bigint>(value2.floatValue) : value2.intvalue;
759
7
                    };
760
7
                    if ((value1.isFloatValue() || value2.isFloatValue()) && match28(parent))
761
0
                        continue;
762
7
                    if (match29(parent)) {
763
3
                        if ((value1.isIntValue() && value2.isTokValue()) || (value1.isTokValue() && value2.isIntValue())) {
764
0
                            if (parent->str() == MatchCompiler::makeConstString("=="))
765
0
                                result.intvalue = 0;
766
0
                            else if (parent->str() == MatchCompiler::makeConstString("!="))
767
0
                                result.intvalue = 1;
768
3
                        } else if (value1.isIntValue() && value2.isIntValue()) {
769
3
                            bool error = false;
770
3
                            result.intvalue = calculate(parent->str(), intValue1(), intValue2(), &error);
771
3
                            if (error)
772
0
                                continue;
773
3
                        } else if (value1.isTokValue() && value2.isTokValue() &&
774
0
                                   (astIsContainer(parent->astOperand1()) || astIsContainer(parent->astOperand2()))) {
775
0
                            const Token* tok1 = value1.tokvalue;
776
0
                            const Token* tok2 = value2.tokvalue;
777
0
                            bool equal = false;
778
0
                            if (match30(tok1) && match30(tok2)) {
779
0
                                equal = tok1->str() == tok2->str();
780
0
                            } else if (match13(tok1) && match13(tok2)) {
781
0
                                std::vector<const Token*> args1 = getArguments(tok1);
782
0
                                std::vector<const Token*> args2 = getArguments(tok2);
783
0
                                if (args1.size() == args2.size()) {
784
0
                                    if (!std::all_of(args1.begin(), args1.end(), std::mem_fn(&Token::hasKnownIntValue)))
785
0
                                        continue;
786
0
                                    if (!std::all_of(args2.begin(), args2.end(), std::mem_fn(&Token::hasKnownIntValue)))
787
0
                                        continue;
788
0
                                    equal = std::equal(args1.begin(),
789
0
                                                       args1.end(),
790
0
                                                       args2.begin(),
791
0
                                                       [&](const Token* atok, const Token* btok) {
792
0
                                        return atok->values().front().intvalue ==
793
0
                                        btok->values().front().intvalue;
794
0
                                    });
795
0
                                } else {
796
0
                                    equal = false;
797
0
                                }
798
0
                            } else {
799
0
                                continue;
800
0
                            }
801
0
                            result.intvalue = parent->str() == MatchCompiler::makeConstString("==") ? equal : !equal;
802
0
                        } else {
803
0
                            continue;
804
0
                        }
805
3
                        setTokenValue(parent, std::move(result), settings);
806
4
                    } else if (match31(parent)) {
807
4
                        if (match19(parent)) {
808
2
                            if (!isFloat && !value1.isIntValue() && !value2.isIntValue())
809
0
                                continue;
810
2
                        } else {
811
2
                            if (value1.isTokValue() || value2.isTokValue())
812
0
                                break;
813
2
                        }
814
4
                        bool error = false;
815
4
                        if (isFloat) {
816
0
                            auto val = calculate(parent->str(), floatValue1, floatValue2, &error);
817
0
                            if (result.isFloatValue()) {
818
0
                                result.floatValue = val;
819
0
                            } else {
820
0
                                result.intvalue = static_cast<MathLib::bigint>(val);
821
0
                            }
822
4
                        } else {
823
4
                            auto val = calculate(parent->str(), intValue1(), intValue2(), &error);
824
4
                            if (result.isFloatValue()) {
825
0
                                result.floatValue = static_cast<double>(val);
826
4
                            } else {
827
4
                                result.intvalue = val;
828
4
                            }
829
4
                        }
830
4
                        if (error)
831
0
                            continue;
832
                        // If the bound comes from the second value then invert the bound when subtracting
833
4
                        if (match32(parent) && value2.bound == result.bound &&
834
4
                            value2.bound != Value::Bound::Point)
835
0
                            result.invertBound();
836
4
                        setTokenValue(parent, std::move(result), settings);
837
4
                    }
838
7
                }
839
90
            }
840
219
        }
841
842
        // !
843
1.99k
        else if (parent->str() == MatchCompiler::makeConstString("!")) {
844
0
            for (const Value &val : tok->values()) {
845
0
                if (!val.isIntValue())
846
0
                    continue;
847
0
                if (val.isImpossible() && val.intvalue != 0)
848
0
                    continue;
849
0
                Value v(val);
850
0
                if (val.isImpossible())
851
0
                    v.setKnown();
852
0
                else
853
0
                    v.intvalue = !v.intvalue;
854
0
                setTokenValue(parent, std::move(v), settings);
855
0
            }
856
0
        }
857
858
        // ~
859
1.99k
        else if (parent->str() == MatchCompiler::makeConstString("~")) {
860
20
            for (const Value &val : tok->values()) {
861
20
                if (!val.isIntValue())
862
10
                    continue;
863
10
                Value v(val);
864
10
                v.intvalue = ~v.intvalue;
865
10
                int bits = 0;
866
10
                if (tok->valueType() &&
867
10
                    tok->valueType()->sign == ValueType::Sign::UNSIGNED &&
868
10
                    tok->valueType()->pointer == 0) {
869
0
                    if (tok->valueType()->type == ValueType::Type::INT)
870
0
                        bits = settings.platform.int_bit;
871
0
                    else if (tok->valueType()->type == ValueType::Type::LONG)
872
0
                        bits = settings.platform.long_bit;
873
0
                }
874
10
                if (bits > 0 && bits < MathLib::bigint_bits)
875
0
                    v.intvalue &= (((MathLib::biguint)1)<<bits) - 1;
876
10
                setTokenValue(parent, std::move(v), settings);
877
10
            }
878
18
        }
879
880
        // unary minus
881
1.97k
        else if (parent->isUnaryOp("-")) {
882
0
            for (const Value &val : tok->values()) {
883
0
                if (!val.isIntValue() && !val.isFloatValue())
884
0
                    continue;
885
0
                Value v(val);
886
0
                if (v.isIntValue()) {
887
0
                    if (v.intvalue == LLONG_MIN)
888
                        // Value can't be inverted
889
0
                        continue;
890
0
                    v.intvalue = -v.intvalue;
891
0
                } else
892
0
                    v.floatValue = -v.floatValue;
893
0
                v.invertBound();
894
0
                setTokenValue(parent, std::move(v), settings);
895
0
            }
896
0
        }
897
898
        // increment
899
1.97k
        else if (parent->str() == MatchCompiler::makeConstString("++")) {
900
20
            for (const Value &val : tok->values()) {
901
20
                if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue())
902
0
                    continue;
903
20
                Value v(val);
904
20
                if (parent == tok->previous()) {
905
20
                    if (v.isIntValue() || v.isSymbolicValue()) {
906
20
                        const ValueType *dst = tok->valueType();
907
20
                        if (dst) {
908
20
                            const size_t sz = ValueFlow::getSizeOf(*dst, settings);
909
20
                            MathLib::bigint newvalue = ValueFlow::truncateIntValue(v.intvalue + 1, sz, dst->sign);
910
20
                            if (v.bound != ValueFlow::Value::Bound::Point) {
911
12
                                if (newvalue < v.intvalue) {
912
0
                                    v.invertBound();
913
0
                                    newvalue -= 2;
914
0
                                }
915
12
                            }
916
20
                            v.intvalue = newvalue;
917
20
                        } else {
918
0
                            v.intvalue = v.intvalue + 1;
919
0
                        }
920
20
                    }
921
0
                    else
922
0
                        v.floatValue = v.floatValue + 1.0;
923
20
                }
924
20
                setTokenValue(parent, std::move(v), settings);
925
20
            }
926
16
        }
927
928
        // decrement
929
1.96k
        else if (parent->str() == MatchCompiler::makeConstString("--")) {
930
15
            for (const Value &val : tok->values()) {
931
15
                if (!val.isIntValue() && !val.isFloatValue() && !val.isSymbolicValue())
932
0
                    continue;
933
15
                Value v(val);
934
15
                if (parent == tok->previous()) {
935
15
                    if (v.isIntValue() || v.isSymbolicValue()) {
936
15
                        const ValueType *dst = tok->valueType();
937
15
                        if (dst) {
938
15
                            const size_t sz = ValueFlow::getSizeOf(*dst, settings);
939
15
                            MathLib::bigint newvalue = ValueFlow::truncateIntValue(v.intvalue - 1, sz, dst->sign);
940
15
                            if (v.bound != ValueFlow::Value::Bound::Point) {
941
3
                                if (newvalue > v.intvalue) {
942
0
                                    v.invertBound();
943
0
                                    newvalue += 2;
944
0
                                }
945
3
                            }
946
15
                            v.intvalue = newvalue;
947
15
                        } else {
948
0
                            v.intvalue = v.intvalue - 1;
949
0
                        }
950
15
                    }
951
0
                    else
952
0
                        v.floatValue = v.floatValue - 1.0;
953
15
                }
954
15
                setTokenValue(parent, std::move(v), settings);
955
15
            }
956
14
        }
957
958
        // C++ init
959
1.94k
        else if (parent->str() == MatchCompiler::makeConstString("{") && match33(parent->previous()) &&
960
1.94k
                 match34(parent->link())) {
961
0
            const Token* lhs = parent->previous()->astOperand1();
962
0
            if (lhs && lhs->valueType()) {
963
0
                if (lhs->valueType()->isIntegral() || lhs->valueType()->isFloat() || (lhs->valueType()->pointer > 0 && value.isIntValue())) {
964
0
                    setTokenValue(parent, std::move(value), settings);
965
0
                }
966
0
            }
967
0
        }
968
969
1.94k
        else if (match35(parent) && parent->astOperand2() == tok) {
970
0
            setTokenValue(parent, std::move(value), settings);
971
0
        }
972
        // Calling std::size or std::empty on an array
973
1.94k
        else if (value.isTokValue() && match13(value.tokvalue) && tok->variable() &&
974
1.94k
                 tok->variable()->isArray() && match2(parent->previous()) && astIsRHS(tok)) {
975
0
            std::vector<const Token*> args = getArguments(value.tokvalue);
976
0
            if (const Library::Function* f = settings.library.getFunction(parent->previous())) {
977
0
                if (f->containerYield == Library::Container::Yield::SIZE) {
978
0
                    Value v(std::move(value));
979
0
                    v.valueType = Value::ValueType::INT;
980
0
                    v.intvalue = args.size();
981
0
                    setTokenValue(parent, std::move(v), settings);
982
0
                } else if (f->containerYield == Library::Container::Yield::EMPTY) {
983
0
                    Value v(std::move(value));
984
0
                    v.intvalue = args.empty();
985
0
                    v.valueType = Value::ValueType::INT;
986
0
                    setTokenValue(parent, std::move(v), settings);
987
0
                }
988
0
            }
989
0
        }
990
2.63k
    }
991
}