Coverage Report

Created: 2023-09-25 06:15

/src/cppcheck/lib/tokenlist.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
#include "tokenlist.h"
21
22
#include "astutils.h"
23
#include "errorlogger.h"
24
#include "errortypes.h"
25
#include "keywords.h"
26
#include "library.h"
27
#include "mathlib.h"
28
#include "path.h"
29
#include "platform.h"
30
#include "settings.h"
31
#include "standards.h"
32
#include "token.h"
33
34
#include <algorithm>
35
#include <cctype>
36
#include <exception>
37
#include <functional>
38
#include <utility>
39
#include <set>
40
#include <stack>
41
#include <unordered_set>
42
43
#include <simplecpp.h>
44
45
// How many compileExpression recursions are allowed?
46
// For practical code this could be endless. But in some special torture test
47
// there needs to be a limit.
48
static const int AST_MAX_DEPTH = 150;
49
50
51
TokenList::TokenList(const Settings* settings) :
52
    mSettings(settings)
53
1.36k
{
54
1.36k
    mTokensFrontBack.list = this;
55
1.36k
}
56
57
TokenList::~TokenList()
58
1.36k
{
59
1.36k
    deallocateTokens();
60
1.36k
}
61
62
//---------------------------------------------------------------------------
63
64
const std::string& TokenList::getSourceFilePath() const
65
75.5k
{
66
75.5k
    if (getFiles().empty()) {
67
0
        return emptyString;
68
0
    }
69
75.5k
    return getFiles()[0];
70
75.5k
}
71
72
//---------------------------------------------------------------------------
73
74
// Deallocate lists..
75
void TokenList::deallocateTokens()
76
1.36k
{
77
1.36k
    deleteTokens(mTokensFrontBack.front);
78
1.36k
    mTokensFrontBack.front = nullptr;
79
1.36k
    mTokensFrontBack.back = nullptr;
80
1.36k
    mFiles.clear();
81
1.36k
}
82
83
void TokenList::determineCppC()
84
1.36k
{
85
1.36k
    if (!mSettings) {
86
0
        mIsC = Path::isC(getSourceFilePath());
87
0
        mIsCpp = Path::isCPP(getSourceFilePath());
88
1.36k
    } else {
89
1.36k
        mIsC = mSettings->enforcedLang == Settings::Language::C || (mSettings->enforcedLang == Settings::Language::None && Path::isC(getSourceFilePath()));
90
1.36k
        mIsCpp = mSettings->enforcedLang == Settings::Language::CPP || (mSettings->enforcedLang == Settings::Language::None && Path::isCPP(getSourceFilePath()));
91
1.36k
    }
92
1.36k
}
93
94
int TokenList::appendFileIfNew(std::string fileName)
95
0
{
96
    // Has this file been tokenized already?
97
0
    for (int i = 0; i < mFiles.size(); ++i)
98
0
        if (Path::sameFileName(mFiles[i], fileName))
99
0
            return i;
100
101
    // The "mFiles" vector remembers what files have been tokenized..
102
0
    mFiles.push_back(std::move(fileName));
103
104
    // Update mIsC and mIsCpp properties
105
0
    if (mFiles.size() == 1) { // Update only useful if first file added to _files
106
0
        determineCppC();
107
0
    }
108
0
    return mFiles.size() - 1;
109
0
}
110
111
void TokenList::clangSetOrigFiles()
112
0
{
113
0
    mOrigFiles = mFiles;
114
0
}
115
116
void TokenList::deleteTokens(Token *tok)
117
1.36k
{
118
93.6k
    while (tok) {
119
92.3k
        Token *next = tok->next();
120
92.3k
        delete tok;
121
92.3k
        tok = next;
122
92.3k
    }
123
1.36k
}
124
125
//---------------------------------------------------------------------------
126
// add a token.
127
//---------------------------------------------------------------------------
128
129
void TokenList::addtoken(const std::string& str, const nonneg int lineno, const nonneg int column, const nonneg int fileno, bool split)
130
0
{
131
0
    if (str.empty())
132
0
        return;
133
134
    // If token contains # characters, split it up
135
0
    if (split) {
136
0
        size_t begin = 0;
137
0
        size_t end = 0;
138
0
        while ((end = str.find("##", begin)) != std::string::npos) {
139
0
            addtoken(str.substr(begin, end - begin), lineno, fileno, false);
140
0
            addtoken("##", lineno, column, fileno, false);
141
0
            begin = end+2;
142
0
        }
143
0
        if (begin != 0) {
144
0
            addtoken(str.substr(begin), lineno, column, fileno, false);
145
0
            return;
146
0
        }
147
0
    }
148
149
0
    if (mTokensFrontBack.back) {
150
0
        mTokensFrontBack.back->insertToken(str);
151
0
    } else {
152
0
        mTokensFrontBack.front = new Token(&mTokensFrontBack);
153
0
        mTokensFrontBack.back = mTokensFrontBack.front;
154
0
        mTokensFrontBack.back->str(str);
155
0
    }
156
157
0
    mTokensFrontBack.back->linenr(lineno);
158
0
    mTokensFrontBack.back->column(column);
159
0
    mTokensFrontBack.back->fileIndex(fileno);
160
0
}
161
162
void TokenList::addtoken(const std::string& str, const Token *locationTok)
163
0
{
164
0
    if (str.empty())
165
0
        return;
166
167
0
    if (mTokensFrontBack.back) {
168
0
        mTokensFrontBack.back->insertToken(str);
169
0
    } else {
170
0
        mTokensFrontBack.front = new Token(&mTokensFrontBack);
171
0
        mTokensFrontBack.back = mTokensFrontBack.front;
172
0
        mTokensFrontBack.back->str(str);
173
0
    }
174
175
0
    mTokensFrontBack.back->linenr(locationTok->linenr());
176
0
    mTokensFrontBack.back->column(locationTok->column());
177
0
    mTokensFrontBack.back->fileIndex(locationTok->fileIndex());
178
0
}
179
180
void TokenList::addtoken(const Token * tok, const nonneg int lineno, const nonneg int column, const nonneg int fileno)
181
0
{
182
0
    if (tok == nullptr)
183
0
        return;
184
185
0
    if (mTokensFrontBack.back) {
186
0
        mTokensFrontBack.back->insertToken(tok->str(), tok->originalName());
187
0
    } else {
188
0
        mTokensFrontBack.front = new Token(&mTokensFrontBack);
189
0
        mTokensFrontBack.back = mTokensFrontBack.front;
190
0
        mTokensFrontBack.back->str(tok->str());
191
0
        if (!tok->originalName().empty())
192
0
            mTokensFrontBack.back->originalName(tok->originalName());
193
0
    }
194
195
0
    mTokensFrontBack.back->linenr(lineno);
196
0
    mTokensFrontBack.back->column(column);
197
0
    mTokensFrontBack.back->fileIndex(fileno);
198
0
    mTokensFrontBack.back->flags(tok->flags());
199
0
}
200
201
void TokenList::addtoken(const Token *tok, const Token *locationTok)
202
0
{
203
0
    if (tok == nullptr || locationTok == nullptr)
204
0
        return;
205
206
0
    if (mTokensFrontBack.back) {
207
0
        mTokensFrontBack.back->insertToken(tok->str(), tok->originalName());
208
0
    } else {
209
0
        mTokensFrontBack.front = new Token(&mTokensFrontBack);
210
0
        mTokensFrontBack.back = mTokensFrontBack.front;
211
0
        mTokensFrontBack.back->str(tok->str());
212
0
        if (!tok->originalName().empty())
213
0
            mTokensFrontBack.back->originalName(tok->originalName());
214
0
    }
215
216
0
    mTokensFrontBack.back->flags(tok->flags());
217
0
    mTokensFrontBack.back->linenr(locationTok->linenr());
218
0
    mTokensFrontBack.back->column(locationTok->column());
219
0
    mTokensFrontBack.back->fileIndex(locationTok->fileIndex());
220
0
}
221
222
void TokenList::addtoken(const Token *tok)
223
0
{
224
0
    if (tok == nullptr)
225
0
        return;
226
227
0
    if (mTokensFrontBack.back) {
228
0
        mTokensFrontBack.back->insertToken(tok->str(), tok->originalName());
229
0
    } else {
230
0
        mTokensFrontBack.front = new Token(&mTokensFrontBack);
231
0
        mTokensFrontBack.back = mTokensFrontBack.front;
232
0
        mTokensFrontBack.back->str(tok->str());
233
0
        if (!tok->originalName().empty())
234
0
            mTokensFrontBack.back->originalName(tok->originalName());
235
0
    }
236
237
0
    mTokensFrontBack.back->flags(tok->flags());
238
0
    mTokensFrontBack.back->linenr(tok->linenr());
239
0
    mTokensFrontBack.back->column(tok->column());
240
0
    mTokensFrontBack.back->fileIndex(tok->fileIndex());
241
0
}
242
243
244
//---------------------------------------------------------------------------
245
// copyTokens - Copy and insert tokens
246
//---------------------------------------------------------------------------
247
248
Token *TokenList::copyTokens(Token *dest, const Token *first, const Token *last, bool one_line)
249
0
{
250
0
    std::stack<Token *> links;
251
0
    Token *tok2 = dest;
252
0
    int linenr = dest->linenr();
253
0
    const int commonFileIndex = dest->fileIndex();
254
0
    for (const Token *tok = first; tok != last->next(); tok = tok->next()) {
255
0
        tok2->insertToken(tok->str());
256
0
        tok2 = tok2->next();
257
0
        tok2->fileIndex(commonFileIndex);
258
0
        tok2->linenr(linenr);
259
0
        tok2->tokType(tok->tokType());
260
0
        tok2->flags(tok->flags());
261
0
        tok2->varId(tok->varId());
262
0
        tok2->setTokenDebug(tok->getTokenDebug());
263
264
        // Check for links and fix them up
265
0
        if (Token::Match(tok2, "(|[|{"))
266
0
            links.push(tok2);
267
0
        else if (Token::Match(tok2, ")|]|}")) {
268
0
            if (links.empty())
269
0
                return tok2;
270
271
0
            Token * link = links.top();
272
273
0
            tok2->link(link);
274
0
            link->link(tok2);
275
276
0
            links.pop();
277
0
        }
278
0
        if (!one_line && tok->next())
279
0
            linenr += tok->next()->linenr() - tok->linenr();
280
0
    }
281
0
    return tok2;
282
0
}
283
284
//---------------------------------------------------------------------------
285
// InsertTokens - Copy and insert tokens
286
//---------------------------------------------------------------------------
287
288
void TokenList::insertTokens(Token *dest, const Token *src, nonneg int n)
289
6.81k
{
290
6.81k
    std::stack<Token *> link;
291
292
20.4k
    while (n > 0) {
293
13.6k
        dest->insertToken(src->str(), src->originalName());
294
13.6k
        dest = dest->next();
295
296
        // Set links
297
13.6k
        if (Token::Match(dest, "(|[|{"))
298
0
            link.push(dest);
299
13.6k
        else if (!link.empty() && Token::Match(dest, ")|]|}")) {
300
0
            Token::createMutualLinks(dest, link.top());
301
0
            link.pop();
302
0
        }
303
304
13.6k
        dest->fileIndex(src->fileIndex());
305
13.6k
        dest->linenr(src->linenr());
306
13.6k
        dest->column(src->column());
307
13.6k
        dest->varId(src->varId());
308
13.6k
        dest->tokType(src->tokType());
309
13.6k
        dest->flags(src->flags());
310
13.6k
        src  = src->next();
311
13.6k
        --n;
312
13.6k
    }
313
6.81k
}
314
315
//---------------------------------------------------------------------------
316
// Tokenize - tokenizes a given file.
317
//---------------------------------------------------------------------------
318
319
bool TokenList::createTokens(std::istream &code, const std::string& file0)
320
0
{
321
0
    appendFileIfNew(file0);
322
323
0
    simplecpp::OutputList outputList;
324
0
    simplecpp::TokenList tokens(code, mFiles, file0, &outputList);
325
326
0
    createTokens(std::move(tokens));
327
328
0
    return outputList.empty();
329
0
}
330
331
//---------------------------------------------------------------------------
332
333
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
334
void TokenList::createTokens(simplecpp::TokenList&& tokenList)
335
1.36k
{
336
1.36k
    if (tokenList.cfront()) {
337
        // this is a copy
338
        // TODO: the same as TokenList.files - move that instead
339
        // TODO: this points to mFiles when called from createTokens(std::istream &, const std::string&)
340
1.36k
        mOrigFiles = mFiles = tokenList.cfront()->location.files;
341
1.36k
    }
342
0
    else
343
0
        mFiles.clear();
344
345
1.36k
    determineCppC();
346
347
81.8k
    for (const simplecpp::Token *tok = tokenList.cfront(); tok;) {
348
349
        // TODO: move from TokenList
350
80.4k
        std::string str = tok->str();
351
352
        // Float literal
353
80.4k
        if (str.size() > 1 && str[0] == '.' && std::isdigit(str[1]))
354
0
            str = '0' + str;
355
356
80.4k
        if (mTokensFrontBack.back) {
357
79.1k
            mTokensFrontBack.back->insertToken(str);
358
79.1k
        } else {
359
1.36k
            mTokensFrontBack.front = new Token(&mTokensFrontBack);
360
1.36k
            mTokensFrontBack.back = mTokensFrontBack.front;
361
1.36k
            mTokensFrontBack.back->str(str);
362
1.36k
        }
363
364
80.4k
        mTokensFrontBack.back->fileIndex(tok->location.fileIndex);
365
80.4k
        mTokensFrontBack.back->linenr(tok->location.line);
366
80.4k
        mTokensFrontBack.back->column(tok->location.col);
367
80.4k
        mTokensFrontBack.back->isExpandedMacro(!tok->macro.empty());
368
369
80.4k
        tok = tok->next;
370
80.4k
        if (tok)
371
79.1k
            tokenList.deleteToken(tok->previous);
372
80.4k
    }
373
374
1.36k
    if (mSettings && mSettings->relativePaths) {
375
0
        for (std::string & mFile : mFiles)
376
0
            mFile = Path::getRelativePath(mFile, mSettings->basePaths);
377
0
    }
378
379
1.36k
    Token::assignProgressValues(mTokensFrontBack.front);
380
1.36k
}
381
382
//---------------------------------------------------------------------------
383
384
std::size_t TokenList::calculateHash() const
385
1.36k
{
386
1.36k
    std::string hashData;
387
93.5k
    for (const Token* tok = front(); tok; tok = tok->next()) {
388
92.2k
        hashData += std::to_string(tok->flags());
389
92.2k
        hashData += std::to_string(tok->varId());
390
92.2k
        hashData += std::to_string(tok->tokType());
391
92.2k
        hashData += tok->str();
392
92.2k
        hashData += tok->originalName();
393
92.2k
    }
394
1.36k
    return (std::hash<std::string>{})(hashData);
395
1.36k
}
396
397
398
//---------------------------------------------------------------------------
399
400
struct AST_state {
401
    std::stack<Token*> op;
402
    int depth{};
403
    int inArrayAssignment{};
404
    bool cpp;
405
    int assign{};
406
    bool inCase{}; // true from case to :
407
    bool stopAtColon{}; // help to properly parse ternary operators
408
    const Token* functionCallEndPar{};
409
18.4k
    explicit AST_state(bool cpp) : cpp(cpp) {}
410
};
411
412
static Token* skipDecl(Token* tok, std::vector<Token*>* inner = nullptr)
413
23.1k
{
414
23.1k
    auto isDecltypeFuncParam = [](const Token* tok) -> bool {
415
0
        if (!Token::simpleMatch(tok, ")"))
416
0
            return false;
417
0
        tok = tok->next();
418
0
        while (Token::Match(tok, "*|&|&&|const"))
419
0
            tok = tok->next();
420
0
        if (Token::simpleMatch(tok, "("))
421
0
            tok = tok->link()->next();
422
0
        return Token::Match(tok, "%name%| ,|)");
423
0
    };
424
425
23.1k
    if (!Token::Match(tok->previous(), "( %name%"))
426
21.9k
        return tok;
427
1.15k
    Token *vartok = tok;
428
2.15k
    while (Token::Match(vartok, "%name%|*|&|::|<")) {
429
1.36k
        if (vartok->str() == "<") {
430
112
            if (vartok->link())
431
2
                vartok = vartok->link();
432
110
            else
433
110
                return tok;
434
1.25k
        } else if (Token::Match(vartok, "%var% [:=(]")) {
435
255
            return vartok;
436
997
        } else if (Token::Match(vartok, "decltype|typeof (") && !isDecltypeFuncParam(tok->linkAt(1))) {
437
0
            if (inner)
438
0
                inner->push_back(vartok->tokAt(2));
439
0
            return vartok->linkAt(1)->next();
440
0
        }
441
999
        vartok = vartok->next();
442
999
    }
443
794
    return tok;
444
1.15k
}
445
446
static bool iscast(const Token *tok, bool cpp)
447
39.6k
{
448
39.6k
    if (!Token::Match(tok, "( ::| %name%"))
449
38.4k
        return false;
450
451
1.26k
    if (Token::simpleMatch(tok->link(), ") ( )"))
452
0
        return false;
453
454
1.26k
    if (tok->previous() && tok->previous()->isName() && tok->previous()->str() != "return" &&
455
1.26k
        (!cpp || !Token::Match(tok->previous(), "delete|throw")))
456
651
        return false;
457
458
616
    if (Token::simpleMatch(tok->previous(), ">") && tok->previous()->link())
459
0
        return false;
460
461
616
    if (Token::Match(tok, "( (| typeof (") && Token::Match(tok->link(), ") %num%"))
462
0
        return true;
463
464
616
    if (Token::Match(tok->link(), ") }|)|]|;"))
465
183
        return false;
466
467
433
    if (Token::Match(tok->link(), ") %cop%") && !Token::Match(tok->link(), ") [&*+-~!]"))
468
230
        return false;
469
470
203
    if (Token::Match(tok->previous(), "= ( %name% ) {") && tok->next()->varId() == 0)
471
0
        return true;
472
473
203
    bool type = false;
474
255
    for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
475
255
        if (tok2->varId() != 0)
476
155
            return false;
477
100
        if (cpp && !type && tok2->str() == "new")
478
0
            return false;
479
480
100
        while (tok2->link() && Token::Match(tok2, "(|[|<"))
481
0
            tok2 = tok2->link()->next();
482
483
100
        if (tok2->str() == ")") {
484
40
            if (Token::simpleMatch(tok2, ") (") && Token::simpleMatch(tok2->linkAt(1), ") ."))
485
0
                return true;
486
40
            if (Token::simpleMatch(tok2, ") {") && !type) {
487
0
                const Token *tok3 = tok2->linkAt(1);
488
0
                while (tok3 != tok2 && Token::Match(tok3, "[{}]"))
489
0
                    tok3 = tok3->previous();
490
0
                return tok3->str() != ";";
491
0
            }
492
40
            const bool res = type || tok2->strAt(-1) == "*" || Token::simpleMatch(tok2, ") ~") ||
493
40
                             (Token::Match(tok2, ") %any%") &&
494
40
                              (!tok2->next()->isOp() || Token::Match(tok2->next(), "!|~|++|--")) &&
495
40
                              !Token::Match(tok2->next(), "[[]);,?:.]"));
496
40
            return res;
497
40
        }
498
499
60
        if (Token::Match(tok2, "&|&& )"))
500
0
            return true;
501
502
60
        if (!Token::Match(tok2, "%name%|*|::"))
503
8
            return false;
504
505
52
        if (tok2->isStandardType() && (tok2->next()->str() != "(" || Token::Match(tok2->next(), "( * *| )")))
506
0
            type = true;
507
52
    }
508
509
0
    return false;
510
203
}
511
512
// int(1), int*(2), ..
513
static Token * findCppTypeInitPar(Token *tok)
514
23.1k
{
515
23.1k
    if (!tok || !Token::Match(tok->previous(), "[,()] %name%"))
516
21.9k
        return nullptr;
517
1.15k
    bool istype = false;
518
2.32k
    while (Token::Match(tok, "%name%|::|<")) {
519
1.26k
        if (tok->str() == "<") {
520
108
            tok = tok->link();
521
108
            if (!tok)
522
106
                return nullptr;
523
108
        }
524
1.16k
        istype |= tok->isStandardType();
525
1.16k
        tok = tok->next();
526
1.16k
    }
527
1.05k
    if (!istype)
528
1.05k
        return nullptr;
529
0
    if (!Token::Match(tok, "[*&]"))
530
0
        return nullptr;
531
0
    while (Token::Match(tok, "[*&]"))
532
0
        tok = tok->next();
533
0
    return (tok && tok->str() == "(") ? tok : nullptr;
534
0
}
535
536
// X{} X<Y>{} etc
537
static bool iscpp11init_impl(const Token * const tok);
538
static bool iscpp11init(const Token * const tok)
539
28.5k
{
540
28.5k
    if (tok->isCpp11init() == TokenImpl::Cpp11init::UNKNOWN)
541
26.6k
        tok->setCpp11init(iscpp11init_impl(tok));
542
28.5k
    return tok->isCpp11init() == TokenImpl::Cpp11init::CPP11INIT;
543
28.5k
}
544
545
static bool iscpp11init_impl(const Token * const tok)
546
26.6k
{
547
26.6k
    if (Token::simpleMatch(tok, "{") && Token::simpleMatch(tok->link()->previous(), "; }"))
548
2.10k
        return false;
549
24.5k
    const Token *nameToken = tok;
550
26.0k
    while (nameToken && nameToken->str() == "{") {
551
1.47k
        if (nameToken->isCpp11init() != TokenImpl::Cpp11init::UNKNOWN)
552
0
            return nameToken->isCpp11init() == TokenImpl::Cpp11init::CPP11INIT;
553
1.47k
        nameToken = nameToken->previous();
554
1.47k
        if (nameToken && nameToken->str() == "," && Token::simpleMatch(nameToken->previous(), "} ,"))
555
0
            nameToken = nameToken->linkAt(-1);
556
1.47k
    }
557
24.5k
    if (!nameToken)
558
0
        return false;
559
24.5k
    if (nameToken->str() == ")" && Token::simpleMatch(nameToken->link()->previous(), "decltype (") &&
560
24.5k
        !Token::simpleMatch(nameToken->link()->tokAt(-2), "."))
561
0
        nameToken = nameToken->link()->previous();
562
24.5k
    if (Token::simpleMatch(nameToken, ", {"))
563
0
        return true;
564
24.5k
    if (nameToken->str() == ">" && nameToken->link())
565
0
        nameToken = nameToken->link()->previous();
566
24.5k
    if (Token::Match(nameToken, "]|*")) {
567
0
        const Token* newTok = nameToken->link() ? nameToken->link()->previous() : nameToken->previous();
568
0
        while (Token::Match(newTok, "%type%|::|*") && !newTok->isKeyword())
569
0
            newTok = newTok->previous();
570
0
        if (Token::simpleMatch(newTok, "new"))
571
0
            return true;
572
0
    }
573
574
24.5k
    auto isCaseStmt = [](const Token* colonTok) {
575
437
        if (!Token::Match(colonTok->tokAt(-1), "%name%|%num%|%char% :"))
576
437
            return false;
577
0
        const Token* caseTok = colonTok->tokAt(-2);
578
0
        while (caseTok && Token::Match(caseTok->tokAt(-1), "::|%name%"))
579
0
            caseTok = caseTok->tokAt(-1);
580
0
        return Token::simpleMatch(caseTok, "case");
581
437
    };
582
583
24.5k
    const Token *endtok = nullptr;
584
24.5k
    if (Token::Match(nameToken, "%name%|return|: {") && !isCaseStmt(nameToken) &&
585
24.5k
        (!Token::simpleMatch(nameToken->tokAt(2), "[") || findLambdaEndScope(nameToken->tokAt(2))))
586
437
        endtok = nameToken->linkAt(1);
587
24.1k
    else if (Token::Match(nameToken,"%name% <") && Token::simpleMatch(nameToken->linkAt(1),"> {"))
588
0
        endtok = nameToken->linkAt(1)->linkAt(1);
589
24.1k
    else if (Token::Match(nameToken->previous(), "%name%|> ( {"))
590
0
        endtok = nameToken->linkAt(1);
591
24.1k
    else if (Token::simpleMatch(nameToken, "decltype") && nameToken->linkAt(1))
592
0
        endtok = nameToken->linkAt(1)->linkAt(1);
593
24.1k
    else
594
24.1k
        return false;
595
437
    if (Token::Match(nameToken, "else|try|do|const|constexpr|override|volatile|&|&&"))
596
437
        return false;
597
0
    if (Token::simpleMatch(nameToken->previous(), ". void {") && nameToken->previous()->originalName() == "->")
598
0
        return false; // trailing return type. The only function body that can contain no semicolon is a void function.
599
0
    if (Token::simpleMatch(nameToken->previous(), "namespace") || Token::simpleMatch(nameToken, "namespace") /*anonymous namespace*/)
600
0
        return false;
601
0
    if (precedes(nameToken->next(), endtok) && !Token::Match(nameToken, "return|:")) {
602
        // If there is semicolon between {..} this is not a initlist
603
0
        for (const Token *tok2 = nameToken->next(); tok2 != endtok; tok2 = tok2->next()) {
604
0
            if (tok2->str() == ";")
605
0
                return false;
606
0
            const Token * lambdaEnd = findLambdaEndScope(tok2);
607
0
            if (lambdaEnd)
608
0
                tok2 = lambdaEnd;
609
0
        }
610
0
    }
611
    // There is no initialisation for example here: 'class Fred {};'
612
0
    if (!Token::simpleMatch(endtok, "} ;"))
613
0
        return true;
614
0
    const Token *prev = nameToken;
615
0
    while (Token::Match(prev, "%name%|::|:|<|>|(|)|,|%num%|%cop%|...")) {
616
0
        if (Token::Match(prev, "class|struct|union|enum"))
617
0
            return false;
618
619
0
        prev = prev->previous();
620
0
    }
621
0
    return true;
622
0
}
623
624
static bool isQualifier(const Token* tok)
625
508
{
626
1.01k
    while (Token::Match(tok, "&|&&|*"))
627
508
        tok = tok->next();
628
508
    return Token::Match(tok, "{|;");
629
508
}
630
631
static void compileUnaryOp(Token *&tok, AST_state& state, void (*f)(Token *&tok, AST_state& state))
632
4.13k
{
633
4.13k
    Token *unaryop = tok;
634
4.13k
    if (f) {
635
4.13k
        tok = tok->next();
636
4.13k
        state.depth++;
637
4.13k
        if (state.depth > AST_MAX_DEPTH)
638
0
            throw InternalError(tok, "maximum AST depth exceeded", InternalError::AST);
639
4.13k
        if (tok)
640
4.13k
            f(tok, state);
641
4.13k
        state.depth--;
642
4.13k
    }
643
644
4.13k
    if (!state.op.empty()) {
645
4.13k
        unaryop->astOperand1(state.op.top());
646
4.13k
        state.op.pop();
647
4.13k
    }
648
4.13k
    state.op.push(unaryop);
649
4.13k
}
650
651
static void compileBinOp(Token *&tok, AST_state& state, void (*f)(Token *&tok, AST_state& state))
652
14.2k
{
653
14.2k
    Token *binop = tok;
654
14.2k
    if (f) {
655
12.8k
        tok = tok->next();
656
12.8k
        if (Token::Match(binop, "::|. ~"))
657
0
            tok = tok->next();
658
12.8k
        state.depth++;
659
12.8k
        if (tok && state.depth <= AST_MAX_DEPTH)
660
12.8k
            f(tok, state);
661
12.8k
        if (state.depth > AST_MAX_DEPTH)
662
0
            throw InternalError(tok, "maximum AST depth exceeded", InternalError::AST);
663
12.8k
        state.depth--;
664
12.8k
    }
665
666
    // TODO: Should we check if op is empty.
667
    // * Is it better to add assertion that it isn't?
668
    // * Write debug warning if it's empty?
669
14.2k
    if (!state.op.empty()) {
670
14.2k
        binop->astOperand2(state.op.top());
671
14.2k
        state.op.pop();
672
14.2k
    }
673
14.2k
    if (!state.op.empty()) {
674
14.2k
        binop->astOperand1(state.op.top());
675
14.2k
        state.op.pop();
676
14.2k
    }
677
14.2k
    state.op.push(binop);
678
14.2k
}
679
680
static void compileExpression(Token *&tok, AST_state& state);
681
682
static void compileTerm(Token *&tok, AST_state& state)
683
37.5k
{
684
37.5k
    if (!tok)
685
0
        return;
686
37.5k
    if (Token::Match(tok, "L %str%|%char%"))
687
0
        tok = tok->next();
688
37.5k
    if (state.inArrayAssignment && Token::Match(tok->previous(), "[{,] . %name%")) { // Jump over . in C style struct initialization
689
0
        state.op.push(tok);
690
0
        tok->astOperand1(tok->next());
691
0
        tok = tok->tokAt(2);
692
0
    }
693
37.5k
    if (state.inArrayAssignment && Token::Match(tok->previous(), "[{,] [ %num%|%name% ]")) {
694
0
        state.op.push(tok);
695
0
        tok->astOperand1(tok->next());
696
0
        tok = tok->tokAt(3);
697
0
    }
698
37.5k
    if (tok->isLiteral()) {
699
9.58k
        state.op.push(tok);
700
9.58k
        do {
701
9.58k
            tok = tok->next();
702
9.58k
        } while (Token::Match(tok, "%name%|%str%"));
703
27.9k
    } else if (tok->isName()) {
704
25.0k
        if (Token::Match(tok, "return|case") || (state.cpp && tok->str() == "throw")) {
705
1.91k
            if (tok->str() == "case")
706
0
                state.inCase = true;
707
1.91k
            const bool tokIsReturn = tok->str() == "return";
708
1.91k
            const bool stopAtColon = state.stopAtColon;
709
1.91k
            state.stopAtColon=true;
710
1.91k
            compileUnaryOp(tok, state, compileExpression);
711
1.91k
            state.stopAtColon=stopAtColon;
712
1.91k
            if (tokIsReturn)
713
1.91k
                state.op.pop();
714
1.91k
            if (state.inCase && Token::simpleMatch(tok, ": ;")) {
715
0
                state.inCase = false;
716
0
                tok = tok->next();
717
0
            }
718
23.1k
        } else if (Token::Match(tok, "sizeof !!(")) {
719
0
            compileUnaryOp(tok, state, compileExpression);
720
0
            state.op.pop();
721
23.1k
        } else if (state.cpp && findCppTypeInitPar(tok)) {  // int(0), int*(123), ..
722
0
            tok = findCppTypeInitPar(tok);
723
0
            state.op.push(tok);
724
0
            tok = tok->tokAt(2);
725
23.1k
        } else if (state.cpp && iscpp11init(tok)) { // X{} X<Y>{} etc
726
0
            state.op.push(tok);
727
0
            tok = tok->next();
728
0
            if (tok->str() == "<")
729
0
                tok = tok->link()->next();
730
731
0
            if (Token::Match(tok, "{ . %name% =|{")) {
732
0
                const Token* end = tok->link();
733
0
                const int inArrayAssignment = state.inArrayAssignment;
734
0
                state.inArrayAssignment = 1;
735
0
                compileBinOp(tok, state, compileExpression);
736
0
                state.inArrayAssignment = inArrayAssignment;
737
0
                if (tok == end)
738
0
                    tok = tok->next();
739
0
                else
740
0
                    throw InternalError(tok, "Syntax error. Unexpected tokens in designated initializer.", InternalError::AST);
741
0
            }
742
23.1k
        } else if (!state.cpp || !Token::Match(tok, "new|delete %name%|*|&|::|(|[")) {
743
23.1k
            std::vector<Token*> inner;
744
23.1k
            tok = skipDecl(tok, &inner);
745
23.1k
            for (Token* tok3 : inner) {
746
0
                AST_state state1(state.cpp);
747
0
                compileExpression(tok3, state1);
748
0
            }
749
23.1k
            bool repeat = true;
750
47.5k
            while (repeat) {
751
24.4k
                repeat = false;
752
24.4k
                if (Token::Match(tok->next(), "%name%")) {
753
1.36k
                    tok = tok->next();
754
1.36k
                    repeat = true;
755
1.36k
                }
756
24.4k
                if (Token::simpleMatch(tok->next(), "<") && Token::Match(tok->linkAt(1), "> %name%")) {
757
3
                    tok = tok->next()->link()->next();
758
3
                    repeat = true;
759
3
                }
760
24.4k
            }
761
23.1k
            state.op.push(tok);
762
23.1k
            if (Token::Match(tok, "%name% <") && tok->linkAt(1))
763
1
                tok = tok->linkAt(1);
764
23.0k
            else if (Token::Match(tok, "%name% ...") || (state.op.size() == 1 && state.depth == 0 && Token::Match(tok->tokAt(-3), "!!& ) ( %name% ) =")))
765
0
                tok = tok->next();
766
23.1k
            tok = tok->next();
767
23.1k
            if (Token::Match(tok, "%str%")) {
768
0
                while (Token::Match(tok, "%name%|%str%"))
769
0
                    tok = tok->next();
770
0
            }
771
23.1k
            if (Token::Match(tok, "%name% %assign%"))
772
0
                tok = tok->next();
773
23.1k
        }
774
25.0k
    } else if (tok->str() == "{") {
775
0
        const Token *prev = tok->previous();
776
0
        if (Token::simpleMatch(prev, ") {") && iscast(prev->link(), state.cpp))
777
0
            prev = prev->link()->previous();
778
0
        if (Token::simpleMatch(tok->link(),"} [")) {
779
0
            tok = tok->next();
780
0
        } else if ((state.cpp && iscpp11init(tok)) || Token::simpleMatch(tok->previous(), "] {")) {
781
0
            Token *const end = tok->link();
782
0
            if (state.op.empty() || Token::Match(tok->previous(), "[{,]") || Token::Match(tok->tokAt(-2), "%name% (")) {
783
0
                if (Token::Match(tok, "{ . %name% =|{")) {
784
0
                    const int inArrayAssignment = state.inArrayAssignment;
785
0
                    state.inArrayAssignment = 1;
786
0
                    compileBinOp(tok, state, compileExpression);
787
0
                    state.inArrayAssignment = inArrayAssignment;
788
0
                } else if (Token::simpleMatch(tok, "{ }")) {
789
0
                    state.op.push(tok);
790
0
                    tok = tok->next();
791
0
                } else {
792
0
                    compileUnaryOp(tok, state, compileExpression);
793
0
                    if (precedes(tok,end)) // typically for something like `MACRO(x, { if (c) { ... } })`, where end is the last curly, and tok is the open curly for the if
794
0
                        tok = end;
795
0
                }
796
0
            } else
797
0
                compileBinOp(tok, state, compileExpression);
798
0
            if (tok != end)
799
0
                throw InternalError(tok, "Syntax error. Unexpected tokens in initializer.", InternalError::AST);
800
0
            if (tok->next())
801
0
                tok = tok->next();
802
0
        } else if (state.cpp && Token::Match(tok->tokAt(-2), "%name% ( {") && !Token::findsimplematch(tok, ";", tok->link())) {
803
0
            if (Token::simpleMatch(tok, "{ }"))
804
0
                tok = tok->tokAt(2);
805
0
            else {
806
0
                Token *tok1 = tok;
807
0
                state.inArrayAssignment++;
808
0
                compileUnaryOp(tok, state, compileExpression);
809
0
                state.inArrayAssignment--;
810
0
                tok = tok1->link()->next();
811
0
            }
812
0
        } else if (!state.inArrayAssignment && !Token::simpleMatch(prev, "=")) {
813
0
            state.op.push(tok);
814
0
            tok = tok->link()->next();
815
0
        } else {
816
0
            if (tok->link() != tok->next()) {
817
0
                state.inArrayAssignment++;
818
0
                compileUnaryOp(tok, state, compileExpression);
819
0
                if (Token::Match(tok, "} [,};]") && state.inArrayAssignment > 0) {
820
0
                    tok = tok->next();
821
0
                    state.inArrayAssignment--;
822
0
                }
823
0
            } else {
824
0
                state.op.push(tok);
825
0
                tok = tok->tokAt(2);
826
0
            }
827
0
        }
828
0
    }
829
37.5k
}
830
831
static void compileScope(Token *&tok, AST_state& state)
832
37.5k
{
833
37.5k
    compileTerm(tok, state);
834
37.5k
    while (tok) {
835
37.5k
        if (tok->str() == "::") {
836
0
            const Token *lastOp = state.op.empty() ? nullptr : state.op.top();
837
0
            if (Token::Match(lastOp, ":: %name%"))
838
0
                lastOp = lastOp->next();
839
0
            if (Token::Match(lastOp, "%name%") &&
840
0
                (lastOp->next() == tok || (Token::Match(lastOp, "%name% <") && lastOp->linkAt(1) && tok == lastOp->linkAt(1)->next())))
841
0
                compileBinOp(tok, state, compileTerm);
842
0
            else
843
0
                compileUnaryOp(tok, state, compileTerm);
844
37.5k
        } else break;
845
37.5k
    }
846
37.5k
}
847
848
static bool isPrefixUnary(const Token* tok, bool cpp)
849
4.94k
{
850
4.94k
    if (cpp && Token::simpleMatch(tok->previous(), "* [") && Token::simpleMatch(tok->link(), "] {")) {
851
0
        for (const Token* prev = tok->previous(); Token::Match(prev, "%name%|::|*|&|>|>>"); prev = prev->previous()) {
852
0
            if (Token::Match(prev, ">|>>")) {
853
0
                if (!prev->link())
854
0
                    break;
855
0
                prev = prev->link();
856
0
            }
857
0
            if (prev->str() == "new")
858
0
                return false;
859
0
        }
860
0
    }
861
4.94k
    if (!tok->previous()
862
4.94k
        || ((Token::Match(tok->previous(), "(|[|{|%op%|;|?|:|,|.|return|::") || (cpp && tok->strAt(-1) == "throw"))
863
4.94k
            && (tok->previous()->tokType() != Token::eIncDecOp || tok->tokType() == Token::eIncDecOp)))
864
3.58k
        return true;
865
866
1.35k
    if (tok->previous()->str() == "}") {
867
0
        const Token* parent = tok->linkAt(-1)->tokAt(-1);
868
0
        return !Token::Match(parent, "%type%") || parent->isKeyword();
869
0
    }
870
871
1.35k
    if (tok->str() == "*" && tok->previous()->tokType() == Token::eIncDecOp && isPrefixUnary(tok->previous(), cpp))
872
0
        return true;
873
874
1.35k
    return tok->strAt(-1) == ")" && iscast(tok->linkAt(-1), cpp);
875
1.35k
}
876
877
static void compilePrecedence2(Token *&tok, AST_state& state)
878
37.4k
{
879
37.4k
    auto doCompileScope = [&](const Token* tok) -> bool {
880
37.4k
        const bool isStartOfCpp11Init = state.cpp && tok && tok->str() == "{" && iscpp11init(tok);
881
37.4k
        if (isStartOfCpp11Init || Token::simpleMatch(tok, "(")) {
882
694
            tok = tok->previous();
883
720
            while (Token::simpleMatch(tok, "*"))
884
26
                tok = tok->previous();
885
694
            while (tok && Token::Match(tok->previous(), ":: %type%"))
886
0
                tok = tok->tokAt(-2);
887
694
            if (tok && !tok->isKeyword())
888
620
                tok = tok->previous();
889
694
            return !Token::Match(tok, "new ::| %type%");
890
694
        }
891
36.7k
        return !findLambdaEndTokenWithoutAST(tok);
892
37.4k
    };
893
894
37.4k
    bool isNew = true;
895
37.4k
    if (doCompileScope(tok)) {
896
37.4k
        compileScope(tok, state);
897
37.4k
        isNew = false;
898
37.4k
    }
899
39.5k
    while (tok) {
900
39.5k
        if (tok->tokType() == Token::eIncDecOp && !isPrefixUnary(tok, state.cpp)) {
901
35
            compileUnaryOp(tok, state, compileScope);
902
39.5k
        } else if (tok->str() == "...") {
903
0
            if (!Token::simpleMatch(tok->previous(), ")"))
904
0
                state.op.push(tok);
905
0
            tok = tok->next();
906
0
            break;
907
39.5k
        } else if (tok->str() == "." && tok->strAt(1) != "*") {
908
0
            if (tok->strAt(1) == ".") {
909
0
                state.op.push(tok);
910
0
                tok = tok->tokAt(3);
911
0
                break;
912
0
            }
913
0
            compileBinOp(tok, state, compileScope);
914
39.5k
        } else if (tok->str() == "[") {
915
0
            if (state.cpp && isPrefixUnary(tok, /*cpp*/ true) && Token::Match(tok->link(), "] (|{|<")) { // Lambda
916
                // What we do here:
917
                // - Nest the round bracket under the square bracket.
918
                // - Nest what follows the lambda (if anything) with the lambda opening [
919
                // - Compile the content of the lambda function as separate tree (this is done later)
920
                // this must be consistent with isLambdaCaptureList
921
0
                Token* const squareBracket = tok;
922
                // Parse arguments in the capture list
923
0
                if (tok->strAt(1) != "]") {
924
0
                    Token* tok2 = tok->next();
925
0
                    AST_state state2(state.cpp);
926
0
                    compileExpression(tok2, state2);
927
0
                    if (!state2.op.empty()) {
928
0
                        squareBracket->astOperand2(state2.op.top());
929
0
                    }
930
0
                }
931
932
0
                const bool hasTemplateArg = Token::simpleMatch(squareBracket->link(), "] <") &&
933
0
                                            Token::simpleMatch(squareBracket->link()->next()->link(), "> (");
934
0
                if (Token::simpleMatch(squareBracket->link(), "] (") || hasTemplateArg) {
935
0
                    Token* const roundBracket = hasTemplateArg ? squareBracket->link()->next()->link()->next() : squareBracket->link()->next();
936
0
                    Token* curlyBracket = roundBracket->link()->next();
937
0
                    while (Token::Match(curlyBracket, "mutable|const|constexpr|consteval"))
938
0
                        curlyBracket = curlyBracket->next();
939
0
                    if (Token::simpleMatch(curlyBracket, "noexcept")) {
940
0
                        if (Token::simpleMatch(curlyBracket->next(), "("))
941
0
                            curlyBracket = curlyBracket->linkAt(1)->next();
942
0
                        else
943
0
                            curlyBracket = curlyBracket->next();
944
0
                    }
945
0
                    if (curlyBracket && curlyBracket->originalName() == "->")
946
0
                        curlyBracket = findTypeEnd(curlyBracket->next());
947
0
                    if (curlyBracket && curlyBracket->str() == "{") {
948
0
                        squareBracket->astOperand1(roundBracket);
949
0
                        roundBracket->astOperand1(curlyBracket);
950
0
                        state.op.push(squareBracket);
951
0
                        tok = curlyBracket->link()->next();
952
0
                        continue;
953
0
                    }
954
0
                } else {
955
0
                    Token* const curlyBracket = squareBracket->link()->next();
956
0
                    squareBracket->astOperand1(curlyBracket);
957
0
                    state.op.push(squareBracket);
958
0
                    tok = curlyBracket->link()->next();
959
0
                    continue;
960
0
                }
961
0
            }
962
963
0
            Token* const tok2 = tok;
964
0
            if (tok->strAt(1) != "]") {
965
0
                compileBinOp(tok, state, compileExpression);
966
0
                if (Token::Match(tok2->previous(), "%type%|* [") && Token::Match(tok, "] { !!}")) {
967
0
                    tok = tok->next();
968
0
                    Token* const tok3 = tok;
969
0
                    compileBinOp(tok, state, compileExpression);
970
0
                    if (tok != tok3->link())
971
0
                        throw InternalError(tok, "Syntax error in {..}", InternalError::AST);
972
0
                    tok = tok->next();
973
0
                    continue;
974
0
                }
975
0
            }
976
0
            else
977
0
                compileUnaryOp(tok, state, compileExpression);
978
0
            tok = tok2->link()->next();
979
39.5k
        } else if (Token::simpleMatch(tok, "( {") && Token::simpleMatch(tok->linkAt(1)->previous(), "; } )") && !Token::Match(tok->previous(), "%name% (")) {
980
0
            state.op.push(tok->next());
981
0
            tok = tok->link()->next();
982
0
            continue;
983
39.5k
        } else if (tok->str() == "(" && (!iscast(tok, state.cpp) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
984
2.08k
            Token* tok2 = tok;
985
2.08k
            tok = tok->next();
986
2.08k
            const bool opPrevTopSquare = !state.op.empty() && state.op.top() && state.op.top()->str() == "[";
987
2.08k
            const std::size_t oldOpSize = state.op.size();
988
2.08k
            compileExpression(tok, state);
989
2.08k
            tok = tok2;
990
2.08k
            if ((oldOpSize > 0 && (isNew || Token::simpleMatch(tok->previous(), "} (")))
991
2.08k
                || (tok->previous() && tok->previous()->isName() && !Token::Match(tok->previous(), "return|case") && (!state.cpp || !Token::Match(tok->previous(), "throw|delete")))
992
2.08k
                || (tok->strAt(-1) == "]" && (!state.cpp || !Token::Match(tok->linkAt(-1)->previous(), "new|delete")))
993
2.08k
                || (tok->strAt(-1) == ">" && tok->linkAt(-1))
994
2.08k
                || (tok->strAt(-1) == ")" && !iscast(tok->linkAt(-1), state.cpp)) // Don't treat brackets to clarify precedence as function calls
995
2.08k
                || (tok->strAt(-1) == "}" && opPrevTopSquare)) {
996
1.38k
                const bool operandInside = oldOpSize < state.op.size();
997
1.38k
                if (operandInside)
998
1.38k
                    compileBinOp(tok, state, nullptr);
999
0
                else
1000
0
                    compileUnaryOp(tok, state, nullptr);
1001
1.38k
            }
1002
2.08k
            tok = tok->link()->next();
1003
37.4k
        } else if (iscast(tok, state.cpp) && Token::simpleMatch(tok->link(), ") {") && Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
1004
0
            Token *cast = tok;
1005
0
            tok = tok->link()->next();
1006
0
            Token *tok1 = tok;
1007
0
            compileUnaryOp(tok, state, compileExpression);
1008
0
            cast->astOperand1(tok1);
1009
0
            tok = tok1->link()->next();
1010
37.4k
        } else if (state.cpp && tok->str() == "{" && iscpp11init(tok)) {
1011
0
            Token* end = tok->link();
1012
0
            if (Token::simpleMatch(tok, "{ }"))
1013
0
            {
1014
0
                compileUnaryOp(tok, state, nullptr);
1015
0
                tok = tok->next();
1016
0
            }
1017
0
            else
1018
0
            {
1019
0
                compileBinOp(tok, state, compileExpression);
1020
0
            }
1021
0
            if (tok == end)
1022
0
                tok = end->next();
1023
0
            else
1024
0
                throw InternalError(tok, "Syntax error. Unexpected tokens in initializer.", InternalError::AST);
1025
37.4k
        } else break;
1026
39.5k
    }
1027
37.4k
}
1028
1029
static void compilePrecedence3(Token *&tok, AST_state& state)
1030
37.4k
{
1031
37.4k
    compilePrecedence2(tok, state);
1032
39.6k
    while (tok) {
1033
39.6k
        if ((Token::Match(tok, "[+-!~*&]") || tok->tokType() == Token::eIncDecOp) &&
1034
39.6k
            isPrefixUnary(tok, state.cpp)) {
1035
2.18k
            if (Token::Match(tok, "* [*,)]")) {
1036
0
                Token* tok2 = tok->next();
1037
0
                while (tok2->next() && tok2->str() == "*")
1038
0
                    tok2 = tok2->next();
1039
0
                if (Token::Match(tok2, "[>),]")) {
1040
0
                    tok = tok2;
1041
0
                    continue;
1042
0
                }
1043
0
            }
1044
2.18k
            compileUnaryOp(tok, state, compilePrecedence3);
1045
37.4k
        } else if (tok->str() == "(" && iscast(tok, state.cpp)) {
1046
1
            Token* castTok = tok;
1047
1
            castTok->isCast(true);
1048
1
            tok = tok->link()->next();
1049
1
            const int inArrayAssignment = state.inArrayAssignment;
1050
1
            if (tok && tok->str() == "{")
1051
0
                state.inArrayAssignment = 1;
1052
1
            compilePrecedence3(tok, state);
1053
1
            state.inArrayAssignment = inArrayAssignment;
1054
1
            compileUnaryOp(castTok, state, nullptr);
1055
37.4k
        } else if (state.cpp && Token::Match(tok, "new %name%|::|(")) {
1056
0
            Token* newtok = tok;
1057
0
            tok = tok->next();
1058
0
            bool innertype = false;
1059
0
            if (tok->str() == "(") {
1060
0
                if (Token::Match(tok, "( &| %name%") && Token::Match(tok->link(), ") ( %type%") && Token::simpleMatch(tok->link()->linkAt(1), ") ("))
1061
0
                    tok = tok->link()->next();
1062
0
                if (Token::Match(tok->link(), ") ::| %type%")) {
1063
0
                    if (Token::Match(tok, "( !!)")) {
1064
0
                        Token *innerTok = tok->next();
1065
0
                        AST_state innerState(true);
1066
0
                        compileExpression(innerTok, innerState);
1067
0
                    }
1068
0
                    tok = tok->link()->next();
1069
0
                } else if (Token::Match(tok, "( %type%") && Token::Match(tok->link(), ") [();,[]")) {
1070
0
                    tok = tok->next();
1071
0
                    innertype = true;
1072
0
                } else if (Token::Match(tok, "( &| %name%") && Token::simpleMatch(tok->link(), ") (")) {
1073
0
                    tok = tok->next();
1074
0
                    innertype = true;
1075
0
                } else {
1076
                    /* bad code */
1077
0
                    continue;
1078
0
                }
1079
0
            }
1080
1081
0
            Token* leftToken = tok;
1082
0
            if (Token::simpleMatch(tok, "::")) {
1083
0
                tok->astOperand1(tok->next());
1084
0
                tok = tok->next();
1085
0
            }
1086
0
            else {
1087
0
                while (Token::Match(tok->next(), ":: %name%")) {
1088
0
                    Token* scopeToken = tok->next(); //The ::
1089
0
                    scopeToken->astOperand1(leftToken);
1090
0
                    scopeToken->astOperand2(scopeToken->next());
1091
0
                    leftToken = scopeToken;
1092
0
                    tok = scopeToken->next();
1093
0
                }
1094
0
            }
1095
1096
0
            state.op.push(tok);
1097
0
            while (Token::Match(tok, "%name%|*|&|<|::")) {
1098
0
                if (tok->link())
1099
0
                    tok = tok->link();
1100
0
                tok = tok->next();
1101
0
            }
1102
0
            if (Token::Match(tok, "( const| %type% ) (")) {
1103
0
                state.op.push(tok->next());
1104
0
                tok = tok->link()->next();
1105
0
                compileBinOp(tok, state, compilePrecedence2);
1106
0
            } else if (Token::Match(tok, "(|{|["))
1107
0
                compilePrecedence2(tok, state);
1108
0
            else if (innertype && Token::simpleMatch(tok, ") [")) {
1109
0
                tok = tok->next();
1110
0
                compilePrecedence2(tok, state);
1111
0
            }
1112
0
            compileUnaryOp(newtok, state, nullptr);
1113
0
            if (innertype && Token::simpleMatch(tok, ") ,"))
1114
0
                tok = tok->next();
1115
37.4k
        } else if (state.cpp && Token::Match(tok, "delete %name%|*|&|::|(|[")) {
1116
0
            Token* tok2 = tok;
1117
0
            tok = tok->next();
1118
0
            if (tok && tok->str() == "[")
1119
0
                tok = tok->link()->next();
1120
0
            compilePrecedence3(tok, state);
1121
0
            compileUnaryOp(tok2, state, nullptr);
1122
0
        }
1123
        // TODO: Handle sizeof
1124
37.4k
        else break;
1125
39.6k
    }
1126
37.4k
}
1127
1128
static void compilePointerToElem(Token *&tok, AST_state& state)
1129
35.2k
{
1130
35.2k
    compilePrecedence3(tok, state);
1131
35.2k
    while (tok) {
1132
35.2k
        if (Token::simpleMatch(tok, ". *")) {
1133
0
            compileBinOp(tok, state, compilePrecedence3);
1134
35.2k
        } else break;
1135
35.2k
    }
1136
35.2k
}
1137
1138
static void compileMulDiv(Token *&tok, AST_state& state)
1139
34.4k
{
1140
34.4k
    compilePointerToElem(tok, state);
1141
35.2k
    while (tok) {
1142
35.2k
        if (Token::Match(tok, "[/%]") || (tok->str() == "*" && !tok->astOperand1() && !isQualifier(tok))) {
1143
814
            if (Token::Match(tok, "* [*,)]")) {
1144
0
                Token* tok2 = tok->next();
1145
0
                while (tok2->next() && tok2->str() == "*")
1146
0
                    tok2 = tok2->next();
1147
0
                if (Token::Match(tok2, "[>),]")) {
1148
0
                    tok = tok2;
1149
0
                    break;
1150
0
                }
1151
0
            }
1152
814
            compileBinOp(tok, state, compilePointerToElem);
1153
34.4k
        } else break;
1154
35.2k
    }
1155
34.4k
}
1156
1157
static void compileAddSub(Token *&tok, AST_state& state)
1158
33.9k
{
1159
33.9k
    compileMulDiv(tok, state);
1160
34.4k
    while (tok) {
1161
34.4k
        if (Token::Match(tok, "+|-") && !tok->astOperand1()) {
1162
529
            compileBinOp(tok, state, compileMulDiv);
1163
33.9k
        } else break;
1164
34.4k
    }
1165
33.9k
}
1166
1167
static void compileShift(Token *&tok, AST_state& state)
1168
33.9k
{
1169
33.9k
    compileAddSub(tok, state);
1170
33.9k
    while (tok) {
1171
33.9k
        if (Token::Match(tok, "<<|>>")) {
1172
0
            compileBinOp(tok, state, compileAddSub);
1173
33.9k
        } else break;
1174
33.9k
    }
1175
33.9k
}
1176
1177
static void compileThreewayComp(Token *&tok, AST_state& state)
1178
33.9k
{
1179
33.9k
    compileShift(tok, state);
1180
33.9k
    while (tok) {
1181
33.9k
        if (tok->str() == "<=>") {
1182
0
            compileBinOp(tok, state, compileShift);
1183
33.9k
        } else break;
1184
33.9k
    }
1185
33.9k
}
1186
1187
static void compileRelComp(Token *&tok, AST_state& state)
1188
32.4k
{
1189
32.4k
    compileThreewayComp(tok, state);
1190
33.9k
    while (tok) {
1191
33.9k
        if (Token::Match(tok, "<|<=|>=|>") && !tok->link()) {
1192
1.50k
            compileBinOp(tok, state, compileThreewayComp);
1193
32.4k
        } else break;
1194
33.9k
    }
1195
32.4k
}
1196
1197
static void compileEqComp(Token *&tok, AST_state& state)
1198
31.9k
{
1199
31.9k
    compileRelComp(tok, state);
1200
32.4k
    while (tok) {
1201
32.4k
        if (Token::Match(tok, "==|!=")) {
1202
486
            compileBinOp(tok, state, compileRelComp);
1203
31.9k
        } else break;
1204
32.4k
    }
1205
31.9k
}
1206
1207
static void compileAnd(Token *&tok, AST_state& state)
1208
31.7k
{
1209
31.7k
    compileEqComp(tok, state);
1210
31.9k
    while (tok) {
1211
31.9k
        if (tok->str() == "&" && !tok->astOperand1() && !isQualifier(tok)) {
1212
252
            Token* tok2 = tok->next();
1213
252
            if (!tok2)
1214
0
                break;
1215
252
            if (tok2->str() == "&")
1216
0
                tok2 = tok2->next();
1217
252
            if (state.cpp && Token::Match(tok2, ",|)")) {
1218
0
                tok = tok2;
1219
0
                break; // rValue reference
1220
0
            }
1221
252
            compileBinOp(tok, state, compileEqComp);
1222
31.7k
        } else break;
1223
31.9k
    }
1224
31.7k
}
1225
1226
static void compileXor(Token *&tok, AST_state& state)
1227
31.4k
{
1228
31.4k
    compileAnd(tok, state);
1229
31.7k
    while (tok) {
1230
31.7k
        if (tok->str() == "^") {
1231
266
            compileBinOp(tok, state, compileAnd);
1232
31.4k
        } else break;
1233
31.7k
    }
1234
31.4k
}
1235
1236
static void compileOr(Token *&tok, AST_state& state)
1237
31.1k
{
1238
31.1k
    compileXor(tok, state);
1239
31.4k
    while (tok) {
1240
31.4k
        if (tok->str() == "|") {
1241
264
            compileBinOp(tok, state, compileXor);
1242
31.1k
        } else break;
1243
31.4k
    }
1244
31.1k
}
1245
1246
static void compileLogicAnd(Token *&tok, AST_state& state)
1247
31.1k
{
1248
31.1k
    compileOr(tok, state);
1249
31.1k
    while (tok) {
1250
31.1k
        if (tok->str() == "&&" && !isQualifier(tok)) {
1251
0
            if (!tok->astOperand1()) {
1252
0
                Token* tok2 = tok->next();
1253
0
                if (!tok2)
1254
0
                    break;
1255
0
                if (state.cpp && Token::Match(tok2, ",|)")) {
1256
0
                    tok = tok2;
1257
0
                    break; // rValue reference
1258
0
                }
1259
0
            }
1260
0
            compileBinOp(tok, state, compileOr);
1261
31.1k
        } else break;
1262
31.1k
    }
1263
31.1k
}
1264
1265
static void compileLogicOr(Token *&tok, AST_state& state)
1266
31.1k
{
1267
31.1k
    compileLogicAnd(tok, state);
1268
31.1k
    while (tok) {
1269
31.1k
        if (tok->str() == "||") {
1270
0
            compileBinOp(tok, state, compileLogicAnd);
1271
31.1k
        } else break;
1272
31.1k
    }
1273
31.1k
}
1274
1275
static void compileAssignTernary(Token *&tok, AST_state& state)
1276
31.1k
{
1277
31.1k
    compileLogicOr(tok, state);
1278
39.8k
    while (tok) {
1279
39.8k
        if (tok->isAssignmentOp()) {
1280
8.71k
            state.assign++;
1281
8.71k
            const Token *tok1 = tok->next();
1282
8.71k
            compileBinOp(tok, state, compileAssignTernary);
1283
8.71k
            if (Token::simpleMatch(tok1, "{") && tok == tok1->link() && tok->next())
1284
0
                tok = tok->next();
1285
8.71k
            if (state.assign > 0)
1286
8.71k
                state.assign--;
1287
31.1k
        } else if (tok->str() == "?") {
1288
            // http://en.cppreference.com/w/cpp/language/operator_precedence says about ternary operator:
1289
            //       "The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored."
1290
            // Hence, we rely on Tokenizer::prepareTernaryOpForAST() to add such parentheses where necessary.
1291
0
            const bool stopAtColon = state.stopAtColon;
1292
0
            state.stopAtColon = false;
1293
0
            if (tok->strAt(1) == ":") {
1294
0
                state.op.push(nullptr);
1295
0
            }
1296
0
            const int assign = state.assign;
1297
0
            state.assign = 0;
1298
0
            compileBinOp(tok, state, compileAssignTernary);
1299
0
            state.assign = assign;
1300
0
            state.stopAtColon = stopAtColon;
1301
31.1k
        } else if (tok->str() == ":") {
1302
0
            if (state.depth == 1U && state.inCase) {
1303
0
                state.inCase = false;
1304
0
                tok = tok->next();
1305
0
                break;
1306
0
            }
1307
0
            if (state.stopAtColon)
1308
0
                break;
1309
0
            if (state.assign > 0)
1310
0
                break;
1311
0
            compileBinOp(tok, state, compileAssignTernary);
1312
31.1k
        } else break;
1313
39.8k
    }
1314
31.1k
}
1315
1316
static void compileComma(Token *&tok, AST_state& state)
1317
22.4k
{
1318
22.4k
    compileAssignTernary(tok, state);
1319
22.4k
    while (tok) {
1320
22.4k
        if (tok->str() == ",") {
1321
0
            if (Token::simpleMatch(tok, ", }"))
1322
0
                tok = tok->next();
1323
0
            else
1324
0
                compileBinOp(tok, state, compileAssignTernary);
1325
22.4k
        } else if (tok->str() == ";" && state.functionCallEndPar && tok->index() < state.functionCallEndPar->index()) {
1326
0
            compileBinOp(tok, state, compileAssignTernary);
1327
22.4k
        } else break;
1328
22.4k
    }
1329
22.4k
}
1330
1331
static void compileExpression(Token *&tok, AST_state& state)
1332
22.4k
{
1333
22.4k
    if (state.depth > AST_MAX_DEPTH)
1334
0
        throw InternalError(tok, "maximum AST depth exceeded", InternalError::AST); // ticket #5592
1335
22.4k
    if (tok)
1336
22.4k
        compileComma(tok, state);
1337
22.4k
}
1338
1339
const Token* isLambdaCaptureList(const Token * tok)
1340
7.69k
{
1341
    // a lambda expression '[x](y){}' is compiled as:
1342
    // [
1343
    // `-(  <<-- optional
1344
    //   `-{
1345
    // see compilePrecedence2
1346
7.69k
    if (!Token::simpleMatch(tok, "["))
1347
7.69k
        return nullptr;
1348
0
    if (!Token::Match(tok->link(), "] (|{"))
1349
0
        return nullptr;
1350
0
    if (Token::simpleMatch(tok->astOperand1(), "{") && tok->astOperand1() == tok->link()->next())
1351
0
        return tok->astOperand1();
1352
0
    if (!tok->astOperand1() || tok->astOperand1()->str() != "(")
1353
0
        return nullptr;
1354
0
    const Token * params = tok->astOperand1();
1355
0
    if (!Token::simpleMatch(params->astOperand1(), "{"))
1356
0
        return nullptr;
1357
0
    return params->astOperand1();
1358
0
}
1359
1360
36.7k
const Token* findLambdaEndTokenWithoutAST(const Token* tok) {
1361
36.7k
    if (!(Token::simpleMatch(tok, "[") && tok->link()))
1362
36.7k
        return nullptr;
1363
0
    tok = tok->link()->next();
1364
0
    if (Token::simpleMatch(tok, "(") && tok->link())
1365
0
        tok = tok->link()->next();
1366
0
    if (!(Token::simpleMatch(tok, "{") && tok->link()))
1367
0
        return nullptr;
1368
0
    return tok->link()->next();
1369
0
}
1370
1371
static Token * createAstAtToken(Token *tok, bool cpp);
1372
1373
// Compile inner expressions inside inner ({..}) and lambda bodies
1374
static void createAstAtTokenInner(Token * const tok1, const Token *endToken, bool cpp)
1375
18.4k
{
1376
55.2k
    for (Token* tok = tok1; precedes(tok, endToken); tok = tok ? tok->next() : nullptr) {
1377
36.7k
        if (tok->str() == "{" && !iscpp11init(tok)) {
1378
0
            const Token * const endToken2 = tok->link();
1379
0
            bool hasAst = false;
1380
0
            for (const Token *inner = tok->next(); inner != endToken2; inner = inner->next()) {
1381
0
                if (inner->astOperand1()) {
1382
0
                    hasAst = true;
1383
0
                    break;
1384
0
                }
1385
0
                if (tok->isConstOp())
1386
0
                    break;
1387
0
                if (inner->str() == "{")
1388
0
                    inner = inner->link();
1389
0
            }
1390
0
            if (!hasAst) {
1391
0
                for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : nullptr)
1392
0
                    tok = createAstAtToken(tok, cpp);
1393
0
            }
1394
36.7k
        } else if (cpp && tok->str() == "[") {
1395
0
            if (isLambdaCaptureList(tok)) {
1396
0
                tok = tok->astOperand1();
1397
0
                if (tok->str() == "(")
1398
0
                    tok = tok->astOperand1();
1399
0
                const Token * const endToken2 = tok->link();
1400
0
                tok = tok->next();
1401
0
                for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : nullptr)
1402
0
                    tok = createAstAtToken(tok, cpp);
1403
0
            }
1404
0
        }
1405
36.7k
        else if (Token::simpleMatch(tok, "( * ) [")) {
1406
0
            bool hasAst = false;
1407
0
            for (const Token* tok2 = tok->linkAt(3); tok2 != tok; tok2 = tok2->previous()) {
1408
0
                if (tok2->astParent() || tok2->astOperand1() || tok2->astOperand2()) {
1409
0
                    hasAst = true;
1410
0
                    break;
1411
0
                }
1412
0
            }
1413
0
            if (!hasAst) {
1414
0
                Token *const startTok = tok = tok->tokAt(4);
1415
0
                const Token* const endtok = startTok->linkAt(-1);
1416
0
                AST_state state(cpp);
1417
0
                compileExpression(tok, state);
1418
0
                createAstAtTokenInner(startTok, endtok, cpp);
1419
0
            }
1420
0
        }
1421
36.7k
    }
1422
18.4k
}
1423
1424
static Token * findAstTop(Token *tok1, const Token *tok2)
1425
0
{
1426
0
    for (Token *tok = tok1; tok && (tok != tok2); tok = tok->next()) {
1427
0
        if (tok->astParent() || tok->astOperand1() || tok->astOperand2()) {
1428
0
            while (tok->astParent() && tok->astParent()->index() >= tok1->index() && tok->astParent()->index() <= tok2->index())
1429
0
                tok = tok->astParent();
1430
0
            return tok;
1431
0
        }
1432
0
        if (Token::simpleMatch(tok, "( {"))
1433
0
            tok = tok->link();
1434
0
    }
1435
0
    for (Token *tok = tok1; tok && (tok != tok2); tok = tok->next()) {
1436
0
        if (tok->isName() || tok->isNumber())
1437
0
            return tok;
1438
0
        if (Token::simpleMatch(tok, "( {"))
1439
0
            tok = tok->link();
1440
0
    }
1441
0
    return nullptr;
1442
0
}
1443
1444
static Token * createAstAtToken(Token *tok, bool cpp)
1445
52.0k
{
1446
    // skip function pointer declaration
1447
52.0k
    if (Token::Match(tok, "%type%") && !Token::Match(tok, "return|throw|if|while|new|delete")) {
1448
9.39k
        Token* type = tok;
1449
20.5k
        while (Token::Match(type, "%type%|*|&|<")) {
1450
11.1k
            if (type->str() == "<") {
1451
0
                if (type->link())
1452
0
                    type = type->link();
1453
0
                else
1454
0
                    break;
1455
0
            }
1456
11.1k
            type = type->next();
1457
11.1k
        }
1458
9.39k
        if (Token::Match(type, "( * *| %var%") &&
1459
9.39k
            Token::Match(type->link()->previous(), "%var%|] ) (") &&
1460
9.39k
            Token::Match(type->link()->linkAt(1), ") [;,)]"))
1461
0
            return type->link()->linkAt(1)->next();
1462
9.39k
    }
1463
1464
52.0k
    if (Token::simpleMatch(tok, "for (")) {
1465
0
        if (cpp && Token::Match(tok, "for ( const| auto &|&&| [")) {
1466
0
            Token *decl = Token::findsimplematch(tok, "[");
1467
0
            if (Token::simpleMatch(decl->link(), "] :")) {
1468
0
                AST_state state1(cpp);
1469
0
                while (decl->str() != "]") {
1470
0
                    if (Token::Match(decl, "%name% ,|]")) {
1471
0
                        state1.op.push(decl);
1472
0
                    } else if (decl->str() == ",") {
1473
0
                        if (!state1.op.empty()) {
1474
0
                            decl->astOperand1(state1.op.top());
1475
0
                            state1.op.pop();
1476
0
                        }
1477
0
                        if (!state1.op.empty()) {
1478
0
                            state1.op.top()->astOperand2(decl);
1479
0
                            state1.op.pop();
1480
0
                        }
1481
0
                        state1.op.push(decl);
1482
0
                    }
1483
0
                    decl = decl->next();
1484
0
                }
1485
0
                if (state1.op.size() > 1) {
1486
0
                    Token *lastName = state1.op.top();
1487
0
                    state1.op.pop();
1488
0
                    state1.op.top()->astOperand2(lastName);
1489
0
                }
1490
0
                decl = decl->next();
1491
1492
0
                Token *colon = decl;
1493
0
                compileExpression(decl, state1);
1494
1495
0
                tok->next()->astOperand1(tok);
1496
0
                tok->next()->astOperand2(colon);
1497
1498
0
                return decl;
1499
0
            }
1500
0
        }
1501
1502
0
        std::vector<Token*> inner;
1503
0
        Token* tok2 = skipDecl(tok->tokAt(2), &inner);
1504
0
        for (Token* tok3 : inner) {
1505
0
            AST_state state1(cpp);
1506
0
            compileExpression(tok3, state1);
1507
0
        }
1508
0
        Token *init1 = nullptr;
1509
0
        Token * const endPar = tok->next()->link();
1510
0
        if (tok2 == tok->tokAt(2) && Token::Match(tok2, "%op%|(")) {
1511
0
            init1 = tok2;
1512
0
            AST_state state1(cpp);
1513
0
            compileExpression(tok2, state1);
1514
0
            if (Token::Match(init1, "( !!{")) {
1515
0
                for (Token *tok3 = init1; tok3 != tok3->link(); tok3 = tok3->next()) {
1516
0
                    if (tok3->astParent()) {
1517
0
                        while (tok3->astParent())
1518
0
                            tok3 = tok3->astParent();
1519
0
                        init1 = tok3;
1520
0
                        break;
1521
0
                    }
1522
0
                    if (!Token::Match(tok3, "%op%|(|["))
1523
0
                        init1 = tok3;
1524
0
                }
1525
0
            }
1526
0
        } else {
1527
0
            while (tok2 && tok2 != endPar && tok2->str() != ";") {
1528
0
                if (tok2->str() == "<" && tok2->link()) {
1529
0
                    tok2 = tok2->link();
1530
0
                } else if (Token::Match(tok2, "%name% )| %op%|(|[|.|:|::") || Token::Match(tok2->previous(), "[(;{}] %cop%|(")) {
1531
0
                    init1 = tok2;
1532
0
                    AST_state state1(cpp);
1533
0
                    compileExpression(tok2, state1);
1534
0
                    if (Token::Match(tok2, ";|)"))
1535
0
                        break;
1536
0
                    init1 = nullptr;
1537
0
                }
1538
0
                if (!tok2) // #7109 invalid code
1539
0
                    return nullptr;
1540
0
                tok2 = tok2->next();
1541
0
            }
1542
0
        }
1543
0
        if (!tok2 || tok2->str() != ";") {
1544
0
            if (tok2 == endPar && init1) {
1545
0
                createAstAtTokenInner(init1->next(), endPar, cpp);
1546
0
                tok->next()->astOperand2(init1);
1547
0
                tok->next()->astOperand1(tok);
1548
0
            }
1549
0
            return tok2;
1550
0
        }
1551
1552
0
        Token * const init = init1 ? init1 : tok2;
1553
1554
0
        Token * const semicolon1 = tok2;
1555
0
        tok2 = tok2->next();
1556
0
        AST_state state2(cpp);
1557
0
        compileExpression(tok2, state2);
1558
1559
0
        Token * const semicolon2 = tok2;
1560
0
        if (!semicolon2)
1561
0
            return nullptr; // invalid code #7235
1562
1563
0
        if (semicolon2->str() == ";") {
1564
0
            tok2 = tok2->next();
1565
0
            AST_state state3(cpp);
1566
0
            if (Token::simpleMatch(tok2, "( {")) {
1567
0
                state3.op.push(tok2->next());
1568
0
                tok2 = tok2->link()->next();
1569
0
            }
1570
0
            compileExpression(tok2, state3);
1571
1572
0
            tok2 = findAstTop(semicolon1->next(), semicolon2);
1573
0
            if (tok2)
1574
0
                semicolon2->astOperand1(tok2);
1575
0
            tok2 = findAstTop(semicolon2->next(), endPar);
1576
0
            if (tok2)
1577
0
                semicolon2->astOperand2(tok2);
1578
0
            else if (!state3.op.empty())
1579
0
                semicolon2->astOperand2(state3.op.top());
1580
0
            semicolon1->astOperand2(semicolon2);
1581
0
        } else {
1582
0
            if (!cpp || state2.op.empty() || !Token::simpleMatch(state2.op.top(), ":"))
1583
0
                throw InternalError(tok, "syntax error", InternalError::SYNTAX);
1584
1585
0
            semicolon1->astOperand2(state2.op.top());
1586
0
        }
1587
1588
0
        if (init != semicolon1)
1589
0
            semicolon1->astOperand1(init->astTop());
1590
0
        tok->next()->astOperand1(tok);
1591
0
        tok->next()->astOperand2(semicolon1);
1592
1593
0
        createAstAtTokenInner(endPar->link(), endPar, cpp);
1594
1595
0
        return endPar;
1596
0
    }
1597
1598
52.0k
    if (Token::simpleMatch(tok, "( {"))
1599
0
        return tok;
1600
1601
52.0k
    if (Token::Match(tok, "%type% <") && tok->linkAt(1) && !Token::Match(tok->linkAt(1), "> [({]"))
1602
0
        return tok->linkAt(1);
1603
1604
52.0k
    if (cpp && !tok->isKeyword() && Token::Match(tok, "%type% ::|<|%name%")) {
1605
8.55k
        Token *tok2 = tok;
1606
8.55k
        while (true) {
1607
8.55k
            if (Token::Match(tok2, "%name%|> :: %name%"))
1608
0
                tok2 = tok2->tokAt(2);
1609
8.55k
            else if (Token::Match(tok2, "%name% <") && tok2->linkAt(1))
1610
0
                tok2 = tok2->linkAt(1);
1611
8.55k
            else
1612
8.55k
                break;
1613
8.55k
        }
1614
8.55k
        if (Token::Match(tok2, "%name%|> %name% {") && tok2->next()->varId() && iscpp11init(tok2->tokAt(2))) {
1615
0
            Token *const tok1 = tok = tok2->next();
1616
0
            AST_state state(cpp);
1617
0
            compileExpression(tok, state);
1618
0
            createAstAtTokenInner(tok1->next(), tok1->linkAt(1), cpp);
1619
0
            return tok;
1620
0
        }
1621
8.55k
    }
1622
1623
52.0k
    if (Token::Match(tok, "%type% %name%|*|&|::") && !Token::Match(tok, "return|new")) {
1624
8.55k
        int typecount = 0;
1625
8.55k
        Token *typetok = tok;
1626
18.8k
        while (Token::Match(typetok, "%type%|::|*|&")) {
1627
10.2k
            if (typetok->isName() && !Token::simpleMatch(typetok->previous(), "::"))
1628
10.2k
                typecount++;
1629
10.2k
            typetok = typetok->next();
1630
10.2k
        }
1631
8.55k
        if (Token::Match(typetok, "%var% =") && typetok->varId())
1632
0
            tok = typetok;
1633
1634
        // Do not create AST for function declaration
1635
8.55k
        if (typetok &&
1636
8.55k
            typecount >= 2 &&
1637
8.55k
            !Token::Match(tok, "return|throw") &&
1638
8.55k
            Token::Match(typetok->previous(), "%name% ( !!*") &&
1639
8.55k
            typetok->previous()->varId() == 0 &&
1640
8.55k
            !typetok->previous()->isKeyword() &&
1641
8.55k
            (Token::Match(typetok->link(), ") const|;|{") || Token::Match(typetok->link(), ") const| = delete ;")))
1642
1.74k
            return typetok;
1643
8.55k
    }
1644
1645
50.3k
    if (Token::Match(tok, "return|case") ||
1646
50.3k
        (cpp && tok->str() == "throw") ||
1647
50.3k
        !tok->previous() ||
1648
50.3k
        Token::Match(tok, "%name% %op%|(|[|.|::|<|?|;") ||
1649
50.3k
        (cpp && Token::Match(tok, "%name% {") && iscpp11init(tok->next())) ||
1650
50.3k
        Token::Match(tok->previous(), "[;{}] %cop%|++|--|( !!{") ||
1651
50.3k
        Token::Match(tok->previous(), "[;{}] %num%|%str%|%char%") ||
1652
50.3k
        Token::Match(tok->previous(), "[;{}] delete new")) {
1653
18.4k
        if (cpp && (Token::Match(tok->tokAt(-2), "[;{}] new|delete %name%") || Token::Match(tok->tokAt(-3), "[;{}] :: new|delete %name%")))
1654
0
            tok = tok->previous();
1655
1656
18.4k
        Token * const tok1 = tok;
1657
18.4k
        AST_state state(cpp);
1658
18.4k
        if (Token::Match(tok, "%name% ("))
1659
1.46k
            state.functionCallEndPar = tok->linkAt(1);
1660
18.4k
        compileExpression(tok, state);
1661
18.4k
        Token * const endToken = tok;
1662
18.4k
        if (endToken == tok1 || !endToken)
1663
0
            return tok1;
1664
1665
18.4k
        createAstAtTokenInner(tok1->next(), endToken, cpp);
1666
1667
18.4k
        return endToken->previous();
1668
18.4k
    }
1669
1670
31.8k
    if (cpp && tok->str() == "{" && iscpp11init(tok)) {
1671
0
        Token * const tok1 = tok;
1672
0
        AST_state state(cpp);
1673
0
        compileExpression(tok, state);
1674
0
        Token* const endToken = tok;
1675
0
        if (endToken == tok1 || !endToken)
1676
0
            return tok1;
1677
1678
0
        createAstAtTokenInner(tok1->next(), endToken, cpp);
1679
0
        return endToken->previous();
1680
0
    }
1681
1682
31.8k
    return tok;
1683
31.8k
}
1684
1685
void TokenList::createAst() const
1686
1.36k
{
1687
53.4k
    for (Token *tok = mTokensFrontBack.front; tok; tok = tok ? tok->next() : nullptr) {
1688
52.0k
        tok = createAstAtToken(tok, isCPP());
1689
52.0k
    }
1690
1.36k
}
1691
1692
struct OnException {
1693
    std::function<void()> f;
1694
1695
1.36k
    ~OnException() {
1696
1.36k
#ifndef _MSC_VER
1697
1.36k
        if (std::uncaught_exception())
1698
1
            f();
1699
1.36k
#endif
1700
1.36k
    }
1701
};
1702
1703
void TokenList::validateAst() const
1704
1.36k
{
1705
1.36k
    OnException oe{[&] {
1706
1
            if (mSettings && mSettings->debugnormal)
1707
0
                mTokensFrontBack.front->printOut();
1708
1
        }};
1709
    // Check for some known issues in AST to avoid crash/hang later on
1710
1.36k
    std::set<const Token*> safeAstTokens;    // list of "safe" AST tokens without endless recursion
1711
93.6k
    for (const Token *tok = mTokensFrontBack.front; tok; tok = tok->next()) {
1712
        // Syntax error if binary operator only has 1 operand
1713
92.2k
        if ((tok->isAssignmentOp() || tok->isComparisonOp() || Token::Match(tok,"[|^/%]")) && tok->astOperand1() && !tok->astOperand2())
1714
0
            throw InternalError(tok, "Syntax Error: AST broken, binary operator has only one operand.", InternalError::AST);
1715
1716
        // Syntax error if we encounter "?" with operand2 that is not ":"
1717
92.2k
        if (tok->str() == "?") {
1718
0
            if (!tok->astOperand1() || !tok->astOperand2())
1719
0
                throw InternalError(tok, "AST broken, ternary operator missing operand(s)", InternalError::AST);
1720
0
            if (tok->astOperand2()->str() != ":")
1721
0
                throw InternalError(tok, "Syntax Error: AST broken, ternary operator lacks ':'.", InternalError::AST);
1722
0
        }
1723
1724
        // Check for endless recursion
1725
92.2k
        const Token* parent = tok->astParent();
1726
92.2k
        if (parent) {
1727
32.5k
            std::set<const Token*> astTokens;    // list of ancestors
1728
32.5k
            astTokens.insert(tok);
1729
37.0k
            do {
1730
37.0k
                if (safeAstTokens.find(parent) != safeAstTokens.end())
1731
22.8k
                    break;
1732
14.2k
                if (astTokens.find(parent) != astTokens.end())
1733
0
                    throw InternalError(tok, "AST broken: endless recursion from '" + tok->str() + "'", InternalError::AST);
1734
14.2k
                astTokens.insert(parent);
1735
14.2k
            } while ((parent = parent->astParent()) != nullptr);
1736
32.5k
            safeAstTokens.insert(astTokens.cbegin(), astTokens.cend());
1737
59.7k
        } else if (tok->str() == ";") {
1738
17.0k
            safeAstTokens.clear();
1739
42.6k
        } else {
1740
42.6k
            safeAstTokens.insert(tok);
1741
42.6k
        }
1742
1743
        // Don't check templates
1744
92.2k
        if (tok->str() == "<" && tok->link()) {
1745
4
            tok = tok->link();
1746
4
            continue;
1747
4
        }
1748
92.2k
        if (tok->isCast() && tok->astOperand1() && tok->link()) { // skip casts (not part of the AST)
1749
0
            tok = tok->link();
1750
0
            continue;
1751
0
        }
1752
1753
92.2k
        if (findLambdaEndToken(tok)) { // skip lambda captures
1754
0
            tok = tok->link();
1755
0
            continue;
1756
0
        }
1757
1758
        // Check binary operators
1759
92.2k
        if (Token::Match(tok, "%or%|%oror%|%assign%|%comp%")) {
1760
            // Skip pure virtual functions
1761
10.9k
            if (Token::simpleMatch(tok->previous(), ") = 0"))
1762
0
                continue;
1763
            // Skip operator definitions
1764
10.9k
            if (Token::simpleMatch(tok->previous(), "operator"))
1765
0
                continue;
1766
            // Skip incomplete code
1767
10.9k
            if (!tok->astOperand1() && !tok->astOperand2() && !tok->astParent())
1768
0
                continue;
1769
            // Skip lambda assignment and/or initializer
1770
10.9k
            if (Token::Match(tok, "= {|^|["))
1771
0
                continue;
1772
            // FIXME: Workaround broken AST assignment in type aliases
1773
10.9k
            if (Token::Match(tok->previous(), "%name% = %name%"))
1774
987
                continue;
1775
9.98k
            if (!tok->astOperand1() || !tok->astOperand2())
1776
1
                throw InternalError(tok, "Syntax Error: AST broken, binary operator '" + tok->str() + "' doesn't have two operands.", InternalError::AST);
1777
9.98k
        }
1778
1779
        // Check control blocks and asserts
1780
91.2k
        if (Token::Match(tok->previous(), "if|while|for|switch|assert|ASSERT (")) {
1781
1.38k
            if (!tok->astOperand1() || !tok->astOperand2())
1782
0
                throw InternalError(tok,
1783
0
                                    "Syntax Error: AST broken, '" + tok->previous()->str() +
1784
0
                                    "' doesn't have two operands.",
1785
0
                                    InternalError::AST);
1786
1.38k
        }
1787
1788
        // Check member access
1789
91.2k
        if (Token::Match(tok, "%var% .")) {
1790
0
            if (!tok->astParent()) {
1791
0
                throw InternalError(
1792
0
                          tok, "Syntax Error: AST broken, '" + tok->str() + "' doesn't have a parent.", InternalError::AST);
1793
0
            }
1794
0
            if (!tok->next()->astOperand1() || !tok->next()->astOperand2()) {
1795
0
                const std::string& op =
1796
0
                    tok->next()->originalName().empty() ? tok->next()->str() : tok->next()->originalName();
1797
0
                throw InternalError(
1798
0
                          tok, "Syntax Error: AST broken, '" + op + "' doesn't have two operands.", InternalError::AST);
1799
0
            }
1800
0
        }
1801
91.2k
    }
1802
1.36k
}
1803
1804
std::string TokenList::getOrigFile(const Token *tok) const
1805
1.55k
{
1806
1.55k
    return mOrigFiles.at(tok->fileIndex());
1807
1.55k
}
1808
1809
const std::string& TokenList::file(const Token *tok) const
1810
3.28k
{
1811
3.28k
    return mFiles.at(tok->fileIndex());
1812
3.28k
}
1813
1814
std::string TokenList::fileLine(const Token *tok) const
1815
0
{
1816
0
    return ErrorMessage::FileLocation(tok, this).stringify();
1817
0
}
1818
1819
bool TokenList::validateToken(const Token* tok) const
1820
0
{
1821
0
    if (!tok)
1822
0
        return true;
1823
0
    for (const Token *t = mTokensFrontBack.front; t; t = t->next()) {
1824
0
        if (tok==t)
1825
0
            return true;
1826
0
    }
1827
0
    return false;
1828
0
}
1829
1830
void TokenList::simplifyPlatformTypes()
1831
1.36k
{
1832
1.36k
    if (!mSettings)
1833
0
        return;
1834
1835
1.36k
    const bool isCPP11  = mSettings->standards.cpp >= Standards::CPP11;
1836
1837
1.36k
    enum { isLongLong, isLong, isInt } type;
1838
1839
    /** @todo This assumes a flat address space. Not true for segmented address space (FAR *). */
1840
1841
1.36k
    if (mSettings->platform.sizeof_size_t == mSettings->platform.sizeof_long)
1842
1.36k
        type = isLong;
1843
0
    else if (mSettings->platform.sizeof_size_t == mSettings->platform.sizeof_long_long)
1844
0
        type = isLongLong;
1845
0
    else if (mSettings->platform.sizeof_size_t == mSettings->platform.sizeof_int)
1846
0
        type = isInt;
1847
0
    else
1848
0
        return;
1849
1850
94.1k
    for (Token *tok = front(); tok; tok = tok->next()) {
1851
        // pre-check to reduce unneeded match calls
1852
92.7k
        if (!Token::Match(tok, "std| ::| %type%"))
1853
56.9k
            continue;
1854
35.7k
        bool isUnsigned;
1855
35.7k
        if (Token::Match(tok, "std| ::| size_t|uintptr_t|uintmax_t")) {
1856
0
            if (isCPP11 && tok->strAt(-1) == "using" && tok->strAt(1) == "=")
1857
0
                continue;
1858
0
            isUnsigned = true;
1859
35.7k
        } else if (Token::Match(tok, "std| ::| ssize_t|ptrdiff_t|intptr_t|intmax_t")) {
1860
0
            if (isCPP11 && tok->strAt(-1) == "using" && tok->strAt(1) == "=")
1861
0
                continue;
1862
0
            isUnsigned = false;
1863
0
        } else
1864
35.7k
            continue;
1865
1866
0
        bool inStd = false;
1867
0
        if (tok->str() == "::") {
1868
0
            tok->deleteThis();
1869
0
        } else if (tok->str() == "std") {
1870
0
            if (tok->next()->str() != "::")
1871
0
                continue;
1872
0
            inStd = true;
1873
0
            tok->deleteNext();
1874
0
            tok->deleteThis();
1875
0
        }
1876
1877
0
        if (inStd)
1878
0
            tok->originalName("std::" + tok->str());
1879
0
        else
1880
0
            tok->originalName(tok->str());
1881
0
        if (isUnsigned)
1882
0
            tok->isUnsigned(true);
1883
1884
0
        switch (type) {
1885
0
        case isLongLong:
1886
0
            tok->isLong(true);
1887
0
            tok->str("long");
1888
0
            break;
1889
0
        case isLong:
1890
0
            tok->str("long");
1891
0
            break;
1892
0
        case isInt:
1893
0
            tok->str("int");
1894
0
            break;
1895
0
        }
1896
0
    }
1897
1898
1.36k
    const std::string platform_type(mSettings->platform.toString());
1899
1900
94.1k
    for (Token *tok = front(); tok; tok = tok->next()) {
1901
92.7k
        if (tok->tokType() != Token::eType && tok->tokType() != Token::eName)
1902
60.7k
            continue;
1903
1904
32.0k
        const Library::PlatformType * const platformtype = mSettings->library.platform_type(tok->str(), platform_type);
1905
1906
32.0k
        if (platformtype) {
1907
            // check for namespace
1908
0
            if (tok->strAt(-1) == "::") {
1909
0
                const Token * tok1 = tok->tokAt(-2);
1910
                // skip when non-global namespace defined
1911
0
                if (tok1 && tok1->tokType() == Token::eName)
1912
0
                    continue;
1913
0
                tok = tok->previous();
1914
0
                tok->deleteThis();
1915
0
            }
1916
0
            Token *typeToken;
1917
0
            if (platformtype->mConstPtr) {
1918
0
                tok->str("const");
1919
0
                tok->insertToken("*");
1920
0
                tok->insertToken(platformtype->mType);
1921
0
                typeToken = tok;
1922
0
            } else if (platformtype->mPointer) {
1923
0
                tok->str(platformtype->mType);
1924
0
                typeToken = tok;
1925
0
                tok->insertToken("*");
1926
0
            } else if (platformtype->mPtrPtr) {
1927
0
                tok->str(platformtype->mType);
1928
0
                typeToken = tok;
1929
0
                tok->insertToken("*");
1930
0
                tok->insertToken("*");
1931
0
            } else {
1932
0
                tok->originalName(tok->str());
1933
0
                tok->str(platformtype->mType);
1934
0
                typeToken = tok;
1935
0
            }
1936
0
            if (platformtype->mSigned)
1937
0
                typeToken->isSigned(true);
1938
0
            if (platformtype->mUnsigned)
1939
0
                typeToken->isUnsigned(true);
1940
0
            if (platformtype->mLong)
1941
0
                typeToken->isLong(true);
1942
0
        }
1943
32.0k
    }
1944
1.36k
}
1945
1946
void TokenList::simplifyStdType()
1947
1.36k
{
1948
1.36k
    auto isVarDeclC = [](const Token* tok) -> bool {
1949
0
        if (!Token::simpleMatch(tok, "}"))
1950
0
            return false;
1951
0
        tok = tok->link()->previous();
1952
0
        while (Token::Match(tok, "%name%")) {
1953
0
            if (Token::Match(tok, "struct|union|enum"))
1954
0
                return true;
1955
0
            tok = tok->previous();
1956
0
        }
1957
0
        return false;
1958
0
    };
1959
1960
94.1k
    for (Token *tok = front(); tok; tok = tok->next()) {
1961
1962
92.7k
        if (isC() && Token::Match(tok, "const|extern *|&|%name%") && (!tok->previous() || Token::Match(tok->previous(), "[;{}]"))) {
1963
0
            if (Token::Match(tok->next(), "%name% !!;"))
1964
0
                continue;
1965
0
            if (isVarDeclC(tok->previous()))
1966
0
                continue;
1967
1968
0
            tok->insertToken("int");
1969
0
            tok->next()->isImplicitInt(true);
1970
0
            continue;
1971
0
        }
1972
1973
92.7k
        if (Token::Match(tok, "char|short|int|long|unsigned|signed|double|float") || (mSettings->standards.c >= Standards::C99 && Token::Match(tok, "complex|_Complex"))) {
1974
8.55k
            bool isFloat= false;
1975
8.55k
            bool isSigned = false;
1976
8.55k
            bool isUnsigned = false;
1977
8.55k
            bool isComplex = false;
1978
8.55k
            int countLong = 0;
1979
8.55k
            Token* typeSpec = nullptr;
1980
1981
8.55k
            Token* tok2 = tok;
1982
17.1k
            for (; tok2->next(); tok2 = tok2->next()) {
1983
17.1k
                if (tok2->str() == "long") {
1984
0
                    countLong++;
1985
0
                    if (!isFloat)
1986
0
                        typeSpec = tok2;
1987
17.1k
                } else if (tok2->str() == "short") {
1988
0
                    typeSpec = tok2;
1989
17.1k
                } else if (tok2->str() == "unsigned")
1990
0
                    isUnsigned = true;
1991
17.1k
                else if (tok2->str() == "signed")
1992
0
                    isSigned = true;
1993
17.1k
                else if (Token::Match(tok2, "float|double")) {
1994
0
                    isFloat = true;
1995
0
                    typeSpec = tok2;
1996
17.1k
                } else if (mSettings->standards.c >= Standards::C99 && Token::Match(tok2, "complex|_Complex"))
1997
0
                    isComplex = !isFloat || tok2->str() == "_Complex" || Token::Match(tok2->next(), "*|&|%name%"); // Ensure that "complex" is not the variables name
1998
17.1k
                else if (Token::Match(tok2, "char|int")) {
1999
8.55k
                    if (!typeSpec)
2000
8.55k
                        typeSpec = tok2;
2001
8.55k
                } else
2002
8.55k
                    break;
2003
17.1k
            }
2004
2005
8.55k
            if (!typeSpec) { // unsigned i; or similar declaration
2006
0
                if (!isComplex) { // Ensure that "complex" is not the variables name
2007
0
                    tok->str("int");
2008
0
                    tok->isSigned(isSigned);
2009
0
                    tok->isUnsigned(isUnsigned);
2010
0
                    tok->isImplicitInt(true);
2011
0
                }
2012
8.55k
            } else {
2013
8.55k
                typeSpec->isLong(typeSpec->isLong() || (isFloat && countLong == 1) || countLong > 1);
2014
8.55k
                typeSpec->isComplex(typeSpec->isComplex() || (isFloat && isComplex));
2015
8.55k
                typeSpec->isSigned(typeSpec->isSigned() || isSigned);
2016
8.55k
                typeSpec->isUnsigned(typeSpec->isUnsigned() || isUnsigned);
2017
2018
                // Remove specifiers
2019
8.55k
                const Token* tok3 = tok->previous();
2020
8.55k
                tok2 = tok2->previous();
2021
17.1k
                while (tok3 != tok2) {
2022
8.55k
                    if (tok2 != typeSpec &&
2023
8.55k
                        (isComplex || !Token::Match(tok2, "complex|_Complex")))  // Ensure that "complex" is not the variables name
2024
0
                        tok2->deleteThis();
2025
8.55k
                    tok2 = tok2->previous();
2026
8.55k
                }
2027
8.55k
            }
2028
8.55k
        }
2029
92.7k
    }
2030
1.36k
}
2031
2032
bool TokenList::isKeyword(const std::string &str) const
2033
78.3k
{
2034
78.3k
    if (mIsCpp) {
2035
        // TODO: integrate into keywords?
2036
        // types and literals are not handled as keywords
2037
78.3k
        static const std::unordered_set<std::string> cpp_types = {"bool", "false", "true"};
2038
78.3k
        if (cpp_types.find(str) != cpp_types.end())
2039
0
            return false;
2040
2041
        // TODO: properly apply configured standard
2042
78.3k
        if (!mSettings || mSettings->standards.cpp >= Standards::CPP20) {
2043
78.3k
            static const auto& cpp20_keywords = Keywords::getAll(Standards::cppstd_t::CPP20);
2044
78.3k
            return cpp20_keywords.find(str) != cpp20_keywords.end();
2045
78.3k
        }
2046
2047
0
        static const auto& cpp_keywords = Keywords::getAll(Standards::cppstd_t::CPP11);
2048
0
        return cpp_keywords.find(str) != cpp_keywords.end();
2049
78.3k
    }
2050
2051
    // TODO: integrate into Keywords?
2052
    // types are not handled as keywords
2053
0
    static const std::unordered_set<std::string> c_types = {"char", "double", "float", "int", "long", "short"};
2054
0
    if (c_types.find(str) != c_types.end())
2055
0
        return false;
2056
2057
    // TODO: use configured standard
2058
0
    static const auto& c_keywords = Keywords::getAll(Standards::cstd_t::C99);
2059
0
    return c_keywords.find(str) != c_keywords.end();
2060
0
}