LCOV - code coverage report
Current view: top level - lib - tokenize.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 6129 6871 89.2 %
Date: 2024-04-28 12:00:40 Functions: 211 216 97.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Cppcheck - A tool for static C/C++ code analysis
       3             :  * Copyright (C) 2007-2024 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 "tokenize.h"
      21             : 
      22             : #include "errorlogger.h"
      23             : #include "errortypes.h"
      24             : #include "library.h"
      25             : #include "mathlib.h"
      26             : #include "path.h"
      27             : #include "platform.h"
      28             : #include "preprocessor.h"
      29             : #include "settings.h"
      30             : #include "standards.h"
      31             : #include "summaries.h"
      32             : #include "symboldatabase.h"
      33             : #include "templatesimplifier.h"
      34             : #include "timer.h"
      35             : #include "token.h"
      36             : #include "utils.h"
      37             : #include "valueflow.h"
      38             : #include "vfvalue.h"
      39             : 
      40             : #include <algorithm>
      41             : #include <cassert>
      42             : #include <cctype>
      43             : #include <cstdlib>
      44             : #include <cstring>
      45             : #include <ctime>
      46             : #include <iostream>
      47             : #include <iterator>
      48             : #include <exception>
      49             : #include <memory>
      50             : #include <set>
      51             : #include <sstream>
      52             : #include <stack>
      53             : #include <stdexcept>
      54             : #include <unordered_map>
      55             : #include <unordered_set>
      56             : #include <utility>
      57             : #include <vector>
      58             : 
      59             : #include <simplecpp.h>
      60             : 
      61             : //---------------------------------------------------------------------------
      62             : 
      63             : namespace {
      64             :     // local struct used in setVarId
      65             :     // in order to store information about the scope
      66             :     struct VarIdScopeInfo {
      67       22632 :         VarIdScopeInfo() = default;
      68       50521 :         VarIdScopeInfo(bool isExecutable, bool isStructInit, bool isEnum, nonneg int startVarid)
      69       50521 :             : isExecutable(isExecutable), isStructInit(isStructInit), isEnum(isEnum), startVarid(startVarid) {}
      70             : 
      71             :         const bool isExecutable{};
      72             :         const bool isStructInit{};
      73             :         const bool isEnum{};
      74             :         const nonneg int startVarid{};
      75             :     };
      76             : }
      77             : 
      78             : /** Return whether tok is the "{" that starts an enumerator list */
      79       14858 : static bool isEnumStart(const Token* tok)
      80             : {
      81       14858 :     if (!tok || tok->str() != "{")
      82           0 :         return false;
      83       14859 :     return (tok->strAt(-1) == "enum") || (tok->strAt(-2) == "enum") || Token::Match(tok->tokAt(-3), "enum class %name%");
      84             : }
      85             : 
      86             : template<typename T>
      87           8 : static void skipEnumBody(T *&tok)
      88             : {
      89           8 :     T *defStart = tok;
      90          34 :     while (Token::Match(defStart, "%name%|::|:"))
      91          26 :         defStart = defStart->next();
      92           8 :     if (defStart && defStart->str() == "{")
      93           7 :         tok = defStart->link()->next();
      94           8 : }
      95             : 
      96      496336 : const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith)
      97             : {
      98      496336 :     if (!tok)
      99           1 :         return nullptr;
     100      496335 :     if (tok->str() == "(")
     101      272519 :         tok = tok->link();
     102      496334 :     if (tok->str() != ")")
     103         130 :         return nullptr;
     104      496201 :     if (!tok->isCpp() && !Token::Match(tok->link()->previous(), "%name%|)"))
     105       11682 :         return nullptr;
     106      484519 :     if (Token::Match(tok, ") ;|{|[")) {
     107      375663 :         tok = tok->next();
     108      376114 :         while (tok && tok->str() == "[" && tok->link()) {
     109         458 :             if (endsWith.find(tok->str()) != std::string::npos)
     110           1 :                 return tok;
     111         457 :             tok = tok->link()->next();
     112             :         }
     113      375655 :         return (tok && endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr;
     114             :     }
     115      108853 :     if (tok->isCpp() && tok->str() == ")") {
     116      107660 :         tok = tok->next();
     117      343344 :         while (Token::Match(tok, "const|noexcept|override|final|volatile|mutable|&|&& !!(") ||
     118      167810 :                (Token::Match(tok, "%name% !!(") && tok->isUpperCaseName()))
     119       67875 :             tok = tok->next();
     120      107661 :         if (tok && tok->str() == ")")
     121       67410 :             tok = tok->next();
     122      107716 :         while (tok && tok->str() == "[")
     123          56 :             tok = tok->link()->next();
     124      107660 :         if (Token::Match(tok, "throw|noexcept ("))
     125        1167 :             tok = tok->linkAt(1)->next();
     126      107660 :         if (Token::Match(tok, "%name% (") && tok->isUpperCaseName())
     127          73 :             tok = tok->linkAt(1)->next();
     128      107662 :         if (tok && tok->originalName() == "->") { // trailing return type
     129        3387 :             for (tok = tok->next(); tok && !Token::Match(tok, ";|{|override|final"); tok = tok->next())
     130        2457 :                 if (tok->link() && Token::Match(tok, "<|[|("))
     131         319 :                     tok = tok->link();
     132             :         }
     133      335384 :         while (Token::Match(tok, "override|final !!(") ||
     134      167661 :                (Token::Match(tok, "%name% !!(") && tok->isUpperCaseName()))
     135       60061 :             tok = tok->next();
     136      107663 :         if (Token::Match(tok, "= 0|default|delete ;"))
     137        1244 :             tok = tok->tokAt(2);
     138      107662 :         if (tok && tok->str() == ":" && !Token::Match(tok->next(), "%name%|::"))
     139         126 :             return nullptr;
     140      107536 :         return (tok && endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr;
     141             :     }
     142        1192 :     return nullptr;
     143             : }
     144             : 
     145             : /**
     146             :  * is tok the start brace { of a class, struct, union, or enum
     147             :  */
     148        4416 : static bool isClassStructUnionEnumStart(const Token * tok)
     149             : {
     150        4416 :     if (!Token::Match(tok->previous(), "class|struct|union|enum|%name%|>|>> {"))
     151         947 :         return false;
     152        3466 :     const Token * tok2 = tok->previous();
     153        8401 :     while (tok2 && !Token::Match(tok2, "class|struct|union|enum|{|}|;"))
     154        4935 :         tok2 = tok2->previous();
     155        3466 :     return Token::Match(tok2, "class|struct|union|enum");
     156             : }
     157             : 
     158             : //---------------------------------------------------------------------------
     159             : 
     160       23898 : Tokenizer::Tokenizer(const Settings &settings, ErrorLogger &errorLogger) :
     161             :     list(&settings),
     162             :     mSettings(settings),
     163             :     mErrorLogger(errorLogger),
     164       23898 :     mTemplateSimplifier(new TemplateSimplifier(*this))
     165       23898 : {}
     166             : 
     167       23897 : Tokenizer::~Tokenizer()
     168             : {
     169       23898 :     delete mSymbolDatabase;
     170       23898 :     delete mTemplateSimplifier;
     171       23898 : }
     172             : 
     173             : 
     174             : //---------------------------------------------------------------------------
     175             : // SizeOfType - gives the size of a type
     176             : //---------------------------------------------------------------------------
     177             : 
     178         722 : nonneg int Tokenizer::sizeOfType(const std::string& type) const
     179             : {
     180         722 :     const std::map<std::string, int>::const_iterator it = mTypeSize.find(type);
     181         722 :     if (it == mTypeSize.end()) {
     182         696 :         const Library::PodType* podtype = mSettings.library.podtype(type);
     183         696 :         if (!podtype)
     184         696 :             return 0;
     185             : 
     186           0 :         return podtype->size;
     187             :     }
     188          26 :     return it->second;
     189             : }
     190             : 
     191          35 : nonneg int Tokenizer::sizeOfType(const Token *type) const
     192             : {
     193          35 :     if (!type || type->str().empty())
     194           0 :         return 0;
     195             : 
     196          35 :     if (type->tokType() == Token::eString)
     197           0 :         return Token::getStrLength(type) + 1U;
     198             : 
     199          35 :     const std::map<std::string, int>::const_iterator it = mTypeSize.find(type->str());
     200          35 :     if (it == mTypeSize.end()) {
     201           4 :         const Library::PodType* podtype = mSettings.library.podtype(type->str());
     202           4 :         if (!podtype)
     203           4 :             return 0;
     204             : 
     205           0 :         return podtype->size;
     206             :     }
     207          31 :     if (type->isLong()) {
     208           0 :         if (type->str() == "double")
     209           0 :             return mSettings.platform.sizeof_long_double;
     210           0 :         if (type->str() == "long")
     211           0 :             return mSettings.platform.sizeof_long_long;
     212             :     }
     213             : 
     214          31 :     return it->second;
     215             : }
     216             : //---------------------------------------------------------------------------
     217             : 
     218             : // check if this statement is a duplicate definition
     219         341 : bool Tokenizer::duplicateTypedef(Token *&tokPtr, const Token *name, const Token *typeDef) const
     220             : {
     221             :     // check for an end of definition
     222         341 :     Token * tok = tokPtr;
     223         341 :     if (tok && Token::Match(tok->next(), ";|,|[|=|)|>|(|{")) {
     224          58 :         Token * end = tok->next();
     225             : 
     226          58 :         if (end->str() == "[") {
     227           0 :             if (!end->link())
     228           0 :                 syntaxError(end); // invalid code
     229           0 :             end = end->link()->next();
     230          58 :         } else if (end->str() == ",") {
     231             :             // check for derived class
     232           4 :             if (Token::Match(tok->previous(), "public|private|protected"))
     233           0 :                 return false;
     234             : 
     235             :             // find end of definition
     236           8 :             while (end && end->next() && !Token::Match(end->next(), ";|)|>")) {
     237           4 :                 if (end->next()->str() == "(")
     238           0 :                     end = end->linkAt(1);
     239             : 
     240           4 :                 end = (end)?end->next():nullptr;
     241             :             }
     242           4 :             if (end)
     243           4 :                 end = end->next();
     244          54 :         } else if (end->str() == "(") {
     245          19 :             if (startsWith(tok->previous()->str(), "operator"))
     246             :                 // conversion operator
     247           9 :                 return false;
     248          10 :             if (tok->previous()->str() == "typedef")
     249             :                 // typedef of function returning this type
     250           0 :                 return false;
     251          10 :             if (Token::Match(tok->previous(), "public:|private:|protected:"))
     252           0 :                 return false;
     253          10 :             if (tok->previous()->str() == ">") {
     254           2 :                 if (!Token::Match(tok->tokAt(-2), "%type%"))
     255           1 :                     return false;
     256             : 
     257           1 :                 if (!Token::Match(tok->tokAt(-3), ",|<"))
     258           1 :                     return false;
     259             : 
     260           0 :                 tokPtr = end->link();
     261           0 :                 return true;
     262             :             }
     263             :         }
     264             : 
     265          47 :         if (end) {
     266          47 :             if (Token::simpleMatch(end, ") {")) { // function parameter ?
     267             :                 // look backwards
     268           0 :                 if (Token::Match(tok->previous(), "%type%") &&
     269           0 :                     !Token::Match(tok->previous(), "return|new|const|struct")) {
     270             :                     // duplicate definition so skip entire function
     271           0 :                     tokPtr = end->next()->link();
     272           0 :                     return true;
     273             :                 }
     274          47 :             } else if (end->str() == ">") { // template parameter ?
     275             :                 // look backwards
     276          18 :                 if (Token::Match(tok->previous(), "%type%") &&
     277           0 :                     !Token::Match(tok->previous(), "return|new|const|volatile")) {
     278             :                     // duplicate definition so skip entire template
     279           0 :                     while (end && end->str() != "{")
     280           0 :                         end = end->next();
     281           0 :                     if (end) {
     282           0 :                         tokPtr = end->link();
     283           0 :                         return true;
     284             :                     }
     285             :                 }
     286             :             } else {
     287             :                 // look backwards
     288          55 :                 if (Token::Match(tok->previous(), "typedef|}|>") ||
     289          56 :                     (end->str() == ";" && tok->previous()->str() == ",") ||
     290          82 :                     (tok->previous()->str() == "*" && tok->next()->str() != "(") ||
     291          26 :                     (Token::Match(tok->previous(), "%type%") &&
     292           8 :                      (!Token::Match(tok->previous(), "return|new|const|friend|public|private|protected|throw|extern") &&
     293           4 :                       !Token::simpleMatch(tok->tokAt(-2), "friend class")))) {
     294             :                     // scan backwards for the end of the previous statement
     295          17 :                     while (tok && tok->previous() && !Token::Match(tok->previous(), ";|{")) {
     296          16 :                         if (tok->previous()->str() == "}") {
     297           3 :                             tok = tok->previous()->link();
     298          13 :                         } else if (tok->previous()->str() == "typedef") {
     299           4 :                             return true;
     300           9 :                         } else if (tok->previous()->str() == "enum") {
     301           0 :                             return true;
     302           9 :                         } else if (tok->previous()->str() == "struct") {
     303           4 :                             if (tok->strAt(-2) == "typedef" &&
     304           4 :                                 tok->next()->str() == "{" &&
     305           2 :                                 typeDef->strAt(3) != "{") {
     306             :                                 // declaration after forward declaration
     307           2 :                                 return true;
     308             :                             }
     309           0 :                             if (tok->next()->str() == "{")
     310           0 :                                 return true;
     311           0 :                             if (Token::Match(tok->next(), ")|*"))
     312           0 :                                 return true;
     313           0 :                             if (tok->next()->str() == name->str())
     314           0 :                                 return true;
     315           0 :                             if (tok->next()->str() != ";")
     316           0 :                                 return true;
     317           0 :                             return false;
     318           7 :                         } else if (tok->previous()->str() == "union") {
     319           0 :                             return tok->next()->str() != ";";
     320           7 :                         } else if (tok->isCpp() && tok->previous()->str() == "class") {
     321           0 :                             return tok->next()->str() != ";";
     322             :                         }
     323          10 :                         if (tok)
     324          10 :                             tok = tok->previous();
     325             :                     }
     326             : 
     327           1 :                     if (tokPtr->strAt(1) != "(" || !Token::Match(tokPtr->linkAt(1), ") .|(|["))
     328           0 :                         return true;
     329             :                 }
     330             :             }
     331             :         }
     332             :     }
     333             : 
     334         324 :     return false;
     335             : }
     336             : 
     337           4 : void Tokenizer::unsupportedTypedef(const Token *tok) const
     338             : {
     339           4 :     if (!mSettings.debugwarnings)
     340           1 :         return;
     341             : 
     342           3 :     std::ostringstream str;
     343           3 :     const Token *tok1 = tok;
     344           3 :     int level = 0;
     345          17 :     while (tok) {
     346          17 :         if (level == 0 && tok->str() == ";")
     347           3 :             break;
     348          14 :         if (tok->str() == "{")
     349           0 :             ++level;
     350          14 :         else if (tok->str() == "}") {
     351           0 :             if (level == 0)
     352           0 :                 break;
     353           0 :             --level;
     354             :         }
     355             : 
     356          14 :         if (tok != tok1)
     357          11 :             str << " ";
     358          14 :         str << tok->str();
     359          14 :         tok = tok->next();
     360             :     }
     361           3 :     if (tok)
     362           3 :         str << " ;";
     363             : 
     364           3 :     reportError(tok1, Severity::debug, "simplifyTypedef",
     365           6 :                 "Failed to parse \'" + str.str() + "\'. The checking continues anyway.");
     366             : }
     367             : 
     368           4 : Token * Tokenizer::deleteInvalidTypedef(Token *typeDef)
     369             : {
     370           4 :     Token *tok = nullptr;
     371             : 
     372             :     // remove typedef but leave ;
     373          19 :     while (typeDef->next()) {
     374          19 :         if (typeDef->next()->str() == ";") {
     375           4 :             typeDef->deleteNext();
     376           4 :             break;
     377             :         }
     378          15 :         if (typeDef->next()->str() == "{")
     379           1 :             Token::eraseTokens(typeDef, typeDef->linkAt(1));
     380          14 :         else if (typeDef->next()->str() == "}")
     381           0 :             break;
     382          15 :         typeDef->deleteNext();
     383             :     }
     384             : 
     385           4 :     if (typeDef != list.front()) {
     386           1 :         tok = typeDef->previous();
     387           1 :         tok->deleteNext();
     388             :     } else {
     389           3 :         list.front()->deleteThis();
     390           3 :         tok = list.front();
     391             :     }
     392             : 
     393           4 :     return tok;
     394             : }
     395             : 
     396             : namespace {
     397             :     struct Space {
     398             :         std::string className;
     399             :         const Token* bodyEnd{};  // for body contains typedef define
     400             :         const Token* bodyEnd2{}; // for body contains typedef using
     401             :         bool isNamespace{};
     402             :         std::set<std::string> recordTypes;
     403             :     };
     404             : }
     405             : 
     406          31 : static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount)
     407             : {
     408          62 :     std::string name;
     409          62 :     std::set<std::string> qualifiers;
     410             : 
     411          32 :     while (Token::Match(tok->next(), "const|volatile")) {
     412           1 :         qualifiers.insert(tok->next()->str());
     413           1 :         tok->deleteNext();
     414             :     }
     415             : 
     416             :     // skip "class|struct|union|enum"
     417          31 :     Token *tok1 = tok->tokAt(2);
     418             : 
     419          31 :     const bool hasName = Token::Match(tok1, "%name%");
     420             : 
     421             :     // skip name
     422          31 :     if (hasName) {
     423          27 :         name = tok1->str();
     424          27 :         tok1 = tok1->next();
     425             :     }
     426             : 
     427             :     // skip base classes if present
     428          31 :     if (tok1->str() == ":") {
     429           3 :         tok1 = tok1->next();
     430           9 :         while (tok1 && tok1->str() != "{")
     431           6 :             tok1 = tok1->next();
     432           3 :         if (!tok1)
     433           0 :             return nullptr;
     434             :     }
     435             : 
     436             :     // skip to end
     437          31 :     tok1 = tok1->link();
     438             : 
     439          31 :     if (!hasName) { // unnamed
     440           4 :         if (tok1->next()) {
     441             :             // use typedef name if available
     442           4 :             if (Token::Match(tok1->next(), "%type%"))
     443           3 :                 name = tok1->next()->str();
     444             :             else // create a unique name
     445           1 :                 name = "Unnamed" + std::to_string((*unnamedCount)++);
     446           4 :             tok->next()->insertToken(name);
     447             :         } else
     448           0 :             return nullptr;
     449             :     }
     450             : 
     451          31 :     tok1->insertToken(";");
     452          31 :     tok1 = tok1->next();
     453             : 
     454          31 :     if (tok1->next() && tok1->next()->str() == ";" && tok1->previous()->str() == "}") {
     455           1 :         tok->deleteThis();
     456           1 :         tok1->deleteThis();
     457           1 :         return nullptr;
     458             :     }
     459          30 :     tok1->insertToken("typedef");
     460          30 :     tok1 = tok1->next();
     461          30 :     Token * tok3 = tok1;
     462          31 :     for (const std::string &qualifier : qualifiers) {
     463           1 :         tok1->insertToken(qualifier);
     464           1 :         tok1 = tok1->next();
     465             :     }
     466          30 :     tok1->insertToken(tok->next()->str()); // struct, union or enum
     467          30 :     tok1 = tok1->next();
     468          30 :     tok1->insertToken(name);
     469          30 :     tok->deleteThis();
     470          30 :     tok = tok3;
     471             : 
     472          30 :     return tok;
     473             : }
     474             : 
     475             : /* This function is called when processing function related typedefs.
     476             :  * If simplifyTypedef generates an "Internal Error" message and the
     477             :  * code that generated it deals in some way with functions, then this
     478             :  * function will probably need to be extended to handle a new function
     479             :  * related pattern */
     480         113 : const Token *Tokenizer::processFunc(const Token *tok2, bool inOperator) const
     481             : {
     482         226 :     if (tok2->next() && tok2->next()->str() != ")" &&
     483         113 :         tok2->next()->str() != ",") {
     484             :         // skip over tokens for some types of canonicalization
     485         112 :         if (Token::Match(tok2->next(), "( * %type% ) ("))
     486           0 :             tok2 = tok2->linkAt(5);
     487         112 :         else if (Token::Match(tok2->next(), "* ( * %type% ) ("))
     488           0 :             tok2 = tok2->linkAt(6);
     489         112 :         else if (Token::Match(tok2->next(), "* ( * %type% ) ;"))
     490           1 :             tok2 = tok2->tokAt(5);
     491         111 :         else if (Token::Match(tok2->next(), "* ( %type% [") &&
     492           0 :                  Token::Match(tok2->linkAt(4), "] ) ;|="))
     493           0 :             tok2 = tok2->linkAt(4)->next();
     494         111 :         else if (Token::Match(tok2->next(), "* ( * %type% ("))
     495           0 :             tok2 = tok2->linkAt(5)->next();
     496         112 :         else if (Token::simpleMatch(tok2->next(), "* [") &&
     497           1 :                  Token::simpleMatch(tok2->linkAt(2), "] ;"))
     498           1 :             tok2 = tok2->next();
     499             :         else {
     500         110 :             if (tok2->next()->str() == "(")
     501           2 :                 tok2 = tok2->next()->link();
     502         108 :             else if (!inOperator && !Token::Match(tok2->next(), "[|>|;")) {
     503         107 :                 tok2 = tok2->next();
     504             : 
     505         121 :                 while (Token::Match(tok2, "*|&") &&
     506          12 :                        !Token::Match(tok2->next(), ")|>"))
     507           2 :                     tok2 = tok2->next();
     508             : 
     509             :                 // skip over namespace
     510         113 :                 while (Token::Match(tok2, "%name% ::"))
     511           6 :                     tok2 = tok2->tokAt(2);
     512             : 
     513         107 :                 if (!tok2)
     514           0 :                     return nullptr;
     515             : 
     516         107 :                 if (tok2->str() == "(" &&
     517         107 :                     tok2->link()->next() &&
     518           0 :                     tok2->link()->next()->str() == "(") {
     519           0 :                     tok2 = tok2->link();
     520             : 
     521           0 :                     if (tok2->next()->str() == "(")
     522           0 :                         tok2 = tok2->next()->link();
     523             :                 }
     524             : 
     525             :                 // skip over typedef parameter
     526         107 :                 if (tok2->next() && tok2->next()->str() == "(") {
     527          15 :                     tok2 = tok2->next()->link();
     528          15 :                     if (!tok2->next())
     529           0 :                         syntaxError(tok2);
     530             : 
     531          15 :                     if (tok2->next()->str() == "(")
     532           0 :                         tok2 = tok2->next()->link();
     533             :                 }
     534             :             }
     535             :         }
     536             :     }
     537         113 :     return tok2;
     538             : }
     539             : 
     540         113 : Token *Tokenizer::processFunc(Token *tok2, bool inOperator)
     541             : {
     542         113 :     return const_cast<Token*>(processFunc(const_cast<const Token*>(tok2), inOperator));
     543             : }
     544             : 
     545       22683 : void Tokenizer::simplifyUsingToTypedef()
     546             : {
     547       22683 :     if (!isCPP() || mSettings.standards.cpp < Standards::CPP11)
     548        6009 :         return;
     549             : 
     550      753246 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
     551             :         // using a::b;  =>   typedef  a::b  b;
     552     1473150 :         if ((Token::Match(tok, "[;{}] using %name% :: %name% ::|;") && !tok->tokAt(2)->isKeyword()) ||
     553      736574 :             (Token::Match(tok, "[;{}] using :: %name% :: %name% ::|;") && !tok->tokAt(3)->isKeyword())) {
     554           7 :             Token *endtok = tok->tokAt(5);
     555           7 :             if (Token::Match(endtok, "%name%"))
     556           3 :                 endtok = endtok->next();
     557           7 :             while (Token::Match(endtok, ":: %name%"))
     558           0 :                 endtok = endtok->tokAt(2);
     559           7 :             if (endtok && endtok->str() == ";") {
     560           7 :                 tok->next()->str("typedef");
     561           7 :                 endtok = endtok->previous();
     562           7 :                 endtok->insertToken(endtok->str());
     563             :             }
     564             :         }
     565             :     }
     566             : }
     567             : 
     568       22651 : void Tokenizer::simplifyTypedefLHS()
     569             : {
     570       22651 :     if (!list.front())
     571           0 :         return;
     572             : 
     573     1001646 :     for (Token* tok = list.front()->next(); tok; tok = tok->next()) {
     574      978998 :         if (tok->str() == "typedef") {
     575         355 :             bool doSimplify = !Token::Match(tok->previous(), ";|{|}|:|public:|private:|protected:");
     576         355 :             if (doSimplify && Token::simpleMatch(tok->previous(), ")") && Token::Match(tok->linkAt(-1)->previous(), "if|for|while"))
     577           0 :                 doSimplify = false;
     578         355 :             bool haveStart = false;
     579         355 :             Token* start{};
     580         355 :             if (!doSimplify && Token::simpleMatch(tok->previous(), "}")) {
     581          26 :                 start = tok->linkAt(-1)->previous();
     582          39 :                 while (Token::Match(start, "%name%")) {
     583          16 :                     if (Token::Match(start, "class|struct|union|enum")) {
     584           3 :                         start = start->previous();
     585           3 :                         doSimplify = true;
     586           3 :                         haveStart = true;
     587           3 :                         break;
     588             :                     }
     589          13 :                     start = start->previous();
     590             :                 }
     591             :             }
     592         355 :             if (doSimplify) {
     593          12 :                 if (!haveStart) {
     594           9 :                     start = tok;
     595          46 :                     while (start && !Token::Match(start, "[;{}]"))
     596          37 :                         start = start->previous();
     597             :                 }
     598          12 :                 if (start)
     599           6 :                     start = start->next();
     600             :                 else
     601           6 :                     start = list.front();
     602          12 :                 start->insertTokenBefore(tok->str());
     603          12 :                 tok->deleteThis();
     604             :             }
     605             :         }
     606             :     }
     607             : }
     608             : 
     609             : namespace {
     610             :     class TypedefSimplifier {
     611             :     private:
     612             :         Token* mTypedefToken;  // The "typedef" token
     613             :         Token* mEndToken{nullptr};  // Semicolon
     614             :         std::pair<Token*, Token*> mRangeType;
     615             :         std::pair<Token*, Token*> mRangeTypeQualifiers;
     616             :         std::pair<Token*, Token*> mRangeAfterVar;
     617             :         Token* mNameToken{nullptr};
     618             :         bool mFail = false;
     619             :         bool mReplaceFailed = false;
     620             :         bool mUsed = false;
     621             : 
     622             :     public:
     623        1154 :         explicit TypedefSimplifier(Token* typedefToken) : mTypedefToken(typedefToken) {
     624        1154 :             Token* start = typedefToken->next();
     625        1154 :             if (Token::simpleMatch(start, "typename"))
     626          21 :                 start = start->next();
     627             : 
     628             :             // TODO handle unnamed structs etc
     629        1154 :             if (Token::Match(start, "const| enum|struct|union|class %name%| {")) {
     630         197 :                 const std::pair<Token*, Token*> rangeBefore(start, Token::findsimplematch(start, "{"));
     631             : 
     632             :                 // find typedef name token
     633         197 :                 Token* nameToken = rangeBefore.second->link()->next();
     634         225 :                 while (Token::Match(nameToken, "%name%|* %name%|*"))
     635          28 :                     nameToken = nameToken->next();
     636         197 :                 const std::pair<Token*, Token*> rangeQualifiers(rangeBefore.second->link()->next(), nameToken);
     637             : 
     638         197 :                 if (Token::Match(nameToken, "%name% ;")) {
     639         183 :                     if (Token::Match(rangeBefore.second->previous(), "enum|struct|union|class {"))
     640          66 :                         rangeBefore.second->previous()->insertToken(nameToken->str());
     641         183 :                     mRangeType = rangeBefore;
     642         183 :                     mRangeTypeQualifiers = rangeQualifiers;
     643         183 :                     Token* typeName = rangeBefore.second->previous();
     644         183 :                     if (typeName->isKeyword()) {
     645             :                         // TODO typeName->insertToken("T:" + std::to_string(num++));
     646           0 :                         typeName->insertToken(nameToken->str());
     647             :                     }
     648         183 :                     mNameToken = nameToken;
     649         183 :                     mEndToken = nameToken->next();
     650         183 :                     return;
     651             :                 }
     652             :             }
     653             : 
     654        2131 :             for (Token* type = start; Token::Match(type, "%name%|*|&|&&"); type = type->next()) {
     655        1777 :                 if (type != start && Token::Match(type, "%name% ;") && !type->isStandardType()) {
     656         296 :                     mRangeType.first = start;
     657         296 :                     mRangeType.second = type;
     658         296 :                     mNameToken = type;
     659         296 :                     mEndToken = mNameToken->next();
     660         296 :                     return;
     661             :                 }
     662        1481 :                 if (type != start && Token::Match(type, "%name% [")) {
     663         112 :                     Token* end = type->linkAt(1);
     664         120 :                     while (Token::simpleMatch(end, "] ["))
     665           8 :                         end = end->linkAt(1);
     666         112 :                     if (!Token::simpleMatch(end, "] ;"))
     667           0 :                         break;
     668         112 :                     mRangeType.first = start;
     669         112 :                     mRangeType.second = type;
     670         112 :                     mNameToken = type;
     671         112 :                     mEndToken = end->next();
     672         112 :                     mRangeAfterVar.first = mNameToken->next();
     673         112 :                     mRangeAfterVar.second = mEndToken;
     674         112 :                     return;
     675             :                 }
     676        1369 :                 if (Token::Match(type->next(), "( * const| %name% ) (") && Token::simpleMatch(type->linkAt(1)->linkAt(1), ") ;")) {
     677         156 :                     mNameToken = type->linkAt(1)->previous();
     678         156 :                     mEndToken = type->linkAt(1)->linkAt(1)->next();
     679         156 :                     mRangeType.first = start;
     680         156 :                     mRangeType.second = mNameToken;
     681         156 :                     mRangeAfterVar.first = mNameToken->next();
     682         156 :                     mRangeAfterVar.second = mEndToken;
     683         156 :                     return;
     684             :                 }
     685        1213 :                 if (Token::Match(type, "%name% ( !!(") && Token::simpleMatch(type->linkAt(1), ") ;") && !type->isStandardType()) {
     686          53 :                     mNameToken = type;
     687          53 :                     mEndToken = type->linkAt(1)->next();
     688          53 :                     mRangeType.first = start;
     689          53 :                     mRangeType.second = type;
     690          53 :                     mRangeAfterVar.first = mNameToken->next();
     691          53 :                     mRangeAfterVar.second = mEndToken;
     692          53 :                     return;
     693             :                 }
     694             :             }
     695             :             // TODO: handle all typedefs
     696             :             if ((false))
     697             :                 printTypedef(typedefToken);
     698         354 :             mFail = true;
     699             :         }
     700             : 
     701         685 :         const Token* getTypedefToken() const {
     702         685 :             return mTypedefToken;
     703             :         }
     704             : 
     705         323 :         bool isUsed() const {
     706         323 :             return mUsed;
     707             :         }
     708             : 
     709          77 :         bool isInvalidConstFunctionType(const std::map<std::string, TypedefSimplifier>& m) const {
     710          77 :             if (!Token::Match(mTypedefToken, "typedef const %name% %name% ;"))
     711          76 :                 return false;
     712           1 :             const auto it = m.find(mTypedefToken->strAt(2));
     713           1 :             if (it == m.end())
     714           0 :                 return false;
     715           1 :             return Token::Match(it->second.mNameToken, "%name% (");
     716             :         }
     717             : 
     718        1154 :         bool fail() const {
     719        1154 :             return mFail;
     720             :         }
     721             : 
     722         323 :         bool replaceFailed() const {
     723         323 :             return mReplaceFailed;
     724             :         }
     725             : 
     726         323 :         bool isStructEtc() const {
     727         323 :             return mRangeType.second && mRangeType.second->str() == "{";
     728             :         }
     729             : 
     730        1446 :         std::string name() const {
     731        2892 :             return mNameToken ? mNameToken->str() : "";
     732             :         }
     733             : 
     734         355 :         void replace(Token* tok) {
     735         355 :             if (tok == mNameToken)
     736          11 :                 return;
     737             : 
     738         355 :             mUsed = true;
     739             : 
     740             :             // Special handling for T() when T is a pointer
     741         355 :             if (Token::Match(tok, "%name% ( )")) {
     742           4 :                 bool pointerType = false;
     743          10 :                 for (const Token* type = mRangeType.first; type != mRangeType.second; type = type->next()) {
     744           8 :                     if (type->str() == "*" || type->str() == "&") {
     745           2 :                         pointerType = true;
     746           2 :                         break;
     747             :                     }
     748             :                 }
     749           4 :                 for (const Token* type = mRangeTypeQualifiers.first; type != mRangeTypeQualifiers.second; type = type->next()) {
     750           0 :                     if (type->str() == "*" || type->str() == "&") {
     751           0 :                         pointerType = true;
     752           0 :                         break;
     753             :                     }
     754             :                 }
     755           4 :                 if (pointerType) {
     756           2 :                     tok->deleteThis();
     757           2 :                     tok->next()->insertToken("0");
     758           2 :                     Token* tok2 = insertTokens(tok, mRangeType);
     759           2 :                     insertTokens(tok2, mRangeTypeQualifiers);
     760           2 :                     return;
     761             :                 }
     762             :             }
     763             : 
     764             :             // Special handling of function pointer cast
     765         353 :             const bool isFunctionPointer = Token::Match(mNameToken, "%name% )");
     766         353 :             if (isFunctionPointer && isCast(tok->previous())) {
     767           3 :                 tok->insertToken("*");
     768           3 :                 insertTokens(tok, std::pair<Token*, Token*>(mRangeType.first, mNameToken->linkAt(1)));
     769           3 :                 tok->deleteThis();
     770           3 :                 return;
     771             :             }
     772             : 
     773             :             // Inherited type => skip "struct" / "class"
     774         350 :             if (Token::Match(mRangeType.first, "const| struct|class %name% {") && Token::Match(tok->previous(), "public|protected|private|<")) {
     775           4 :                 tok->originalName(tok->str());
     776           4 :                 tok->str(mRangeType.second->previous()->str());
     777           4 :                 return;
     778             :             }
     779             : 
     780         346 :             if (Token::Match(tok, "%name% ::")) {
     781           2 :                 if (Token::Match(mRangeType.first, "const| struct|class %name% %name% ;")) {
     782           2 :                     tok->originalName(tok->str());
     783           2 :                     tok->str(mRangeType.second->previous()->str());
     784             :                 } else {
     785           0 :                     mReplaceFailed = true;
     786             :                 }
     787           2 :                 return;
     788             :             }
     789             : 
     790             :             // pointer => move "const"
     791         344 :             if (Token::simpleMatch(tok->previous(), "const")) {
     792          24 :                 bool pointerType = false;
     793          58 :                 for (const Token* type = mRangeType.first; type != mRangeType.second; type = type->next()) {
     794          39 :                     if (type->str() == "*") {
     795           5 :                         pointerType = true;
     796           5 :                         break;
     797             :                     }
     798             :                 }
     799          24 :                 if (pointerType) {
     800           5 :                     tok->insertToken("const");
     801           5 :                     tok->next()->column(tok->column());
     802           5 :                     tok->next()->setMacroName(tok->previous()->getMacroName());
     803           5 :                     tok->deletePrevious();
     804             :                 }
     805             :             }
     806             : 
     807             :             // Do not duplicate class/struct/enum/union
     808         344 :             if (Token::Match(tok->previous(), "enum|union|struct|class")) {
     809           2 :                 bool found = false;
     810           2 :                 const std::string &kw = tok->previous()->str();
     811           2 :                 for (const Token* type = mRangeType.first; type != mRangeType.second; type = type->next()) {
     812           2 :                     if (type->str() == kw) {
     813           2 :                         found = true;
     814           2 :                         break;
     815             :                     }
     816             :                 }
     817           2 :                 if (found)
     818           2 :                     tok->deletePrevious();
     819             :                 else {
     820           0 :                     mReplaceFailed = true;
     821           0 :                     return;
     822             :                 }
     823             :             }
     824             : 
     825             :             // don't add class|struct|union in inheritance list
     826         344 :             auto rangeType = mRangeType;
     827         344 :             if (Token::Match(tok->previous(), "public|private|protected")) {
     828           6 :                 while (Token::Match(rangeType.first, "const|class|struct|union"))
     829           3 :                     rangeType.first = rangeType.first->next();
     830             :             }
     831             : 
     832         344 :             Token* const tok2 = insertTokens(tok, rangeType);
     833         344 :             Token* const tok3 = insertTokens(tok2, mRangeTypeQualifiers);
     834             : 
     835         344 :             tok2->originalName(tok->str());
     836         344 :             tok3->originalName(tok->str());
     837         344 :             Token *after = tok3;
     838        1087 :             while (Token::Match(after, "%name%|*|&|&&|::"))
     839         743 :                 after = after->next();
     840         344 :             if (Token::Match(mNameToken, "%name% (") && Token::simpleMatch(tok3->next(), "*")) {
     841          18 :                 while (Token::Match(after, "(|["))
     842           6 :                     after = after->link()->next();
     843          12 :                 if (after) {
     844          12 :                     tok3->insertToken("(");
     845          12 :                     after->previous()->insertToken(")");
     846          12 :                     Token::createMutualLinks(tok3->next(), after->previous());
     847             :                 }
     848             :             }
     849             : 
     850         344 :             bool useAfterVarRange = true;
     851         344 :             if (Token::simpleMatch(mRangeAfterVar.first, "[")) {
     852          67 :                 if (Token::Match(after->previous(), "%name% ( !!*")) {
     853          11 :                     useAfterVarRange = false;
     854             :                     // Function return type => replace array with "*"
     855          27 :                     for (const Token* a = mRangeAfterVar.first; Token::simpleMatch(a, "["); a = a->link()->next())
     856          16 :                         tok3->insertToken("*");
     857          56 :                 } else if (Token::Match(after->previous(), "%name% ( * %name% ) [")) {
     858           0 :                     after = after->linkAt(4)->next();
     859             :                 } else {
     860          56 :                     Token* prev = after->previous();
     861          56 :                     if (prev->isName() && prev != tok3)
     862          48 :                         prev = prev->previous();
     863          56 :                     if (Token::Match(prev, "*|&|&&") && prev != tok3) {
     864          34 :                         while (Token::Match(prev, "*|&|&&") && prev != tok3)
     865          18 :                             prev = prev->previous();
     866          16 :                         prev->insertToken("(");
     867          16 :                         after->previous()->insertToken(")");
     868             :                     }
     869             :                 }
     870             :             }
     871             : 
     872         344 :             if (isFunctionPointer) {
     873          70 :                 if (Token::Match(after, "( * %name% ) ("))
     874           6 :                     after = after->link()->linkAt(1)->next();
     875          64 :                 else if (after->str() == "(") {
     876           9 :                     useAfterVarRange = false;
     877           9 :                     if (Token::simpleMatch(tok3->previous(), "( *"))
     878           9 :                         tok3->deletePrevious();
     879             :                 }
     880          55 :                 else if (after->str() == "[") {
     881           6 :                     while (after && after->str() == "[")
     882           3 :                         after = after->link()->next();
     883             :                 }
     884             :             }
     885             :             else {
     886         286 :                 while (Token::simpleMatch(after, "["))
     887          12 :                     after = after->link()->next();
     888             :             }
     889             : 
     890         344 :             if (!after)
     891           0 :                 throw InternalError(tok, "Failed to simplify typedef. Is the code valid?");
     892             : 
     893         344 :             Token* const tok4 = useAfterVarRange ? insertTokens(after->previous(), mRangeAfterVar)->next() : tok3->next();
     894             : 
     895         344 :             tok->deleteThis();
     896             : 
     897             :             // Unsplit variable declarations
     898         385 :             if (tok4 && tok4->isSplittedVarDeclEq() &&
     899          41 :                 ((tok4->isCpp() && Token::Match(tok4->tokAt(-2), "&|&& %name% ;")) || Token::Match(tok4->previous(), "] ; %name% = {"))) {
     900           5 :                 tok4->deleteNext();
     901           5 :                 tok4->deleteThis();
     902             :             }
     903             : 
     904             :             // Set links
     905         688 :             std::stack<Token*> brackets;
     906        2068 :             for (; tok != tok4; tok = tok->next()) {
     907        1724 :                 if (Token::Match(tok, "[{([]"))
     908         266 :                     brackets.push(tok);
     909        1458 :                 else if (Token::Match(tok, "[})]]")) {
     910         266 :                     Token::createMutualLinks(brackets.top(), tok);
     911         266 :                     brackets.pop();
     912             :                 }
     913             :             }
     914             :         }
     915             : 
     916         323 :         void removeDeclaration() {
     917         323 :             if (Token::simpleMatch(mRangeType.second, "{")) {
     918         164 :                 while (Token::Match(mTypedefToken, "typedef|const"))
     919          83 :                     mTypedefToken->deleteThis();
     920          81 :                 Token::eraseTokens(mRangeType.second->link(), mEndToken);
     921             :             } else {
     922         242 :                 Token::eraseTokens(mTypedefToken, mEndToken);
     923         242 :                 mTypedefToken->deleteThis();
     924             :             }
     925         323 :         }
     926             : 
     927         840 :         static int canReplaceStatic(const Token* tok) {
     928         840 :             if (!Token::Match(tok, "%name% %name%|*|&|&&|;|(|)|,|::")) {
     929         114 :                 if (Token::Match(tok->previous(), "( %name% =") && Token::Match(tok->linkAt(-1), ") %name%|{") && !tok->tokAt(-2)->isKeyword())
     930           1 :                     return true;
     931         113 :                 if (Token::Match(tok->previous(), ", %name% ="))
     932           3 :                     return true;
     933         110 :                 if (Token::Match(tok->previous(), "new %name% ["))
     934           2 :                     return true;
     935         108 :                 if (Token::Match(tok->previous(), "< %name%") && tok->previous()->findClosingBracket())
     936          24 :                     return true;
     937          84 :                 if (Token::Match(tok->previous(), ", %name% >|>>")) {
     938          30 :                     for (const Token* prev = tok->previous(); prev; prev = prev->previous()) {
     939          30 :                         if (Token::Match(prev, "[;{}(]"))
     940           0 :                             break;
     941          30 :                         if (prev->str() == "<" && prev->findClosingBracket() == tok->next())
     942           5 :                             return true;
     943          25 :                         if (prev->str() == ")")
     944           3 :                             prev = prev->link();
     945             :                     }
     946           0 :                     return true;
     947             :                 }
     948          79 :                 if (Token::Match(tok->previous(), "public|protected|private"))
     949           7 :                     return true;
     950          72 :                 if (Token::Match(tok->previous(), ", %name% :")) {
     951           1 :                     bool isGeneric = false;
     952           4 :                     for (; tok; tok = tok->previous()) {
     953           4 :                         if (Token::Match(tok, ")|]"))
     954           1 :                             tok = tok->link();
     955           3 :                         else if (Token::Match(tok, "[;{}(]")) {
     956           1 :                             isGeneric = Token::simpleMatch(tok->previous(), "_Generic (");
     957           1 :                             break;
     958             :                         }
     959             :                     }
     960           1 :                     return isGeneric;
     961             :                 }
     962          71 :                 return false;
     963             :             }
     964         726 :             return -1;
     965             :         }
     966             : 
     967         604 :         bool canReplace(const Token* tok) {
     968         604 :             if (mNameToken == tok)
     969          81 :                 return false;
     970         523 :             if (!Token::Match(tok->previous(), "%name%|;|{|}|(|,|<") && !Token::Match(tok->previous(), "!!. %name% ("))
     971          18 :                 return false;
     972             :             {
     973         505 :                 const int res = canReplaceStatic(tok);
     974         505 :                 if (res == 0 || res == 1)
     975          85 :                     return res != 0;
     976             :             }
     977         420 :             if (Token::Match(tok->previous(), "%name%") && !tok->previous()->isKeyword())
     978           5 :                 return false;
     979         415 :             if (Token::simpleMatch(tok->next(), "(") && Token::Match(tok->linkAt(1), ") %name%|{"))
     980           0 :                 return false;
     981         415 :             if (Token::Match(tok->previous(), "struct|union|class|enum %name% %name%") &&
     982         451 :                 Token::simpleMatch(mRangeType.second, "{") &&
     983          36 :                 tok->str() != mRangeType.second->previous()->str())
     984           2 :                 return true;
     985         413 :             if (Token::Match(tok->previous(), "; %name% ;"))
     986           1 :                 return false;
     987         412 :             if (Token::Match(tok->previous(), "<|, %name% * ,|>"))
     988           5 :                 return true;
     989         920 :             for (const Token* after = tok->next(); after; after = after->next()) {
     990         920 :                 if (Token::Match(after, "%name%|::|&|*|&&"))
     991         513 :                     continue;
     992         407 :                 if (after->str() == "<" && after->link())
     993           0 :                     break;
     994         407 :                 if (after->isNumber())
     995           1 :                     return false;
     996         406 :                 if (after->isComparisonOp() || after->isArithmeticalOp())
     997           5 :                     return false;
     998         401 :                 break;
     999             :             }
    1000         453 :             for (const Token* before = tok->previous(); before; before = before->previous()) {
    1001         453 :                 if (Token::Match(before, "[+-*/&|~!]"))
    1002           0 :                     return false;
    1003         453 :                 if (Token::Match(before, "struct|union|class|enum") || before->isStandardType())
    1004          82 :                     return false;
    1005         371 :                 if (before->str() == "::")
    1006           0 :                     return false;
    1007         371 :                 if (before->isName())
    1008          52 :                     continue;
    1009         319 :                 break;
    1010             :             }
    1011         319 :             return true;
    1012             :         }
    1013             : 
    1014         242 :         Token* endToken() const {
    1015         242 :             return mEndToken;
    1016             :         }
    1017             : 
    1018             :     private:
    1019          73 :         static bool isCast(const Token* tok) {
    1020          73 :             if (Token::Match(tok, "( %name% ) (|%name%"))
    1021           2 :                 return !tok->tokAt(2)->isKeyword();
    1022          71 :             if (Token::Match(tok, "< %name% > (") && tok->previous() && endsWith(tok->previous()->str(), "_cast", 5))
    1023           1 :                 return true;
    1024          70 :             return false;
    1025             :         }
    1026             : 
    1027        1019 :         static Token* insertTokens(Token* to, std::pair<Token*,Token*> range) {
    1028        2215 :             for (const Token* from = range.first; from != range.second; from = from->next()) {
    1029        1196 :                 to->insertToken(from->str());
    1030        1196 :                 to->next()->column(to->column());
    1031        1196 :                 to = to->next();
    1032        1196 :                 to->isSimplifiedTypedef(true);
    1033        1196 :                 to->isExternC(from->isExternC());
    1034             :             }
    1035        1019 :             return to;
    1036             :         }
    1037             : 
    1038             :         static void printTypedef(const Token *tok) {
    1039             :             int indent = 0;
    1040             :             while (tok && (indent > 0 || tok->str() != ";")) {
    1041             :                 if (tok->str() == "{")
    1042             :                     ++indent;
    1043             :                 else if (tok->str() == "}")
    1044             :                     --indent;
    1045             :                 std::cout << " " << tok->str();
    1046             :                 tok = tok->next();
    1047             :             }
    1048             :             std::cout << "\n";
    1049             :         }
    1050             :     };
    1051             : }
    1052             : 
    1053       22687 : void Tokenizer::simplifyTypedef()
    1054             : {
    1055             :     // Simplify global typedefs that are not redefined with the fast 1-pass simplification.
    1056             :     // Then use the slower old typedef simplification.
    1057       45371 :     std::map<std::string, int> numberOfTypedefs;
    1058     1025107 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    1059     1002420 :         if (tok->str() == "typedef") {
    1060         652 :             TypedefSimplifier ts(tok);
    1061         652 :             if (!ts.fail())
    1062         452 :                 numberOfTypedefs[ts.name()]++;
    1063         652 :             continue;
    1064             :         }
    1065             :     }
    1066             : 
    1067       22686 :     int indentlevel = 0;
    1068       45372 :     std::map<std::string, TypedefSimplifier> typedefs;
    1069     1021568 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    1070      998873 :         if (!tok->isName()) {
    1071      594928 :             if (tok->str()[0] == '{')
    1072       47805 :                 ++indentlevel;
    1073      547129 :             else if (tok->str()[0] == '}')
    1074       47802 :                 --indentlevel;
    1075      595427 :             continue;
    1076             :         }
    1077             : 
    1078      403945 :         if (indentlevel == 0 && tok->str() == "typedef") {
    1079         502 :             TypedefSimplifier ts(tok);
    1080        1366 :             if (!ts.fail() && numberOfTypedefs[ts.name()] == 1 &&
    1081         864 :                 (numberOfTypedefs.find(ts.getTypedefToken()->strAt(1)) == numberOfTypedefs.end() || ts.getTypedefToken()->strAt(2) == "(")) {
    1082         323 :                 if (mSettings.severity.isEnabled(Severity::portability) && ts.isInvalidConstFunctionType(typedefs))
    1083           1 :                     reportError(tok->next(), Severity::portability, "invalidConstFunctionType",
    1084           2 :                                 "It is unspecified behavior to const qualify a function type.");
    1085         323 :                 typedefs.emplace(ts.name(), ts);
    1086         323 :                 if (!ts.isStructEtc())
    1087         242 :                     tok = ts.endToken();
    1088             :             }
    1089         502 :             continue;
    1090             :         }
    1091             : 
    1092      403459 :         auto it = typedefs.find(tok->str());
    1093      403456 :         if (it != typedefs.end() && it->second.canReplace(tok)) {
    1094         694 :             std::set<std::string> r;
    1095         702 :             while (it != typedefs.end() && r.insert(tok->str()).second) {
    1096         355 :                 it->second.replace(tok);
    1097         355 :                 it = typedefs.find(tok->str());
    1098             :             }
    1099      403109 :         } else if (tok->str() == "enum") {
    1100        1487 :             while (Token::Match(tok, "%name%|:|::"))
    1101        1108 :                 tok = tok->next();
    1102         379 :             if (!tok)
    1103           0 :                 break;
    1104         379 :             if (tok->str() == "{")
    1105         351 :                 tok = tok->link();
    1106             :         }
    1107             :     }
    1108             : 
    1109       22683 :     if (!typedefs.empty())
    1110             :     {
    1111             :         // remove typedefs
    1112         584 :         for (auto &t: typedefs) {
    1113         323 :             if (!t.second.replaceFailed()) {
    1114         323 :                 const Token* const typedefToken = t.second.getTypedefToken();
    1115         646 :                 TypedefInfo typedefInfo;
    1116         323 :                 typedefInfo.name = t.second.name();
    1117         323 :                 typedefInfo.filename = list.file(typedefToken);
    1118         323 :                 typedefInfo.lineNumber = typedefToken->linenr();
    1119         323 :                 typedefInfo.column = typedefToken->column();
    1120         323 :                 typedefInfo.used = t.second.isUsed();
    1121         323 :                 mTypedefInfo.push_back(std::move(typedefInfo));
    1122             : 
    1123         323 :                 t.second.removeDeclaration();
    1124             :             }
    1125             :         }
    1126             : 
    1127         463 :         while (Token::Match(list.front(), "; %any%"))
    1128         202 :             list.front()->deleteThis();
    1129             :     }
    1130             : 
    1131       22683 :     simplifyTypedefCpp();
    1132       22678 : }
    1133             : 
    1134         433 : static bool isEnumScope(const Token* tok)
    1135             : {
    1136         433 :     if (!Token::simpleMatch(tok, "{"))
    1137           0 :         return false;
    1138         433 :     tok = tok->previous();
    1139         614 :     while (tok && !tok->isKeyword() && Token::Match(tok, "%name%|::|:"))
    1140         181 :         tok = tok->previous();
    1141         433 :     if (Token::simpleMatch(tok, "class"))
    1142          44 :         tok = tok->previous();
    1143         433 :     return Token::simpleMatch(tok, "enum");
    1144             : }
    1145             : 
    1146       22687 : void Tokenizer::simplifyTypedefCpp()
    1147             : {
    1148       22687 :     bool isNamespace = false;
    1149       22705 :     std::string className, fullClassName;
    1150       22680 :     bool hasClass = false;
    1151       22680 :     bool goback = false;
    1152             : 
    1153             :     // add global namespace
    1154       22689 :     std::vector<Space> spaceInfo(1);
    1155             : 
    1156             :     // Convert "using a::b;" to corresponding typedef statements
    1157       22683 :     simplifyUsingToTypedef();
    1158             : 
    1159       22681 :     const std::time_t maxTime = mSettings.typedefMaxTime > 0 ? std::time(nullptr) + mSettings.typedefMaxTime: 0;
    1160             : 
    1161     1022795 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    1162     1000121 :         if (!list.getFiles().empty())
    1163     1000116 :             mErrorLogger.reportProgress(list.getFiles()[0], "Tokenize (typedef)", tok->progressValue());
    1164             : 
    1165     1000115 :         if (Settings::terminated())
    1166           0 :             return;
    1167             : 
    1168     1000116 :         if (maxTime > 0 && std::time(nullptr) > maxTime) {
    1169           0 :             if (mSettings.debugwarnings) {
    1170           0 :                 ErrorMessage::FileLocation loc(list.getFiles()[0], 0, 0);
    1171           0 :                 ErrorMessage errmsg({std::move(loc)},
    1172             :                                     emptyString,
    1173             :                                     Severity::debug,
    1174             :                                     "Typedef simplification instantiation maximum time exceeded",
    1175             :                                     "typedefMaxTime",
    1176           0 :                                     Certainty::normal);
    1177           0 :                 mErrorLogger.reportErr(errmsg);
    1178             :             }
    1179           0 :             return;
    1180             :         }
    1181             : 
    1182     1000116 :         if (goback) {
    1183             :             //jump back once, see the comment at the end of the function
    1184         130 :             goback = false;
    1185         130 :             tok = tok->previous();
    1186             :         }
    1187             : 
    1188     1000116 :         if (tok->str() != "typedef") {
    1189      999777 :             if (Token::simpleMatch(tok, "( typedef")) {
    1190             :                 // Skip typedefs inside parentheses (#2453 and #4002)
    1191           0 :                 tok = tok->next();
    1192     1011999 :             } else if (Token::Match(tok, "class|struct|namespace %any%") &&
    1193       12224 :                        (!tok->previous() || tok->previous()->str() != "enum")) {
    1194        7789 :                 isNamespace = (tok->str() == "namespace");
    1195        7789 :                 hasClass = true;
    1196        7789 :                 className = tok->next()->str();
    1197        7789 :                 const Token *tok1 = tok->next();
    1198        7789 :                 fullClassName = className;
    1199        7894 :                 while (Token::Match(tok1, "%name% :: %name%")) {
    1200         105 :                     tok1 = tok1->tokAt(2);
    1201         105 :                     fullClassName += " :: " + tok1->str();
    1202             :                 }
    1203      992001 :             } else if (hasClass && tok->str() == ";") {
    1204        1238 :                 hasClass = false;
    1205      990762 :             } else if (hasClass && tok->str() == "{") {
    1206        6110 :                 if (!isNamespace)
    1207        5619 :                     spaceInfo.back().recordTypes.insert(fullClassName);
    1208             : 
    1209        6110 :                 Space info;
    1210        6110 :                 info.isNamespace = isNamespace;
    1211        6110 :                 info.className = className;
    1212        6110 :                 info.bodyEnd = tok->link();
    1213        6110 :                 info.bodyEnd2 = tok->link();
    1214        6110 :                 spaceInfo.push_back(std::move(info));
    1215             : 
    1216        6110 :                 hasClass = false;
    1217      984652 :             } else if (spaceInfo.size() > 1 && tok->str() == "}" && spaceInfo.back().bodyEnd == tok) {
    1218        6109 :                 spaceInfo.pop_back();
    1219             :             }
    1220      999796 :             continue;
    1221             :         }
    1222             : 
    1223             :         // pull struct, union, enum or class definition out of typedef
    1224             :         // use typedef name for unnamed struct, union, enum or class
    1225         336 :         const Token* tokClass = tok->next();
    1226         350 :         while (Token::Match(tokClass, "const|volatile"))
    1227          14 :             tokClass = tokClass->next();
    1228         336 :         if (Token::Match(tokClass, "struct|enum|union|class %type%| {|:")) {
    1229          31 :             Token *tok1 = splitDefinitionFromTypedef(tok, &mUnnamedCount);
    1230          31 :             if (!tok1)
    1231           1 :                 continue;
    1232          30 :             tok = tok1;
    1233             :         }
    1234             : 
    1235             :         /** @todo add support for union */
    1236         335 :         if (Token::Match(tok->next(), "enum %type% %type% ;") && tok->strAt(2) == tok->strAt(3)) {
    1237           2 :             tok->deleteNext(3);
    1238           2 :             tok->deleteThis();
    1239           2 :             if (tok->next())
    1240           2 :                 tok->deleteThis();
    1241             :             //now the next token to process is 'tok', not 'tok->next()';
    1242           2 :             goback = true;
    1243           2 :             continue;
    1244             :         }
    1245             : 
    1246             :         Token *typeName;
    1247         333 :         Token *typeStart = nullptr;
    1248         333 :         Token *typeEnd = nullptr;
    1249         333 :         Token *argStart = nullptr;
    1250         333 :         Token *argEnd = nullptr;
    1251         333 :         Token *arrayStart = nullptr;
    1252         333 :         Token *arrayEnd = nullptr;
    1253         333 :         Token *specStart = nullptr;
    1254         333 :         Token *specEnd = nullptr;
    1255         333 :         Token *typeDef = tok;
    1256         333 :         Token *argFuncRetStart = nullptr;
    1257         333 :         Token *argFuncRetEnd = nullptr;
    1258         333 :         Token *funcStart = nullptr;
    1259         333 :         Token *funcEnd = nullptr;
    1260         333 :         Token *tokOffset = tok->next();
    1261         333 :         bool function = false;
    1262         333 :         bool functionPtr = false;
    1263         333 :         bool functionRetFuncPtr = false;
    1264         333 :         bool functionPtrRetFuncPtr = false;
    1265         333 :         bool ptrToArray = false;
    1266         333 :         bool refToArray = false;
    1267         333 :         bool ptrMember = false;
    1268         333 :         bool typeOf = false;
    1269         333 :         Token *namespaceStart = nullptr;
    1270         333 :         Token *namespaceEnd = nullptr;
    1271             : 
    1272             :         // check for invalid input
    1273         333 :         if (!tokOffset || tokOffset->isControlFlowKeyword())
    1274           0 :             syntaxError(tok);
    1275             : 
    1276         333 :         if (tokOffset->str() == "::") {
    1277          17 :             typeStart = tokOffset;
    1278          17 :             tokOffset = tokOffset->next();
    1279             : 
    1280          33 :             while (Token::Match(tokOffset, "%type% ::"))
    1281          16 :                 tokOffset = tokOffset->tokAt(2);
    1282             : 
    1283          17 :             typeEnd = tokOffset;
    1284             : 
    1285          17 :             if (Token::Match(tokOffset, "%type%"))
    1286          17 :                 tokOffset = tokOffset->next();
    1287         316 :         } else if (Token::Match(tokOffset, "%type% ::")) {
    1288          50 :             typeStart = tokOffset;
    1289             : 
    1290           4 :             do {
    1291          54 :                 tokOffset = tokOffset->tokAt(2);
    1292          54 :             } while (Token::Match(tokOffset, "%type% ::"));
    1293             : 
    1294          50 :             typeEnd = tokOffset;
    1295             : 
    1296          50 :             if (Token::Match(tokOffset, "%type%"))
    1297          50 :                 tokOffset = tokOffset->next();
    1298         266 :         } else if (Token::Match(tokOffset, "%type%")) {
    1299         264 :             typeStart = tokOffset;
    1300             : 
    1301         853 :             while (Token::Match(tokOffset, "const|struct|enum %type%") ||
    1302         545 :                    (tokOffset->next() && tokOffset->next()->isStandardType() && !Token::Match(tokOffset->next(), "%name% ;")))
    1303          44 :                 tokOffset = tokOffset->next();
    1304             : 
    1305         264 :             typeEnd = tokOffset;
    1306         264 :             if (!Token::Match(tokOffset->next(), "%name% ;"))
    1307         190 :                 tokOffset = tokOffset->next();
    1308             : 
    1309         268 :             while (Token::Match(tokOffset, "%type%") &&
    1310         323 :                    (tokOffset->isStandardType() || Token::Match(tokOffset, "unsigned|signed")) &&
    1311          55 :                    !Token::Match(tokOffset->next(), "%name% ;")) {
    1312           4 :                 typeEnd = tokOffset;
    1313           4 :                 tokOffset = tokOffset->next();
    1314             :             }
    1315             : 
    1316         264 :             bool atEnd = false;
    1317         634 :             while (!atEnd) {
    1318         370 :                 if (tokOffset && tokOffset->str() == "::") {
    1319           7 :                     typeEnd = tokOffset;
    1320           7 :                     tokOffset = tokOffset->next();
    1321             :                 }
    1322             : 
    1323         591 :                 if (Token::Match(tokOffset, "%type%") &&
    1324         591 :                     tokOffset->next() && !Token::Match(tokOffset->next(), "[|;|,|(")) {
    1325         106 :                     typeEnd = tokOffset;
    1326         106 :                     tokOffset = tokOffset->next();
    1327         264 :                 } else if (Token::simpleMatch(tokOffset, "const (")) {
    1328           5 :                     typeEnd = tokOffset;
    1329           5 :                     tokOffset = tokOffset->next();
    1330           5 :                     atEnd = true;
    1331             :                 } else
    1332         259 :                     atEnd = true;
    1333             :             }
    1334             :         } else
    1335           2 :             continue; // invalid input
    1336             : 
    1337             :         // check for invalid input
    1338         331 :         if (!tokOffset)
    1339           1 :             syntaxError(tok);
    1340             : 
    1341             :         // check for template
    1342         330 :         if (!isC() && tokOffset->str() == "<") {
    1343          59 :             typeEnd = tokOffset->findClosingBracket();
    1344             : 
    1345          65 :             while (typeEnd && Token::Match(typeEnd->next(), ":: %type%"))
    1346           6 :                 typeEnd = typeEnd->tokAt(2);
    1347             : 
    1348          59 :             if (!typeEnd) {
    1349             :                 // internal error
    1350           0 :                 return;
    1351             :             }
    1352             : 
    1353          61 :             while (Token::Match(typeEnd->next(), "const|volatile"))
    1354           2 :                 typeEnd = typeEnd->next();
    1355             : 
    1356          59 :             tok = typeEnd;
    1357          59 :             tokOffset = tok->next();
    1358             :         }
    1359             : 
    1360         338 :         std::list<std::string> pointers;
    1361             :         // check for pointers and references
    1362         374 :         while (Token::Match(tokOffset, "*|&|&&|const")) {
    1363          44 :             pointers.push_back(tokOffset->str());
    1364          44 :             tokOffset = tokOffset->next();
    1365             :         }
    1366             : 
    1367             :         // check for invalid input
    1368         330 :         if (!tokOffset)
    1369           0 :             syntaxError(tok);
    1370             : 
    1371         330 :         if (tokOffset->isName() && !tokOffset->isKeyword()) {
    1372             :             // found the type name
    1373         189 :             typeName = tokOffset;
    1374         189 :             tokOffset = tokOffset->next();
    1375             : 
    1376             :             // check for array
    1377         207 :             while (tokOffset && tokOffset->str() == "[") {
    1378          18 :                 if (!arrayStart)
    1379          14 :                     arrayStart = tokOffset;
    1380          18 :                 arrayEnd = tokOffset->link();
    1381          18 :                 tokOffset = arrayEnd->next();
    1382             :             }
    1383             : 
    1384             :             // check for end or another
    1385         189 :             if (Token::Match(tokOffset, ";|,"))
    1386         184 :                 tok = tokOffset;
    1387             : 
    1388             :             // or a function typedef
    1389           5 :             else if (tokOffset && tokOffset->str() == "(") {
    1390           5 :                 Token *tokOffset2 = nullptr;
    1391           5 :                 if (Token::Match(tokOffset, "( *|%name%")) {
    1392           4 :                     tokOffset2 = tokOffset->next();
    1393           4 :                     if (tokOffset2->str() == "typename")
    1394           1 :                         tokOffset2 = tokOffset2->next();
    1395           6 :                     while (Token::Match(tokOffset2, "%type% ::"))
    1396           2 :                         tokOffset2 = tokOffset2->tokAt(2);
    1397             :                 }
    1398             : 
    1399             :                 // unhandled typedef, skip it and continue
    1400           5 :                 if (typeName->str() == "void") {
    1401           0 :                     unsupportedTypedef(typeDef);
    1402           0 :                     tok = deleteInvalidTypedef(typeDef);
    1403           0 :                     if (tok == list.front())
    1404             :                         //now the next token to process is 'tok', not 'tok->next()';
    1405           0 :                         goback = true;
    1406           0 :                     continue;
    1407             :                 }
    1408             : 
    1409             :                 // function pointer
    1410           5 :                 if (Token::Match(tokOffset2, "* %name% ) (")) {
    1411             :                     // name token wasn't a name, it was part of the type
    1412           1 :                     typeEnd = typeEnd->next();
    1413           1 :                     functionPtr = true;
    1414           1 :                     funcStart = funcEnd = tokOffset2; // *
    1415           1 :                     tokOffset = tokOffset2->tokAt(3); // (
    1416           1 :                     typeName = tokOffset->tokAt(-2);
    1417           1 :                     argStart = tokOffset;
    1418           1 :                     argEnd = tokOffset->link();
    1419           1 :                     tok = argEnd->next();
    1420             :                 }
    1421             : 
    1422             :                 // function
    1423           4 :                 else if (isFunctionHead(tokOffset->link(), ";,")) {
    1424           2 :                     function = true;
    1425           2 :                     if (tokOffset->link()->next()->str() == "const") {
    1426           1 :                         specStart = tokOffset->link()->next();
    1427           1 :                         specEnd = specStart;
    1428             :                     }
    1429           2 :                     argStart = tokOffset;
    1430           2 :                     argEnd = tokOffset->link();
    1431           2 :                     tok = argEnd->next();
    1432           2 :                     if (specStart)
    1433           1 :                         tok = tok->next();
    1434             :                 }
    1435             : 
    1436             :                 // syntax error
    1437             :                 else
    1438           2 :                     syntaxError(tok);
    1439             :             }
    1440             : 
    1441             :             // unhandled typedef, skip it and continue
    1442             :             else {
    1443           0 :                 unsupportedTypedef(typeDef);
    1444           0 :                 tok = deleteInvalidTypedef(typeDef);
    1445           0 :                 if (tok == list.front())
    1446             :                     //now the next token to process is 'tok', not 'tok->next()';
    1447           0 :                     goback = true;
    1448           0 :                 continue;
    1449             :             }
    1450             :         }
    1451             : 
    1452             :         // typeof: typedef typeof ( ... ) type;
    1453         142 :         else if (Token::simpleMatch(tokOffset->previous(), "typeof (") &&
    1454           1 :                  Token::Match(tokOffset->link(), ") %type% ;")) {
    1455           1 :             argStart = tokOffset;
    1456           1 :             argEnd = tokOffset->link();
    1457           1 :             typeName = tokOffset->link()->next();
    1458           1 :             tok = typeName->next();
    1459           1 :             typeOf = true;
    1460             :         }
    1461             : 
    1462             :         // function: typedef ... ( ... type )( ... );
    1463             :         //           typedef ... (( ... type )( ... ));
    1464             :         //           typedef ... ( * ( ... type )( ... ));
    1465         414 :         else if (tokOffset->str() == "(" && (
    1466         274 :                      (tokOffset->link() && Token::Match(tokOffset->link()->previous(), "%type% ) (") &&
    1467         102 :                       Token::Match(tokOffset->link()->next()->link(), ") const|volatile|;")) ||
    1468          37 :                      (Token::simpleMatch(tokOffset, "( (") &&
    1469           4 :                       tokOffset->next() && Token::Match(tokOffset->next()->link()->previous(), "%type% ) (") &&
    1470           2 :                       Token::Match(tokOffset->next()->link()->next()->link(), ") const|volatile| ) ;|,")) ||
    1471          33 :                      (Token::simpleMatch(tokOffset, "( * (") &&
    1472           4 :                       tokOffset->linkAt(2) && Token::Match(tokOffset->linkAt(2)->previous(), "%type% ) (") &&
    1473           4 :                       Token::Match(tokOffset->linkAt(2)->next()->link(), ") const|volatile| ) ;|,")))) {
    1474         104 :             if (tokOffset->next()->str() == "(")
    1475           4 :                 tokOffset = tokOffset->next();
    1476         100 :             else if (Token::simpleMatch(tokOffset, "( * (")) {
    1477           0 :                 pointers.emplace_back("*");
    1478           0 :                 tokOffset = tokOffset->tokAt(2);
    1479             :             }
    1480             : 
    1481         104 :             if (tokOffset->link()->strAt(-2) == "*")
    1482          78 :                 functionPtr = true;
    1483             :             else
    1484          26 :                 function = true;
    1485         104 :             funcStart = tokOffset->next();
    1486         104 :             tokOffset = tokOffset->link();
    1487         104 :             funcEnd = tokOffset->tokAt(-2);
    1488         104 :             typeName = tokOffset->previous();
    1489         104 :             argStart = tokOffset->next();
    1490         104 :             argEnd = tokOffset->next()->link();
    1491         104 :             if (!argEnd)
    1492           2 :                 syntaxError(argStart);
    1493             : 
    1494         102 :             tok = argEnd->next();
    1495         102 :             Token *spec = tok;
    1496         102 :             if (Token::Match(spec, "const|volatile")) {
    1497          31 :                 specStart = spec;
    1498          31 :                 specEnd = spec;
    1499          41 :                 while (Token::Match(spec->next(), "const|volatile")) {
    1500          10 :                     specEnd = spec->next();
    1501          10 :                     spec = specEnd;
    1502             :                 }
    1503          31 :                 tok = specEnd->next();
    1504             :             }
    1505         102 :             if (!tok)
    1506           0 :                 syntaxError(specEnd);
    1507             : 
    1508         102 :             if (tok->str() == ")")
    1509           2 :                 tok = tok->next();
    1510             :         }
    1511             : 
    1512          36 :         else if (Token::Match(tokOffset, "( %type% (")) {
    1513           8 :             function = true;
    1514           8 :             if (tokOffset->link()->next()) {
    1515           8 :                 tok = tokOffset->link()->next();
    1516           8 :                 tokOffset = tokOffset->tokAt(2);
    1517           8 :                 typeName = tokOffset->previous();
    1518           8 :                 argStart = tokOffset;
    1519           8 :                 argEnd = tokOffset->link();
    1520             :             } else {
    1521             :                 // internal error
    1522           0 :                 continue;
    1523             :             }
    1524             :         }
    1525             : 
    1526             :         // pointer to function returning pointer to function
    1527          28 :         else if (Token::Match(tokOffset, "( * ( * %type% ) (") &&
    1528          29 :                  Token::simpleMatch(tokOffset->linkAt(6), ") ) (") &&
    1529           1 :                  Token::Match(tokOffset->linkAt(6)->linkAt(2), ") ;|,")) {
    1530           1 :             functionPtrRetFuncPtr = true;
    1531             : 
    1532           1 :             tokOffset = tokOffset->tokAt(6);
    1533           1 :             typeName = tokOffset->tokAt(-2);
    1534           1 :             argStart = tokOffset;
    1535           1 :             argEnd = tokOffset->link();
    1536           1 :             if (!argEnd)
    1537           0 :                 syntaxError(arrayStart);
    1538             : 
    1539           1 :             argFuncRetStart = argEnd->tokAt(2);
    1540           1 :             argFuncRetEnd = argFuncRetStart->link();
    1541           1 :             if (!argFuncRetEnd)
    1542           0 :                 syntaxError(argFuncRetStart);
    1543             : 
    1544           1 :             tok = argFuncRetEnd->next();
    1545             :         }
    1546             : 
    1547             :         // function returning pointer to function
    1548          27 :         else if (Token::Match(tokOffset, "( * %type% (") &&
    1549          30 :                  Token::simpleMatch(tokOffset->linkAt(3), ") ) (") &&
    1550           3 :                  Token::Match(tokOffset->linkAt(3)->linkAt(2), ") ;|,")) {
    1551           3 :             functionRetFuncPtr = true;
    1552             : 
    1553           3 :             tokOffset = tokOffset->tokAt(3);
    1554           3 :             typeName = tokOffset->previous();
    1555           3 :             argStart = tokOffset;
    1556           3 :             argEnd = tokOffset->link();
    1557             : 
    1558           3 :             argFuncRetStart = argEnd->tokAt(2);
    1559           3 :             if (!argFuncRetStart)
    1560           0 :                 syntaxError(tokOffset);
    1561             : 
    1562           3 :             argFuncRetEnd = argFuncRetStart->link();
    1563           3 :             if (!argFuncRetEnd)
    1564           0 :                 syntaxError(tokOffset);
    1565             : 
    1566           3 :             tok = argFuncRetEnd->next();
    1567          24 :         } else if (Token::Match(tokOffset, "( * ( %type% ) (")) {
    1568           3 :             functionRetFuncPtr = true;
    1569             : 
    1570           3 :             tokOffset = tokOffset->tokAt(5);
    1571           3 :             typeName = tokOffset->tokAt(-2);
    1572           3 :             argStart = tokOffset;
    1573           3 :             argEnd = tokOffset->link();
    1574           3 :             if (!argEnd)
    1575           0 :                 syntaxError(arrayStart);
    1576             : 
    1577           3 :             argFuncRetStart = argEnd->tokAt(2);
    1578           3 :             if (!argFuncRetStart)
    1579           0 :                 syntaxError(tokOffset);
    1580             : 
    1581           3 :             argFuncRetEnd = argFuncRetStart->link();
    1582           3 :             if (!argFuncRetEnd)
    1583           2 :                 syntaxError(tokOffset);
    1584             : 
    1585           1 :             tok = argFuncRetEnd->next();
    1586             :         }
    1587             : 
    1588             :         // pointer/reference to array
    1589          21 :         else if (Token::Match(tokOffset, "( *|& %type% ) [")) {
    1590          10 :             ptrToArray = (tokOffset->next()->str() == "*");
    1591          10 :             refToArray = !ptrToArray;
    1592          10 :             tokOffset = tokOffset->tokAt(2);
    1593          10 :             typeName = tokOffset;
    1594          10 :             arrayStart = tokOffset->tokAt(2);
    1595          10 :             arrayEnd = arrayStart->link();
    1596          10 :             if (!arrayEnd)
    1597           0 :                 syntaxError(arrayStart);
    1598             : 
    1599          10 :             tok = arrayEnd->next();
    1600             :         }
    1601             : 
    1602             :         // pointer to class member
    1603          11 :         else if (Token::Match(tokOffset, "( %type% :: * %type% ) ;")) {
    1604           7 :             tokOffset = tokOffset->tokAt(2);
    1605           7 :             namespaceStart = tokOffset->previous();
    1606           7 :             namespaceEnd = tokOffset;
    1607           7 :             ptrMember = true;
    1608           7 :             tokOffset = tokOffset->tokAt(2);
    1609           7 :             typeName = tokOffset;
    1610           7 :             tok = tokOffset->tokAt(2);
    1611             :         }
    1612             : 
    1613             :         // unhandled typedef, skip it and continue
    1614             :         else {
    1615           4 :             unsupportedTypedef(typeDef);
    1616           4 :             tok = deleteInvalidTypedef(typeDef);
    1617           4 :             if (tok == list.front())
    1618             :                 //now the next token to process is 'tok', not 'tok->next()';
    1619           3 :                 goback = true;
    1620           4 :             continue;
    1621             :         }
    1622             : 
    1623         320 :         bool done = false;
    1624         320 :         bool ok = true;
    1625             : 
    1626         322 :         TypedefInfo typedefInfo;
    1627         320 :         typedefInfo.name = typeName->str();
    1628         320 :         typedefInfo.filename = list.file(typeName);
    1629         320 :         typedefInfo.lineNumber = typeName->linenr();
    1630         320 :         typedefInfo.column = typeName->column();
    1631         320 :         typedefInfo.used = false;
    1632         320 :         mTypedefInfo.push_back(std::move(typedefInfo));
    1633             : 
    1634         647 :         while (!done) {
    1635         331 :             std::string pattern = typeName->str();
    1636         329 :             int scope = 0;
    1637         329 :             bool simplifyType = false;
    1638         329 :             bool inMemberFunc = false;
    1639         329 :             int memberScope = 0;
    1640         329 :             bool globalScope = false;
    1641         329 :             int classLevel = spaceInfo.size();
    1642         329 :             bool inTypeDef = false;
    1643         329 :             bool inEnum = false;
    1644         331 :             std::string removed;
    1645         331 :             std::string classPath;
    1646         482 :             for (size_t i = 1; i < spaceInfo.size(); ++i) {
    1647         153 :                 if (!classPath.empty())
    1648          33 :                     classPath += " :: ";
    1649         153 :                 classPath += spaceInfo[i].className;
    1650             :             }
    1651             : 
    1652       13930 :             for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    1653       13630 :                 if (Settings::terminated())
    1654           0 :                     return;
    1655             : 
    1656       13630 :                 removed.clear();
    1657             : 
    1658       13630 :                 if (Token::simpleMatch(tok2, "typedef"))
    1659         211 :                     inTypeDef = true;
    1660             : 
    1661       13630 :                 if (inTypeDef && Token::simpleMatch(tok2, ";"))
    1662         209 :                     inTypeDef = false;
    1663             : 
    1664             :                 // Check for variable declared with the same name
    1665       15871 :                 if (!inTypeDef && spaceInfo.size() == 1 && Token::Match(tok2->previous(), "%name%") &&
    1666        2241 :                     !tok2->previous()->isKeyword()) {
    1667        1798 :                     Token* varDecl = tok2;
    1668        1936 :                     while (Token::Match(varDecl, "*|&|&&|const"))
    1669         138 :                         varDecl = varDecl->next();
    1670        1798 :                     if (Token::Match(varDecl, "%name% ;|,|)|=") && varDecl->str() == typeName->str()) {
    1671             :                         // Skip to the next closing brace
    1672           2 :                         if (Token::Match(varDecl, "%name% ) {")) { // is argument variable
    1673           1 :                             tok2 = varDecl->linkAt(2)->next();
    1674             :                         } else {
    1675           1 :                             tok2 = varDecl;
    1676          11 :                             while (tok2 && !Token::simpleMatch(tok2, "}")) {
    1677          10 :                                 if (Token::Match(tok2, "(|{|["))
    1678           0 :                                     tok2 = tok2->link();
    1679          10 :                                 tok2 = tok2->next();
    1680             :                             }
    1681             :                         }
    1682           2 :                         if (!tok2)
    1683           0 :                             break;
    1684           2 :                         continue;
    1685             :                     }
    1686             :                 }
    1687             : 
    1688       13628 :                 if (tok2->link()) { // Pre-check for performance
    1689             :                     // check for end of scope
    1690        3398 :                     if (tok2->str() == "}") {
    1691             :                         // check for end of member function
    1692         615 :                         if (inMemberFunc) {
    1693          61 :                             --memberScope;
    1694          61 :                             if (memberScope == 0)
    1695          61 :                                 inMemberFunc = false;
    1696             :                         }
    1697         615 :                         inEnum = false;
    1698             : 
    1699         615 :                         if (classLevel > 1 && tok2 == spaceInfo[classLevel - 1].bodyEnd2) {
    1700         164 :                             --classLevel;
    1701         164 :                             pattern.clear();
    1702             : 
    1703         378 :                             for (int i = classLevel; i < spaceInfo.size(); ++i)
    1704         214 :                                 pattern += (spaceInfo[i].className + " :: ");
    1705             : 
    1706         164 :                             pattern += typeName->str();
    1707             :                         } else {
    1708         451 :                             if (scope == 0 && !(classLevel > 1 && tok2 == spaceInfo[classLevel - 1].bodyEnd))
    1709          27 :                                 break;
    1710         424 :                             scope = std::max(scope - 1, 0);
    1711             :                         }
    1712             :                     }
    1713             : 
    1714             :                     // check for member functions
    1715        3921 :                     else if (tok2->isCpp() && tok2->str() == "(" && isFunctionHead(tok2, "{:")) {
    1716         211 :                         const Token *func = tok2->previous();
    1717             : 
    1718             :                         /** @todo add support for multi-token operators */
    1719         211 :                         if (func->previous()->str() == "operator")
    1720           0 :                             func = func->previous();
    1721             : 
    1722         211 :                         if (!func->previous())
    1723           0 :                             syntaxError(func);
    1724             : 
    1725             :                         // check for qualifier
    1726         211 :                         if (Token::Match(func->tokAt(-2), "%name% ::")) {
    1727          80 :                             int offset = -2;
    1728         159 :                             while (Token::Match(func->tokAt(offset - 2), "%name% ::"))
    1729          79 :                                 offset -= 2;
    1730             :                             // check for available and matching class name
    1731         150 :                             if (spaceInfo.size() > 1 && classLevel < spaceInfo.size() &&
    1732          70 :                                 func->strAt(offset) == spaceInfo[classLevel].className) {
    1733          61 :                                 memberScope = 0;
    1734          61 :                                 inMemberFunc = true;
    1735             :                             }
    1736             :                         }
    1737             :                     }
    1738             : 
    1739             :                     // check for entering a new scope
    1740        2572 :                     else if (tok2->str() == "{") {
    1741             :                         // check for entering a new namespace
    1742         436 :                         if (tok2->isCpp()) {
    1743         433 :                             if (tok2->strAt(-2) == "namespace") {
    1744          36 :                                 if (classLevel < spaceInfo.size() &&
    1745          64 :                                     spaceInfo[classLevel].isNamespace &&
    1746          28 :                                     spaceInfo[classLevel].className == tok2->previous()->str()) {
    1747          11 :                                     spaceInfo[classLevel].bodyEnd2 = tok2->link();
    1748          11 :                                     ++classLevel;
    1749          11 :                                     pattern.clear();
    1750          15 :                                     for (int i = classLevel; i < spaceInfo.size(); ++i)
    1751           4 :                                         pattern += spaceInfo[i].className + " :: ";
    1752             : 
    1753          11 :                                     pattern += typeName->str();
    1754             :                                 }
    1755          36 :                                 ++scope;
    1756             :                             }
    1757         433 :                             if (isEnumScope(tok2))
    1758          32 :                                 inEnum = true;
    1759             :                         }
    1760             : 
    1761             :                         // keep track of scopes within member function
    1762         436 :                         if (inMemberFunc)
    1763          61 :                             ++memberScope;
    1764             : 
    1765         436 :                         ++scope;
    1766             :                     }
    1767             :                 }
    1768             : 
    1769             :                 // check for operator typedef
    1770             :                 /** @todo add support for multi-token operators */
    1771       20440 :                 else if (tok2->isCpp() &&
    1772       10228 :                          tok2->str() == "operator" &&
    1773          35 :                          tok2->next() &&
    1774          17 :                          tok2->next()->str() == typeName->str() &&
    1775          22 :                          tok2->linkAt(2) &&
    1776       20450 :                          tok2->strAt(2) == "(" &&
    1777          10 :                          Token::Match(tok2->linkAt(2), ") const| {")) {
    1778             :                     // check for qualifier
    1779           5 :                     if (tok2->previous()->str() == "::") {
    1780             :                         // check for available and matching class name
    1781           2 :                         if (spaceInfo.size() > 1 && classLevel < spaceInfo.size() &&
    1782           1 :                             tok2->strAt(-2) == spaceInfo[classLevel].className) {
    1783           1 :                             tok2 = tok2->next();
    1784           1 :                             simplifyType = true;
    1785             :                         }
    1786             :                     }
    1787             :                 }
    1788             : 
    1789       10225 :                 else if (Token::Match(tok2->previous(), "class|struct %name% [:{]")) {
    1790             :                     // don't replace names in struct/class definition
    1791             :                 }
    1792             : 
    1793             :                 // check for typedef that can be substituted
    1794       13638 :                 else if ((tok2->isNameOnly() || (tok2->isName() && (tok2->isExpandedMacro() || tok2->isInline()))) &&
    1795        3534 :                          (Token::simpleMatch(tok2, pattern.c_str(), pattern.size()) ||
    1796          74 :                           (inMemberFunc && tok2->str() == typeName->str()))) {
    1797             :                     // member function class variables don't need qualification
    1798         430 :                     if (!(inMemberFunc && tok2->str() == typeName->str()) && pattern.find("::") != std::string::npos) { // has a "something ::"
    1799          68 :                         Token *start = tok2;
    1800          68 :                         int count = 0;
    1801          68 :                         int back = classLevel - 1;
    1802          68 :                         bool good = true;
    1803             :                         // check for extra qualification
    1804          82 :                         while (back >= 1) {
    1805          21 :                             Token *qualificationTok = start->tokAt(-2);
    1806          21 :                             if (!Token::Match(qualificationTok, "%type% ::"))
    1807           4 :                                 break;
    1808          17 :                             if (qualificationTok->str() == spaceInfo[back].className) {
    1809          14 :                                 start = qualificationTok;
    1810          14 :                                 back--;
    1811          14 :                                 count++;
    1812             :                             } else {
    1813           3 :                                 good = false;
    1814           3 :                                 break;
    1815             :                             }
    1816             :                         }
    1817             :                         // check global namespace
    1818          68 :                         if (good && back == 1 && start->strAt(-1) == "::")
    1819           1 :                             good = false;
    1820             : 
    1821          68 :                         if (good) {
    1822             :                             // remove any extra qualification if present
    1823          76 :                             while (count) {
    1824          12 :                                 if (!removed.empty())
    1825           4 :                                     removed.insert(0, " ");
    1826          12 :                                 removed.insert(0, tok2->strAt(-2) + " " + tok2->strAt(-1));
    1827          12 :                                 tok2->tokAt(-3)->deleteNext(2);
    1828          12 :                                 --count;
    1829             :                             }
    1830             : 
    1831             :                             // remove global namespace if present
    1832          64 :                             if (tok2->strAt(-1) == "::") {
    1833           6 :                                 removed.insert(0, ":: ");
    1834           6 :                                 tok2->tokAt(-2)->deleteNext();
    1835           6 :                                 globalScope = true;
    1836             :                             }
    1837             : 
    1838             :                             // remove qualification if present
    1839         157 :                             for (int i = classLevel; i < spaceInfo.size(); ++i) {
    1840          93 :                                 if (!removed.empty())
    1841          39 :                                     removed += " ";
    1842          93 :                                 removed += (tok2->str() + " " + tok2->strAt(1));
    1843          93 :                                 tok2->deleteThis();
    1844          93 :                                 tok2->deleteThis();
    1845             :                             }
    1846          64 :                             simplifyType = true;
    1847             :                         }
    1848             :                     } else {
    1849         362 :                         if (tok2->strAt(-1) == "::") {
    1850          21 :                             int relativeSpaceInfoSize = spaceInfo.size();
    1851          21 :                             Token * tokBeforeType = tok2->previous();
    1852          38 :                             while (relativeSpaceInfoSize > 1 &&
    1853         122 :                                    tokBeforeType && tokBeforeType->str() == "::" &&
    1854          32 :                                    tokBeforeType->strAt(-1) == spaceInfo[relativeSpaceInfoSize-1].className) {
    1855          31 :                                 tokBeforeType = tokBeforeType->tokAt(-2);
    1856          31 :                                 --relativeSpaceInfoSize;
    1857             :                             }
    1858          21 :                             if (tokBeforeType && tokBeforeType->str() != "::") {
    1859          17 :                                 Token::eraseTokens(tokBeforeType, tok2);
    1860          17 :                                 simplifyType = true;
    1861             :                             }
    1862         341 :                         } else if (Token::Match(tok2->previous(), "case|;|{|} %type% :")) {
    1863           0 :                             tok2 = tok2->next();
    1864         341 :                         } else if (duplicateTypedef(tok2, typeName, typeDef)) {
    1865             :                             // skip to end of scope if not already there
    1866           6 :                             if (tok2->str() != "}") {
    1867          76 :                                 while (tok2->next()) {
    1868          74 :                                     if (tok2->next()->str() == "{")
    1869           1 :                                         tok2 = tok2->linkAt(1)->previous();
    1870          73 :                                     else if (tok2->next()->str() == "}")
    1871           4 :                                         break;
    1872             : 
    1873          70 :                                     tok2 = tok2->next();
    1874             :                                 }
    1875             :                             }
    1876         335 :                         } else if (Token::Match(tok2->tokAt(-2), "%type% *|&")) {
    1877             :                             // Ticket #5868: Don't substitute variable names
    1878         335 :                         } else if (tok2->previous()->str() != ".") {
    1879         335 :                             simplifyType = (TypedefSimplifier::canReplaceStatic(tok2) != 0);
    1880             :                         }
    1881             :                     }
    1882             :                 }
    1883             : 
    1884       13601 :                 simplifyType = simplifyType && (!inEnum || !Token::simpleMatch(tok2->next(), "="));
    1885       13601 :                 simplifyType = simplifyType && !(Token::simpleMatch(tok2->next(), "<") && Token::simpleMatch(typeEnd, ">"));
    1886             : 
    1887       13601 :                 if (simplifyType) {
    1888         407 :                     mTypedefInfo.back().used = true;
    1889             : 
    1890             :                     // can't simplify 'operator functionPtr ()' and 'functionPtr operator ... ()'
    1891         591 :                     if (functionPtr && (tok2->previous()->str() == "operator" ||
    1892         184 :                                         (tok2->next() && tok2->next()->str() == "operator"))) {
    1893           2 :                         simplifyType = false;
    1894           2 :                         tok2 = tok2->next();
    1895           2 :                         continue;
    1896             :                     }
    1897             : 
    1898             :                     // There are 2 categories of typedef substitutions:
    1899             :                     // 1. variable declarations that preserve the variable name like
    1900             :                     //    global, local, and function parameters
    1901             :                     // 2. not variable declarations that have no name like derived
    1902             :                     //    classes, casts, operators, and template parameters
    1903             : 
    1904             :                     // try to determine which category this substitution is
    1905         405 :                     bool inCast = false;
    1906         405 :                     bool inTemplate = false;
    1907         405 :                     bool inOperator = false;
    1908         405 :                     bool inSizeof = false;
    1909             : 
    1910         405 :                     const bool sameStartEnd = (typeStart == typeEnd);
    1911             : 
    1912             :                     // check for derived class: class A : some_typedef {
    1913         405 :                     const bool isDerived = Token::Match(tok2->previous(), "public|protected|private|: %type% {|,");
    1914             : 
    1915             :                     // check for cast: (some_typedef) A or static_cast<some_typedef>(A)
    1916             :                     // todo: check for more complicated casts like: (const some_typedef *)A
    1917         845 :                     if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")" && tok2->strAt(-2) != "sizeof") ||
    1918         869 :                         (tok2->previous()->str() == "<" && Token::simpleMatch(tok2->next(), "> (")) ||
    1919         380 :                         Token::Match(tok2->tokAt(-2), "( const %name% )"))
    1920          25 :                         inCast = true;
    1921             : 
    1922             :                     // check for template parameters: t<some_typedef> t1
    1923         413 :                     else if (Token::Match(tok2->previous(), "<|,") &&
    1924          33 :                              Token::Match(tok2->next(), "&|*| &|*| >|,"))
    1925          25 :                         inTemplate = true;
    1926             : 
    1927         355 :                     else if (Token::Match(tok2->tokAt(-2), "sizeof ( %type% )"))
    1928           0 :                         inSizeof = true;
    1929             : 
    1930             :                     // check for operator
    1931         799 :                     if (tok2->strAt(-1) == "operator" ||
    1932         394 :                         Token::simpleMatch(tok2->tokAt(-2), "operator const"))
    1933          13 :                         inOperator = true;
    1934             : 
    1935         405 :                     if (typeStart->str() == "typename" && tok2->strAt(-1)=="typename") {
    1936             :                         // Remove one typename if it is already contained in the goal
    1937           1 :                         typeStart = typeStart->next();
    1938             :                     }
    1939             : 
    1940             :                     // skip over class or struct in derived class declaration
    1941         405 :                     bool structRemoved = false;
    1942         405 :                     if ((isDerived || inTemplate) && Token::Match(typeStart, "class|struct")) {
    1943           3 :                         if (typeStart->str() == "struct")
    1944           3 :                             structRemoved = true;
    1945           3 :                         typeStart = typeStart->next();
    1946             :                     }
    1947         405 :                     if (Token::Match(typeStart, "struct|class|union") && Token::Match(tok2, "%name% ::"))
    1948           0 :                         typeStart = typeStart->next();
    1949             : 
    1950         405 :                     if (sameStartEnd)
    1951         225 :                         typeEnd = typeStart;
    1952             : 
    1953             :                     // Is this a "T()" expression where T is a pointer type?
    1954         405 :                     const bool isPointerTypeCall = !inOperator && Token::Match(tok2, "%name% ( )") && !pointers.empty();
    1955             : 
    1956             :                     // start substituting at the typedef name by replacing it with the type
    1957         405 :                     Token* replStart = tok2; // track first replaced token
    1958        3189 :                     for (Token* tok3 = typeStart; tok3 && (tok3->str() != ";"); tok3 = tok3->next())
    1959        2784 :                         tok3->isSimplifiedTypedef(true);
    1960         405 :                     if (isPointerTypeCall) {
    1961           0 :                         tok2->deleteThis();
    1962           0 :                         tok2->insertToken("0");
    1963           0 :                         tok2 = tok2->next();
    1964           0 :                         tok2->next()->insertToken("0");
    1965             :                     }
    1966         405 :                     if (Token::Match(tok2->tokAt(-1), "class|struct|union") && tok2->strAt(-1) == typeStart->str())
    1967           3 :                         tok2->deletePrevious();
    1968         405 :                     tok2->str(typeStart->str());
    1969             : 
    1970             :                     // restore qualification if it was removed
    1971         405 :                     if (Token::Match(typeStart, "class|struct|union") || structRemoved) {
    1972          34 :                         if (structRemoved)
    1973           3 :                             tok2 = tok2->previous();
    1974             : 
    1975          34 :                         if (globalScope) {
    1976           2 :                             replStart = tok2->insertToken("::");
    1977           2 :                             tok2 = tok2->next();
    1978             :                         }
    1979             : 
    1980          43 :                         for (int i = classLevel; i < spaceInfo.size(); ++i) {
    1981           9 :                             tok2->insertToken(spaceInfo[i].className);
    1982           9 :                             tok2 = tok2->next();
    1983           9 :                             tok2->insertToken("::");
    1984           9 :                             tok2 = tok2->next();
    1985             :                         }
    1986             :                     }
    1987             : 
    1988             :                     // add some qualification back if needed
    1989         405 :                     Token *start = tok2;
    1990         407 :                     std::string removed1 = removed;
    1991         405 :                     std::string::size_type idx = removed1.rfind(" ::");
    1992             : 
    1993         405 :                     if (idx != std::string::npos)
    1994          64 :                         removed1.resize(idx);
    1995         405 :                     if (removed1 == classPath && !removed1.empty()) {
    1996          83 :                         for (std::vector<Space>::const_reverse_iterator it = spaceInfo.crbegin(); it != spaceInfo.crend(); ++it) {
    1997          83 :                             if (it->recordTypes.find(start->str()) != it->recordTypes.end()) {
    1998           8 :                                 std::string::size_type spaceIdx = 0;
    1999           8 :                                 std::string::size_type startIdx = 0;
    2000          18 :                                 while ((spaceIdx = removed1.find(' ', startIdx)) != std::string::npos) {
    2001          10 :                                     tok2->previous()->insertToken(removed1.substr(startIdx, spaceIdx - startIdx));
    2002          10 :                                     startIdx = spaceIdx + 1;
    2003             :                                 }
    2004           8 :                                 tok2->previous()->insertToken(removed1.substr(startIdx));
    2005           8 :                                 replStart = tok2->previous()->insertToken("::");
    2006           8 :                                 break;
    2007             :                             }
    2008          75 :                             idx = removed1.rfind(" ::");
    2009          75 :                             if (idx == std::string::npos)
    2010          47 :                                 break;
    2011             : 
    2012          28 :                             removed1.resize(idx);
    2013             :                         }
    2014             :                     }
    2015         405 :                     replStart->isSimplifiedTypedef(true);
    2016         405 :                     Token* constTok = Token::simpleMatch(tok2->previous(), "const") ? tok2->previous() : nullptr;
    2017             :                     // add remainder of type
    2018         405 :                     tok2 = TokenList::copyTokens(tok2, typeStart->next(), typeEnd);
    2019             : 
    2020         405 :                     if (!pointers.empty()) {
    2021         104 :                         for (const std::string &p : pointers) {
    2022          61 :                             tok2->insertToken(p);
    2023          61 :                             tok2->isSimplifiedTypedef(true);
    2024          61 :                             tok2 = tok2->next();
    2025             :                         }
    2026          43 :                         if (constTok) {
    2027           0 :                             constTok->deleteThis();
    2028           0 :                             tok2->insertToken("const");
    2029           0 :                             tok2->isSimplifiedTypedef(true);
    2030           0 :                             tok2 = tok2->next();
    2031             :                         }
    2032             :                     }
    2033             : 
    2034         405 :                     if (funcStart && funcEnd) {
    2035         112 :                         tok2->insertToken("(");
    2036         112 :                         tok2 = tok2->next();
    2037         112 :                         Token *paren = tok2;
    2038         112 :                         tok2 = TokenList::copyTokens(tok2, funcStart, funcEnd);
    2039             : 
    2040         112 :                         if (!inCast)
    2041         105 :                             tok2 = processFunc(tok2, inOperator);
    2042             : 
    2043         112 :                         if (!tok2)
    2044           0 :                             break;
    2045             : 
    2046         112 :                         while (Token::Match(tok2, "%name%|] ["))
    2047           0 :                             tok2 = tok2->linkAt(1);
    2048             : 
    2049         112 :                         tok2->insertToken(")");
    2050         112 :                         tok2 = tok2->next();
    2051         112 :                         Token::createMutualLinks(tok2, paren);
    2052             : 
    2053         112 :                         tok2 = TokenList::copyTokens(tok2, argStart, argEnd);
    2054             : 
    2055         112 :                         if (specStart) {
    2056          32 :                             Token *spec = specStart;
    2057          32 :                             tok2->insertToken(spec->str());
    2058          32 :                             tok2 = tok2->next();
    2059          42 :                             while (spec != specEnd) {
    2060          10 :                                 spec = spec->next();
    2061          10 :                                 tok2->insertToken(spec->str());
    2062          10 :                                 tok2 = tok2->next();
    2063             :                             }
    2064         112 :                         }
    2065             :                     }
    2066             : 
    2067         293 :                     else if (functionPtr || function) {
    2068             :                         // don't add parentheses around function names because it
    2069             :                         // confuses other simplifications
    2070           8 :                         bool needParen = true;
    2071           8 :                         if (!inTemplate && function && tok2->next() && tok2->next()->str() != "*")
    2072           1 :                             needParen = false;
    2073           8 :                         if (needParen) {
    2074           7 :                             tok2->insertToken("(");
    2075           7 :                             tok2 = tok2->next();
    2076             :                         }
    2077           8 :                         Token *tok3 = tok2;
    2078           8 :                         if (namespaceStart) {
    2079           0 :                             const Token *tok4 = namespaceStart;
    2080             : 
    2081           0 :                             while (tok4 != namespaceEnd) {
    2082           0 :                                 tok2->insertToken(tok4->str());
    2083           0 :                                 tok2 = tok2->next();
    2084           0 :                                 tok4 = tok4->next();
    2085             :                             }
    2086           0 :                             tok2->insertToken(namespaceEnd->str());
    2087           0 :                             tok2 = tok2->next();
    2088             :                         }
    2089           8 :                         if (functionPtr) {
    2090           0 :                             tok2->insertToken("*");
    2091           0 :                             tok2 = tok2->next();
    2092             :                         }
    2093             : 
    2094           8 :                         if (!inCast)
    2095           8 :                             tok2 = processFunc(tok2, inOperator);
    2096             : 
    2097           8 :                         if (needParen) {
    2098           7 :                             if (!tok2)
    2099           0 :                                 syntaxError(nullptr);
    2100             : 
    2101           7 :                             tok2->insertToken(")");
    2102           7 :                             tok2 = tok2->next();
    2103           7 :                             Token::createMutualLinks(tok2, tok3);
    2104             :                         }
    2105           8 :                         if (!tok2)
    2106           0 :                             syntaxError(nullptr);
    2107             : 
    2108           8 :                         tok2 = TokenList::copyTokens(tok2, argStart, argEnd);
    2109           8 :                         if (inTemplate) {
    2110           5 :                             if (!tok2)
    2111           0 :                                 syntaxError(nullptr);
    2112             : 
    2113           5 :                             tok2 = tok2->next();
    2114             :                         }
    2115             : 
    2116           8 :                         if (specStart) {
    2117           1 :                             Token *spec = specStart;
    2118           1 :                             tok2->insertToken(spec->str());
    2119           1 :                             tok2 = tok2->next();
    2120           1 :                             while (spec != specEnd) {
    2121           0 :                                 spec = spec->next();
    2122           0 :                                 tok2->insertToken(spec->str());
    2123           0 :                                 tok2 = tok2->next();
    2124             :                             }
    2125           8 :                         }
    2126         285 :                     } else if (functionRetFuncPtr || functionPtrRetFuncPtr) {
    2127           3 :                         tok2->insertToken("(");
    2128           3 :                         tok2 = tok2->next();
    2129           3 :                         Token *tok3 = tok2;
    2130           3 :                         tok2->insertToken("*");
    2131           3 :                         tok2 = tok2->next();
    2132             : 
    2133           3 :                         Token * tok4 = nullptr;
    2134           3 :                         if (functionPtrRetFuncPtr) {
    2135           1 :                             tok2->insertToken("(");
    2136           1 :                             tok2 = tok2->next();
    2137           1 :                             tok4 = tok2;
    2138           1 :                             tok2->insertToken("*");
    2139           1 :                             tok2 = tok2->next();
    2140             :                         }
    2141             : 
    2142             :                         // skip over variable name if there
    2143           3 :                         if (!inCast) {
    2144           3 :                             if (!tok2 || !tok2->next())
    2145           0 :                                 syntaxError(nullptr);
    2146             : 
    2147           3 :                             if (tok2->next()->str() != ")")
    2148           3 :                                 tok2 = tok2->next();
    2149             :                         }
    2150             : 
    2151           3 :                         if (tok4 && functionPtrRetFuncPtr) {
    2152           1 :                             tok2->insertToken(")");
    2153           1 :                             tok2 = tok2->next();
    2154           1 :                             Token::createMutualLinks(tok2, tok4);
    2155             :                         }
    2156             : 
    2157           3 :                         tok2 = TokenList::copyTokens(tok2, argStart, argEnd);
    2158             : 
    2159           3 :                         tok2->insertToken(")");
    2160           3 :                         tok2 = tok2->next();
    2161           3 :                         Token::createMutualLinks(tok2, tok3);
    2162             : 
    2163           3 :                         tok2 = TokenList::copyTokens(tok2, argFuncRetStart, argFuncRetEnd);
    2164         282 :                     } else if (ptrToArray || refToArray) {
    2165          14 :                         tok2->insertToken("(");
    2166          14 :                         tok2 = tok2->next();
    2167          14 :                         Token *tok3 = tok2;
    2168             : 
    2169          14 :                         if (ptrToArray)
    2170           5 :                             tok2->insertToken("*");
    2171             :                         else
    2172           9 :                             tok2->insertToken("&");
    2173          14 :                         tok2 = tok2->next();
    2174             : 
    2175          14 :                         bool hasName = false;
    2176             :                         // skip over name
    2177          27 :                         if (tok2->next() && tok2->next()->str() != ")" && tok2->next()->str() != "," &&
    2178          13 :                             tok2->next()->str() != ">") {
    2179          12 :                             hasName = true;
    2180          12 :                             if (tok2->next()->str() != "(")
    2181          11 :                                 tok2 = tok2->next();
    2182             : 
    2183             :                             // check for function and skip over args
    2184          12 :                             if (tok2 && tok2->next() && tok2->next()->str() == "(")
    2185           2 :                                 tok2 = tok2->next()->link();
    2186             : 
    2187             :                             // check for array
    2188          12 :                             if (tok2 && tok2->next() && tok2->next()->str() == "[")
    2189           1 :                                 tok2 = tok2->next()->link();
    2190             :                         }
    2191             : 
    2192          14 :                         tok2->insertToken(")");
    2193          14 :                         Token::createMutualLinks(tok2->next(), tok3);
    2194             : 
    2195          14 :                         if (!hasName)
    2196          14 :                             tok2 = tok2->next();
    2197         268 :                     } else if (ptrMember) {
    2198           8 :                         if (Token::simpleMatch(tok2, "* (")) {
    2199           5 :                             tok2->insertToken("*");
    2200           5 :                             tok2 = tok2->next();
    2201             :                         } else {
    2202             :                             // This is the case of casting operator.
    2203             :                             // Name is not available, and () should not be
    2204             :                             // inserted
    2205           3 :                             const bool castOperator = inOperator && Token::Match(tok2, "%type% (");
    2206           3 :                             Token *openParenthesis = nullptr;
    2207             : 
    2208           3 :                             if (!castOperator) {
    2209           2 :                                 tok2->insertToken("(");
    2210           2 :                                 tok2 = tok2->next();
    2211             : 
    2212           2 :                                 openParenthesis = tok2;
    2213             :                             }
    2214             : 
    2215           3 :                             const Token *tok4 = namespaceStart;
    2216             : 
    2217           6 :                             while (tok4 != namespaceEnd) {
    2218           3 :                                 tok2->insertToken(tok4->str());
    2219           3 :                                 tok2 = tok2->next();
    2220           3 :                                 tok4 = tok4->next();
    2221             :                             }
    2222           3 :                             tok2->insertToken(namespaceEnd->str());
    2223           3 :                             tok2 = tok2->next();
    2224             : 
    2225           3 :                             tok2->insertToken("*");
    2226           3 :                             tok2 = tok2->next();
    2227             : 
    2228           3 :                             if (openParenthesis) {
    2229             :                                 // Skip over name, if any
    2230           2 :                                 if (Token::Match(tok2->next(), "%name%"))
    2231           1 :                                     tok2 = tok2->next();
    2232             : 
    2233           2 :                                 tok2->insertToken(")");
    2234           2 :                                 tok2 = tok2->next();
    2235             : 
    2236           2 :                                 Token::createMutualLinks(tok2, openParenthesis);
    2237             :                             }
    2238             :                         }
    2239         260 :                     } else if (typeOf) {
    2240           1 :                         tok2 = TokenList::copyTokens(tok2, argStart, argEnd);
    2241         259 :                     } else if (Token::Match(tok2, "%name% [")) {
    2242           0 :                         while (Token::Match(tok2, "%name%|] [")) {
    2243           0 :                             tok2 = tok2->linkAt(1);
    2244             :                         }
    2245           0 :                         tok2 = tok2->previous();
    2246             :                     }
    2247             : 
    2248         405 :                     if (arrayStart && arrayEnd) {
    2249           0 :                         do {
    2250          34 :                             if (!tok2->next())
    2251           0 :                                 syntaxError(tok2); // can't recover so quit
    2252             : 
    2253          34 :                             if (!inCast && !inSizeof && !inTemplate)
    2254          32 :                                 tok2 = tok2->next();
    2255             : 
    2256          34 :                             if (tok2->str() == "const")
    2257           0 :                                 tok2 = tok2->next();
    2258             : 
    2259             :                             // reference or pointer to array?
    2260          34 :                             if (Token::Match(tok2, "&|*|&&")) {
    2261          10 :                                 tok2 = tok2->previous();
    2262          10 :                                 tok2->insertToken("(");
    2263          10 :                                 Token *tok3 = tok2->next();
    2264             : 
    2265             :                                 // handle missing variable name
    2266          10 :                                 if (Token::Match(tok3, "( *|&|&& *|&|&& %name%"))
    2267           0 :                                     tok2 = tok3->tokAt(3);
    2268          10 :                                 else if (Token::Match(tok2->tokAt(3), "[(),;]"))
    2269           3 :                                     tok2 = tok2->tokAt(2);
    2270           7 :                                 else if (Token::simpleMatch(tok2->tokAt(3), ">"))
    2271           1 :                                     tok2 = tok2->tokAt(2);
    2272             :                                 else
    2273           6 :                                     tok2 = tok2->tokAt(3);
    2274          10 :                                 if (!tok2)
    2275           0 :                                     syntaxError(nullptr);
    2276             : 
    2277          10 :                                 while (tok2->strAt(1) == "::")
    2278           0 :                                     tok2 = tok2->tokAt(2);
    2279             : 
    2280             :                                 // skip over function parameters
    2281          10 :                                 if (tok2->str() == "(")
    2282           0 :                                     tok2 = tok2->link();
    2283             : 
    2284          10 :                                 if (tok2->strAt(1) == "(")
    2285           5 :                                     tok2 = tok2->linkAt(1);
    2286             : 
    2287             :                                 // skip over const/noexcept
    2288          15 :                                 while (Token::Match(tok2->next(), "const|noexcept")) {
    2289           5 :                                     tok2 = tok2->next();
    2290           5 :                                     if (Token::Match(tok2->next(), "( true|false )"))
    2291           3 :                                         tok2 = tok2->tokAt(3);
    2292             :                                 }
    2293             : 
    2294          10 :                                 tok2->insertToken(")");
    2295          10 :                                 tok2 = tok2->next();
    2296          10 :                                 Token::createMutualLinks(tok2, tok3);
    2297             :                             }
    2298             : 
    2299          34 :                             if (!tok2->next())
    2300           2 :                                 syntaxError(tok2); // can't recover so quit
    2301             : 
    2302             :                             // skip over array dimensions
    2303          33 :                             while (tok2->next()->str() == "[")
    2304           1 :                                 tok2 = tok2->linkAt(1);
    2305             : 
    2306          32 :                             tok2 = TokenList::copyTokens(tok2, arrayStart, arrayEnd);
    2307          32 :                             if (!tok2->next())
    2308           0 :                                 syntaxError(tok2);
    2309             : 
    2310          32 :                             if (tok2->str() == "=") {
    2311           0 :                                 if (tok2->next()->str() == "{")
    2312           0 :                                     tok2 = tok2->next()->link()->next();
    2313           0 :                                 else if (tok2->next()->str().at(0) == '\"')
    2314           0 :                                     tok2 = tok2->tokAt(2);
    2315             :                             }
    2316          32 :                         } while (Token::Match(tok2, ", %name% ;|=|,"));
    2317             :                     }
    2318             : 
    2319         403 :                     simplifyType = false;
    2320             :                 }
    2321       13597 :                 if (!tok2)
    2322           0 :                     break;
    2323             :             }
    2324             : 
    2325         327 :             if (!tok)
    2326           0 :                 syntaxError(nullptr);
    2327             : 
    2328         327 :             if (tok->str() == ";")
    2329         315 :                 done = true;
    2330          12 :             else if (tok->str() == ",") {
    2331           9 :                 arrayStart = nullptr;
    2332           9 :                 arrayEnd = nullptr;
    2333           9 :                 tokOffset = tok->next();
    2334           9 :                 pointers.clear();
    2335             : 
    2336          25 :                 while (Token::Match(tokOffset, "*|&")) {
    2337          16 :                     pointers.push_back(tokOffset->str());
    2338          16 :                     tokOffset = tokOffset->next();
    2339             :                 }
    2340             : 
    2341           9 :                 if (Token::Match(tokOffset, "%type%")) {
    2342           9 :                     typeName = tokOffset;
    2343           9 :                     tokOffset = tokOffset->next();
    2344             : 
    2345           9 :                     if (tokOffset && tokOffset->str() == "[") {
    2346           0 :                         arrayStart = tokOffset;
    2347             : 
    2348             :                         for (;;) {
    2349           0 :                             while (tokOffset->next() && !Token::Match(tokOffset->next(), ";|,"))
    2350           0 :                                 tokOffset = tokOffset->next();
    2351             : 
    2352           0 :                             if (!tokOffset->next())
    2353           0 :                                 return; // invalid input
    2354           0 :                             if (tokOffset->next()->str() == ";")
    2355           0 :                                 break;
    2356           0 :                             if (tokOffset->str() == "]")
    2357           0 :                                 break;
    2358           0 :                             tokOffset = tokOffset->next();
    2359             :                         }
    2360             : 
    2361           0 :                         arrayEnd = tokOffset;
    2362           0 :                         tokOffset = tokOffset->next();
    2363             :                     }
    2364             : 
    2365           9 :                     if (Token::Match(tokOffset, ";|,"))
    2366           9 :                         tok = tokOffset;
    2367             :                     else {
    2368             :                         // we encountered a typedef we don't support yet so just continue
    2369           0 :                         done = true;
    2370           0 :                         ok = false;
    2371             :                     }
    2372             :                 } else {
    2373             :                     // we encountered a typedef we don't support yet so just continue
    2374           0 :                     done = true;
    2375           0 :                     ok = false;
    2376             :                 }
    2377             :             } else {
    2378             :                 // something is really wrong (internal error)
    2379           3 :                 done = true;
    2380           3 :                 ok = false;
    2381             :             }
    2382             :         }
    2383             : 
    2384         318 :         if (ok) {
    2385             :             // remove typedef
    2386         315 :             Token::eraseTokens(typeDef, tok);
    2387             : 
    2388         315 :             if (typeDef != list.front()) {
    2389         186 :                 tok = typeDef->previous();
    2390         186 :                 tok->deleteNext();
    2391             :                 //no need to remove last token in the list
    2392         186 :                 if (tok->tokAt(2))
    2393         185 :                     tok->deleteNext();
    2394             :             } else {
    2395         129 :                 list.front()->deleteThis();
    2396             :                 //no need to remove last token in the list
    2397         129 :                 if (list.front()->next())
    2398         126 :                     list.front()->deleteThis();
    2399         129 :                 tok = list.front();
    2400             :                 //now the next token to process is 'tok', not 'tok->next()';
    2401         129 :                 goback = true;
    2402             :             }
    2403             :         }
    2404             :     }
    2405             : }
    2406             : 
    2407             : namespace {
    2408             :     struct ScopeInfo3 {
    2409             :         enum Type { Global, Namespace, Record, MemberFunction, Other };
    2410       17685 :         ScopeInfo3() : parent(nullptr), type(Global), bodyStart(nullptr), bodyEnd(nullptr) {}
    2411       36279 :         ScopeInfo3(ScopeInfo3 *parent_, Type type_, std::string name_, const Token *bodyStart_, const Token *bodyEnd_)
    2412       36279 :             : parent(parent_), type(type_), name(std::move(name_)), bodyStart(bodyStart_), bodyEnd(bodyEnd_) {
    2413       36277 :             if (name.empty())
    2414       29058 :                 return;
    2415        7219 :             fullName = name;
    2416        7219 :             ScopeInfo3 *scope = parent;
    2417        8330 :             while (scope && scope->parent) {
    2418        1231 :                 if (scope->name.empty())
    2419         120 :                     break;
    2420        1111 :                 fullName = scope->name + " :: " + fullName;
    2421        1111 :                 scope = scope->parent;
    2422             :             }
    2423             :         }
    2424             :         ScopeInfo3 *parent;
    2425             :         std::list<ScopeInfo3> children;
    2426             :         Type type;
    2427             :         std::string fullName;
    2428             :         std::string name;
    2429             :         const Token * bodyStart;
    2430             :         const Token * bodyEnd;
    2431             :         std::set<std::string> usingNamespaces;
    2432             :         std::set<std::string> recordTypes;
    2433             :         std::set<std::string> baseTypes;
    2434             : 
    2435       36280 :         ScopeInfo3 *addChild(Type scopeType, const std::string &scopeName, const Token *bodyStartToken, const Token *bodyEndToken) {
    2436       36280 :             children.emplace_back(this, scopeType, scopeName, bodyStartToken, bodyEndToken);
    2437       36277 :             return &children.back();
    2438             :         }
    2439             : 
    2440           2 :         bool hasChild(const std::string &childName) const {
    2441           2 :             return std::any_of(children.cbegin(), children.cend(), [&](const ScopeInfo3& child) {
    2442           2 :                 return child.name == childName;
    2443           2 :             });
    2444             :         }
    2445             : 
    2446         455 :         const ScopeInfo3 * findInChildren(const std::string & scope) const {
    2447         819 :             for (const auto & child : children) {
    2448         374 :                 if (child.type == Record && (child.name == scope || child.fullName == scope))
    2449          10 :                     return &child;
    2450             : 
    2451         365 :                 const ScopeInfo3 * temp = child.findInChildren(scope);
    2452         365 :                 if (temp)
    2453           1 :                     return temp;
    2454             :             }
    2455         445 :             return nullptr;
    2456             :         }
    2457             : 
    2458          58 :         const ScopeInfo3 * findScope(const std::string & scope) const {
    2459          58 :             const ScopeInfo3 * tempScope = this;
    2460         182 :             while (tempScope) {
    2461             :                 // check children
    2462         159 :                 auto it = std::find_if(tempScope->children.cbegin(), tempScope->children.cend(), [&](const ScopeInfo3& child) {
    2463         159 :                     return &child != this && child.type == Record && (child.name == scope || child.fullName == scope);
    2464         158 :                 });
    2465         158 :                 if (it != tempScope->children.end())
    2466          34 :                     return &*it;
    2467             :                 // check siblings for same name
    2468         133 :                 if (tempScope->parent) {
    2469         236 :                     for (const auto &sibling : tempScope->parent->children) {
    2470         136 :                         if (sibling.name == tempScope->name && &sibling != this) {
    2471          90 :                             const ScopeInfo3 * temp = sibling.findInChildren(scope);
    2472          90 :                             if (temp)
    2473           9 :                                 return temp;
    2474             :                         }
    2475             :                     }
    2476             :                 }
    2477         124 :                 tempScope = tempScope->parent;
    2478             :             }
    2479          24 :             return nullptr;
    2480             :         }
    2481             : 
    2482          35 :         bool findTypeInBase(const std::string &scope) const {
    2483          35 :             if (scope.empty())
    2484           5 :                 return false;
    2485             :             // check in base types first
    2486          30 :             if (baseTypes.find(scope) != baseTypes.end())
    2487           6 :                 return true;
    2488             :             // check in base types base types
    2489          26 :             for (const std::string & base : baseTypes) {
    2490           9 :                 const ScopeInfo3 * baseScope = findScope(base);
    2491             :                 // bail on uninstantiated recursive template
    2492           9 :                 if (baseScope == this)
    2493           7 :                     return false;
    2494           9 :                 if (baseScope && baseScope->fullName == scope)
    2495           5 :                     return true;
    2496           4 :                 if (baseScope && baseScope->findTypeInBase(scope))
    2497           2 :                     return true;
    2498             :             }
    2499          17 :             return false;
    2500             :         }
    2501             : 
    2502          90 :         ScopeInfo3 * findScope(const ScopeInfo3 * scope) {
    2503          90 :             if (scope->bodyStart == bodyStart)
    2504          25 :                 return this;
    2505          87 :             for (auto & child : children) {
    2506          65 :                 ScopeInfo3 * temp = child.findScope(scope);
    2507          65 :                 if (temp)
    2508          43 :                     return temp;
    2509             :             }
    2510          22 :             return nullptr;
    2511             :         }
    2512             :     };
    2513             : 
    2514       81288 :     void setScopeInfo(Token *tok, ScopeInfo3 *&scopeInfo, bool debug=false)
    2515             :     {
    2516       81288 :         if (!tok)
    2517       74901 :             return;
    2518       81288 :         if (tok->str() == "{" && scopeInfo->parent && tok == scopeInfo->bodyStart)
    2519        6286 :             return;
    2520       75002 :         if (tok->str() == "}") {
    2521       36301 :             if (scopeInfo->parent && tok == scopeInfo->bodyEnd)
    2522       36300 :                 scopeInfo = scopeInfo->parent;
    2523             :             else {
    2524             :                 // Try to find parent scope
    2525           1 :                 ScopeInfo3 *parent = scopeInfo->parent;
    2526           2 :                 while (parent && parent->bodyEnd != tok)
    2527           1 :                     parent = parent->parent;
    2528           1 :                 if (parent) {
    2529           0 :                     scopeInfo = parent;
    2530           0 :                     if (debug)
    2531           0 :                         throw std::runtime_error("Internal error: unmatched }");
    2532             :                 }
    2533             :             }
    2534       36301 :             return;
    2535             :         }
    2536       38700 :         if (!Token::Match(tok, "namespace|class|struct|union %name% {|:|::|<")) {
    2537             :             // check for using namespace
    2538       32317 :             if (Token::Match(tok, "using namespace %name% ;|::")) {
    2539         140 :                 const Token * tok1 = tok->tokAt(2);
    2540         280 :                 std::string nameSpace;
    2541         362 :                 while (tok1 && tok1->str() != ";") {
    2542         222 :                     if (!nameSpace.empty())
    2543          82 :                         nameSpace += " ";
    2544         222 :                     nameSpace += tok1->str();
    2545         222 :                     tok1 = tok1->next();
    2546             :                 }
    2547         140 :                 scopeInfo->usingNamespaces.insert(std::move(nameSpace));
    2548             :             }
    2549             :             // check for member function
    2550       32178 :             else if (tok->str() == "{") {
    2551       29994 :                 bool added = false;
    2552       29994 :                 Token *tok1 = tok;
    2553       30340 :                 while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept"))
    2554         346 :                     tok1 = tok1->previous();
    2555       29994 :                 if (tok1->previous() && (tok1->strAt(-1) == ")" || tok->strAt(-1) == "}")) {
    2556       26859 :                     tok1 = tok1->linkAt(-1);
    2557       26859 :                     if (Token::Match(tok1->previous(), "throw|noexcept (")) {
    2558          60 :                         tok1 = tok1->previous();
    2559          78 :                         while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept"))
    2560          18 :                             tok1 = tok1->previous();
    2561          60 :                         if (tok1->strAt(-1) != ")")
    2562           1 :                             return;
    2563          59 :                         tok1 = tok1->linkAt(-1);
    2564             :                     } else {
    2565       27255 :                         while (Token::Match(tok1->tokAt(-2), ":|, %name%")) {
    2566         457 :                             tok1 = tok1->tokAt(-2);
    2567         457 :                             if (tok1->strAt(-1) != ")" && tok1->strAt(-1) != "}")
    2568           0 :                                 return;
    2569         457 :                             tok1 = tok1->linkAt(-1);
    2570             :                         }
    2571             :                     }
    2572       26859 :                     if (tok1->strAt(-1) == ">")
    2573          50 :                         tok1 = tok1->previous()->findOpeningBracket();
    2574       52834 :                     if (tok1 && (Token::Match(tok1->tokAt(-3), "%name% :: %name%") ||
    2575       25978 :                                  Token::Match(tok1->tokAt(-4), "%name% :: ~ %name%"))) {
    2576         933 :                         tok1 = tok1->tokAt(-2);
    2577         933 :                         if (tok1->str() == "~")
    2578          54 :                             tok1 = tok1->previous();
    2579         933 :                         std::string scope = tok1->strAt(-1);
    2580        1094 :                         while (Token::Match(tok1->tokAt(-2), ":: %name%")) {
    2581         161 :                             scope = tok1->strAt(-3) + " :: " + scope;
    2582         161 :                             tok1 = tok1->tokAt(-2);
    2583             :                         }
    2584         933 :                         scopeInfo = scopeInfo->addChild(ScopeInfo3::MemberFunction, scope, tok, tok->link());
    2585         933 :                         added = true;
    2586             :                     }
    2587             :                 }
    2588             : 
    2589       29992 :                 if (!added)
    2590       29060 :                     scopeInfo = scopeInfo->addChild(ScopeInfo3::Other, emptyString, tok, tok->link());
    2591             :             }
    2592       32313 :             return;
    2593             :         }
    2594             : 
    2595        6382 :         const bool record = Token::Match(tok, "class|struct|union %name%");
    2596        6382 :         tok = tok->next();
    2597       12764 :         std::string classname = tok->str();
    2598        6581 :         while (Token::Match(tok, "%name% :: %name%")) {
    2599         199 :             tok = tok->tokAt(2);
    2600         199 :             classname += " :: " + tok->str();
    2601             :         }
    2602             : 
    2603             :         // add record type to scope info
    2604        6382 :         if (record)
    2605        5588 :             scopeInfo->recordTypes.insert(classname);
    2606        6382 :         tok = tok->next();
    2607             : 
    2608             :         // skip template parameters
    2609        6382 :         if (tok && tok->str() == "<") {
    2610          94 :             tok = tok->findClosingBracket();
    2611          94 :             if (tok)
    2612          93 :                 tok = tok->next();
    2613             :         }
    2614             : 
    2615             :         // get base class types
    2616       12764 :         std::set<std::string> baseTypes;
    2617        6382 :         if (tok && tok->str() == ":") {
    2618          36 :             do {
    2619         694 :                 tok = tok->next();
    2620        1164 :                 while (Token::Match(tok, "public|protected|private|virtual"))
    2621         470 :                     tok = tok->next();
    2622        1388 :                 std::string base;
    2623        1489 :                 while (tok && !Token::Match(tok, ";|,|{")) {
    2624         795 :                     if (!base.empty())
    2625         105 :                         base += ' ';
    2626         795 :                     base += tok->str();
    2627         795 :                     tok = tok->next();
    2628             :                     // add template parameters
    2629         795 :                     if (tok && tok->str() == "<") {
    2630          81 :                         const Token* endTok = tok->findClosingBracket();
    2631          81 :                         if (endTok) {
    2632          81 :                             endTok = endTok->next();
    2633         466 :                             while (tok != endTok) {
    2634         385 :                                 base += tok->str();
    2635         385 :                                 tok = tok->next();
    2636             :                             }
    2637             :                         }
    2638             :                     }
    2639             :                 }
    2640         694 :                 baseTypes.insert(std::move(base));
    2641         694 :             } while (tok && !Token::Match(tok, ";|{"));
    2642             :         }
    2643             : 
    2644        6382 :         if (tok && tok->str() == "{") {
    2645        6286 :             scopeInfo = scopeInfo->addChild(record ? ScopeInfo3::Record : ScopeInfo3::Namespace, classname, tok, tok->link());
    2646        6286 :             scopeInfo->baseTypes = std::move(baseTypes);
    2647             :         }
    2648             :     }
    2649             : 
    2650         349 :     Token *findSemicolon(Token *tok)
    2651             :     {
    2652         349 :         int level = 0;
    2653             : 
    2654        7238 :         for (; tok && (level > 0 || tok->str() != ";"); tok = tok->next()) {
    2655        6889 :             if (tok->str() == "{")
    2656          15 :                 ++level;
    2657        6874 :             else if (level > 0 && tok->str() == "}")
    2658          15 :                 --level;
    2659             :         }
    2660             : 
    2661         349 :         return tok;
    2662             :     }
    2663             : 
    2664        9457 :     bool usingMatch(
    2665             :         const Token *nameToken,
    2666             :         const std::string &scope,
    2667             :         Token *&tok,
    2668             :         const std::string &scope1,
    2669             :         const ScopeInfo3 *currentScope,
    2670             :         const ScopeInfo3 *memberClassScope)
    2671             :     {
    2672        9457 :         Token *tok1 = tok;
    2673             : 
    2674        9457 :         if (tok1 && tok1->str() != nameToken->str())
    2675        9061 :             return false;
    2676             : 
    2677             :         // skip this using
    2678         396 :         if (tok1 == nameToken) {
    2679         155 :             tok = findSemicolon(tok1);
    2680         155 :             return false;
    2681             :         }
    2682             : 
    2683             :         // skip other using with this name
    2684         241 :         if (tok1->strAt(-1) == "using") {
    2685             :             // fixme: this is wrong
    2686             :             // skip to end of scope
    2687          12 :             if (currentScope->bodyEnd)
    2688           9 :                 tok = const_cast<Token*>(currentScope->bodyEnd->previous());
    2689          12 :             return false;
    2690             :         }
    2691             : 
    2692         229 :         if (Token::Match(tok1->tokAt(-1), "class|struct|union|enum|namespace")) {
    2693             :             // fixme
    2694          12 :             return false;
    2695             :         }
    2696             : 
    2697             :         // get qualification
    2698         434 :         std::string qualification;
    2699         217 :         const Token* tok2 = tok1;
    2700         217 :         std::string::size_type index = scope.size();
    2701         217 :         std::string::size_type new_index = std::string::npos;
    2702         217 :         bool match = true;
    2703         262 :         while (Token::Match(tok2->tokAt(-2), "%name% ::") && !tok2->tokAt(-2)->isKeyword()) {
    2704          45 :             std::string last;
    2705          45 :             if (match && !scope1.empty()) {
    2706          35 :                 new_index = scope1.rfind(' ', index - 1);
    2707          35 :                 if (new_index != std::string::npos)
    2708          19 :                     last = scope1.substr(new_index, index - new_index);
    2709          16 :                 else if (!qualification.empty())
    2710           3 :                     last.clear();
    2711             :                 else
    2712          13 :                     last = scope1;
    2713             :             } else
    2714          10 :                 match = false;
    2715          45 :             if (match && tok2->strAt(-2) == last)
    2716           3 :                 index = new_index;
    2717             :             else {
    2718          42 :                 if (!qualification.empty())
    2719          14 :                     qualification = " :: " + qualification;
    2720          42 :                 qualification = tok2->strAt(-2) + qualification;
    2721             :             }
    2722          45 :             tok2 = tok2->tokAt(-2);
    2723             :         }
    2724             : 
    2725         434 :         std::string fullScope1 = scope1;
    2726         217 :         if (!scope1.empty() && !qualification.empty())
    2727          20 :             fullScope1 += " :: ";
    2728         217 :         fullScope1 += qualification;
    2729             : 
    2730         217 :         if (scope == fullScope1)
    2731         162 :             return true;
    2732             : 
    2733          55 :         const ScopeInfo3 *scopeInfo = memberClassScope ? memberClassScope : currentScope;
    2734             : 
    2735             :         // check in base types
    2736          55 :         if (qualification.empty() && scopeInfo->findTypeInBase(scope))
    2737          11 :             return true;
    2738             : 
    2739             :         // check using namespace
    2740          44 :         const ScopeInfo3 * tempScope = scopeInfo;
    2741         162 :         while (tempScope) {
    2742             :             //if (!tempScope->parent->usingNamespaces.empty()) {
    2743         125 :             const std::set<std::string>& usingNS = tempScope->usingNamespaces;
    2744         125 :             if (!usingNS.empty()) {
    2745           8 :                 if (qualification.empty()) {
    2746           6 :                     if (usingNS.find(scope) != usingNS.end())
    2747           6 :                         return true;
    2748             :                 } else {
    2749           2 :                     const std::string suffix = " :: " + qualification;
    2750           2 :                     if (std::any_of(usingNS.cbegin(), usingNS.cend(), [&](const std::string& ns) {
    2751           2 :                         return scope == ns + suffix;
    2752             :                     }))
    2753           1 :                         return true;
    2754             :                 }
    2755             :             }
    2756         118 :             tempScope = tempScope->parent;
    2757             :         }
    2758             : 
    2759          74 :         std::string newScope1 = scope1;
    2760             : 
    2761             :         // scopes didn't match so try higher scopes
    2762          37 :         index = newScope1.size();
    2763          54 :         while (!newScope1.empty()) {
    2764          43 :             const std::string::size_type separator = newScope1.rfind(" :: ", index - 1);
    2765          43 :             if (separator != std::string::npos)
    2766          15 :                 newScope1.resize(separator);
    2767             :             else
    2768          28 :                 newScope1.clear();
    2769             : 
    2770          43 :             std::string newFullScope1 = newScope1;
    2771          43 :             if (!newScope1.empty() && !qualification.empty())
    2772          10 :                 newFullScope1 += " :: ";
    2773          43 :             newFullScope1 += qualification;
    2774             : 
    2775          43 :             if (scope == newFullScope1)
    2776          26 :                 return true;
    2777             :         }
    2778             : 
    2779          11 :         return false;
    2780             :     }
    2781             : 
    2782          40 :     std::string memberFunctionScope(const Token *tok)
    2783             :     {
    2784          40 :         std::string qualification;
    2785          40 :         const Token *qualTok = tok->strAt(-2) == "~" ? tok->tokAt(-4) : tok->tokAt(-3);
    2786          83 :         while (Token::Match(qualTok, "%type% ::")) {
    2787          43 :             if (!qualification.empty())
    2788           3 :                 qualification = " :: " + qualification;
    2789          43 :             qualification = qualTok->str() + qualification;
    2790          43 :             qualTok = qualTok->tokAt(-2);
    2791             :         }
    2792          40 :         return qualification;
    2793             :     }
    2794             : 
    2795          25 :     const Token * memberFunctionEnd(const Token *tok)
    2796             :     {
    2797          25 :         if (tok->str() != "(")
    2798           0 :             return nullptr;
    2799          25 :         const Token *end = tok->link()->next();
    2800          66 :         while (end) {
    2801          66 :             if (end->str() == "{" && !Token::Match(end->tokAt(-2), ":|, %name%"))
    2802          25 :                 return end;
    2803          41 :             if (end->str() == ";")
    2804           0 :                 break;
    2805          41 :             end = end->next();
    2806             :         }
    2807           0 :         return nullptr;
    2808             :     }
    2809             : } // namespace
    2810             : 
    2811        9497 : bool Tokenizer::isMemberFunction(const Token *openParen)
    2812             : {
    2813        9497 :     return (Token::Match(openParen->tokAt(-2), ":: %name% (") ||
    2814       19035 :             Token::Match(openParen->tokAt(-3), ":: ~ %name% (")) &&
    2815       19035 :            isFunctionHead(openParen, "{|:");
    2816             : }
    2817             : 
    2818         191 : static bool scopesMatch(const std::string &scope1, const std::string &scope2, const ScopeInfo3 *globalScope)
    2819             : {
    2820         191 :     if (scope1.empty() || scope2.empty())
    2821         163 :         return false;
    2822             : 
    2823             :     // check if scopes match
    2824          28 :     if (scope1 == scope2)
    2825          25 :         return true;
    2826             : 
    2827             :     // check if scopes only differ by global qualification
    2828           3 :     if (scope1 == (":: " + scope2)) {
    2829           2 :         std::string::size_type end = scope2.find_first_of(' ');
    2830           2 :         if (end == std::string::npos)
    2831           1 :             end = scope2.size();
    2832           2 :         if (globalScope->hasChild(scope2.substr(0, end)))
    2833           2 :             return true;
    2834           1 :     } else if (scope2 == (":: " + scope1)) {
    2835           0 :         std::string::size_type end = scope1.find_first_of(' ');
    2836           0 :         if (end == std::string::npos)
    2837           0 :             end = scope1.size();
    2838           0 :         if (globalScope->hasChild(scope1.substr(0, end)))
    2839           0 :             return true;
    2840             :     }
    2841             : 
    2842           1 :     return false;
    2843             : }
    2844             : 
    2845         206 : static unsigned int tokDistance(const Token* tok1, const Token* tok2) {
    2846         206 :     unsigned int dist = 0;
    2847         206 :     const Token* tok = tok1;
    2848        6268 :     while (tok != tok2) {
    2849        6062 :         ++dist;
    2850        6062 :         tok = tok->next();
    2851             :     }
    2852         206 :     return dist;
    2853             : }
    2854             : 
    2855       23490 : bool Tokenizer::simplifyUsing()
    2856             : {
    2857       23490 :     if (!isCPP() || mSettings.standards.cpp < Standards::CPP11)
    2858        5985 :         return false;
    2859             : 
    2860             :     // simplify using N::x; to using x = N::x;
    2861      801552 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    2862      784049 :         if (!Token::Match(tok, "using ::| %name% ::"))
    2863      784022 :             continue;
    2864          25 :         const Token* ns = tok->tokAt(tok->strAt(1) == "::" ? 2 : 1);
    2865          25 :         if (ns->isKeyword())
    2866           2 :             continue;
    2867          23 :         Token* end = tok->tokAt(3);
    2868          72 :         while (end && !Token::Match(end, "[;,]")) {
    2869          49 :             if (end->str() == "<") // skip template args
    2870           3 :                 end = end->findClosingBracket();
    2871             :             else
    2872          46 :                 end = end->next();
    2873             :         }
    2874          23 :         if (!end)
    2875           0 :             continue;
    2876          23 :         if (!end->tokAt(-1)->isNameOnly() || end->tokAt(-2)->isLiteral()) // e.g. operator=, operator""sv
    2877          10 :             continue;
    2878          13 :         tok->insertToken(end->strAt(-1))->insertToken("=")->isSimplifiedTypedef(true);
    2879          13 :         if (end->str() == ",") { // comma-separated list
    2880           3 :             end->str(";");
    2881           3 :             end->insertToken("using");
    2882             :         }
    2883          13 :         tok = end;
    2884             :     }
    2885             : 
    2886       17504 :     const unsigned int maxReplacementTokens = 1000; // limit the number of tokens we replace
    2887             : 
    2888       17504 :     bool substitute = false;
    2889       35004 :     ScopeInfo3 scopeInfo;
    2890       17499 :     ScopeInfo3 *currentScope = &scopeInfo;
    2891             :     struct Using {
    2892         174 :         Using(Token *start, Token *end) : startTok(start), endTok(end) {}
    2893             :         Token *startTok;
    2894             :         Token *endTok;
    2895             :     };
    2896       35003 :     std::list<Using> usingList;
    2897             : 
    2898      760958 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    2899      743456 :         if (!list.getFiles().empty())
    2900      743454 :             mErrorLogger.reportProgress(list.getFiles()[0], "Tokenize (using)", tok->progressValue());
    2901             : 
    2902      743452 :         if (Settings::terminated())
    2903           0 :             return substitute;
    2904             : 
    2905      743455 :         if (Token::Match(tok, "enum class|struct")) {
    2906          75 :             Token *bodyStart = tok;
    2907         426 :             while (Token::Match(bodyStart, "%name%|:|::|<")) {
    2908         351 :                 if (bodyStart->str() == "<")
    2909           0 :                     bodyStart = bodyStart->findClosingBracket();
    2910         351 :                 bodyStart = bodyStart ? bodyStart->next() : nullptr;
    2911             :             }
    2912          75 :             if (Token::simpleMatch(bodyStart, "{"))
    2913          71 :                 tok = bodyStart->link();
    2914      743277 :             continue;
    2915             :         }
    2916             : 
    2917     1406718 :         if (Token::Match(tok, "{|}|namespace|class|struct|union") ||
    2918      663338 :             Token::Match(tok, "using namespace %name% ;|::")) {
    2919             :             try {
    2920       80173 :                 setScopeInfo(tok, currentScope, mSettings.debugwarnings);
    2921           0 :             } catch (const std::runtime_error &) {
    2922           0 :                 reportError(tok, Severity::debug, "simplifyUsingUnmatchedBodyEnd",
    2923           0 :                             "simplifyUsing: unmatched body end");
    2924             :             }
    2925       80172 :             continue;
    2926             :         }
    2927             : 
    2928             :         // skip template declarations
    2929      663208 :         if (Token::Match(tok, "template < !!>")) {
    2930             :             // add template record type to scope info
    2931        2127 :             const Token *end = tok->next()->findClosingBracket();
    2932        2127 :             if (end && Token::Match(end->next(), "class|struct|union %name%"))
    2933        1295 :                 currentScope->recordTypes.insert(end->strAt(2));
    2934             : 
    2935        2127 :             Token *declEndToken = TemplateSimplifier::findTemplateDeclarationEnd(tok);
    2936        2127 :             if (declEndToken)
    2937        2126 :                 tok = declEndToken;
    2938        2127 :             continue;
    2939             :         }
    2940             : 
    2941             :         // look for non-template type aliases
    2942     1317355 :         if (!(tok->strAt(-1) != ">" &&
    2943      656262 :               (Token::Match(tok, "using %name% = ::| %name%") ||
    2944      656078 :                (Token::Match(tok, "using %name% [ [") &&
    2945           0 :                 Token::Match(tok->linkAt(2), "] ] = ::| %name%")))))
    2946      660899 :             continue;
    2947             : 
    2948         189 :         const std::string& name = tok->strAt(1);
    2949         184 :         const Token *nameToken = tok->next();
    2950         184 :         std::string scope = currentScope->fullName;
    2951         184 :         Token *usingStart = tok;
    2952             :         Token *start;
    2953         184 :         if (tok->strAt(2) == "=") {
    2954         184 :             if (currentScope->type == ScopeInfo3::Record && tok->tokAt(2)->isSimplifiedTypedef())  // don't simplify within class definition
    2955           4 :                 continue;
    2956         180 :             start = tok->tokAt(3);
    2957             :         }
    2958             :         else
    2959           0 :             start = tok->linkAt(2)->tokAt(3);
    2960         180 :         Token *usingEnd = findSemicolon(start);
    2961         180 :         if (!usingEnd)
    2962           0 :             continue;
    2963             : 
    2964             :         // Move struct defined in using out of using.
    2965             :         // using T = struct t { }; => struct t { }; using T = struct t;
    2966             :         // fixme: this doesn't handle attributes
    2967         180 :         if (Token::Match(start, "class|struct|union|enum %name%| {|:")) {
    2968          14 :             Token *structEnd = start->tokAt(1);
    2969          14 :             const bool hasName = Token::Match(structEnd, "%name%");
    2970             : 
    2971             :             // skip over name if present
    2972          14 :             if (hasName)
    2973           5 :                 structEnd = structEnd->next();
    2974             : 
    2975             :             // skip over base class information
    2976          14 :             if (structEnd->str() == ":") {
    2977           2 :                 structEnd = structEnd->next(); // skip over ":"
    2978           6 :                 while (structEnd && structEnd->str() != "{")
    2979           4 :                     structEnd = structEnd->next();
    2980           2 :                 if (!structEnd)
    2981           0 :                     continue;
    2982             :             }
    2983             : 
    2984             :             // use link to go to end
    2985          14 :             structEnd = structEnd->link();
    2986             : 
    2987             :             // add ';' after end of struct
    2988          14 :             structEnd->insertToken(";", emptyString);
    2989             : 
    2990             :             // add name for anonymous struct
    2991          14 :             if (!hasName) {
    2992          18 :                 std::string newName;
    2993           9 :                 if (structEnd->strAt(2) == ";")
    2994           7 :                     newName = name;
    2995             :                 else
    2996           2 :                     newName = "Unnamed" + std::to_string(mUnnamedCount++);
    2997           9 :                 TokenList::copyTokens(structEnd->next(), tok, start);
    2998           9 :                 structEnd->tokAt(5)->insertToken(newName, emptyString);
    2999           9 :                 start->insertToken(newName, emptyString);
    3000             :             } else
    3001           5 :                 TokenList::copyTokens(structEnd->next(), tok, start->next());
    3002             : 
    3003             :             // add using after end of struct
    3004          14 :             usingStart = structEnd->tokAt(2);
    3005          14 :             nameToken = usingStart->next();
    3006          14 :             if (usingStart->strAt(2) == "=")
    3007          14 :                 start = usingStart->tokAt(3);
    3008             :             else
    3009           0 :                 start = usingStart->linkAt(2)->tokAt(3);
    3010          14 :             usingEnd = findSemicolon(start);
    3011             : 
    3012             :             // delete original using before struct
    3013          14 :             tok->deleteThis();
    3014          14 :             tok->deleteThis();
    3015          14 :             tok->deleteThis();
    3016          14 :             tok = usingStart;
    3017             :         }
    3018             : 
    3019             :         // remove 'typename' and 'template'
    3020         166 :         else if (start->str() == "typename") {
    3021           1 :             start->deleteThis();
    3022           1 :             Token *temp = start;
    3023           2 :             while (Token::Match(temp, "%name% ::"))
    3024           1 :                 temp = temp->tokAt(2);
    3025           1 :             if (Token::Match(temp, "template %name%"))
    3026           0 :                 temp->deleteThis();
    3027             :         }
    3028             : 
    3029         180 :         if (usingEnd)
    3030         180 :             tok = usingEnd;
    3031             : 
    3032             :         // Unfortunately we have to start searching from the beginning
    3033             :         // of the token stream because templates are instantiated at
    3034             :         // the end of the token stream and it may be used before then.
    3035         180 :         ScopeInfo3 scopeInfo1;
    3036         180 :         ScopeInfo3 *currentScope1 = &scopeInfo1;
    3037         180 :         Token *startToken = list.front();
    3038         180 :         Token *endToken = nullptr;
    3039         180 :         bool inMemberFunc = false;
    3040         180 :         const ScopeInfo3 * memberFuncScope = nullptr;
    3041         180 :         const Token * memberFuncEnd = nullptr;
    3042             : 
    3043             :         // We can limit the search to the current function when the type alias
    3044             :         // is defined in that function.
    3045         180 :         if (currentScope->type == ScopeInfo3::Other ||
    3046         164 :             currentScope->type == ScopeInfo3::MemberFunction) {
    3047          25 :             scopeInfo1 = scopeInfo;
    3048          25 :             currentScope1 = scopeInfo1.findScope(currentScope);
    3049          25 :             if (!currentScope1)
    3050           0 :                 return substitute; // something bad happened
    3051          25 :             startToken = usingEnd->next();
    3052          25 :             endToken = const_cast<Token*>(currentScope->bodyEnd->next());
    3053          25 :             if (currentScope->type == ScopeInfo3::MemberFunction) {
    3054           9 :                 const ScopeInfo3 * temp = currentScope->findScope(currentScope->fullName);
    3055           9 :                 if (temp) {
    3056           2 :                     inMemberFunc = true;
    3057           2 :                     memberFuncScope = temp;
    3058           2 :                     memberFuncEnd = endToken;
    3059             :                 }
    3060             :             }
    3061             :         }
    3062             : 
    3063         360 :         std::string scope1 = currentScope1->fullName;
    3064         180 :         bool skip = false; // don't erase type aliases we can't parse
    3065         180 :         Token *enumOpenBrace = nullptr;
    3066       10870 :         for (Token* tok1 = startToken; !skip && tok1 && tok1 != endToken; tok1 = tok1->next()) {
    3067             :             // skip enum body
    3068       10690 :             if (tok1 && tok1 == enumOpenBrace) {
    3069          11 :                 tok1 = tok1->link();
    3070          11 :                 enumOpenBrace = nullptr;
    3071       10485 :                 continue;
    3072             :             }
    3073             : 
    3074       20255 :             if ((Token::Match(tok1, "{|}|namespace|class|struct|union") && tok1->strAt(-1) != "using") ||
    3075        9576 :                 Token::Match(tok1, "using namespace %name% ;|::")) {
    3076             :                 try {
    3077        1111 :                     setScopeInfo(tok1, currentScope1, mSettings.debugwarnings);
    3078           0 :                 } catch (const std::runtime_error &) {
    3079           0 :                     reportError(tok1, Severity::debug, "simplifyUsingUnmatchedBodyEnd",
    3080           0 :                                 "simplifyUsing: unmatched body end");
    3081             :                 }
    3082        1111 :                 scope1 = currentScope1->fullName;
    3083        1111 :                 if (inMemberFunc && memberFuncEnd && tok1 == memberFuncEnd) {
    3084          25 :                     inMemberFunc = false;
    3085          25 :                     memberFuncScope = nullptr;
    3086          25 :                     memberFuncEnd = nullptr;
    3087             :                 }
    3088        1111 :                 continue;
    3089             :             }
    3090             : 
    3091             :             // skip template definitions
    3092        9568 :             if (Token::Match(tok1, "template < !!>")) {
    3093          58 :                 Token *declEndToken = TemplateSimplifier::findTemplateDeclarationEnd(tok1);
    3094          58 :                 if (declEndToken)
    3095          58 :                     tok1 = declEndToken;
    3096          58 :                 continue;
    3097             :             }
    3098             : 
    3099             :             // check for enum with body
    3100        9510 :             if (tok1->str() == "enum") {
    3101          13 :                 if (Token::Match(tok1, "enum class|struct"))
    3102           2 :                     tok1 = tok1->next();
    3103          13 :                 Token *defStart = tok1;
    3104          41 :                 while (Token::Match(defStart, "%name%|::|:"))
    3105          28 :                     defStart = defStart->next();
    3106          13 :                 if (Token::simpleMatch(defStart, "{"))
    3107          11 :                     enumOpenBrace = defStart;
    3108          13 :                 continue;
    3109             :             }
    3110             : 
    3111             :             // check for member function and adjust scope
    3112        9497 :             if (isMemberFunction(tok1)) {
    3113          40 :                 if (!scope1.empty())
    3114          28 :                     scope1 += " :: ";
    3115          40 :                 scope1 += memberFunctionScope(tok1);
    3116          40 :                 const ScopeInfo3 * temp = currentScope1->findScope(scope1);
    3117          40 :                 if (temp) {
    3118          25 :                     const Token *end = memberFunctionEnd(tok1);
    3119          25 :                     if (end) {
    3120          25 :                         inMemberFunc = true;
    3121          25 :                         memberFuncScope = temp;
    3122          25 :                         memberFuncEnd = end;
    3123             :                     }
    3124             :                 }
    3125          40 :                 continue;
    3126             :             }
    3127        9457 :             if (inMemberFunc && memberFuncScope) {
    3128         145 :                 if (!usingMatch(nameToken, scope, tok1, scope1, currentScope1, memberFuncScope))
    3129         129 :                     continue;
    3130        9312 :             } else if (!usingMatch(nameToken, scope, tok1, scope1, currentScope1, nullptr))
    3131        9122 :                 continue;
    3132             : 
    3133         206 :             const auto nReplace = tokDistance(start, usingEnd);
    3134         206 :             if (nReplace > maxReplacementTokens) {
    3135           1 :                 simplifyUsingError(usingStart, usingEnd);
    3136           1 :                 continue;
    3137             :             }
    3138             : 
    3139             :             // remove the qualification
    3140         205 :             std::string fullScope = scope;
    3141         205 :             std::string removed;
    3142         219 :             while (Token::Match(tok1->tokAt(-2), "%name% ::") && !tok1->tokAt(-2)->isKeyword()) {
    3143          41 :                 removed = (tok1->strAt(-2) + " :: ") + removed;
    3144          41 :                 if (fullScope == tok1->strAt(-2)) {
    3145          27 :                     tok1->deletePrevious();
    3146          27 :                     tok1->deletePrevious();
    3147          27 :                     break;
    3148             :                 }
    3149          14 :                 const std::string::size_type idx = fullScope.rfind("::");
    3150             : 
    3151          14 :                 if (idx == std::string::npos)
    3152           0 :                     break;
    3153             : 
    3154          14 :                 if (tok1->strAt(-2) == fullScope.substr(idx + 3)) {
    3155          14 :                     tok1->deletePrevious();
    3156          14 :                     tok1->deletePrevious();
    3157          14 :                     fullScope.resize(idx - 1);
    3158             :                 } else
    3159           0 :                     break;
    3160             :             }
    3161             : 
    3162             :             // remove global namespace if present
    3163         205 :             if (tok1->strAt(-1) == "::") {
    3164           2 :                 removed.insert(0, ":: ");
    3165           2 :                 tok1->deletePrevious();
    3166             :             }
    3167             : 
    3168         205 :             Token * arrayStart = nullptr;
    3169             : 
    3170             :             // parse the type
    3171         205 :             Token *type = start;
    3172         205 :             if (type->str() == "::") {
    3173           2 :                 type = type->next();
    3174           4 :                 while (Token::Match(type, "%type% ::"))
    3175           2 :                     type = type->tokAt(2);
    3176           2 :                 if (Token::Match(type, "%type%"))
    3177           2 :                     type = type->next();
    3178         203 :             } else if (Token::Match(type, "%type% ::")) {
    3179           1 :                 do {
    3180          43 :                     type = type->tokAt(2);
    3181          43 :                 } while (Token::Match(type, "%type% ::"));
    3182          42 :                 if (Token::Match(type, "%type%"))
    3183          42 :                     type = type->next();
    3184         161 :             } else if (Token::Match(type, "%type%")) {
    3185         554 :                 while (Token::Match(type, "const|class|struct|union|enum %type%") ||
    3186         346 :                        (type->next() && type->next()->isStandardType()))
    3187          47 :                     type = type->next();
    3188             : 
    3189         161 :                 type = type->next();
    3190             : 
    3191         164 :                 while (Token::Match(type, "%type%") &&
    3192           3 :                        (type->isStandardType() || Token::Match(type, "unsigned|signed"))) {
    3193           0 :                     type = type->next();
    3194             :                 }
    3195             : 
    3196         161 :                 bool atEnd = false;
    3197         327 :                 while (!atEnd) {
    3198         166 :                     if (type && type->str() == "::") {
    3199           2 :                         type = type->next();
    3200             :                     }
    3201             : 
    3202         171 :                     if (Token::Match(type, "%type%") &&
    3203         171 :                         type->next() && !Token::Match(type->next(), "[|,|(")) {
    3204           5 :                         type = type->next();
    3205         161 :                     } else if (Token::simpleMatch(type, "const (")) {
    3206           0 :                         type = type->next();
    3207           0 :                         atEnd = true;
    3208             :                     } else
    3209         161 :                         atEnd = true;
    3210             :                 }
    3211             :             } else
    3212           0 :                 syntaxError(type);
    3213             : 
    3214             :             // check for invalid input
    3215         205 :             if (!type)
    3216           0 :                 syntaxError(tok1);
    3217             : 
    3218             :             // check for template
    3219         205 :             if (type->str() == "<") {
    3220          78 :                 type = type->findClosingBracket();
    3221             : 
    3222          79 :                 while (type && Token::Match(type->next(), ":: %type%"))
    3223           1 :                     type = type->tokAt(2);
    3224             : 
    3225          78 :                 if (!type) {
    3226           0 :                     syntaxError(tok1);
    3227             :                 }
    3228             : 
    3229          78 :                 while (Token::Match(type->next(), "const|volatile"))
    3230           0 :                     type = type->next();
    3231             : 
    3232          78 :                 type = type->next();
    3233             :             }
    3234             : 
    3235             :             // check for pointers and references
    3236         205 :             std::list<std::string> pointers;
    3237         236 :             while (Token::Match(type, "*|&|&&|const")) {
    3238          31 :                 pointers.push_back(type->str());
    3239          31 :                 type = type->next();
    3240             :             }
    3241             : 
    3242             :             // check for array
    3243         205 :             if (type && type->str() == "[") {
    3244           0 :                 do {
    3245           8 :                     if (!arrayStart)
    3246           8 :                         arrayStart = type;
    3247             : 
    3248           8 :                     bool atEnd = false;
    3249          16 :                     while (!atEnd) {
    3250          24 :                         while (type->next() && !Token::Match(type->next(), ";|,")) {
    3251          16 :                             type = type->next();
    3252             :                         }
    3253             : 
    3254           8 :                         if (!type->next())
    3255           0 :                             syntaxError(type); // invalid input
    3256           8 :                         else if (type->next()->str() == ";")
    3257           8 :                             atEnd = true;
    3258           0 :                         else if (type->str() == "]")
    3259           0 :                             atEnd = true;
    3260             :                         else
    3261           0 :                             type = type->next();
    3262             :                     }
    3263             : 
    3264           8 :                     type = type->next();
    3265           8 :                 } while (type && type->str() == "[");
    3266             :             }
    3267             : 
    3268             :             // make sure we are in a good state
    3269         205 :             if (!tok1 || !tok1->next())
    3270           0 :                 break; // bail
    3271             : 
    3272         205 :             Token* after = tok1->next();
    3273             :             // check if type was parsed
    3274         205 :             if (type && type == usingEnd) {
    3275             :                 // check for array syntax and add type around variable
    3276         199 :                 if (arrayStart) {
    3277           8 :                     if (Token::Match(tok1->next(), "%name%")) {
    3278           4 :                         TokenList::copyTokens(tok1->next(), arrayStart, usingEnd->previous());
    3279           4 :                         TokenList::copyTokens(tok1, start, arrayStart->previous());
    3280           4 :                         tok1->deleteThis();
    3281           4 :                         substitute = true;
    3282             :                     }
    3283             :                 } else {
    3284             :                     // add some qualification back if needed
    3285         191 :                     std::string removed1 = std::move(removed);
    3286         191 :                     std::string::size_type idx = removed1.rfind(" ::");
    3287         191 :                     if (idx != std::string::npos)
    3288          28 :                         removed1.resize(idx);
    3289         191 :                     if (scopesMatch(removed1, scope, &scopeInfo1)) {
    3290          27 :                         ScopeInfo3 * tempScope = currentScope;
    3291          35 :                         while (tempScope->parent) {
    3292          34 :                             if (tempScope->recordTypes.find(start->str()) != tempScope->recordTypes.end()) {
    3293          12 :                                 std::string::size_type spaceIdx = 0;
    3294          12 :                                 std::string::size_type startIdx = 0;
    3295          23 :                                 while ((spaceIdx = removed1.find(' ', startIdx)) != std::string::npos) {
    3296          11 :                                     tok1->previous()->insertToken(removed1.substr(startIdx, spaceIdx - startIdx));
    3297          11 :                                     startIdx = spaceIdx + 1;
    3298             :                                 }
    3299          12 :                                 tok1->previous()->insertToken(removed1.substr(startIdx));
    3300          12 :                                 tok1->previous()->insertToken("::");
    3301          12 :                                 break;
    3302             :                             }
    3303          22 :                             idx = removed1.rfind(" ::");
    3304          22 :                             if (idx == std::string::npos)
    3305          14 :                                 break;
    3306             : 
    3307           8 :                             removed1.resize(idx);
    3308           8 :                             tempScope = tempScope->parent;
    3309             :                         }
    3310             :                     }
    3311             : 
    3312             :                     // Is this a "T()" expression where T is a pointer type?
    3313         191 :                     if (Token::Match(tok1, "%name% ( )") && !pointers.empty()) {
    3314           1 :                         Token* tok2 = tok1->linkAt(1);
    3315           1 :                         tok1->deleteThis();
    3316           1 :                         TokenList::copyTokens(tok1, start, usingEnd->previous());
    3317           1 :                         tok2->insertToken("0");
    3318           1 :                         after = tok2->next();
    3319             :                     }
    3320             :                     else { // just replace simple type aliases
    3321         190 :                         TokenList::copyTokens(tok1, start, usingEnd->previous());
    3322         190 :                         tok1->deleteThis();
    3323             :                     }
    3324         191 :                     substitute = true;
    3325         199 :                 }
    3326             :             } else {
    3327           6 :                 skip = true;
    3328           6 :                 simplifyUsingError(usingStart, usingEnd);
    3329             :             }
    3330         205 :             tok1 = after->previous();
    3331             :         }
    3332             : 
    3333         180 :         if (!skip)
    3334         174 :             usingList.emplace_back(usingStart, usingEnd);
    3335             :     }
    3336             : 
    3337             :     // delete all used type alias definitions
    3338       17679 :     for (std::list<Using>::reverse_iterator it = usingList.rbegin(); it != usingList.rend(); ++it) {
    3339         174 :         Token *usingStart = it->startTok;
    3340         174 :         Token *usingEnd = it->endTok;
    3341         174 :         if (usingStart->previous()) {
    3342         135 :             if (usingEnd->next())
    3343         132 :                 Token::eraseTokens(usingStart->previous(), usingEnd->next());
    3344             :             else {
    3345           3 :                 Token::eraseTokens(usingStart->previous(), usingEnd);
    3346           3 :                 usingEnd->deleteThis();
    3347             :             }
    3348             :         } else {
    3349          39 :             if (usingEnd->next()) {
    3350          38 :                 Token::eraseTokens(usingStart, usingEnd->next());
    3351          38 :                 usingStart->deleteThis();
    3352             :             } else {
    3353             :                 // this is the only code being checked so leave ';'
    3354           1 :                 Token::eraseTokens(usingStart, usingEnd);
    3355           1 :                 usingStart->deleteThis();
    3356             :             }
    3357             :         }
    3358             :     }
    3359             : 
    3360       17504 :     return substitute;
    3361             : }
    3362             : 
    3363           7 : void Tokenizer::simplifyUsingError(const Token* usingStart, const Token* usingEnd)
    3364             : {
    3365           7 :     if (mSettings.debugwarnings) {
    3366           4 :         std::string str;
    3367        2349 :         for (const Token *tok = usingStart; tok && tok != usingEnd; tok = tok->next()) {
    3368        2347 :             if (!str.empty())
    3369        2345 :                 str += ' ';
    3370        2347 :             str += tok->str();
    3371             :         }
    3372           2 :         str += " ;";
    3373           2 :         std::list<const Token *> callstack(1, usingStart);
    3374           2 :         mErrorLogger.reportErr(ErrorMessage(callstack, &list, Severity::debug, "simplifyUsing",
    3375           4 :                                             "Failed to parse \'" + str + "\'. The checking continues anyway.", Certainty::normal));
    3376             :     }
    3377           7 : }
    3378             : 
    3379       23291 : bool Tokenizer::simplifyTokens1(const std::string &configuration)
    3380             : {
    3381             :     // Fill the map mTypeSize..
    3382       23291 :     fillTypeSizes();
    3383             : 
    3384       23288 :     mConfiguration = configuration;
    3385             : 
    3386       23288 :     if (mTimerResults) {
    3387        1320 :         Timer t("Tokenizer::simplifyTokens1::simplifyTokenList1", mSettings.showtime, mTimerResults);
    3388         660 :         if (!simplifyTokenList1(list.getFiles().front().c_str()))
    3389           0 :             return false;
    3390             :     } else {
    3391       22628 :         if (!simplifyTokenList1(list.getFiles().front().c_str()))
    3392           0 :             return false;
    3393             :     }
    3394             : 
    3395       22626 :     if (mTimerResults) {
    3396        1978 :         Timer t("Tokenizer::simplifyTokens1::createAst", mSettings.showtime, mTimerResults);
    3397         660 :         list.createAst();
    3398         659 :         list.validateAst(mSettings.debugnormal);
    3399             :     } else {
    3400       21966 :         list.createAst();
    3401       21963 :         list.validateAst(mSettings.debugnormal);
    3402             :     }
    3403             : 
    3404       22591 :     if (mTimerResults) {
    3405        1976 :         Timer t("Tokenizer::simplifyTokens1::createSymbolDatabase", mSettings.showtime, mTimerResults);
    3406         660 :         createSymbolDatabase();
    3407             :     } else {
    3408       21932 :         createSymbolDatabase();
    3409             :     }
    3410             : 
    3411       22567 :     if (mTimerResults) {
    3412        1980 :         Timer t("Tokenizer::simplifyTokens1::setValueType", mSettings.showtime, mTimerResults);
    3413         660 :         mSymbolDatabase->setValueTypeInTokenList(false);
    3414         660 :         mSymbolDatabase->setValueTypeInTokenList(true);
    3415             :     } else {
    3416       21907 :         mSymbolDatabase->setValueTypeInTokenList(false);
    3417       21910 :         mSymbolDatabase->setValueTypeInTokenList(true);
    3418             :     }
    3419             : 
    3420       22570 :     if (!mSettings.buildDir.empty())
    3421           0 :         Summaries::create(*this, configuration);
    3422             : 
    3423             :     // TODO: do not run valueflow if no checks are being performed at all - e.g. unusedFunctions only
    3424       22570 :     const char* disableValueflowEnv = std::getenv("DISABLE_VALUEFLOW");
    3425       22570 :     const bool doValueFlow = !disableValueflowEnv || (std::strcmp(disableValueflowEnv, "1") != 0);
    3426             : 
    3427       22570 :     if (doValueFlow) {
    3428       22570 :         if (mTimerResults) {
    3429        1980 :             Timer t("Tokenizer::simplifyTokens1::ValueFlow", mSettings.showtime, mTimerResults);
    3430         660 :             ValueFlow::setValues(list, *mSymbolDatabase, mErrorLogger, mSettings, mTimerResults);
    3431             :         } else {
    3432       21910 :             ValueFlow::setValues(list, *mSymbolDatabase, mErrorLogger, mSettings, mTimerResults);
    3433             :         }
    3434             : 
    3435       22566 :         arraySizeAfterValueFlow();
    3436             :     }
    3437             : 
    3438             :     // Warn about unhandled character literals
    3439       22566 :     if (mSettings.severity.isEnabled(Severity::portability)) {
    3440      447691 :         for (const Token *tok = tokens(); tok; tok = tok->next()) {
    3441      441491 :             if (tok->tokType() == Token::eChar && tok->values().empty()) {
    3442             :                 try {
    3443           0 :                     simplecpp::characterLiteralToLL(tok->str());
    3444           0 :                 } catch (const std::exception &e) {
    3445           0 :                     unhandledCharLiteral(tok, e.what());
    3446             :                 }
    3447             :             }
    3448             :         }
    3449             :     }
    3450             : 
    3451       22568 :     if (doValueFlow) {
    3452       22567 :         mSymbolDatabase->setArrayDimensionsUsingValueFlow();
    3453             :     }
    3454             : 
    3455       22570 :     printDebugOutput(1);
    3456             : 
    3457       22566 :     return true;
    3458             : }
    3459             : 
    3460             : //---------------------------------------------------------------------------
    3461             : 
    3462       16749 : void Tokenizer::findComplicatedSyntaxErrorsInTemplates()
    3463             : {
    3464       16749 :     validate();
    3465       16748 :     mTemplateSimplifier->checkComplicatedSyntaxErrorsInTemplates();
    3466       16744 : }
    3467             : 
    3468       22669 : void Tokenizer::checkForEnumsWithTypedef()
    3469             : {
    3470     1006421 :     for (const Token *tok = list.front(); tok; tok = tok->next()) {
    3471      983757 :         if (Token::Match(tok, "enum %name% {")) {
    3472         129 :             tok = tok->tokAt(2);
    3473         129 :             const Token *tok2 = Token::findsimplematch(tok, "typedef", tok->link());
    3474         129 :             if (tok2)
    3475           2 :                 syntaxError(tok2);
    3476         127 :             tok = tok->link();
    3477             :         }
    3478             :     }
    3479       22667 : }
    3480             : 
    3481       23291 : void Tokenizer::fillTypeSizes()
    3482             : {
    3483       23291 :     mTypeSize.clear();
    3484       23291 :     mTypeSize["char"] = 1;
    3485       23289 :     mTypeSize["_Bool"] = mSettings.platform.sizeof_bool;
    3486       23288 :     mTypeSize["bool"] = mSettings.platform.sizeof_bool;
    3487       23290 :     mTypeSize["short"] = mSettings.platform.sizeof_short;
    3488       23288 :     mTypeSize["int"] = mSettings.platform.sizeof_int;
    3489       23291 :     mTypeSize["long"] = mSettings.platform.sizeof_long;
    3490       23290 :     mTypeSize["long long"] = mSettings.platform.sizeof_long_long;
    3491       23291 :     mTypeSize["float"] = mSettings.platform.sizeof_float;
    3492       23290 :     mTypeSize["double"] = mSettings.platform.sizeof_double;
    3493       23291 :     mTypeSize["long double"] = mSettings.platform.sizeof_long_double;
    3494       23289 :     mTypeSize["wchar_t"] = mSettings.platform.sizeof_wchar_t;
    3495       23289 :     mTypeSize["size_t"] = mSettings.platform.sizeof_size_t;
    3496       23291 :     mTypeSize["*"] = mSettings.platform.sizeof_pointer;
    3497       23288 : }
    3498             : 
    3499       23076 : void Tokenizer::combineOperators()
    3500             : {
    3501       23076 :     const bool cpp = isCPP();
    3502             : 
    3503             :     // Combine tokens..
    3504      987108 :     for (Token *tok = list.front(); tok && tok->next(); tok = tok->next()) {
    3505      964003 :         const char c1 = tok->str()[0];
    3506             : 
    3507      963997 :         if (tok->str().length() == 1 && tok->next()->str().length() == 1) {
    3508      442604 :             const char c2 = tok->next()->str()[0];
    3509             : 
    3510             :             // combine +-*/ and =
    3511      442604 :             if (c2 == '=' && (std::strchr("+-*/%|^=!<>", c1)) && !Token::Match(tok->previous(), "%type% *")) {
    3512             :                 // skip templates
    3513          13 :                 if (cpp && (tok->str() == ">" || Token::simpleMatch(tok->previous(), "> *"))) {
    3514             :                     const Token* opening =
    3515          13 :                         tok->str() == ">" ? tok->findOpeningBracket() : tok->previous()->findOpeningBracket();
    3516          13 :                     if (opening && Token::Match(opening->previous(), "%name%"))
    3517          13 :                         continue;
    3518             :                 }
    3519           0 :                 tok->str(tok->str() + c2);
    3520           0 :                 tok->deleteNext();
    3521           0 :                 continue;
    3522             :             }
    3523      521424 :         } else if (tok->next()->str() == "=") {
    3524        4643 :             if (tok->str() == ">>") {
    3525           0 :                 tok->str(">>=");
    3526           0 :                 tok->deleteNext();
    3527        4643 :             } else if (tok->str() == "<<") {
    3528           0 :                 tok->str("<<=");
    3529           0 :                 tok->deleteNext();
    3530             :             }
    3531      524014 :         } else if (cpp && (c1 == 'p' || c1 == '_') &&
    3532        7232 :                    Token::Match(tok, "private|protected|public|__published : !!:")) {
    3533        1425 :             bool simplify = false;
    3534        1425 :             int par = 0;
    3535        1437 :             for (const Token *prev = tok->previous(); prev; prev = prev->previous()) {
    3536        1437 :                 if (prev->str() == ")") {
    3537           3 :                     ++par;
    3538        1434 :                 } else if (prev->str() == "(") {
    3539           3 :                     if (par == 0U)
    3540           0 :                         break;
    3541           3 :                     --par;
    3542             :                 }
    3543        1437 :                 if (par != 0U || prev->str() == "(")
    3544           8 :                     continue;
    3545        1429 :                 if (Token::Match(prev, "[;{}]")) {
    3546        1419 :                     simplify = true;
    3547        1419 :                     break;
    3548             :                 }
    3549          10 :                 if (prev->isName() && prev->isUpperCaseName())
    3550           4 :                     continue;
    3551           6 :                 if (prev->isName() && endsWith(prev->str(), ':'))
    3552           4 :                     simplify = true;
    3553           6 :                 break;
    3554             :             }
    3555        1425 :             if (simplify) {
    3556        1423 :                 tok->str(tok->str() + ":");
    3557        1423 :                 tok->deleteNext();
    3558             :             }
    3559      515357 :         } else if (tok->str() == "->") {
    3560             :             // If the preceding sequence is "( & %name% )", replace it by "%name%"
    3561        1526 :             Token *t = tok->tokAt(-4);
    3562        1526 :             if (Token::Match(t, "( & %name% )") && !Token::simpleMatch(t->previous(), ">")) {
    3563          62 :                 t->deleteThis();
    3564          62 :                 t->deleteThis();
    3565          62 :                 t->deleteNext();
    3566          62 :                 tok->str(".");
    3567             :             } else {
    3568        1464 :                 tok->str(".");
    3569        1464 :                 tok->originalName("->");
    3570             :             }
    3571             :         }
    3572             :     }
    3573       23075 : }
    3574             : 
    3575       23631 : void Tokenizer::combineStringAndCharLiterals()
    3576             : {
    3577             :     // Combine strings
    3578     1024193 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3579     1000565 :         if (!isStringLiteral(tok->str()))
    3580      990092 :             continue;
    3581             : 
    3582       10470 :         tok->str(simplifyString(tok->str()));
    3583             : 
    3584       10484 :         while (Token::Match(tok->next(), "%str%") || Token::Match(tok->next(), "_T|_TEXT|TEXT ( %str% )")) {
    3585          14 :             if (tok->next()->isName()) {
    3586           1 :                 if (!mSettings.platform.isWindows())
    3587           0 :                     break;
    3588           1 :                 tok->deleteNext(2);
    3589           1 :                 tok->next()->deleteNext();
    3590             :             }
    3591             :             // Two strings after each other, combine them
    3592          14 :             tok->concatStr(simplifyString(tok->next()->str()));
    3593          14 :             tok->deleteNext();
    3594             :         }
    3595             :     }
    3596       23629 : }
    3597             : 
    3598       22700 : void Tokenizer::concatenateNegativeNumberAndAnyPositive()
    3599             : {
    3600     1004033 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3601      981330 :         if (!Token::Match(tok, "?|:|,|(|[|{|return|case|sizeof|%op% +|-") || tok->tokType() == Token::eIncDecOp)
    3602      980508 :             continue;
    3603             : 
    3604         865 :         while (tok->str() != ">" && tok->next() && tok->next()->str() == "+" && (!Token::Match(tok->tokAt(2), "%name% (|;") || Token::Match(tok, "%op%")))
    3605          40 :             tok->deleteNext();
    3606             : 
    3607         825 :         if (Token::Match(tok->next(), "- %num%")) {
    3608         751 :             tok->deleteNext();
    3609         751 :             tok->next()->str("-" + tok->next()->str());
    3610             :         }
    3611             :     }
    3612       22701 : }
    3613             : 
    3614       16765 : void Tokenizer::simplifyExternC()
    3615             : {
    3616       16765 :     if (isC())
    3617           0 :         return;
    3618             : 
    3619             :     // Add attributes to all tokens within `extern "C"` inlines and blocks, and remove the `extern "C"` tokens.
    3620      737963 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3621      721202 :         if (Token::Match(tok, "extern \"C\"|\"C++\"")) {
    3622          18 :             Token *tok2 = tok->next();
    3623          18 :             const bool isExtC = tok->next()->str().size() == 3;
    3624          18 :             if (tok->strAt(2) == "{") {
    3625           8 :                 tok2 = tok2->next(); // skip {
    3626          85 :                 while ((tok2 = tok2->next()) && tok2 != tok->linkAt(2))
    3627          77 :                     tok2->isExternC(isExtC);
    3628           8 :                 tok->linkAt(2)->deleteThis(); // }
    3629           8 :                 tok->deleteNext(2); // "C" {
    3630             :             } else {
    3631          80 :                 while ((tok2 = tok2->next()) && !Token::Match(tok2, "[;{]"))
    3632          70 :                     tok2->isExternC(isExtC);
    3633          10 :                 tok->deleteNext(); // "C"
    3634             :             }
    3635          18 :             tok->deleteThis(); // extern
    3636             :         }
    3637             :     }
    3638             : }
    3639             : 
    3640       22702 : void Tokenizer::simplifyRoundCurlyParentheses()
    3641             : {
    3642     1003924 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3643      981236 :         while (Token::Match(tok, "[;{}:] ( {") &&
    3644          10 :                Token::simpleMatch(tok->linkAt(2), "} ) ;")) {
    3645           4 :             if (tok->str() == ":" && !Token::Match(tok->tokAt(-2),"[;{}] %type% :"))
    3646           0 :                 break;
    3647           4 :             Token *end = tok->linkAt(2)->tokAt(-3);
    3648           4 :             if (Token::Match(end, "[;{}] %num%|%str% ;"))
    3649           2 :                 end->deleteNext(2);
    3650           4 :             tok->linkAt(2)->previous()->deleteNext(3);
    3651           4 :             tok->deleteNext(2);
    3652             :         }
    3653      981218 :         if (Token::Match(tok, "( { %bool%|%char%|%num%|%str%|%name% ; } )")) {
    3654           3 :             tok->deleteNext();
    3655           3 :             tok->deleteThis();
    3656           3 :             tok->deleteNext(3);
    3657             :         }
    3658             :     }
    3659       22700 : }
    3660             : 
    3661       23254 : void Tokenizer::simplifySQL()
    3662             : {
    3663     1018893 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3664      995628 :         if (!Token::simpleMatch(tok, "__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL"))
    3665      995631 :             continue;
    3666             : 
    3667          11 :         const Token *end = findSQLBlockEnd(tok);
    3668          12 :         if (end == nullptr)
    3669           4 :             syntaxError(nullptr);
    3670             : 
    3671           8 :         const std::string instruction = tok->stringifyList(end);
    3672             :         // delete all tokens until the embedded SQL block end
    3673           8 :         Token::eraseTokens(tok, end);
    3674             : 
    3675             :         // insert "asm ( "instruction" ) ;"
    3676           8 :         tok->str("asm");
    3677             :         // it can happen that 'end' is NULL when wrong code is inserted
    3678           8 :         if (!tok->next())
    3679           0 :             tok->insertToken(";");
    3680           8 :         tok->insertToken(")");
    3681           8 :         tok->insertToken("\"" + instruction + "\"");
    3682           8 :         tok->insertToken("(");
    3683             :         // jump to ';' and continue
    3684           8 :         tok = tok->tokAt(3);
    3685             :     }
    3686       23246 : }
    3687             : 
    3688       22624 : void Tokenizer::simplifyArrayAccessSyntax()
    3689             : {
    3690             :     // 0[a] -> a[0]
    3691     1014451 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3692      991829 :         if (tok->isNumber() && Token::Match(tok, "%num% [ %name% ]")) {
    3693           2 :             const std::string number(tok->str());
    3694           1 :             Token* indexTok = tok->tokAt(2);
    3695           1 :             tok->str(indexTok->str());
    3696           1 :             tok->varId(indexTok->varId());
    3697           1 :             indexTok->str(number);
    3698             :         }
    3699             :     }
    3700       22625 : }
    3701             : 
    3702       22626 : void Tokenizer::simplifyParameterVoid()
    3703             : {
    3704     1011399 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    3705      988779 :         if (Token::Match(tok, "%name% ( void )") && !Token::Match(tok, "sizeof|decltype|typeof|return")) {
    3706        2998 :             tok->next()->deleteNext();
    3707        2998 :             tok->next()->setRemovedVoidParameter(true);
    3708             :         }
    3709             :     }
    3710       22627 : }
    3711             : 
    3712       22627 : void Tokenizer::simplifyRedundantConsecutiveBraces()
    3713             : {
    3714             :     // Remove redundant consecutive braces, i.e. '.. { { .. } } ..' -> '.. { .. } ..'.
    3715     1008750 :     for (Token *tok = list.front(); tok;) {
    3716      986124 :         if (Token::simpleMatch(tok, "= {")) {
    3717         579 :             tok = tok->linkAt(1);
    3718      985538 :         } else if (Token::simpleMatch(tok, "{ {") && Token::simpleMatch(tok->next()->link(), "} }")) {
    3719             :             //remove internal parentheses
    3720          36 :             tok->next()->link()->deleteThis();
    3721          36 :             tok->deleteNext();
    3722             :         } else
    3723      985505 :             tok = tok->next();
    3724             :     }
    3725       22627 : }
    3726             : 
    3727       22626 : void Tokenizer::simplifyDoublePlusAndDoubleMinus()
    3728             : {
    3729             :     // Convert - - into + and + - into -
    3730     1014432 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3731      991826 :         while (tok->next()) {
    3732      969206 :             if (tok->str() == "+") {
    3733        1247 :                 if (tok->next()->str()[0] == '-') {
    3734           6 :                     tok = tok->next();
    3735           6 :                     if (tok->str().size() == 1) {
    3736           2 :                         tok = tok->previous();
    3737           2 :                         tok->str("-");
    3738           2 :                         tok->deleteNext();
    3739           4 :                     } else if (tok->isNumber()) {
    3740           3 :                         tok->str(tok->str().substr(1));
    3741           3 :                         tok = tok->previous();
    3742           3 :                         tok->str("-");
    3743             :                     }
    3744           6 :                     continue;
    3745             :                 }
    3746      967954 :             } else if (tok->str() == "-") {
    3747         485 :                 if (tok->next()->str()[0] == '-') {
    3748           7 :                     tok = tok->next();
    3749           7 :                     if (tok->str().size() == 1) {
    3750           4 :                         tok = tok->previous();
    3751           4 :                         tok->str("+");
    3752           4 :                         tok->deleteNext();
    3753           3 :                     } else if (tok->isNumber()) {
    3754           3 :                         tok->str(tok->str().substr(1));
    3755           3 :                         tok = tok->previous();
    3756           3 :                         tok->str("+");
    3757             :                     }
    3758           7 :                     continue;
    3759             :                 }
    3760             :             }
    3761             : 
    3762      969186 :             break;
    3763             :         }
    3764             :     }
    3765       22624 : }
    3766             : 
    3767             : /** Specify array size if it hasn't been given */
    3768             : 
    3769       22626 : void Tokenizer::arraySize()
    3770             : {
    3771         262 :     auto getStrTok = [](Token* tok, bool addLength, Token*& endStmt) -> Token* {
    3772         262 :         if (addLength) {
    3773           1 :             endStmt = tok->tokAt(5);
    3774           1 :             return tok->tokAt(4);
    3775             :         }
    3776         261 :         if (Token::Match(tok, "%var% [ ] =")) {
    3777         261 :             tok = tok->tokAt(4);
    3778         261 :             int parCount = 0;
    3779         262 :             while (Token::simpleMatch(tok, "(")) {
    3780           1 :                 ++parCount;
    3781           1 :                 tok = tok->next();
    3782             :             }
    3783         261 :             if (Token::Match(tok, "%str%")) {
    3784         106 :                 endStmt = tok->tokAt(parCount + 1);
    3785         106 :                 return tok;
    3786             :             }
    3787             :         }
    3788         155 :         return nullptr;
    3789             :     };
    3790             : 
    3791     1011997 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3792      989378 :         if (!tok->isName() || !Token::Match(tok, "%var% [ ] ="))
    3793      989109 :             continue;
    3794         262 :         bool addlength = false;
    3795         262 :         if (Token::Match(tok->previous(), "!!* %var% [ ] = { %str% } ;")) {
    3796           1 :             Token *t = tok->tokAt(3);
    3797           1 :             t->deleteNext();
    3798           1 :             t->next()->deleteNext();
    3799           1 :             addlength = true;
    3800             :         }
    3801             : 
    3802         262 :         Token* endStmt{};
    3803         262 :         if (const Token* strTok = getStrTok(tok, addlength, endStmt)) {
    3804         107 :             const int sz = Token::getStrArraySize(strTok);
    3805         107 :             tok->next()->insertToken(std::to_string(sz));
    3806         107 :             tok = endStmt;
    3807             :         }
    3808             : 
    3809         155 :         else if (Token::Match(tok, "%var% [ ] = {")) {
    3810         151 :             MathLib::biguint sz = 1;
    3811         151 :             tok = tok->next();
    3812         151 :             Token *end = tok->linkAt(3);
    3813         839 :             for (Token *tok2 = tok->tokAt(4); tok2 && tok2 != end; tok2 = tok2->next()) {
    3814         690 :                 if (tok2->link() && Token::Match(tok2, "{|(|[|<")) {
    3815          33 :                     if (tok2->str() == "[" && tok2->link()->strAt(1) == "=") { // designated initializer
    3816           4 :                         if (Token::Match(tok2, "[ %num% ]"))
    3817           2 :                             sz = std::max(sz, MathLib::toBigUNumber(tok2->strAt(1)) + 1U);
    3818             :                         else {
    3819           2 :                             sz = 0;
    3820           2 :                             break;
    3821             :                         }
    3822             :                     }
    3823          31 :                     tok2 = tok2->link();
    3824         657 :                 } else if (tok2->str() == ",") {
    3825         207 :                     if (!Token::Match(tok2->next(), "[},]"))
    3826         204 :                         ++sz;
    3827             :                     else {
    3828           3 :                         tok2 = tok2->previous();
    3829           3 :                         tok2->deleteNext();
    3830             :                     }
    3831             :                 }
    3832             :             }
    3833             : 
    3834         151 :             if (sz != 0)
    3835         149 :                 tok->insertToken(std::to_string(sz));
    3836             : 
    3837         151 :             tok = end->next() ? end->next() : end;
    3838             :         }
    3839             :     }
    3840       22622 : }
    3841             : 
    3842       22568 : void Tokenizer::arraySizeAfterValueFlow()
    3843             : {
    3844             :     // After ValueFlow, adjust array sizes.
    3845       97114 :     for (const Variable* var: mSymbolDatabase->variableList()) {
    3846       74545 :         if (!var || !var->isArray())
    3847       74545 :             continue;
    3848        2429 :         if (!Token::Match(var->nameToken(), "%name% [ ] = { ["))
    3849        2428 :             continue;
    3850           1 :         MathLib::bigint maxIndex = -1;
    3851           1 :         const Token* const startToken = var->nameToken()->tokAt(4);
    3852           1 :         const Token* const endToken = startToken->link();
    3853           7 :         for (const Token* tok = startToken; tok != endToken; tok = tok->next()) {
    3854           6 :             if (!Token::Match(tok, "[{,] [") || !Token::simpleMatch(tok->linkAt(1), "] ="))
    3855           5 :                 continue;
    3856           1 :             const Token* expr = tok->next()->astOperand1();
    3857           1 :             if (expr && expr->hasKnownIntValue())
    3858           1 :                 maxIndex = std::max(maxIndex, expr->getKnownIntValue());
    3859             :         }
    3860           1 :         if (maxIndex >= 0) {
    3861             :             // insert array size
    3862           1 :             Token* tok = const_cast<Token*>(var->nameToken()->next());
    3863           1 :             tok->insertToken(std::to_string(maxIndex + 1));
    3864             :             // ast
    3865           1 :             tok->astOperand2(tok->next());
    3866             :             // Token::scope
    3867           1 :             tok->next()->scope(tok->scope());
    3868             :             // Value flow
    3869           2 :             ValueFlow::Value value(maxIndex + 1);
    3870           1 :             value.setKnown();
    3871           1 :             tok->next()->addValue(value);
    3872             :             // Set array dimensions
    3873           1 :             Dimension d;
    3874           1 :             d.num = maxIndex + 1;
    3875           2 :             std::vector<Dimension> dimensions{d};
    3876           1 :             const_cast<Variable*>(var)->setDimensions(dimensions);
    3877             :         }
    3878             :     }
    3879       22565 : }
    3880             : 
    3881           8 : static Token *skipTernaryOp(Token *tok)
    3882             : {
    3883           8 :     int colonLevel = 1;
    3884          16 :     while (nullptr != (tok = tok->next())) {
    3885          16 :         if (tok->str() == "?") {
    3886           0 :             ++colonLevel;
    3887          16 :         } else if (tok->str() == ":") {
    3888           6 :             --colonLevel;
    3889           6 :             if (colonLevel == 0) {
    3890           6 :                 tok = tok->next();
    3891           6 :                 break;
    3892             :             }
    3893             :         }
    3894          10 :         if (tok->link() && Token::Match(tok, "[(<]"))
    3895           3 :             tok = tok->link();
    3896           7 :         else if (Token::Match(tok->next(), "[{};)]"))
    3897           2 :             break;
    3898             :     }
    3899           8 :     if (colonLevel > 0) // Ticket #5214: Make sure the ':' matches the proper '?'
    3900           2 :         return nullptr;
    3901           6 :     return tok;
    3902             : }
    3903             : 
    3904             : // Skips until the colon at the end of the case label, the argument must point to the "case" token.
    3905             : // In case of success returns the colon token.
    3906             : // In case of failure returns the token that caused the error.
    3907         345 : static Token *skipCaseLabel(Token *tok)
    3908             : {
    3909         345 :     assert(tok->str() == "case");
    3910         708 :     while (nullptr != (tok = tok->next())) {
    3911         708 :         if (Token::Match(tok, "(|["))
    3912          10 :             tok = tok->link();
    3913         698 :         else if (tok->str() == "?") {
    3914           8 :             Token * tok1 = skipTernaryOp(tok);
    3915           8 :             if (!tok1)
    3916           2 :                 return tok;
    3917           6 :             tok = tok1;
    3918             :         }
    3919         706 :         if (Token::Match(tok, "[:{};]"))
    3920         343 :             return tok;
    3921             :     }
    3922           0 :     return nullptr;
    3923             : }
    3924             : 
    3925      991069 : const Token * Tokenizer::startOfExecutableScope(const Token * tok)
    3926             : {
    3927      991069 :     if (tok->str() != ")")
    3928      912212 :         return nullptr;
    3929             : 
    3930       78857 :     tok = Tokenizer::isFunctionHead(tok, ":{");
    3931             : 
    3932       78858 :     if (Token::Match(tok, ": %name% [({]")) {
    3933        1672 :         while (Token::Match(tok, "[:,] %name% [({]"))
    3934         892 :             tok = tok->linkAt(2)->next();
    3935             :     }
    3936             : 
    3937       78858 :     return (tok && tok->str() == "{") ? tok : nullptr;
    3938             : }
    3939             : 
    3940             : 
    3941             : /** simplify labels and case|default in the code: add a ";" if not already in.*/
    3942             : 
    3943       22684 : void Tokenizer::simplifyLabelsCaseDefault()
    3944             : {
    3945       22684 :     const bool cpp = isCPP();
    3946       22682 :     bool executablescope = false;
    3947       22682 :     int indentLevel = 0;
    3948      739200 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    3949             :         // Simplify labels in the executable scope..
    3950      716527 :         auto *start = const_cast<Token *>(startOfExecutableScope(tok));
    3951      716525 :         if (start) {
    3952       28980 :             tok = start;
    3953       28980 :             executablescope = true;
    3954             :         }
    3955             : 
    3956      716525 :         if (!executablescope)
    3957      321019 :             continue;
    3958             : 
    3959      395506 :         if (tok->str() == "{") {
    3960       41437 :             if (tok->previous()->str() == "=")
    3961         474 :                 tok = tok->link();
    3962             :             else
    3963       40963 :                 ++indentLevel;
    3964      354067 :         } else if (tok->str() == "}") {
    3965       40947 :             --indentLevel;
    3966       40947 :             if (indentLevel == 0) {
    3967       28971 :                 executablescope = false;
    3968       28971 :                 continue;
    3969             :             }
    3970      313124 :         } else if (Token::Match(tok, "(|["))
    3971       57354 :             tok = tok->link();
    3972             : 
    3973      366543 :         if (Token::Match(tok, "[;{}:] case")) {
    3974         337 :             tok = skipCaseLabel(tok->next());
    3975         337 :             if (!tok)
    3976           0 :                 break;
    3977         337 :             if (tok->str() != ":" || tok->strAt(-1) == "case" || !tok->next())
    3978           8 :                 syntaxError(tok);
    3979         329 :             if (tok->next()->str() != ";" && tok->next()->str() != "case")
    3980         262 :                 tok->insertToken(";");
    3981             :             else
    3982          67 :                 tok = tok->previous();
    3983      366201 :         } else if (Token::Match(tok, "[;{}] %name% : !!;")) {
    3984         124 :             if (!cpp || !Token::Match(tok->next(), "class|struct|enum")) {
    3985         121 :                 tok = tok->tokAt(2);
    3986         121 :                 tok->insertToken(";");
    3987             :             }
    3988             :         }
    3989             :     }
    3990       22675 : }
    3991             : 
    3992             : 
    3993       22684 : void Tokenizer::simplifyCaseRange()
    3994             : {
    3995     1008035 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    3996      985355 :         if (Token::Match(tok, "case %num%|%char% ... %num%|%char% :")) {
    3997           8 :             const MathLib::bigint start = MathLib::toBigNumber(tok->strAt(1));
    3998           8 :             MathLib::bigint end = MathLib::toBigNumber(tok->strAt(3));
    3999           8 :             end = std::min(start + 50, end); // Simplify it 50 times at maximum
    4000           8 :             if (start < end) {
    4001           6 :                 tok = tok->tokAt(2);
    4002           6 :                 tok->str(":");
    4003           6 :                 tok->insertToken("case");
    4004          61 :                 for (MathLib::bigint i = end-1; i > start; i--) {
    4005          55 :                     tok->insertToken(":");
    4006          55 :                     tok->insertToken(std::to_string(i));
    4007          55 :                     tok->insertToken("case");
    4008             :                 }
    4009             :             }
    4010             :         }
    4011             :     }
    4012       22682 : }
    4013             : 
    4014       16714 : void Tokenizer::calculateScopes()
    4015             : {
    4016      746972 :     for (auto *tok = list.front(); tok; tok = tok->next())
    4017      730265 :         tok->scopeInfo(nullptr);
    4018             : 
    4019       33424 :     std::string nextScopeNameAddition;
    4020       33424 :     std::shared_ptr<ScopeInfo2> primaryScope = std::make_shared<ScopeInfo2>("", nullptr);
    4021       16713 :     list.front()->scopeInfo(std::move(primaryScope));
    4022             : 
    4023      747102 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    4024      730385 :         if (tok == list.front() || !tok->scopeInfo()) {
    4025      695518 :             if (tok != list.front())
    4026      678804 :                 tok->scopeInfo(tok->previous()->scopeInfo());
    4027             : 
    4028      695523 :             if (Token::Match(tok, "using namespace %name% ::|<|;")) {
    4029         108 :                 std::string usingNamespaceName;
    4030         260 :                 for (const Token* namespaceNameToken = tok->tokAt(2);
    4031         260 :                      namespaceNameToken && namespaceNameToken->str() != ";";
    4032         152 :                      namespaceNameToken = namespaceNameToken->next()) {
    4033         152 :                     usingNamespaceName += namespaceNameToken->str();
    4034         152 :                     usingNamespaceName += " ";
    4035             :                 }
    4036         108 :                 if (!usingNamespaceName.empty())
    4037         108 :                     usingNamespaceName.pop_back();
    4038         108 :                 tok->scopeInfo()->usingNamespaces.insert(std::move(usingNamespaceName));
    4039      695422 :             } else if (Token::Match(tok, "namespace|class|struct|union %name% {|::|:|<")) {
    4040       11514 :                 for (Token* nameTok = tok->next(); nameTok && !Token::Match(nameTok, "{|:"); nameTok = nameTok->next()) {
    4041        6096 :                     if (Token::Match(nameTok, ";|<")) {
    4042         178 :                         nextScopeNameAddition = "";
    4043         178 :                         break;
    4044             :                     }
    4045        5918 :                     nextScopeNameAddition.append(nameTok->str());
    4046        5918 :                     nextScopeNameAddition.append(" ");
    4047             :                 }
    4048        5596 :                 if (!nextScopeNameAddition.empty())
    4049        5418 :                     nextScopeNameAddition.pop_back();
    4050             :             }
    4051             : 
    4052      695505 :             if (Token::simpleMatch(tok, "{")) {
    4053             :                 // This might be the opening of a member function
    4054       34869 :                 Token *tok1 = tok;
    4055       35225 :                 while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept"))
    4056         356 :                     tok1 = tok1->previous();
    4057       34870 :                 if (tok1->previous() && tok1->strAt(-1) == ")") {
    4058       26335 :                     bool member = true;
    4059       26335 :                     tok1 = tok1->linkAt(-1);
    4060       26336 :                     if (Token::Match(tok1->previous(), "throw|noexcept")) {
    4061          62 :                         tok1 = tok1->previous();
    4062          80 :                         while (Token::Match(tok1->previous(), "const|volatile|final|override|&|&&|noexcept"))
    4063          18 :                             tok1 = tok1->previous();
    4064          62 :                         if (tok1->strAt(-1) != ")")
    4065           1 :                             member = false;
    4066       26275 :                     } else if (Token::Match(tok->tokAt(-2), ":|, %name%")) {
    4067           0 :                         tok1 = tok1->tokAt(-2);
    4068           0 :                         if (tok1->strAt(-1) != ")")
    4069           0 :                             member = false;
    4070             :                     }
    4071       26337 :                     if (member) {
    4072       26336 :                         if (tok1->strAt(-1) == ">")
    4073          41 :                             tok1 = tok1->previous()->findOpeningBracket();
    4074       26336 :                         if (tok1 && Token::Match(tok1->tokAt(-3), "%name% :: %name%")) {
    4075         696 :                             tok1 = tok1->tokAt(-2);
    4076        1392 :                             std::string scope = tok1->strAt(-1);
    4077         832 :                             while (Token::Match(tok1->tokAt(-2), ":: %name%")) {
    4078         136 :                                 scope = tok1->strAt(-3) + " :: " + scope;
    4079         136 :                                 tok1 = tok1->tokAt(-2);
    4080             :                             }
    4081             : 
    4082         696 :                             if (!nextScopeNameAddition.empty() && !scope.empty())
    4083           4 :                                 nextScopeNameAddition += " :: ";
    4084         696 :                             nextScopeNameAddition += scope;
    4085             :                         }
    4086             :                     }
    4087             :                 }
    4088             : 
    4089             :                 // New scope is opening, record it here
    4090       69750 :                 std::shared_ptr<ScopeInfo2> newScopeInfo = std::make_shared<ScopeInfo2>(tok->scopeInfo()->name, tok->link(), tok->scopeInfo()->usingNamespaces);
    4091             : 
    4092       34877 :                 if (!newScopeInfo->name.empty() && !nextScopeNameAddition.empty())
    4093         598 :                     newScopeInfo->name.append(" :: ");
    4094       34875 :                 newScopeInfo->name.append(nextScopeNameAddition);
    4095       34877 :                 nextScopeNameAddition = "";
    4096             : 
    4097       34877 :                 if (tok->link())
    4098       34876 :                     tok->link()->scopeInfo(tok->scopeInfo());
    4099       34874 :                 tok->scopeInfo(std::move(newScopeInfo));
    4100             :             }
    4101             :         }
    4102             :     }
    4103       16717 : }
    4104             : 
    4105       16717 : void Tokenizer::simplifyTemplates()
    4106             : {
    4107       16717 :     if (isC())
    4108           0 :         return;
    4109             : 
    4110       16713 :     const std::time_t maxTime = mSettings.templateMaxTime > 0 ? std::time(nullptr) + mSettings.templateMaxTime : 0;
    4111       16713 :     mTemplateSimplifier->simplifyTemplates(
    4112             :         maxTime);
    4113             : }
    4114             : //---------------------------------------------------------------------------
    4115             : 
    4116             : 
    4117             : namespace {
    4118             :     /** Class used in Tokenizer::setVarIdPass1 */
    4119             :     class VariableMap {
    4120             :     private:
    4121             :         std::unordered_map<std::string, nonneg int> mVariableId;
    4122             :         std::unordered_map<std::string, nonneg int> mVariableId_global;
    4123             :         std::stack<std::vector<std::pair<std::string, nonneg int>>> mScopeInfo;
    4124             :         mutable nonneg int mVarId{};
    4125             :     public:
    4126       22637 :         VariableMap() = default;
    4127             :         void enterScope();
    4128             :         bool leaveScope();
    4129             :         void addVariable(const std::string& varname, bool globalNamespace);
    4130         168 :         bool hasVariable(const std::string& varname) const {
    4131         168 :             return mVariableId.find(varname) != mVariableId.end();
    4132             :         }
    4133             : 
    4134      677793 :         const std::unordered_map<std::string, nonneg int>& map(bool global) const {
    4135      677793 :             return global ? mVariableId_global : mVariableId;
    4136             :         }
    4137      191503 :         nonneg int& getVarId() {
    4138      191503 :             return mVarId;
    4139             :         }
    4140             :     };
    4141             : }
    4142             : 
    4143             : 
    4144       62003 : void VariableMap::enterScope()
    4145             : {
    4146       62003 :     mScopeInfo.emplace(/*std::vector<std::pair<std::string, nonneg int>>()*/);
    4147       62003 : }
    4148             : 
    4149       62004 : bool VariableMap::leaveScope()
    4150             : {
    4151       62004 :     if (mScopeInfo.empty())
    4152          15 :         return false;
    4153             : 
    4154      110548 :     for (const std::pair<std::string, nonneg int>& outerVariable : mScopeInfo.top()) {
    4155       48558 :         if (outerVariable.second != 0)
    4156         137 :             mVariableId[outerVariable.first] = outerVariable.second;
    4157             :         else
    4158       48421 :             mVariableId.erase(outerVariable.first);
    4159             :     }
    4160       61988 :     mScopeInfo.pop();
    4161       61986 :     return true;
    4162             : }
    4163             : 
    4164       50573 : void VariableMap::addVariable(const std::string& varname, bool globalNamespace)
    4165             : {
    4166       50573 :     if (mScopeInfo.empty()) {
    4167        2014 :         mVariableId[varname] = ++mVarId;
    4168        2014 :         if (globalNamespace)
    4169        2014 :             mVariableId_global[varname] = mVariableId[varname];
    4170       50434 :         return;
    4171             :     }
    4172       48558 :     std::unordered_map<std::string, nonneg int>::iterator it = mVariableId.find(varname);
    4173       48558 :     if (it == mVariableId.end()) {
    4174       48421 :         mScopeInfo.top().emplace_back(varname, 0);
    4175       48421 :         mVariableId[varname] = ++mVarId;
    4176       48420 :         if (globalNamespace)
    4177       15583 :             mVariableId_global[varname] = mVariableId[varname];
    4178       48420 :         return;
    4179             :     }
    4180         137 :     mScopeInfo.top().emplace_back(varname, it->second);
    4181         137 :     it->second = ++mVarId;
    4182             : }
    4183             : 
    4184      250414 : static bool setVarIdParseDeclaration(Token*& tok, const VariableMap& variableMap, bool executableScope)
    4185             : {
    4186      250414 :     const Token* const tok1 = tok;
    4187      250414 :     Token* tok2 = tok;
    4188      250414 :     if (!tok2->isName())
    4189       99473 :         return false;
    4190             : 
    4191      150941 :     nonneg int typeCount = 0;
    4192      150941 :     nonneg int singleNameCount = 0;
    4193      150941 :     bool hasstruct = false;   // Is there a "struct" or "class"?
    4194      150941 :     bool bracket = false;
    4195      150941 :     bool ref = false;
    4196      410020 :     while (tok2) {
    4197      409996 :         if (tok2->isName()) {
    4198      255257 :             if (Token::simpleMatch(tok2, "alignas (")) {
    4199           2 :                 tok2 = tok2->linkAt(1)->next();
    4200           2 :                 continue;
    4201             :             }
    4202      255255 :             if (tok2->isCpp() && Token::Match(tok2, "namespace|public|private|protected"))
    4203         500 :                 return false;
    4204      254757 :             if (tok2->isCpp() && Token::simpleMatch(tok2, "decltype (")) {
    4205          30 :                 typeCount = 1;
    4206          30 :                 tok2 = tok2->linkAt(1)->next();
    4207          30 :                 continue;
    4208             :             }
    4209      254727 :             if (Token::Match(tok2, "struct|union|enum") || (tok2->isCpp() && Token::Match(tok2, "class|typename"))) {
    4210        7741 :                 hasstruct = true;
    4211        7741 :                 typeCount = 0;
    4212        7741 :                 singleNameCount = 0;
    4213      246986 :             } else if (Token::Match(tok2, "const|extern")) {
    4214             :                 // just skip "const", "extern"
    4215      239037 :             } else if (!hasstruct && variableMap.map(false).count(tok2->str()) && tok2->previous()->str() != "::") {
    4216       23631 :                 ++typeCount;
    4217       23631 :                 tok2 = tok2->next();
    4218       23631 :                 if (!tok2 || tok2->str() != "::")
    4219       23630 :                     break;
    4220             :             } else {
    4221      215406 :                 if (tok2->str() != "void" || Token::Match(tok2, "void const| *|(")) // just "void" cannot be a variable type
    4222      189975 :                     ++typeCount;
    4223      215406 :                 ++singleNameCount;
    4224             :             }
    4225      263310 :         } else if (tok2->isCpp() && ((TemplateSimplifier::templateParameters(tok2) > 0) ||
    4226      108571 :                                      Token::simpleMatch(tok2, "< >") /* Ticket #4764 */)) {
    4227        2784 :             const Token *start = tok;
    4228        2784 :             if (Token::Match(start->previous(), "%or%|%oror%|&&|&|^|+|-|*|/"))
    4229           0 :                 return false;
    4230        2784 :             Token* const closingBracket = tok2->findClosingBracket();
    4231        2784 :             if (closingBracket == nullptr) { /* Ticket #8151 */
    4232           0 :                 throw tok2;
    4233             :             }
    4234        2784 :             tok2 = closingBracket;
    4235        2784 :             if (tok2->str() != ">")
    4236           0 :                 break;
    4237        2784 :             singleNameCount = 1;
    4238        2784 :             if (Token::Match(tok2, "> %name% %or%|%oror%|&&|&|^|+|-|*|/") && !Token::Match(tok2, "> const [*&]"))
    4239           1 :                 return false;
    4240        2783 :             if (Token::Match(tok2, "> %name% )")) {
    4241         183 :                 if (Token::Match(tok2->linkAt(2)->previous(), "if|for|while ("))
    4242           3 :                     return false;
    4243         180 :                 if (!Token::Match(tok2->linkAt(2)->previous(), "%name%|] ("))
    4244           1 :                     return false;
    4245             :             }
    4246      151956 :         } else if (Token::Match(tok2, "&|&&")) {
    4247        4256 :             ref = !bracket;
    4248      147695 :         } else if (singleNameCount >= 1 && Token::Match(tok2, "( [*&]") && Token::Match(tok2->link(), ") (|[")) {
    4249         640 :             for (const Token* tok3 = tok2->tokAt(2); Token::Match(tok3, "!!)"); tok3 = tok3->next()) {
    4250         351 :                 if (Token::Match(tok3, "(|["))
    4251          61 :                     tok3 = tok3->link();
    4252         351 :                 if (tok3->str() == ",")
    4253           1 :                     return false;
    4254             :             }
    4255         289 :             bracket = true; // Skip: Seems to be valid pointer to array or function pointer
    4256      147405 :         } else if (singleNameCount >= 1 && Token::Match(tok2, "( * %name% [") && Token::Match(tok2->linkAt(3), "] ) [;,]")) {
    4257           3 :             bracket = true;
    4258      147402 :         } else if (singleNameCount >= 1 && tok2->previous() && tok2->previous()->isStandardType() && Token::Match(tok2, "( *|&| %name% ) ;")) {
    4259           9 :             bracket = true;
    4260      147392 :         } else if (tok2->str() == "::") {
    4261        7200 :             singleNameCount = 0;
    4262      140191 :         } else if (tok2->str() != "*" && tok2->str() != "...") {
    4263      126782 :             break;
    4264             :         }
    4265      259047 :         tok2 = tok2->next();
    4266             :     }
    4267             : 
    4268      150436 :     if (tok2) {
    4269      150412 :         bool isLambdaArg = false;
    4270             :         {
    4271      150412 :             const Token *tok3 = tok->previous();
    4272      150412 :             if (tok3 && tok3->str() == ",") {
    4273       77120 :                 while (tok3 && !Token::Match(tok3,";|(|[|{")) {
    4274       64480 :                     if (Token::Match(tok3, ")|]"))
    4275        1514 :                         tok3 = tok3->link();
    4276       64480 :                     tok3 = tok3->previous();
    4277             :                 }
    4278             : 
    4279       12640 :                 if (tok3 && executableScope && Token::Match(tok3->previous(), "%name% (")) {
    4280        6476 :                     const Token *fdecl = tok3->previous();
    4281        6476 :                     int count = 0;
    4282       13061 :                     while (Token::Match(fdecl, "%name%|*")) {
    4283        6585 :                         fdecl = fdecl->previous();
    4284        6585 :                         count++;
    4285             :                     }
    4286        6476 :                     if (!Token::Match(fdecl, "[;{}] %name%") || count <= 1)
    4287        6375 :                         return false;
    4288             :                 }
    4289             :             }
    4290             : 
    4291      144183 :             if (tok3 && tok3->isCpp() && Token::simpleMatch(tok3->previous(), "] (") &&
    4292         149 :                 (Token::simpleMatch(tok3->link(), ") {") || Token::Match(tok3->link(), ") . %name%")))
    4293         137 :                 isLambdaArg = true;
    4294             :         }
    4295             : 
    4296             : 
    4297      144034 :         tok = tok2;
    4298             : 
    4299             :         // In executable scopes, references must be assigned
    4300             :         // Catching by reference is an exception
    4301      144034 :         if (executableScope && ref && !isLambdaArg) {
    4302         395 :             if (Token::Match(tok2, "(|=|{|:"))
    4303             :                 ;   // reference is assigned => ok
    4304          66 :             else if (tok2->str() != ")" || tok2->link()->strAt(-1) != "catch")
    4305          41 :                 return false;   // not catching by reference => not declaration
    4306             :         }
    4307             :     }
    4308             : 
    4309             :     // Check if array declaration is valid (#2638)
    4310             :     // invalid declaration: AAA a[4] = 0;
    4311      144019 :     if (typeCount >= 2 && executableScope && Token::Match(tok2, ")| [")) {
    4312        1518 :         const Token *tok3 = tok2->str() == ")" ? tok2->next() : tok2;
    4313        3100 :         while (tok3 && tok3->str() == "[") {
    4314        1582 :             tok3 = tok3->link()->next();
    4315             :         }
    4316        1518 :         if (Token::Match(tok3, "= %num%"))
    4317           3 :             return false;
    4318        1515 :         if (bracket && Token::Match(tok1->previous(), "[(,]") && Token::Match(tok3, "[,)]"))
    4319           2 :             return false;
    4320             :     }
    4321             : 
    4322      144014 :     return (typeCount >= 2 && tok2 && Token::Match(tok2->tokAt(-2), "!!:: %type%"));
    4323             : }
    4324             : 
    4325             : 
    4326      118748 : static void setVarIdStructMembers(Token *&tok1,
    4327             :                                   std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
    4328             :                                   nonneg int &varId)
    4329             : {
    4330      118748 :     Token *tok = tok1;
    4331             : 
    4332      118748 :     if (Token::Match(tok, "%name% = { . %name% =|{")) {
    4333          10 :         const nonneg int struct_varid = tok->varId();
    4334          10 :         if (struct_varid == 0)
    4335           0 :             return;
    4336             : 
    4337          10 :         std::map<std::string, nonneg int>& members = structMembers[struct_varid];
    4338             : 
    4339          10 :         tok = tok->tokAt(3);
    4340          67 :         while (tok->str() != "}") {
    4341          57 :             if (Token::Match(tok, "{|[|("))
    4342           8 :                 tok = tok->link();
    4343          57 :             if (Token::Match(tok->previous(), "[,{] . %name% =|{")) {
    4344          13 :                 tok = tok->next();
    4345          13 :                 const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
    4346          13 :                 if (it == members.end()) {
    4347          13 :                     members[tok->str()] = ++varId;
    4348          13 :                     tok->varId(varId);
    4349             :                 } else {
    4350           0 :                     tok->varId(it->second);
    4351             :                 }
    4352             :             }
    4353          57 :             tok = tok->next();
    4354             :         }
    4355             : 
    4356          10 :         return;
    4357             :     }
    4358             : 
    4359      120468 :     while (Token::Match(tok->next(), ")| . %name% !!(")) {
    4360             :         // Don't set varid for trailing return type
    4361        3505 :         if (tok->strAt(1) == ")" && Token::Match(tok->linkAt(1)->tokAt(-1), "%name%|]") &&
    4362        1767 :             Tokenizer::isFunctionHead(tok->linkAt(1), "{|;")) {
    4363          25 :             tok = tok->tokAt(3);
    4364          25 :             continue;
    4365             :         }
    4366        1713 :         const nonneg int struct_varid = tok->varId();
    4367        1713 :         tok = tok->tokAt(2);
    4368        1713 :         if (struct_varid == 0)
    4369           0 :             continue;
    4370             : 
    4371        1713 :         if (tok->str() == ".")
    4372          44 :             tok = tok->next();
    4373             : 
    4374             :         // Don't set varid for template function
    4375        1713 :         if (TemplateSimplifier::templateParameters(tok->next()) > 0)
    4376           8 :             break;
    4377             : 
    4378        1705 :         std::map<std::string, nonneg int>& members = structMembers[struct_varid];
    4379        1705 :         const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
    4380        1705 :         if (it == members.end()) {
    4381        1344 :             members[tok->str()] = ++varId;
    4382        1344 :             tok->varId(varId);
    4383             :         } else {
    4384         361 :             tok->varId(it->second);
    4385             :         }
    4386             :     }
    4387             :     // tok can't be null
    4388      118738 :     tok1 = tok;
    4389             : }
    4390             : 
    4391        6062 : static bool setVarIdClassDeclaration(Token* const startToken,
    4392             :                                      VariableMap& variableMap,
    4393             :                                      const nonneg int scopeStartVarId,
    4394             :                                      std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers)
    4395             : {
    4396             :     // end of scope
    4397        6062 :     const Token* const endToken = startToken->link();
    4398             : 
    4399             :     // determine class name
    4400       12124 :     std::string className;
    4401       13457 :     for (const Token *tok = startToken->previous(); tok; tok = tok->previous()) {
    4402       13376 :         if (!tok->isName() && tok->str() != ":")
    4403         662 :             break;
    4404       12714 :         if (Token::Match(tok, "class|struct|enum %type% [:{]")) {
    4405        5319 :             className = tok->next()->str();
    4406        5319 :             break;
    4407             :         }
    4408             :     }
    4409             : 
    4410             :     // replace varids..
    4411        6062 :     int indentlevel = 0;
    4412        6062 :     bool initList = false;
    4413        6062 :     bool inEnum = false;
    4414        6062 :     const Token *initListArgLastToken = nullptr;
    4415       79545 :     for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
    4416       73483 :         if (!tok)
    4417           0 :             return false;
    4418       73483 :         if (initList) {
    4419        3653 :             if (tok == initListArgLastToken)
    4420         412 :                 initListArgLastToken = nullptr;
    4421        5656 :             else if (!initListArgLastToken &&
    4422        3734 :                      Token::Match(tok->previous(), "%name%|>|>> {|(") &&
    4423         493 :                      Token::Match(tok->link(), "}|) ,|{"))
    4424         412 :                 initListArgLastToken = tok->link();
    4425             :         }
    4426       73483 :         if (tok->str() == "{") {
    4427        3445 :             inEnum = isEnumStart(tok);
    4428        3445 :             if (initList && !initListArgLastToken)
    4429         365 :                 initList = false;
    4430        3445 :             ++indentlevel;
    4431       70038 :         } else if (tok->str() == "}") {
    4432        3445 :             --indentlevel;
    4433        3445 :             inEnum = false;
    4434       66593 :         } else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
    4435         403 :             const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(false).find(tok->str());
    4436         403 :             if (it != variableMap.map(false).end()) {
    4437         350 :                 tok->varId(it->second);
    4438             :             }
    4439       66190 :         } else if (tok->isName() && tok->varId() <= scopeStartVarId) {
    4440       24505 :             if (indentlevel > 0 || initList) {
    4441        5049 :                 if (Token::Match(tok->previous(), "::|.") && tok->strAt(-2) != "this" && !Token::simpleMatch(tok->tokAt(-5), "( * this ) ."))
    4442         538 :                     continue;
    4443        4511 :                 if (!tok->next())
    4444           0 :                     return false;
    4445        4511 :                 if (tok->next()->str() == "::") {
    4446         255 :                     if (tok->str() == className)
    4447          16 :                         tok = tok->tokAt(2);
    4448             :                     else
    4449         239 :                         continue;
    4450             :                 }
    4451             : 
    4452        4272 :                 if (!inEnum) {
    4453        4055 :                     const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(false).find(tok->str());
    4454        4055 :                     if (it != variableMap.map(false).end()) {
    4455         628 :                         tok->varId(it->second);
    4456         628 :                         setVarIdStructMembers(tok, structMembers, variableMap.getVarId());
    4457             :                     }
    4458             :                 }
    4459             :             }
    4460       41685 :         } else if (indentlevel == 0 && tok->str() == ":" && !initListArgLastToken)
    4461         442 :             initList = true;
    4462             :     }
    4463        6062 :     return true;
    4464             : }
    4465             : 
    4466             : 
    4467             : 
    4468             : // Update the variable ids..
    4469             : // Parse each function..
    4470        2666 : void Tokenizer::setVarIdClassFunction(const std::string &classname,
    4471             :                                       Token * const startToken,
    4472             :                                       const Token * const endToken,
    4473             :                                       const std::map<std::string, nonneg int> &varlist,
    4474             :                                       std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
    4475             :                                       nonneg int &varId_)
    4476             : {
    4477        2666 :     const auto pos = classname.rfind(' '); // TODO handle multiple scopes
    4478        5332 :     const std::string lastScope = classname.substr(pos == std::string::npos ? 0 : pos + 1);
    4479       23672 :     for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) {
    4480       21006 :         if (tok2->varId() != 0 || !tok2->isName())
    4481       17581 :             continue;
    4482        4279 :         if (Token::Match(tok2->tokAt(-2), ("!!" + lastScope + " ::").c_str()))
    4483         292 :             continue;
    4484        3987 :         if (Token::Match(tok2->tokAt(-4), "%name% :: %name% ::")) // Currently unsupported
    4485           8 :             continue;
    4486        3979 :         if (Token::Match(tok2->tokAt(-2), "!!this .") && !Token::simpleMatch(tok2->tokAt(-5), "( * this ) ."))
    4487         308 :             continue;
    4488        3671 :         if (Token::Match(tok2, "%name% ::"))
    4489         246 :             continue;
    4490             : 
    4491        3425 :         const std::map<std::string, nonneg int>::const_iterator it = varlist.find(tok2->str());
    4492        3425 :         if (it != varlist.end()) {
    4493         397 :             tok2->varId(it->second);
    4494         397 :             setVarIdStructMembers(tok2, structMembers, varId_);
    4495             :         }
    4496             :     }
    4497        2666 : }
    4498             : 
    4499             : 
    4500             : 
    4501       22638 : void Tokenizer::setVarId()
    4502             : {
    4503             :     // Clear all variable ids
    4504     1014526 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    4505      991888 :         if (tok->isName())
    4506      396156 :             tok->varId(0);
    4507             :     }
    4508             : 
    4509       22637 :     setVarIdPass1();
    4510             : 
    4511       22633 :     setPodTypes();
    4512             : 
    4513       22629 :     setVarIdPass2();
    4514       22626 : }
    4515             : 
    4516             : 
    4517             : // Variable declarations can't start with "return" etc.
    4518             : #define NOTSTART_C "NOT", "case", "default", "goto", "not", "return", "sizeof", "typedef"
    4519             : static const std::unordered_set<std::string> notstart_c = { NOTSTART_C };
    4520             : static const std::unordered_set<std::string> notstart_cpp = { NOTSTART_C,
    4521             :                                                               "delete", "friend", "new", "throw", "using", "virtual", "explicit", "const_cast", "dynamic_cast", "reinterpret_cast", "static_cast", "template"
    4522             : };
    4523             : 
    4524       22637 : void Tokenizer::setVarIdPass1()
    4525             : {
    4526             :     // Variable declarations can't start with "return" etc.
    4527       22637 :     const std::unordered_set<std::string>& notstart = (isC()) ? notstart_c : notstart_cpp;
    4528             : 
    4529       22642 :     VariableMap variableMap;
    4530       22641 :     std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
    4531             : 
    4532       22642 :     std::stack<VarIdScopeInfo> scopeStack;
    4533             : 
    4534       22634 :     scopeStack.emplace(/*VarIdScopeInfo()*/);
    4535       22639 :     std::stack<const Token *> functionDeclEndStack;
    4536       22633 :     const Token *functionDeclEndToken = nullptr;
    4537       22633 :     bool initlist = false;
    4538       22633 :     bool inlineFunction = false;
    4539      829077 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    4540      829002 :         if (tok->isOp())
    4541       55678 :             continue;
    4542      773321 :         if (tok->isCpp() && Token::simpleMatch(tok, "template <")) {
    4543         726 :             Token* closingBracket = tok->next()->findClosingBracket();
    4544         726 :             if (closingBracket)
    4545         726 :                 tok = closingBracket;
    4546         726 :             continue;
    4547             :         }
    4548             : 
    4549      772598 :         if (tok == functionDeclEndToken) {
    4550       43028 :             functionDeclEndStack.pop();
    4551       43028 :             functionDeclEndToken = functionDeclEndStack.empty() ? nullptr : functionDeclEndStack.top();
    4552       43028 :             if (tok->str() == ":")
    4553         424 :                 initlist = true;
    4554       42604 :             else if (tok->str() == ";") {
    4555        3497 :                 if (!variableMap.leaveScope())
    4556           1 :                     cppcheckError(tok);
    4557       39107 :             } else if (tok->str() == "{") {
    4558       39107 :                 scopeStack.emplace(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/ false, variableMap.getVarId());
    4559             : 
    4560             :                 // check if this '{' is a start of an "if" body
    4561       39110 :                 const Token * ifToken = tok->previous();
    4562       39110 :                 if (ifToken && ifToken->str() == ")")
    4563       38697 :                     ifToken = ifToken->link();
    4564             :                 else
    4565         409 :                     ifToken = nullptr;
    4566       39106 :                 if (ifToken)
    4567       38697 :                     ifToken = ifToken->previous();
    4568       39106 :                 if (ifToken && ifToken->str() == "if") {
    4569             :                     // open another scope to differentiate between variables declared in the "if" condition and in the "if" body
    4570        8638 :                     variableMap.enterScope();
    4571             :                 }
    4572             :             }
    4573      729570 :         } else if (!initlist && tok->str()=="(") {
    4574      105102 :             const Token * newFunctionDeclEnd = nullptr;
    4575      105102 :             if (!scopeStack.top().isExecutable)
    4576       43493 :                 newFunctionDeclEnd = isFunctionHead(tok, "{:;");
    4577             :             else {
    4578       61609 :                 const Token* tokenLinkNext = tok->link()->next();
    4579       61610 :                 if (Token::simpleMatch(tokenLinkNext, ".")) { // skip trailing return type
    4580         330 :                     tokenLinkNext = tokenLinkNext->next();
    4581         669 :                     while (Token::Match(tokenLinkNext, "%name%|::")) {
    4582         339 :                         tokenLinkNext = tokenLinkNext->next();
    4583         339 :                         if (Token::simpleMatch(tokenLinkNext, "<") && tokenLinkNext->link())
    4584           0 :                             tokenLinkNext = tokenLinkNext->link()->next();
    4585             :                     }
    4586             :                 }
    4587       61610 :                 if (tokenLinkNext && tokenLinkNext->str() == "{") // might be for- or while-loop or if-statement
    4588       10379 :                     newFunctionDeclEnd = tokenLinkNext;
    4589             :             }
    4590      105106 :             if (newFunctionDeclEnd && newFunctionDeclEnd != functionDeclEndToken) {
    4591       43036 :                 functionDeclEndStack.push(newFunctionDeclEnd);
    4592       43035 :                 functionDeclEndToken = newFunctionDeclEnd;
    4593       43035 :                 variableMap.enterScope();
    4594             :             }
    4595      624471 :         } else if (Token::Match(tok, "{|}")) {
    4596       62229 :             inlineFunction = false;
    4597             : 
    4598       62229 :             const Token * const startToken = (tok->str() == "{") ? tok : tok->link();
    4599             : 
    4600             :             // parse anonymous namespaces as part of the current scope
    4601      124284 :             if (!Token::Match(startToken->previous(), "union|struct|enum|namespace {") &&
    4602       62054 :                 !(initlist && Token::Match(startToken->previous(), "%name%|>|>>|(") && Token::Match(startToken->link(), "} ,|{|)"))) {
    4603             : 
    4604       61950 :                 if (tok->str() == "{") {
    4605             :                     bool isExecutable;
    4606       11419 :                     const Token *prev = tok->previous();
    4607       27347 :                     while (Token::Match(prev, "%name%|."))
    4608       15928 :                         prev = prev->previous();
    4609       11419 :                     const bool isLambda = prev && prev->str() == ")" && Token::simpleMatch(prev->link()->previous(), "] (");
    4610       11457 :                     if ((!isLambda && (tok->strAt(-1) == ")" || Token::Match(tok->tokAt(-2), ") %type%"))) ||
    4611          38 :                         (initlist && tok->strAt(-1) == "}")) {
    4612         427 :                         isExecutable = true;
    4613             :                     } else {
    4614       15402 :                         isExecutable = ((scopeStack.top().isExecutable || initlist || tok->strAt(-1) == "else") &&
    4615        4416 :                                         !isClassStructUnionEnumStart(tok));
    4616       10987 :                         if (!(scopeStack.top().isStructInit || tok->strAt(-1) == "="))
    4617       10330 :                             variableMap.enterScope();
    4618             :                     }
    4619       11413 :                     initlist = false;
    4620       11413 :                     scopeStack.emplace(isExecutable, scopeStack.top().isStructInit || tok->strAt(-1) == "=", isEnumStart(tok), variableMap.getVarId());
    4621             :                 } else { /* if (tok->str() == "}") */
    4622       50532 :                     bool isNamespace = false;
    4623       66376 :                     for (const Token *tok1 = tok->link()->previous(); tok1 && tok1->isName(); tok1 = tok1->previous()) {
    4624       16297 :                         if (tok1->str() == "namespace") {
    4625         453 :                             isNamespace = true;
    4626         453 :                             break;
    4627             :                         }
    4628             :                     }
    4629             :                     // Set variable ids in class declaration..
    4630       50533 :                     if (!initlist && !isC() && !scopeStack.top().isExecutable && tok->link() && !isNamespace) {
    4631        6062 :                         if (!setVarIdClassDeclaration(tok->link(),
    4632             :                                                       variableMap,
    4633        6062 :                                                       scopeStack.top().startVarid,
    4634             :                                                       structMembers)) {
    4635           0 :                             syntaxError(nullptr);
    4636             :                         }
    4637             :                     }
    4638             : 
    4639       50531 :                     if (!scopeStack.top().isStructInit) {
    4640       49871 :                         variableMap.leaveScope();
    4641             : 
    4642             :                         // check if this '}' is an end of an "else" body or an "if" body without an "else" part
    4643       49868 :                         const Token * ifToken = startToken->previous();
    4644       49868 :                         if (ifToken && ifToken->str() == ")")
    4645       39085 :                             ifToken = ifToken->link()->previous();
    4646             :                         else
    4647       10783 :                             ifToken = nullptr;
    4648       49867 :                         if (startToken->strAt(-1) == "else" || (ifToken && ifToken->str() == "if" && tok->strAt(1) != "else")) {
    4649             :                             // leave the extra scope used to differentiate between variables declared in the "if" condition and in the "if" body
    4650        8636 :                             variableMap.leaveScope();
    4651             :                         }
    4652             :                     }
    4653             : 
    4654       50527 :                     scopeStack.pop();
    4655       50527 :                     if (scopeStack.empty()) {  // should be impossible
    4656           3 :                         scopeStack.emplace(/*VarIdScopeInfo()*/);
    4657             :                     }
    4658             :                 }
    4659             :             }
    4660             :         }
    4661             : 
    4662      772600 :         if ((!scopeStack.top().isStructInit &&
    4663      770101 :              (tok == list.front() ||
    4664     1301922 :               Token::Match(tok, "[;{}]") ||
    4665     1982606 :               (tok->str() == "(" && !scopeStack.top().isExecutable && isFunctionHead(tok,";:")) ||
    4666      585132 :               (tok->str() == "," && (!scopeStack.top().isExecutable || inlineFunction || !tok->previous()->varId())) ||
    4667     2174906 :               (tok->isName() && endsWith(tok->str(), ':')))) ||
    4668     1404794 :             (tok->str() == "(" && isFunctionHead(tok, "{"))) {
    4669             : 
    4670             :             // No variable declarations in sizeof
    4671      282583 :             if (Token::simpleMatch(tok->previous(), "sizeof (")) {
    4672        9758 :                 continue;
    4673             :             }
    4674             : 
    4675      282539 :             if (Settings::terminated())
    4676           0 :                 return;
    4677             : 
    4678             :             // locate the variable name..
    4679      282538 :             Token* tok2 = (tok->isName()) ? tok : tok->next();
    4680             : 
    4681             :             // private: protected: public: etc
    4682      285070 :             while (tok2 && endsWith(tok2->str(), ':')) {
    4683        2531 :                 tok2 = tok2->next();
    4684             :             }
    4685      282537 :             if (!tok2)
    4686       22560 :                 break;
    4687             : 
    4688             :             // Variable declaration can't start with "return", etc
    4689      259977 :             if (notstart.find(tok2->str()) != notstart.end())
    4690        9555 :                 continue;
    4691             : 
    4692      250420 :             if (!isC() && Token::simpleMatch(tok2, "const new"))
    4693           1 :                 continue;
    4694             : 
    4695             :             bool decl;
    4696      250419 :             if (isCPP() && mSettings.standards.cpp >= Standards::CPP17 && Token::Match(tok, "[(;{}] const| auto &|&&| [")) {
    4697             :                 // Structured bindings
    4698           7 :                 tok2 = Token::findsimplematch(tok, "[");
    4699          11 :                 if ((Token::simpleMatch(tok->previous(), "for (") && Token::simpleMatch(tok2->link(), "] :")) ||
    4700           4 :                     Token::simpleMatch(tok2->link(), "] =")) {
    4701          37 :                     while (tok2 && tok2->str() != "]") {
    4702          30 :                         if (Token::Match(tok2, "%name% [,]]"))
    4703          15 :                             variableMap.addVariable(tok2->str(), false);
    4704          30 :                         tok2 = tok2->next();
    4705             :                     }
    4706           7 :                     continue;
    4707             :                 }
    4708             :             }
    4709             : 
    4710             :             try { /* Ticket #8151 */
    4711      250415 :                 decl = setVarIdParseDeclaration(tok2, variableMap, scopeStack.top().isExecutable);
    4712           0 :             } catch (const Token * errTok) {
    4713           0 :                 syntaxError(errTok);
    4714             :             }
    4715             : 
    4716      294994 :             if (tok->str() == "(" && isFunctionHead(tok, "{") && scopeStack.top().isExecutable)
    4717       11270 :                 inlineFunction = true;
    4718             : 
    4719      250413 :             if (decl) {
    4720       58303 :                 if (isCPP()) {
    4721       43412 :                     if (Token *declTypeTok = Token::findsimplematch(tok, "decltype (", tok2)) {
    4722         127 :                         for (Token *declTok = declTypeTok->linkAt(1); declTok != declTypeTok; declTok = declTok->previous()) {
    4723         102 :                             if (declTok->isName() && !Token::Match(declTok->previous(), "::|.") && variableMap.hasVariable(declTok->str()))
    4724           7 :                                 declTok->varId(variableMap.map(false).find(declTok->str())->second);
    4725             :                         }
    4726             :                     }
    4727             :                 }
    4728             : 
    4729       58307 :                 const Token* prev2 = tok2->previous();
    4730       58307 :                 if (Token::Match(prev2, "%type% [;[=,)]") && tok2->previous()->str() != "const")
    4731             :                     ;
    4732        9820 :                 else if (Token::Match(prev2, "%type% :") && tok->strAt(-1) == "for")
    4733             :                     ;
    4734        9625 :                 else if (Token::Match(prev2, "%type% ( !!)") && Token::simpleMatch(tok2->link(), ") ;")) {
    4735             :                     // In C++ , a variable can't be called operator+ or something like that.
    4736        3635 :                     if (prev2->isCpp() &&
    4737        1805 :                         prev2->isOperatorKeyword())
    4738         148 :                         continue;
    4739             : 
    4740        1682 :                     const Token *tok3 = tok2->next();
    4741        1682 :                     if (!tok3->isStandardType() && tok3->str() != "void" && !Token::Match(tok3, "struct|union|class %type%") && tok3->str() != "." && !Token::Match(tok2->link()->previous(), "[&*]")) {
    4742        1409 :                         if (!scopeStack.top().isExecutable) {
    4743             :                             // Detecting initializations with () in non-executable scope is hard and often impossible to be done safely. Thus, only treat code as a variable that definitely is one.
    4744         138 :                             decl = false;
    4745         138 :                             bool rhs = false;
    4746         280 :                             for (; tok3; tok3 = tok3->nextArgumentBeforeCreateLinks2()) {
    4747         165 :                                 if (tok3->str() == "=") {
    4748           0 :                                     rhs = true;
    4749           0 :                                     continue;
    4750             :                                 }
    4751             : 
    4752         165 :                                 if (tok3->str() == ",") {
    4753           0 :                                     rhs = false;
    4754           0 :                                     continue;
    4755             :                                 }
    4756             : 
    4757         165 :                                 if (rhs)
    4758           0 :                                     continue;
    4759             : 
    4760         165 :                                 if (tok3->isLiteral() ||
    4761         289 :                                     (tok3->isName() && (variableMap.hasVariable(tok3->str()) ||
    4762         251 :                                                         (tok3->strAt(-1) == "(" && Token::simpleMatch(tok3->next(), "(") && !Token::simpleMatch(tok3->linkAt(1)->next(), "(")))) ||
    4763         288 :                                     tok3->isOp() ||
    4764         463 :                                     tok3->str() == "(" ||
    4765         308 :                                     notstart.find(tok3->str()) != notstart.end()) {
    4766          23 :                                     decl = true;
    4767          23 :                                     break;
    4768             :                                 }
    4769             :                             }
    4770             :                         }
    4771             :                     } else
    4772         273 :                         decl = false;
    4773        7795 :                 } else if (isCPP() && Token::Match(prev2, "%type% {") && Token::simpleMatch(tok2->link(), "} ;")) { // C++11 initialization style
    4774         984 :                     if (tok2->link() != tok2->next() && // add value-initialized variable T x{};
    4775         404 :                         (Token::Match(prev2, "do|try|else") || Token::Match(prev2->tokAt(-2), "struct|class|:")))
    4776           0 :                         continue;
    4777             :                 } else
    4778        7216 :                     decl = false;
    4779             : 
    4780       58160 :                 if (decl) {
    4781       50556 :                     if (isC() && Token::Match(prev2->previous(), "&|&&"))
    4782          16 :                         syntaxErrorC(prev2, prev2->strAt(-2) + prev2->strAt(-1) + " " + prev2->str());
    4783       50552 :                     variableMap.addVariable(prev2->str(), scopeStack.size() <= 1);
    4784             : 
    4785       50549 :                     if (Token::simpleMatch(tok->previous(), "for (") && Token::Match(prev2, "%name% [=,]")) {
    4786        2020 :                         for (const Token *tok3 = prev2->next(); tok3 && tok3->str() != ";"; tok3 = tok3->next()) {
    4787        1492 :                             if (Token::Match(tok3, "[([]"))
    4788         137 :                                 tok3 = tok3->link();
    4789        1492 :                             if (Token::Match(tok3, ", %name% [,=;]"))
    4790           7 :                                 variableMap.addVariable(tok3->next()->str(), false);
    4791             :                         }
    4792             :                     }
    4793             : 
    4794             :                     // set varid for template parameters..
    4795       50549 :                     tok = tok->next();
    4796      150778 :                     while (Token::Match(tok, "%name%|::"))
    4797      100228 :                         tok = tok->next();
    4798       50546 :                     if (tok && tok->str() == "<") {
    4799        2316 :                         const Token *end = tok->findClosingBracket();
    4800        9035 :                         while (tok != end) {
    4801        6854 :                             if (tok->isName() && !(Token::simpleMatch(tok->next(), "<") &&
    4802         135 :                                                    Token::Match(tok->tokAt(-1), ":: %name%"))) {
    4803        2928 :                                 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(false).find(tok->str());
    4804        2928 :                                 if (it != variableMap.map(false).end())
    4805           6 :                                     tok->varId(it->second);
    4806             :                             }
    4807        6719 :                             tok = tok->next();
    4808             :                         }
    4809             :                     }
    4810             : 
    4811       50547 :                     tok = tok2->previous();
    4812             :                 }
    4813             :             }
    4814             :         }
    4815             : 
    4816      740280 :         if (tok->isName() && !tok->isKeyword() && !tok->isStandardType()) {
    4817             :             // don't set variable id after a struct|enum|union
    4818      230539 :             if (Token::Match(tok->previous(), "struct|enum|union") || (tok->isCpp() && tok->strAt(-1) == "class"))
    4819        6851 :                 continue;
    4820             : 
    4821      223684 :             bool globalNamespace = false;
    4822      223684 :             if (!isC()) {
    4823      165020 :                 if (tok->previous() && tok->previous()->str() == "::") {
    4824          84 :                     if (Token::Match(tok->tokAt(-2), ")|]|%name%"))
    4825           0 :                         continue;
    4826          84 :                     globalNamespace = true;
    4827             :                 }
    4828      165018 :                 if (tok->next() && tok->next()->str() == "::")
    4829        6668 :                     continue;
    4830      158352 :                 if (Token::simpleMatch(tok->tokAt(-2), ":: template"))
    4831           0 :                     continue;
    4832             :             }
    4833             : 
    4834             :             // function declaration inside executable scope? Function declaration is of form: type name "(" args ")"
    4835      217021 :             if (scopeStack.top().isExecutable && Token::Match(tok, "%name% [,)[]")) {
    4836       45244 :                 bool par = false;
    4837             :                 const Token* start;
    4838             :                 Token* end;
    4839             : 
    4840             :                 // search begin of function declaration
    4841       98765 :                 for (start = tok; Token::Match(start, "%name%|*|&|,|("); start = start->previous()) {
    4842       93511 :                     if (start->str() == "(") {
    4843       18909 :                         if (par)
    4844           1 :                             break;
    4845       18908 :                         par = true;
    4846             :                     }
    4847       93510 :                     if (Token::Match(start, "[(,]")) {
    4848       40106 :                         if (!Token::Match(start, "[(,] %type% %name%|*|&"))
    4849       39953 :                             break;
    4850             :                     }
    4851       53557 :                     if (start->varId() > 0)
    4852          36 :                         break;
    4853             :                 }
    4854             : 
    4855             :                 // search end of function declaration
    4856      109628 :                 for (end = tok->next(); Token::Match(end, "%name%|*|&|,|[|]|%num%"); end = end->next()) {}
    4857             : 
    4858             :                 // there are tokens which can't appear at the begin of a function declaration such as "return"
    4859       45244 :                 const bool isNotstartKeyword = start->next() && notstart.find(start->next()->str()) != notstart.end();
    4860             : 
    4861             :                 // now check if it is a function declaration
    4862       45244 :                 if (Token::Match(start, "[;{}] %type% %name%|*") && par && Token::simpleMatch(end, ") ;") && !isNotstartKeyword) {
    4863             :                     // function declaration => don't set varid
    4864           5 :                     tok = end;
    4865           5 :                     continue;
    4866             :                 }
    4867             :             }
    4868             : 
    4869      433647 :             if ((!scopeStack.top().isEnum || !(Token::Match(tok->previous(), "{|,") && Token::Match(tok->next(), ",|=|}"))) &&
    4870      216633 :                 !Token::simpleMatch(tok->next(), ": ;")) {
    4871      216494 :                 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(globalNamespace).find(tok->str());
    4872      216503 :                 if (it != variableMap.map(globalNamespace).end()) {
    4873      117723 :                     tok->varId(it->second);
    4874      117723 :                     setVarIdStructMembers(tok, structMembers, variableMap.getVarId());
    4875             :                 }
    4876             :             }
    4877      509740 :         } else if (Token::Match(tok, "::|. %name%") && Token::Match(tok->previous(), ")|]|>|%name%")) {
    4878             :             // Don't set varid after a :: or . token
    4879       12344 :             tok = tok->next();
    4880      497401 :         } else if (tok->str() == ":" && Token::Match(tok->tokAt(-2), "class %type%")) {
    4881         667 :             do {
    4882        1022 :                 tok = tok->next();
    4883        1022 :             } while (tok && (tok->isName() || tok->str() == ","));
    4884         355 :             if (!tok)
    4885           2 :                 break;
    4886         353 :             tok = tok->previous();
    4887             :         }
    4888             :     }
    4889             : 
    4890       22631 :     mVarId = variableMap.getVarId();
    4891             : }
    4892             : 
    4893             : namespace {
    4894             :     struct Member {
    4895       11006 :         Member(std::list<std::string> s, std::list<const Token *> ns, Token *t) : usingnamespaces(std::move(ns)), scope(std::move(s)), tok(t) {}
    4896             :         std::list<const Token *> usingnamespaces;
    4897             :         std::list<std::string> scope;
    4898             :         Token *tok;
    4899             :     };
    4900             : }
    4901             : 
    4902        5958 : static std::string getScopeName(const std::list<ScopeInfo2> &scopeInfo)
    4903             : {
    4904        5958 :     std::string ret;
    4905        6588 :     for (const ScopeInfo2 &si : scopeInfo)
    4906         630 :         ret += (ret.empty() ? "" : " :: ") + (si.name);
    4907        5958 :     return ret;
    4908             : }
    4909             : 
    4910        8488 : static Token * matchMemberName(const std::list<std::string> &scope, const Token *nsToken, Token *memberToken, const std::list<ScopeInfo2> &scopeInfo)
    4911             : {
    4912        8488 :     std::list<ScopeInfo2>::const_iterator scopeIt = scopeInfo.cbegin();
    4913             : 
    4914             :     // Current scope..
    4915        9045 :     for (std::list<std::string>::const_iterator it = scope.cbegin(); it != scope.cend(); ++it) {
    4916         623 :         if (scopeIt == scopeInfo.cend() || scopeIt->name != *it)
    4917          66 :             return nullptr;
    4918         557 :         ++scopeIt;
    4919             :     }
    4920             : 
    4921             :     // using namespace..
    4922        8422 :     if (nsToken) {
    4923        1508 :         while (Token::Match(nsToken, "%name% ::")) {
    4924         516 :             if (scopeIt != scopeInfo.end() && nsToken->str() == scopeIt->name) {
    4925         222 :                 nsToken = nsToken->tokAt(2);
    4926         222 :                 ++scopeIt;
    4927             :             } else {
    4928         294 :                 return nullptr;
    4929             :             }
    4930             :         }
    4931         992 :         if (!Token::Match(nsToken, "%name% ;"))
    4932           0 :             return nullptr;
    4933         992 :         if (scopeIt == scopeInfo.end() || nsToken->str() != scopeIt->name)
    4934         804 :             return nullptr;
    4935         188 :         ++scopeIt;
    4936             :     }
    4937             : 
    4938             :     // Parse member tokens..
    4939        8577 :     while (scopeIt != scopeInfo.end()) {
    4940        7922 :         if (!Token::Match(memberToken, "%name% ::|<"))
    4941         545 :             return nullptr;
    4942        7377 :         if (memberToken->str() != scopeIt->name)
    4943        6124 :             return nullptr;
    4944        1253 :         if (memberToken->next()->str() == "<") {
    4945          11 :             memberToken = memberToken->next()->findClosingBracket();
    4946          11 :             if (!Token::simpleMatch(memberToken, "> ::"))
    4947           0 :                 return nullptr;
    4948             :         }
    4949        1253 :         memberToken = memberToken->tokAt(2);
    4950        1253 :         ++scopeIt;
    4951             :     }
    4952             : 
    4953         655 :     return Token::Match(memberToken, "~| %name%") ? memberToken : nullptr;
    4954             : }
    4955             : 
    4956        7178 : static Token * matchMemberName(const Member &member, const std::list<ScopeInfo2> &scopeInfo)
    4957             : {
    4958        7178 :     if (scopeInfo.empty())
    4959           0 :         return nullptr;
    4960             : 
    4961             :     // Does this member match without "using namespace"..
    4962        7178 :     Token *ret = matchMemberName(member.scope, nullptr, member.tok, scopeInfo);
    4963        7178 :     if (ret)
    4964         636 :         return ret;
    4965             : 
    4966             :     // Try to match member using the "using namespace ..." namespaces..
    4967        7833 :     for (const Token *ns : member.usingnamespaces) {
    4968        1310 :         ret = matchMemberName(member.scope, ns, member.tok, scopeInfo);
    4969        1310 :         if (ret)
    4970          19 :             return ret;
    4971             :     }
    4972             : 
    4973        6523 :     return nullptr;
    4974             : }
    4975             : 
    4976        3465 : static Token * matchMemberVarName(const Member &var, const std::list<ScopeInfo2> &scopeInfo)
    4977             : {
    4978        3465 :     Token *tok = matchMemberName(var, scopeInfo);
    4979        3465 :     if (Token::Match(tok, "%name%")) {
    4980         198 :         if (!tok->next() || tok->strAt(1) != "(" || (tok->tokAt(2) && tok->tokAt(2)->isLiteral()))
    4981         198 :             return tok;
    4982             :     }
    4983        3267 :     return nullptr;
    4984             : }
    4985             : 
    4986        3713 : static Token * matchMemberFunctionName(const Member &func, const std::list<ScopeInfo2> &scopeInfo)
    4987             : {
    4988        3713 :     Token *tok = matchMemberName(func, scopeInfo);
    4989        3713 :     return Token::Match(tok, "~| %name% (") ? tok : nullptr;
    4990             : }
    4991             : 
    4992             : template<typename T>
    4993         364 : static T* skipInitializerList(T* tok)
    4994             : {
    4995         364 :     T* const start = tok;
    4996         770 :     while (Token::Match(tok, "[:,] ::| %name%")) {
    4997         414 :         tok = tok->tokAt(tok->strAt(1) == "::" ? 1 : 2);
    4998         422 :         while (Token::Match(tok, ":: %name%"))
    4999           8 :             tok = tok->tokAt(2);
    5000         414 :         if (!Token::Match(tok, "[({<]") || !tok->link())
    5001           8 :             return start;
    5002         406 :         const bool isTemplate = tok->str() == "<";
    5003         406 :         tok = tok->link()->next();
    5004         406 :         if (isTemplate && tok && tok->link())
    5005           0 :             tok = tok->link()->next();
    5006             :     }
    5007         356 :     return tok;
    5008             : }
    5009             : 
    5010       22631 : void Tokenizer::setVarIdPass2()
    5011             : {
    5012       45261 :     std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
    5013             : 
    5014             :     // Member functions and variables in this source
    5015       45261 :     std::list<Member> allMemberFunctions;
    5016       45262 :     std::list<Member> allMemberVars;
    5017       22632 :     if (!isC()) {
    5018       33426 :         std::map<const Token *, std::string> endOfScope;
    5019       33422 :         std::list<std::string> scope;
    5020       33421 :         std::list<const Token *> usingnamespaces;
    5021      720603 :         for (Token *tok = list.front(); tok; tok = tok->next()) {
    5022      703899 :             if (!tok->previous() || Token::Match(tok->previous(), "[;{}]")) {
    5023      139840 :                 if (Token::Match(tok, "using namespace %name% ::|;")) {
    5024         108 :                     Token *endtok = tok->tokAt(2);
    5025         130 :                     while (Token::Match(endtok, "%name% ::"))
    5026          22 :                         endtok = endtok->tokAt(2);
    5027         108 :                     if (Token::Match(endtok, "%name% ;"))
    5028         108 :                         usingnamespaces.push_back(tok->tokAt(2));
    5029         108 :                     tok = endtok;
    5030      692882 :                     continue;
    5031             :                 }
    5032      139738 :                 if (Token::Match(tok, "namespace %name% {")) {
    5033         453 :                     scope.push_back(tok->strAt(1));
    5034         453 :                     endOfScope[tok->linkAt(2)] = tok->strAt(1);
    5035             :                 }
    5036             :             }
    5037             : 
    5038      703793 :             if (tok->str() == "}") {
    5039       35413 :                 const std::map<const Token *, std::string>::iterator it = endOfScope.find(tok);
    5040       35406 :                 if (it != endOfScope.end())
    5041         453 :                     scope.remove(it->second);
    5042             :             }
    5043             : 
    5044      703779 :             Token* const tok1 = tok;
    5045      703779 :             if (Token::Match(tok, "%name% :: ~| %name%"))
    5046       10584 :                 tok = tok->next();
    5047      693195 :             else if (Token::Match(tok, "%name% <") && Token::Match(tok->next()->findClosingBracket(),"> :: ~| %name%"))
    5048         147 :                 tok = tok->next()->findClosingBracket()->next();
    5049      700545 :             else if (usingnamespaces.empty() || tok->varId() || !tok->isName() || tok->isStandardType() || tok->tokType() == Token::eKeyword || tok->tokType() == Token::eBoolean ||
    5050      700823 :                      Token::Match(tok->previous(), ".|namespace|class|struct|&|&&|*|> %name%") || Token::Match(tok->previous(), "%type%| %name% ( %type%|)") || Token::Match(tok, "public:|private:|protected:") ||
    5051         278 :                      (!tok->next() && Token::Match(tok->previous(), "}|; %name%")))
    5052      692774 :                 continue;
    5053             : 
    5054       11006 :             if (tok->strAt(-1) == "::" && tok->tokAt(-2) && tok->tokAt(-2)->isName())
    5055           0 :                 continue;
    5056             : 
    5057       12047 :             while (Token::Match(tok, ":: ~| %name%")) {
    5058       11708 :                 tok = tok->next();
    5059       11708 :                 if (tok->str() == "~")
    5060          59 :                     tok = tok->next();
    5061       11649 :                 else if (Token::Match(tok, "%name% <") && Token::Match(tok->next()->findClosingBracket(),"> :: ~| %name%"))
    5062         419 :                     tok = tok->next()->findClosingBracket()->next();
    5063       11230 :                 else if (Token::Match(tok, "%name% ::"))
    5064         562 :                     tok = tok->next();
    5065             :                 else
    5066       10668 :                     break;
    5067             :             }
    5068       11007 :             if (!tok->next())
    5069           1 :                 syntaxError(tok);
    5070       11006 :             if (Token::Match(tok, "%name% (") && !(tok->tokAt(2) && tok->tokAt(2)->isLiteral()))
    5071        4412 :                 allMemberFunctions.emplace_back(scope, usingnamespaces, tok1);
    5072             :             else
    5073        6594 :                 allMemberVars.emplace_back(scope, usingnamespaces, tok1);
    5074             :         }
    5075             :     }
    5076             : 
    5077       45259 :     std::list<ScopeInfo2> scopeInfo;
    5078             : 
    5079             :     // class members..
    5080       45259 :     std::map<std::string, std::map<std::string, nonneg int>> varsByClass;
    5081     1014395 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    5082      997776 :         while (tok->str() == "}" && !scopeInfo.empty() && tok == scopeInfo.back().bodyEnd)
    5083        6005 :             scopeInfo.pop_back();
    5084             : 
    5085      991764 :         if (!Token::Match(tok, "namespace|class|struct %name% {|:|::|<"))
    5086      989047 :             continue;
    5087             : 
    5088        5960 :         const std::string &scopeName(getScopeName(scopeInfo));
    5089        5960 :         const std::string scopeName2(scopeName.empty() ? std::string() : (scopeName + " :: "));
    5090             : 
    5091        5960 :         std::list<const Token*> classnameTokens{ tok->next() };
    5092        5958 :         Token* tokStart = tok->tokAt(2);
    5093        6212 :         while (Token::Match(tokStart, ":: %name%") || tokStart->str() == "<") {
    5094         256 :             if (tokStart->str() == "<") {
    5095             :                 // skip the template part
    5096          68 :                 Token* closeTok = tokStart->findClosingBracket();
    5097          68 :                 if (!closeTok)
    5098           2 :                     syntaxError(tok);
    5099          66 :                 tokStart = closeTok->next();
    5100             :             } else {
    5101         188 :                 classnameTokens.push_back(tokStart->next());
    5102         188 :                 tokStart = tokStart->tokAt(2);
    5103             :             }
    5104             :         }
    5105             : 
    5106        5956 :         std::string classname;
    5107       12100 :         for (const Token *it : classnameTokens)
    5108        6144 :             classname += (classname.empty() ? "" : " :: ") + it->str();
    5109             : 
    5110        5956 :         std::map<std::string, nonneg int> &thisClassVars = varsByClass[scopeName2 + classname];
    5111        7998 :         while (Token::Match(tokStart, ":|::|,|%name%")) {
    5112        2042 :             if (Token::Match(tokStart, "%name% <")) { // TODO: why skip templates?
    5113          75 :                 tokStart = tokStart->next()->findClosingBracket();
    5114          75 :                 if (tokStart)
    5115          75 :                     tokStart = tokStart->next();
    5116          75 :                 continue;
    5117             :             }
    5118        1967 :             if (Token::Match(tokStart, "%name% ,|{")) {
    5119        1264 :                 std::string baseClassName = tokStart->str();
    5120         632 :                 const Token* baseStart = tokStart;
    5121         670 :                 while (Token::Match(baseStart->tokAt(-2), "%name% ::")) { // build base class name
    5122          38 :                     baseClassName.insert(0, baseStart->strAt(-2) + " :: ");
    5123          38 :                     baseStart = baseStart->tokAt(-2);
    5124             :                 }
    5125        1264 :                 std::string scopeName3(scopeName2);
    5126         636 :                 while (!scopeName3.empty()) {
    5127          42 :                     const std::string name = scopeName3 + baseClassName;
    5128          42 :                     if (varsByClass.find(name) != varsByClass.end()) {
    5129           7 :                         baseClassName = name;
    5130           7 :                         break;
    5131             :                     }
    5132             :                     // Remove last scope name
    5133          35 :                     if (scopeName3.size() <= 8)
    5134          29 :                         break;
    5135           6 :                     scopeName3.erase(scopeName3.size() - 4);
    5136           6 :                     const std::string::size_type pos = scopeName3.rfind(" :: ");
    5137           6 :                     if (pos == std::string::npos)
    5138           2 :                         break;
    5139           4 :                     scopeName3.erase(pos + 4);
    5140             :                 }
    5141         632 :                 const std::map<std::string, nonneg int>& baseClassVars = varsByClass[baseClassName];
    5142         632 :                 thisClassVars.insert(baseClassVars.cbegin(), baseClassVars.cend());
    5143             :             }
    5144        1967 :             tokStart = tokStart->next();
    5145             :         }
    5146        5956 :         if (!Token::simpleMatch(tokStart, "{"))
    5147          81 :             continue;
    5148             : 
    5149             :         // What member variables are there in this class?
    5150        6005 :         std::transform(classnameTokens.cbegin(), classnameTokens.cend(), std::back_inserter(scopeInfo), [&](const Token* tok) {
    5151       12010 :             return ScopeInfo2(tok->str(), tokStart->link());
    5152        5875 :         });
    5153             : 
    5154       43805 :         for (Token *tok2 = tokStart->next(); tok2 && tok2 != tokStart->link(); tok2 = tok2->next()) {
    5155             :             // skip parentheses..
    5156       37930 :             if (tok2->link()) {
    5157        6422 :                 if (tok2->str() == "(") {
    5158        4605 :                     Token *funcstart = const_cast<Token*>(isFunctionHead(tok2, "{"));
    5159        4605 :                     if (funcstart) {
    5160        2257 :                         setVarIdClassFunction(scopeName2 + classname, funcstart, funcstart->link(), thisClassVars, structMembers, mVarId);
    5161        2257 :                         tok2 = funcstart->link();
    5162        2257 :                         continue;
    5163             :                     }
    5164             :                 }
    5165        4165 :                 if (tok2->str() == "{" && !Token::simpleMatch(tok2->previous(), "union")) {
    5166         721 :                     if (tok2->strAt(-1) == ")")
    5167           0 :                         setVarIdClassFunction(scopeName2 + classname, tok2, tok2->link(), thisClassVars, structMembers, mVarId);
    5168         721 :                     tok2 = tok2->link();
    5169        3444 :                 } else if (Token::Match(tok2, "( %name%|)") && !Token::Match(tok2->link(), "(|[")) {
    5170        2306 :                     tok2 = tok2->link();
    5171             : 
    5172             :                     // Skip initialization list
    5173        2306 :                     if (Token::simpleMatch(tok2, ") :"))
    5174         354 :                         tok2 = skipInitializerList(tok2->next());
    5175             :                 }
    5176             :             }
    5177             : 
    5178             :             // Found a member variable..
    5179       31508 :             else if (tok2->varId() > 0)
    5180        3557 :                 thisClassVars[tok2->str()] = tok2->varId();
    5181             :         }
    5182             : 
    5183             :         // Are there any member variables in this class?
    5184        5875 :         if (thisClassVars.empty())
    5185        3015 :             continue;
    5186             : 
    5187             :         // Member variables
    5188        6325 :         for (const Member &var : allMemberVars) {
    5189        3465 :             Token *tok2 = matchMemberVarName(var, scopeInfo);
    5190        3465 :             if (!tok2)
    5191        3267 :                 continue;
    5192         198 :             if (tok2->varId() == 0)
    5193         188 :                 tok2->varId(thisClassVars[tok2->str()]);
    5194             :         }
    5195             : 
    5196        2860 :         if (isC() || tok->str() == "namespace")
    5197         140 :             continue;
    5198             : 
    5199             :         // Set variable ids in member functions for this class..
    5200        6433 :         for (const Member &func : allMemberFunctions) {
    5201        3713 :             Token *tok2 = matchMemberFunctionName(func, scopeInfo);
    5202        3713 :             if (!tok2)
    5203        3294 :                 continue;
    5204             : 
    5205         419 :             if (tok2->str() == "~")
    5206          25 :                 tok2 = tok2->linkAt(2);
    5207             :             else
    5208         394 :                 tok2 = tok2->linkAt(1);
    5209             : 
    5210             :             // If this is a function implementation.. add it to funclist
    5211         419 :             Token * start = const_cast<Token *>(isFunctionHead(tok2, "{"));
    5212         419 :             if (start) {
    5213         355 :                 setVarIdClassFunction(classname, start, start->link(), thisClassVars, structMembers, mVarId);
    5214             :             }
    5215             : 
    5216         419 :             if (Token::Match(tok2, ") %name% ("))
    5217           5 :                 tok2 = tok2->linkAt(2);
    5218             : 
    5219             :             // constructor with initializer list
    5220         419 :             if (!Token::Match(tok2, ") : ::| %name%"))
    5221         364 :                 continue;
    5222             : 
    5223          55 :             Token *tok3 = tok2;
    5224         115 :             while (Token::Match(tok3, "[)}] [,:]")) {
    5225          60 :                 tok3 = tok3->tokAt(2);
    5226          60 :                 if (Token::Match(tok3, ":: %name%"))
    5227           1 :                     tok3 = tok3->next();
    5228          60 :                 while (Token::Match(tok3, "%name% :: %name%"))
    5229           0 :                     tok3 = tok3->tokAt(2);
    5230          60 :                 if (!Token::Match(tok3, "%name% (|{|<"))
    5231           0 :                     break;
    5232             : 
    5233             :                 // set varid
    5234          60 :                 const std::map<std::string, nonneg int>::const_iterator varpos = thisClassVars.find(tok3->str());
    5235          60 :                 if (varpos != thisClassVars.end())
    5236          53 :                     tok3->varId(varpos->second);
    5237             : 
    5238             :                 // goto end of var
    5239          60 :                 if (tok3->strAt(1) == "<") {
    5240           1 :                     tok3 = tok3->next()->findClosingBracket();
    5241           1 :                     if (tok3 && tok3->next() && tok3->next()->link())
    5242           1 :                         tok3 = tok3->next()->link();
    5243             :                 } else
    5244          59 :                     tok3 = tok3->linkAt(1);
    5245             :             }
    5246          55 :             if (Token::Match(tok3, ")|} {")) {
    5247          54 :                 setVarIdClassFunction(classname, tok2, tok3->next()->link(), thisClassVars, structMembers, mVarId);
    5248             :             }
    5249             :         }
    5250             :     }
    5251       22626 : }
    5252             : 
    5253     3008216 : static void linkBrackets(const Tokenizer & tokenizer, std::stack<const Token*>& type, std::stack<Token*>& links, Token * const token, const char open, const char close)
    5254             : {
    5255     3008216 :     if (token->str()[0] == open) {
    5256      162365 :         links.push(token);
    5257      162365 :         type.push(token);
    5258     2845867 :     } else if (token->str()[0] == close) {
    5259      162353 :         if (links.empty()) {
    5260             :             // Error, { and } don't match.
    5261           8 :             tokenizer.unmatchedToken(token);
    5262             :         }
    5263      162347 :         if (type.top()->str()[0] != open) {
    5264           5 :             tokenizer.unmatchedToken(type.top());
    5265             :         }
    5266      162340 :         type.pop();
    5267             : 
    5268      162341 :         Token::createMutualLinks(links.top(), token);
    5269      162340 :         links.pop();
    5270             :     }
    5271     3008224 : }
    5272             : 
    5273       23751 : void Tokenizer::createLinks()
    5274             : {
    5275       47500 :     std::stack<const Token*> type;
    5276       47499 :     std::stack<Token*> links1;
    5277       47500 :     std::stack<Token*> links2;
    5278       47502 :     std::stack<Token*> links3;
    5279     1026510 :     for (Token *token = list.front(); token; token = token->next()) {
    5280     1002773 :         if (token->link()) {
    5281           0 :             token->link(nullptr);
    5282             :         }
    5283             : 
    5284     1002773 :         linkBrackets(*this, type, links1, token, '{', '}');
    5285             : 
    5286     1002769 :         linkBrackets(*this, type, links2, token, '(', ')');
    5287             : 
    5288     1002768 :         linkBrackets(*this, type, links3, token, '[', ']');
    5289             :     }
    5290             : 
    5291       23738 :     if (!links1.empty()) {
    5292             :         // Error, { and } don't match.
    5293           5 :         unmatchedToken(links1.top());
    5294             :     }
    5295             : 
    5296       23733 :     if (!links2.empty()) {
    5297             :         // Error, ( and ) don't match.
    5298           2 :         unmatchedToken(links2.top());
    5299             :     }
    5300             : 
    5301       23731 :     if (!links3.empty()) {
    5302             :         // Error, [ and ] don't match.
    5303           2 :         unmatchedToken(links3.top());
    5304             :     }
    5305       23728 : }
    5306             : 
    5307       23004 : void Tokenizer::createLinks2()
    5308             : {
    5309       23004 :     if (isC())
    5310        5917 :         return;
    5311             : 
    5312       17086 :     bool isStruct = false;
    5313             : 
    5314       34174 :     std::stack<Token*> type;
    5315       34175 :     std::stack<Token*> templateTokens;
    5316      751789 :     for (Token *token = list.front(); token; token = token->next()) {
    5317      734702 :         if (Token::Match(token, "%name%|> %name% [:<]"))
    5318        1156 :             isStruct = true;
    5319      733548 :         else if (Token::Match(token, "[;{}]"))
    5320      140682 :             isStruct = false;
    5321             : 
    5322      734694 :         if (token->link()) {
    5323      229088 :             if (Token::Match(token, "{|[|("))
    5324      114539 :                 type.push(token);
    5325      114548 :             else if (!type.empty() && Token::Match(token, "}|]|)")) {
    5326      114575 :                 while (type.top()->str() == "<") {
    5327          31 :                     if (!templateTokens.empty() && templateTokens.top()->next() == type.top())
    5328           0 :                         templateTokens.pop();
    5329          31 :                     type.pop();
    5330             :                 }
    5331      114543 :                 type.pop();
    5332             :             }
    5333      505606 :         } else if (templateTokens.empty() && !isStruct && Token::Match(token, "%oror%|&&|;")) {
    5334       70510 :             if (Token::Match(token, "&& [,>]"))
    5335           1 :                 continue;
    5336             :             // If there is some such code:  A<B||C>..
    5337             :             // Then this is probably a template instantiation if either "B" or "C" has comparisons
    5338       70510 :             if (token->tokType() == Token::eLogicalOp && !type.empty() && type.top()->str() == "<") {
    5339          18 :                 const Token *prev = token->previous();
    5340          18 :                 bool foundComparison = false;
    5341          38 :                 while (Token::Match(prev, "%name%|%num%|%str%|%cop%|)|]") && prev != type.top()) {
    5342          20 :                     if (prev->str() == ")" || prev->str() == "]")
    5343           1 :                         prev = prev->link();
    5344          19 :                     else if (prev->tokType() == Token::eLogicalOp)
    5345           0 :                         break;
    5346          19 :                     else if (prev->isComparisonOp())
    5347           1 :                         foundComparison = true;
    5348          20 :                     prev = prev->previous();
    5349             :                 }
    5350          18 :                 if (prev == type.top() && foundComparison)
    5351           1 :                     continue;
    5352          17 :                 const Token *next = token->next();
    5353          17 :                 foundComparison = false;
    5354          42 :                 while (Token::Match(next, "%name%|%num%|%str%|%cop%|(|[") && next->str() != ">") {
    5355          26 :                     if (next->str() == "(" || next->str() == "[")
    5356           1 :                         next = next->link();
    5357          25 :                     else if (next->tokType() == Token::eLogicalOp)
    5358           1 :                         break;
    5359          24 :                     else if (next->isComparisonOp())
    5360           4 :                         foundComparison = true;
    5361          25 :                     next = next->next();
    5362             :                 }
    5363          17 :                 if (next && next->str() == ">" && foundComparison)
    5364           1 :                     continue;
    5365             :             }
    5366             : 
    5367       70545 :             while (!type.empty() && type.top()->str() == "<") {
    5368          44 :                 const Token* end = type.top()->findClosingBracket();
    5369          44 :                 if (Token::Match(end, "> %comp%|;|.|=|{|(|::"))
    5370           6 :                     break;
    5371             :                 // Variable declaration
    5372          38 :                 if (Token::Match(end, "> %var% ;") && (type.top()->tokAt(-2) == nullptr || Token::Match(type.top()->tokAt(-2), ";|}|{")))
    5373           1 :                     break;
    5374          37 :                 type.pop();
    5375             :             }
    5376      445970 :         } else if (token->str() == "<" &&
    5377       10864 :                    ((token->previous() && (token->previous()->isTemplate() ||
    5378        6291 :                                            (token->previous()->isName() && !token->previous()->varId()) ||
    5379        1744 :                                            (token->strAt(-1) == "]" && (!Token::Match(token->linkAt(-1)->previous(), "%name%|)") || token->linkAt(-1)->previous()->isKeyword())) ||
    5380         930 :                                            (token->strAt(-1) == ")" && token->linkAt(-1)->strAt(-1) == "operator"))) ||
    5381         858 :                     Token::Match(token->next(), ">|>>"))) {
    5382        4573 :             type.push(token);
    5383        4573 :             if (token->previous()->str() == "template")
    5384         754 :                 templateTokens.push(token);
    5385      430531 :         } else if (token->str() == ">" || token->str() == ">>") {
    5386        5183 :             if (type.empty() || type.top()->str() != "<") // < and > don't match.
    5387         682 :                 continue;
    5388        4506 :             Token * const top1 = type.top();
    5389        4506 :             type.pop();
    5390        4506 :             Token * const top2 = type.empty() ? nullptr : type.top();
    5391        4506 :             type.push(top1);
    5392        4506 :             if (!top2 || top2->str() != "<") {
    5393        4159 :                 if (token->str() == ">>")
    5394           2 :                     continue;
    5395        4159 :                 if (!Token::Match(token->next(), "%name%|%cop%|%assign%|::|,|(|)|{|}|;|[|]|:|.|=|?|...") &&
    5396           2 :                     !Token::Match(token->next(), "&& %name% ="))
    5397           2 :                     continue;
    5398             :             }
    5399             : 
    5400        4502 :             if (token->str() == ">>" && top1 && top2) {
    5401           1 :                 type.pop();
    5402           1 :                 type.pop();
    5403             :                 // Split the angle brackets
    5404           1 :                 token->str(">");
    5405           1 :                 Token::createMutualLinks(top1, token->insertTokenBefore(">"));
    5406           1 :                 Token::createMutualLinks(top2, token);
    5407           1 :                 if (templateTokens.size() == 2 && (top1 == templateTokens.top() || top2 == templateTokens.top())) {
    5408           0 :                     templateTokens.pop();
    5409           0 :                     templateTokens.pop();
    5410             :                 }
    5411             :             } else {
    5412        4501 :                 type.pop();
    5413        6794 :                 if (Token::Match(token, "> %name%") && !token->next()->isKeyword() &&
    5414        6795 :                     Token::Match(top1->tokAt(-2), "%op% %name% <") && top1->strAt(-2) != "<" &&
    5415           1 :                     (templateTokens.empty() || top1 != templateTokens.top()))
    5416           1 :                     continue;
    5417        4500 :                 Token::createMutualLinks(top1, token);
    5418        4500 :                 if (!templateTokens.empty() && top1 == templateTokens.top())
    5419         754 :                     templateTokens.pop();
    5420             :             }
    5421             :         }
    5422             :     }
    5423             : }
    5424             : 
    5425       22628 : void Tokenizer::markCppCasts()
    5426             : {
    5427       22628 :     if (isC())
    5428        5917 :         return;
    5429      745601 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    5430      728893 :         if (Token::Match(tok, "const_cast|dynamic_cast|reinterpret_cast|static_cast")) {
    5431         197 :             if (!Token::simpleMatch(tok->next(), "<") || !Token::simpleMatch(tok->linkAt(1), "> ("))
    5432           2 :                 syntaxError(tok);
    5433         195 :             tok = tok->linkAt(1)->next();
    5434         195 :             tok->isCast(true);
    5435             :         }
    5436             :     }
    5437             : 
    5438             : }
    5439             : 
    5440       22687 : void Tokenizer::sizeofAddParentheses()
    5441             : {
    5442     1007944 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    5443      985261 :         if (!Token::Match(tok, "sizeof !!("))
    5444      985215 :             continue;
    5445          42 :         if (tok->next()->isLiteral() || Token::Match(tok->next(), "%name%|*|~|!|&")) {
    5446          37 :             Token *endToken = tok->next();
    5447          37 :             while (Token::simpleMatch(endToken, "* *"))
    5448           0 :                 endToken = endToken->next();
    5449          65 :             while (Token::Match(endToken->next(), "%name%|%num%|%str%|[|(|.|::|++|--|!|~") || (Token::Match(endToken, "%type% * %op%|?|:|const|;|,"))) {
    5450          28 :                 if (Token::Match(endToken->next(), "(|["))
    5451           4 :                     endToken = endToken->linkAt(1);
    5452             :                 else
    5453          24 :                     endToken = endToken->next();
    5454             :             }
    5455             : 
    5456             :             // Add ( after sizeof and ) behind endToken
    5457          37 :             tok->insertToken("(");
    5458          37 :             endToken->insertToken(")");
    5459          37 :             Token::createMutualLinks(tok->next(), endToken->next());
    5460             :         }
    5461             :     }
    5462       22685 : }
    5463             : 
    5464       23291 : bool Tokenizer::simplifyTokenList1(const char FileName[])
    5465             : {
    5466       23291 :     if (Settings::terminated())
    5467           0 :         return false;
    5468             : 
    5469             :     // if MACRO
    5470     1020485 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    5471      997200 :         if (Token::Match(tok, "if|for|while|BOOST_FOREACH %name% (")) {
    5472           9 :             if (Token::simpleMatch(tok, "for each")) {
    5473             :                 // 'for each ( )' -> 'asm ( )'
    5474           2 :                 tok->str("asm");
    5475           2 :                 tok->deleteNext();
    5476           7 :             } else if (tok->strAt(1) == "constexpr") {
    5477           5 :                 tok->deleteNext();
    5478           5 :                 tok->isConstexpr(true);
    5479             :             } else {
    5480           2 :                 syntaxError(tok);
    5481             :             }
    5482             :         }
    5483             :     }
    5484             : 
    5485             :     // Is there C++ code in C file?
    5486       23289 :     validateC();
    5487             : 
    5488             :     // Combine strings and character literals, e.g. L"string", L'c', "string1" "string2"
    5489       23254 :     combineStringAndCharLiterals();
    5490             : 
    5491             :     // replace inline SQL with "asm()" (Oracle PRO*C). Ticket: #1959
    5492       23253 :     simplifySQL();
    5493             : 
    5494       23248 :     createLinks();
    5495             : 
    5496             :     // Simplify debug intrinsics
    5497       23228 :     simplifyDebug();
    5498             : 
    5499       23228 :     removePragma();
    5500             : 
    5501             :     // Simplify the C alternative tokens (and, or, etc.)
    5502       23225 :     simplifyCAlternativeTokens();
    5503             : 
    5504       23225 :     simplifyFunctionTryCatch();
    5505             : 
    5506       23228 :     simplifyHeadersAndUnusedTemplates();
    5507             : 
    5508             :     // Remove __asm..
    5509       23229 :     simplifyAsm();
    5510             : 
    5511             :     // foo < bar < >> => foo < bar < > >
    5512       23227 :     if (isCPP() || mSettings.daca)
    5513       17084 :         splitTemplateRightAngleBrackets(!isCPP());
    5514             : 
    5515             :     // Remove extra "template" tokens that are not used by cppcheck
    5516       23225 :     removeExtraTemplateKeywords();
    5517             : 
    5518       23223 :     simplifySpaceshipOperator();
    5519             : 
    5520             :     // @..
    5521       23226 :     simplifyAt();
    5522             : 
    5523             :     // Remove __declspec()
    5524       23224 :     simplifyDeclspec();
    5525             : 
    5526             :     // Remove "inline", "register", and "restrict"
    5527       23228 :     simplifyKeyword();
    5528             : 
    5529             :     // Remove [[attribute]]
    5530       23226 :     simplifyCPPAttribute();
    5531             : 
    5532             :     // remove __attribute__((?))
    5533       23223 :     simplifyAttribute();
    5534             : 
    5535             :     // Bail out if code is garbage
    5536       23218 :     if (mTimerResults) {
    5537        1980 :         Timer t("Tokenizer::simplifyTokens1::simplifyTokenList1::findGarbageCode", mSettings.showtime, mTimerResults);
    5538         660 :         findGarbageCode();
    5539             :     } else {
    5540       22558 :         findGarbageCode();
    5541             :     }
    5542             : 
    5543       22703 :     checkConfiguration();
    5544             : 
    5545             :     // if (x) MACRO() ..
    5546      961816 :     for (const Token *tok = list.front(); tok; tok = tok->next()) {
    5547      939124 :         if (Token::simpleMatch(tok, "if (")) {
    5548        8656 :             tok = tok->next()->link();
    5549        8656 :             if (Token::Match(tok, ") %name% (") &&
    5550        8660 :                 tok->next()->isUpperCaseName() &&
    5551           4 :                 Token::Match(tok->linkAt(2), ") {|else")) {
    5552           4 :                 syntaxError(tok->next());
    5553             :             }
    5554             :         }
    5555             :     }
    5556             : 
    5557       22698 :     if (Settings::terminated())
    5558           0 :         return false;
    5559             : 
    5560             :     // convert C++17 style nested namespaces to old style namespaces
    5561       22701 :     simplifyNestedNamespace();
    5562             : 
    5563             :     // convert c++20 coroutines
    5564       22702 :     simplifyCoroutines();
    5565             : 
    5566             :     // simplify namespace aliases
    5567       22703 :     simplifyNamespaceAliases();
    5568             : 
    5569             :     // simplify cppcheck attributes __cppcheck_?__(?)
    5570       22702 :     simplifyCppcheckAttribute();
    5571             : 
    5572             :     // Combine tokens..
    5573       22700 :     combineOperators();
    5574             : 
    5575             :     // combine "- %num%"
    5576       22699 :     concatenateNegativeNumberAndAnyPositive();
    5577             : 
    5578             :     // remove extern "C" and extern "C" {}
    5579       22701 :     if (isCPP())
    5580       16765 :         simplifyExternC();
    5581             : 
    5582             :     // simplify weird but legal code: "[;{}] ( { code; } ) ;"->"[;{}] code;"
    5583       22702 :     simplifyRoundCurlyParentheses();
    5584             : 
    5585             :     // check for simple syntax errors..
    5586     1003857 :     for (const Token *tok = list.front(); tok; tok = tok->next()) {
    5587      981166 :         if (Token::simpleMatch(tok, "> struct {") &&
    5588           2 :             Token::simpleMatch(tok->linkAt(2), "} ;")) {
    5589           2 :             syntaxError(tok);
    5590             :         }
    5591             :     }
    5592             : 
    5593       22697 :     if (!simplifyAddBraces())
    5594           0 :         return false;
    5595             : 
    5596       22687 :     sizeofAddParentheses();
    5597             : 
    5598             :     // Simplify: 0[foo] -> *(foo)
    5599     1007914 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    5600      985238 :         if (Token::simpleMatch(tok, "0 [") && tok->linkAt(1)) {
    5601           1 :             tok->str("*");
    5602           1 :             tok->next()->str("(");
    5603           1 :             tok->linkAt(1)->str(")");
    5604             :         }
    5605             :     }
    5606             : 
    5607       22684 :     if (Settings::terminated())
    5608           0 :         return false;
    5609             : 
    5610       22684 :     validate();
    5611             : 
    5612             :     // simplify simple calculations inside <..>
    5613       22686 :     if (isCPP()) {
    5614       16754 :         Token *lt = nullptr;
    5615      741799 :         for (Token *tok = list.front(); tok; tok = tok->next()) {
    5616      725042 :             if (Token::Match(tok, "[;{}]"))
    5617      129899 :                 lt = nullptr;
    5618      595136 :             else if (Token::Match(tok, "%type% <"))
    5619        6807 :                 lt = tok->next();
    5620      588340 :             else if (lt && Token::Match(tok, ">|>> %name%|::|(")) {
    5621        4408 :                 const Token * const end = tok;
    5622       17272 :                 for (tok = lt; tok != end; tok = tok->next()) {
    5623       12864 :                     if (tok->isNumber())
    5624         310 :                         TemplateSimplifier::simplifyNumericCalculations(tok);
    5625             :                 }
    5626        4408 :                 lt = tok->next();
    5627             :             }
    5628             :         }
    5629             :     }
    5630             : 
    5631             :     // Convert K&R function declarations to modern C
    5632       22683 :     simplifyVarDecl(true);
    5633       22683 :     simplifyFunctionParameters();
    5634             : 
    5635             :     // simplify case ranges (gcc extension)
    5636       22678 :     simplifyCaseRange();
    5637             : 
    5638             :     // simplify labels and 'case|default'-like syntaxes
    5639       22682 :     simplifyLabelsCaseDefault();
    5640             : 
    5641       39424 :     if (!isC() && !mSettings.library.markupFile(FileName)) {
    5642       16749 :         findComplicatedSyntaxErrorsInTemplates();
    5643             :     }
    5644             : 
    5645       22672 :     if (Settings::terminated())
    5646           0 :         return false;
    5647             : 
    5648             :     // remove calling conventions __cdecl, __stdcall..
    5649       22672 :     simplifyCallingConvention();
    5650             : 
    5651       22674 :     addSemicolonAfterUnknownMacro();
    5652             : 
    5653             :     // remove some unhandled macros in global scope
    5654       22670 :     removeMacrosInGlobalScope();
    5655             : 
    5656             :     // remove undefined macro in class definition:
    5657             :     // class DLLEXPORT Fred { };
    5658             :     // class Fred FINAL : Base { };
    5659       22666 :     removeMacroInClassDef();
    5660             : 
    5661             :     // That call here fixes #7190
    5662       22667 :     validate();
    5663             : 
    5664             :     // remove unnecessary member qualification..
    5665       22667 :     removeUnnecessaryQualification();
    5666             : 
    5667             :     // convert Microsoft memory functions
    5668       22667 :     simplifyMicrosoftMemoryFunctions();
    5669             : 
    5670             :     // convert Microsoft string functions
    5671       22669 :     simplifyMicrosoftStringFunctions();
    5672             : 
    5673       22668 :     if (Settings::terminated())
    5674           0 :         return false;
    5675             : 
    5676             :     // remove Borland stuff..
    5677       22668 :     simplifyBorland();
    5678             : 
    5679             :     // syntax error: enum with typedef in it
    5680       22668 :     checkForEnumsWithTypedef();
    5681             : 
    5682             :     // Add parentheses to ternary operator where necessary
    5683       22667 :     prepareTernaryOpForAST();
    5684             : 
    5685             :     // Change initialisation of variable to assignment
    5686       22664 :     simplifyInitVar();
    5687             : 
    5688             :     // Split up variable declarations.
    5689       22665 :     simplifyVarDecl(false);
    5690             : 
    5691       22665 :     reportUnknownMacros();
    5692             : 
    5693       22651 :     simplifyTypedefLHS();
    5694             : 
    5695             :     // typedef..
    5696       22649 :     if (mTimerResults) {
    5697        1979 :         Timer t("Tokenizer::simplifyTokens1::simplifyTokenList1::simplifyTypedef", mSettings.showtime, mTimerResults);
    5698         660 :         simplifyTypedef();
    5699             :     } else {
    5700       21990 :         simplifyTypedef();
    5701             :     }
    5702             : 
    5703             :     // using A = B;
    5704       22712 :     while (simplifyUsing())
    5705             :         ;
    5706             : 
    5707             :     // Add parentheses to ternary operator where necessary
    5708             :     // TODO: this is only necessary if one typedef simplification had a comma and was used within ?:
    5709             :     // If typedef handling is refactored and moved to symboldatabase someday we can remove this
    5710       22640 :     prepareTernaryOpForAST();
    5711             : 
    5712             :     // class x y {
    5713       22640 :     if (isCPP() && mSettings.severity.isEnabled(Severity::information)) {
    5714      164146 :         for (const Token *tok = list.front(); tok; tok = tok->next()) {
    5715      163706 :             if (Token::Match(tok, "class %type% %type% [:{]")) {
    5716           1 :                 unhandled_macro_class_x_y(tok);
    5717             :             }
    5718             :         }
    5719             :     }
    5720             : 
    5721             :     // catch bad typedef canonicalization
    5722             :     //
    5723             :     // to reproduce bad typedef, download upx-ucl from:
    5724             :     // http://packages.debian.org/sid/upx-ucl
    5725             :     // analyse the file src/stub/src/i386-linux.elf.interp-main.c
    5726       22641 :     validate();
    5727             : 
    5728             :     // The simplify enum have inner loops
    5729       22642 :     if (Settings::terminated())
    5730           0 :         return false;
    5731             : 
    5732             :     // Put ^{} statements in asm()
    5733       22642 :     simplifyAsm2();
    5734             : 
    5735             :     // When the assembly code has been cleaned up, no @ is allowed
    5736      629870 :     for (const Token *tok = list.front(); tok; tok = tok->next()) {
    5737      607226 :         if (tok->str() == "(") {
    5738       87504 :             const Token *tok1 = tok;
    5739       87504 :             tok = tok->link();
    5740       87504 :             if (!tok)
    5741           0 :                 syntaxError(tok1);
    5742      519734 :         } else if (tok->str() == "@") {
    5743           0 :             syntaxError(tok);
    5744             :         }
    5745             :     }
    5746             : 
    5747             :     // Order keywords "static" and "const"
    5748       22640 :     simplifyStaticConst();
    5749             : 
    5750             :     // convert platform dependent types to standard types
    5751             :     // 32 bits: size_t -> unsigned long
    5752             :     // 64 bits: size_t -> unsigned long long
    5753       22637 :     list.simplifyPlatformTypes();
    5754             : 
    5755             :     // collapse compound standard types into a single token
    5756             :     // unsigned long long int => long (with _isUnsigned=true,_isLong=true)
    5757       22634 :     list.simplifyStdType();
    5758             : 
    5759       22642 :     if (Settings::terminated())
    5760           0 :         return false;
    5761             : 
    5762             :     // simplify bit fields..
    5763       22642 :     simplifyBitfields();
    5764             : 
    5765       22638 :     if (Settings::terminated())
    5766           0 :         return false;
    5767             : 
    5768             :     // struct simplification "struct S {} s; => struct S { } ; S s ;
    5769       22638 :     simplifyStructDecl();
    5770             : 
    5771       22642 :     if (Settings::terminated())
    5772           0 :         return false;
    5773             : 
    5774             :     // x = ({ 123; });  =>   { x = 123; }
    5775       22642 :     simplifyAssignmentBlock();
    5776             : 
    5777       22638 :     if (Settings::terminated())
    5778           0 :         return false;
    5779             : 
    5780       22638 :     simplifyVariableMultipleAssign();
    5781             : 
    5782             :     // Collapse operator name tokens into single token
    5783             :     // operator = => operator=
    5784       22641 :     simplifyOperatorName();
    5785             : 
    5786             :     // Remove redundant parentheses
    5787       22641 :     simplifyRedundantParentheses();
    5788             : 
    5789       22636 :     if (isCPP()) {
    5790       16713 :         simplifyTypeIntrinsics();
    5791             : 
    5792             :         // Handle templates..
    5793       16715 :         if (mTimerResults) {
    5794        1979 :             Timer t("Tokenizer::simplifyTokens1::simplifyTokenList1::simplifyTemplates", mSettings.showtime, mTimerResults);
    5795         660 :             simplifyTemplates();
    5796             :         } else {
    5797       16055 :             simplifyTemplates();
    5798             :         }
    5799             : 
    5800             :         // The simplifyTemplates have inner loops
    5801       16716 :         if (Settings::terminated())
    5802           0 :             return false;
    5803             : 
    5804       16716 :         validate(); // #6847 - invalid code
    5805             :     }
    5806             : 
    5807             :     // Simplify pointer to standard types (C only)
    5808       22640 :     simplifyPointerToStandardType();
    5809             : 
    5810             :     // simplify function pointers
    5811       22640 :     simplifyFunctionPointers();
    5812             : 
    5813             :     // Change initialisation of variable to assignment
    5814       22638 :     simplifyInitVar();
    5815             : 
    5816             :     // Split up variable declarations.
    5817       22637 :     simplifyVarDecl(false);
    5818             : 
    5819       22638 :     elseif();
    5820             : 
    5821       22638 :     validate(); // #6772 "segmentation fault (invalid code) in Tokenizer::setVarId"
    5822             : 
    5823       22636 :     if (mTimerResults) {
    5824        1978 :         Timer t("Tokenizer::simplifyTokens1::simplifyTokenList1::setVarId", mSettings.showtime, mTimerResults);
    5825         660 :         setVarId();
    5826             :     } else {
    5827       21976 :         setVarId();
    5828             :     }
    5829             : 
    5830             :     // Link < with >
    5831       22627 :     createLinks2();
    5832             : 
    5833             :     // Mark C++ casts
    5834       22628 :     markCppCasts();
    5835             : 
    5836             :     // specify array size
    5837       22627 :     arraySize();
    5838             : 
    5839             :     // The simplify enum might have inner loops
    5840       22622 :     if (Settings::terminated())
    5841           0 :         return false;
    5842             : 
    5843             :     // Add std:: in front of std classes, when using namespace std; was given
    5844       22624 :     simplifyNamespaceStd();
    5845             : 
    5846             :     // Change initialisation of variable to assignment
    5847       22626 :     simplifyInitVar();
    5848             : 
    5849       22626 :     simplifyDoublePlusAndDoubleMinus();
    5850             : 
    5851       22624 :     simplifyArrayAccessSyntax();
    5852             : 
    5853       22625 :     Token::assignProgressValues(list.front());
    5854             : 
    5855       22624 :     removeRedundantSemicolons();
    5856             : 
    5857       22626 :     simplifyParameterVoid();
    5858             : 
    5859       22627 :     simplifyRedundantConsecutiveBraces();
    5860             : 
    5861       22627 :     simplifyEmptyNamespaces();
    5862             : 
    5863       22627 :     simplifyIfSwitchForInit();
    5864             : 
    5865       22628 :     simplifyOverloadedOperators();
    5866             : 
    5867       22622 :     validate();
    5868             : 
    5869       22627 :     list.front()->assignIndexes();
    5870             : 
    5871       22626 :     return true;
    5872             : }
    5873             : //---------------------------------------------------------------------------
    5874             : 
    5875       23249 : void Tokenizer::printDebugOutput(int simplification) const
    5876             : {
    5877       46497 :     const bool debug = (simplification != 1U && mSettings.debugSimplified) ||
    5878       23248 :                        (simplification != 2U && mSettings.debugnormal);
    5879             : 
    5880       23249 :     if (debug && list.front()) {
    5881           0 :         list.front()->printOut(nullptr, list.getFiles());
    5882             : 
    5883           0 :         if (mSettings.xml)
    5884           0 :             std::cout << "<debug>" << std::endl;
    5885             : 
    5886           0 :         if (mSymbolDatabase) {
    5887           0 :             if (mSettings.xml)
    5888           0 :                 mSymbolDatabase->printXml(std::cout);
    5889           0 :             else if (mSettings.verbose) {
    5890           0 :                 mSymbolDatabase->printOut("Symbol database");
    5891             :             }
    5892             :         }
    5893             : 
    5894           0 :         if (mSettings.verbose)
    5895           0 :             list.front()->printAst(mSettings.verbose, mSettings.xml, list.getFiles(), std::cout);
    5896             : 
    5897           0 :         list.front()->printValueFlow(mSettings.xml, std::cout);
    5898             : 
    5899           0 :         if (mSettings.xml)
    5900           0 :             std::cout << "</debug>" << std::endl;
    5901             :     }
    5902             : 
    5903       23249 :     if (mSymbolDatabase && simplification == 2U && mSettings.debugwarnings) {
    5904           0 :         printUnknownTypes();
    5905             : 
    5906             :         // the typeStartToken() should come before typeEndToken()
    5907           0 :         for (const Variable *var : mSymbolDatabase->variableList()) {
    5908           0 :             if (!var)
    5909           0 :                 continue;
    5910             : 
    5911           0 :             const Token * typetok = var->typeStartToken();
    5912           0 :             while (typetok && typetok != var->typeEndToken())
    5913           0 :                 typetok = typetok->next();
    5914             : 
    5915           0 :             if (typetok != var->typeEndToken()) {
    5916           0 :                 reportError(var->typeStartToken(),
    5917             :                             Severity::debug,
    5918             :                             "debug",
    5919           0 :                             "Variable::typeStartToken() of variable '" + var->name() + "' is not located before Variable::typeEndToken(). The location of the typeStartToken() is '" + var->typeStartToken()->str() + "' at line " + std::to_string(var->typeStartToken()->linenr()));
    5920             :             }
    5921             :         }
    5922             :     }
    5923       23249 : }
    5924             : 
    5925           4 : void Tokenizer::dump(std::ostream &out) const
    5926             : {
    5927             :     // Create a xml data dump.
    5928             :     // The idea is not that this will be readable for humans. It's a
    5929             :     // data dump that 3rd party tools could load and get useful info from.
    5930             : 
    5931           8 :     std::string outs;
    5932             : 
    5933           8 :     std::set<const Library::Container*> containers;
    5934             : 
    5935           4 :     outs += "  <directivelist>";
    5936           4 :     outs += '\n';
    5937          28 :     for (const Directive &dir : mDirectives) {
    5938          24 :         outs += "    <directive ";
    5939          24 :         outs += "file=\"";
    5940          24 :         outs += ErrorLogger::toxml(Path::getRelativePath(dir.file, mSettings.basePaths));
    5941          24 :         outs += "\" ";
    5942          24 :         outs += "linenr=\"";
    5943          24 :         outs += std::to_string(dir.linenr);
    5944          24 :         outs += "\" ";
    5945             :         // str might contain characters such as '"', '<' or '>' which
    5946             :         // could result in invalid XML, so run it through toxml().
    5947          24 :         outs += "str=\"";
    5948          24 :         outs += ErrorLogger::toxml(dir.str);
    5949          24 :         outs +="\"/>";
    5950          24 :         outs += '\n';
    5951             :     }
    5952           4 :     outs += "  </directivelist>";
    5953           4 :     outs += '\n';
    5954             : 
    5955             :     // tokens..
    5956           4 :     outs += "  <tokenlist>";
    5957           4 :     outs += '\n';
    5958           4 :     for (const Token *tok = list.front(); tok; tok = tok->next()) {
    5959           0 :         outs += "    <token id=\"";
    5960           0 :         outs += id_string(tok);
    5961           0 :         outs += "\" file=\"";
    5962           0 :         outs += ErrorLogger::toxml(list.file(tok));
    5963           0 :         outs += "\" linenr=\"";
    5964           0 :         outs += std::to_string(tok->linenr());
    5965           0 :         outs += "\" column=\"";
    5966           0 :         outs += std::to_string(tok->column());
    5967           0 :         outs += "\"";
    5968             : 
    5969           0 :         outs += " str=\"";
    5970           0 :         outs += ErrorLogger::toxml(tok->str());
    5971           0 :         outs += '\"';
    5972             : 
    5973           0 :         outs += " scope=\"";
    5974           0 :         outs += id_string(tok->scope());
    5975           0 :         outs += '\"';
    5976           0 :         if (tok->isName()) {
    5977           0 :             outs += " type=\"name\"";
    5978           0 :             if (tok->isUnsigned())
    5979           0 :                 outs += " isUnsigned=\"true\"";
    5980           0 :             else if (tok->isSigned())
    5981           0 :                 outs += " isSigned=\"true\"";
    5982           0 :         } else if (tok->isNumber()) {
    5983           0 :             outs += " type=\"number\"";
    5984           0 :             if (MathLib::isInt(tok->str()))
    5985           0 :                 outs += " isInt=\"true\"";
    5986           0 :             if (MathLib::isFloat(tok->str()))
    5987           0 :                 outs += " isFloat=\"true\"";
    5988           0 :         } else if (tok->tokType() == Token::eString) {
    5989           0 :             outs += " type=\"string\" strlen=\"";
    5990           0 :             outs += std::to_string(Token::getStrLength(tok));
    5991           0 :             outs += '\"';
    5992             :         }
    5993           0 :         else if (tok->tokType() == Token::eChar)
    5994           0 :             outs += " type=\"char\"";
    5995           0 :         else if (tok->isBoolean())
    5996           0 :             outs += " type=\"boolean\"";
    5997           0 :         else if (tok->isOp()) {
    5998           0 :             outs += " type=\"op\"";
    5999           0 :             if (tok->isArithmeticalOp())
    6000           0 :                 outs += " isArithmeticalOp=\"true\"";
    6001           0 :             else if (tok->isAssignmentOp())
    6002           0 :                 outs += " isAssignmentOp=\"true\"";
    6003           0 :             else if (tok->isComparisonOp())
    6004           0 :                 outs += " isComparisonOp=\"true\"";
    6005           0 :             else if (tok->tokType() == Token::eLogicalOp)
    6006           0 :                 outs += " isLogicalOp=\"true\"";
    6007             :         }
    6008           0 :         if (tok->isCast())
    6009           0 :             outs += " isCast=\"true\"";
    6010           0 :         if (tok->isExternC())
    6011           0 :             outs += " externLang=\"C\"";
    6012           0 :         if (tok->isExpandedMacro())
    6013           0 :             outs += " macroName=\"" + tok->getMacroName() + "\"";
    6014           0 :         if (tok->isTemplateArg())
    6015           0 :             outs += " isTemplateArg=\"true\"";
    6016           0 :         if (tok->isRemovedVoidParameter())
    6017           0 :             outs += " isRemovedVoidParameter=\"true\"";
    6018           0 :         if (tok->isSplittedVarDeclComma())
    6019           0 :             outs += " isSplittedVarDeclComma=\"true\"";
    6020           0 :         if (tok->isSplittedVarDeclEq())
    6021           0 :             outs += " isSplittedVarDeclEq=\"true\"";
    6022           0 :         if (tok->isImplicitInt())
    6023           0 :             outs += " isImplicitInt=\"true\"";
    6024           0 :         if (tok->isComplex())
    6025           0 :             outs += " isComplex=\"true\"";
    6026           0 :         if (tok->isRestrict())
    6027           0 :             outs += " isRestrict=\"true\"";
    6028           0 :         if (tok->isAtomic())
    6029           0 :             outs += " isAtomic=\"true\"";
    6030           0 :         if (tok->isAttributeExport())
    6031           0 :             outs += " isAttributeExport=\"true\"";
    6032           0 :         if (tok->isAttributeMaybeUnused())
    6033           0 :             outs += " isAttributeMaybeUnused=\"true\"";
    6034           0 :         if (tok->isAttributeUnused())
    6035           0 :             outs += " isAttributeUnused=\"true\"";
    6036           0 :         if (tok->link()) {
    6037           0 :             outs += " link=\"";
    6038           0 :             outs += id_string(tok->link());
    6039           0 :             outs += '\"';
    6040             :         }
    6041           0 :         if (tok->varId() > 0) {
    6042           0 :             outs += " varId=\"";
    6043           0 :             outs += std::to_string(tok->varId());
    6044           0 :             outs += '\"';
    6045             :         }
    6046           0 :         if (tok->exprId() > 0) {
    6047           0 :             outs += " exprId=\"";
    6048           0 :             outs += std::to_string(tok->exprId());
    6049           0 :             outs += '\"';
    6050             :         }
    6051           0 :         if (tok->variable()) {
    6052           0 :             outs += " variable=\"";
    6053           0 :             outs += id_string(tok->variable());
    6054           0 :             outs += '\"';
    6055             :         }
    6056           0 :         if (tok->function()) {
    6057           0 :             outs += " function=\"";
    6058           0 :             outs += id_string(tok->function());
    6059           0 :             outs += '\"';
    6060             :         }
    6061           0 :         if (!tok->values().empty()) {
    6062           0 :             outs += " values=\"";
    6063           0 :             outs += id_string(&tok->values());
    6064           0 :             outs += '\"';
    6065             :         }
    6066           0 :         if (tok->type()) {
    6067           0 :             outs += " type-scope=\"";
    6068           0 :             outs += id_string(tok->type()->classScope);
    6069           0 :             outs += '\"';
    6070             :         }
    6071           0 :         if (tok->astParent()) {
    6072           0 :             outs += " astParent=\"";
    6073           0 :             outs += id_string(tok->astParent());
    6074           0 :             outs += '\"';
    6075             :         }
    6076           0 :         if (tok->astOperand1()) {
    6077           0 :             outs += " astOperand1=\"";
    6078           0 :             outs += id_string(tok->astOperand1());
    6079           0 :             outs += '\"';
    6080             :         }
    6081           0 :         if (tok->astOperand2()) {
    6082           0 :             outs += " astOperand2=\"";
    6083           0 :             outs += id_string(tok->astOperand2());
    6084           0 :             outs += '\"';
    6085             :         }
    6086           0 :         if (!tok->originalName().empty()) {
    6087           0 :             outs += " originalName=\"";
    6088           0 :             outs += tok->originalName();
    6089           0 :             outs += '\"';
    6090             :         }
    6091           0 :         if (tok->valueType()) {
    6092           0 :             const std::string vt = tok->valueType()->dump();
    6093           0 :             if (!vt.empty()) {
    6094           0 :                 outs += ' ';
    6095           0 :                 outs += vt;
    6096             :             }
    6097           0 :             containers.insert(tok->valueType()->container);
    6098             :         }
    6099           0 :         if (!tok->varId() && tok->scope()->isExecutable() && Token::Match(tok, "%name% (")) {
    6100           0 :             if (mSettings.library.isnoreturn(tok))
    6101           0 :                 outs += " noreturn=\"true\"";
    6102             :         }
    6103             : 
    6104           0 :         outs += "/>";
    6105           0 :         outs += '\n';
    6106             :     }
    6107           4 :     outs += "  </tokenlist>";
    6108           4 :     outs += '\n';
    6109             : 
    6110           4 :     out << outs;
    6111           4 :     outs.clear();
    6112             : 
    6113           4 :     if (mSymbolDatabase)
    6114           0 :         mSymbolDatabase->printXml(out);
    6115             : 
    6116           4 :     containers.erase(nullptr);
    6117           4 :     if (!containers.empty()) {
    6118           0 :         outs += "  <containers>";
    6119           0 :         outs += '\n';
    6120           0 :         for (const Library::Container* c: containers) {
    6121           0 :             outs += "    <container id=\"";
    6122           0 :             outs += id_string(c);
    6123           0 :             outs += "\" array-like-index-op=\"";
    6124           0 :             outs += bool_to_string(c->arrayLike_indexOp);
    6125           0 :             outs += "\" ";
    6126           0 :             outs += "std-string-like=\"";
    6127           0 :             outs += bool_to_string(c->stdStringLike);
    6128           0 :             outs += "\"/>";
    6129           0 :             outs += '\n';
    6130             :         }
    6131           0 :         outs += "  </containers>";
    6132           0 :         outs += '\n';
    6133             :     }
    6134             : 
    6135           4 :     if (list.front())
    6136           0 :         list.front()->printValueFlow(true, out);
    6137             : 
    6138           4 :     if (!mTypedefInfo.empty()) {
    6139           0 :         outs += "  <typedef-info>";
    6140           0 :         outs += '\n';
    6141           0 :         for (const TypedefInfo &typedefInfo: mTypedefInfo) {
    6142           0 :             outs += "    <info";
    6143             : 
    6144           0 :             outs += " name=\"";
    6145           0 :             outs += typedefInfo.name;
    6146           0 :             outs += "\"";
    6147             : 
    6148           0 :             outs += " file=\"";
    6149           0 :             outs += ErrorLogger::toxml(typedefInfo.filename);
    6150           0 :             outs += "\"";
    6151             : 
    6152           0 :             outs += " line=\"";
    6153           0 :             outs += std::to_string(typedefInfo.lineNumber);
    6154           0 :             outs += "\"";
    6155             : 
    6156           0 :             outs += " column=\"";
    6157           0 :             outs += std::to_string(typedefInfo.column);
    6158           0 :             outs += "\"";
    6159             : 
    6160           0 :             outs += " used=\"";
    6161           0 :             outs += std::to_string(typedefInfo.used?1:0);
    6162           0 :             outs += "\"";
    6163             : 
    6164           0 :             outs += "/>";
    6165           0 :             outs += '\n';
    6166             :         }
    6167           0 :         outs += "  </typedef-info>";
    6168           0 :         outs += '\n';
    6169             :     }
    6170           4 :     outs += mTemplateSimplifier->dump();
    6171             : 
    6172           4 :     out << outs;
    6173           4 : }
    6174             : 
    6175       23229 : void Tokenizer::simplifyHeadersAndUnusedTemplates()
    6176             : {
    6177       23229 :     if (mSettings.checkHeaders && mSettings.checkUnusedTemplates)
    6178             :         // Full analysis. All information in the headers are kept.
    6179       23225 :         return;
    6180             : 
    6181           4 :     const bool checkHeaders = mSettings.checkHeaders;
    6182           4 :     const bool removeUnusedIncludedFunctions = !mSettings.checkHeaders;
    6183           4 :     const bool removeUnusedIncludedClasses   = !mSettings.checkHeaders;
    6184           4 :     const bool removeUnusedIncludedTemplates = !mSettings.checkUnusedTemplates || !mSettings.checkHeaders;
    6185           4 :     const bool removeUnusedTemplates = !mSettings.checkUnusedTemplates;
    6186             : 
    6187             :     // checkHeaders:
    6188             :     //
    6189             :     // If it is true then keep all code in the headers. It's possible
    6190             :     // to remove unused types/variables if false positives / false
    6191             :     // negatives can be avoided.
    6192             :     //
    6193             :     // If it is false, then we want to remove selected stuff from the
    6194             :     // headers but not *everything*. The intention here is to not damage
    6195             :     // the analysis of the source file. You should get all warnings in
    6196             :     // the source file. You should not get false positives.
    6197             : 
    6198             :     // functions and types to keep
    6199           8 :     std::set<std::string> keep;
    6200         135 :     for (const Token *tok = list.front(); tok; tok = tok->next()) {
    6201         131 :         if (tok->isCpp() && Token::simpleMatch(tok, "template <")) {
    6202           4 :             const Token *closingBracket = tok->next()->findClosingBracket();
    6203           4 :             if (Token::Match(closingBracket, "> class|struct %name% {"))
    6204           1 :                 tok = closingBracket->linkAt(3);
    6205             :         }
    6206             : 
    6207         131 :         if (!tok->isName() || tok->isKeyword())
    6208          87 :             continue;
    6209             : 
    6210          44 :         if (!checkHeaders && tok->fileIndex() != 0)
    6211          12 :             continue;
    6212             : 
    6213          32 :         if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->linkAt(1), ") {")) {
    6214           4 :             keep.insert(tok->str());
    6215           4 :             continue;
    6216             :         }
    6217             : 
    6218          28 :         if (Token::Match(tok, "%name% %name%|::|*|&|<")) {
    6219          10 :             keep.insert(tok->str());
    6220             :         }
    6221             :     }
    6222             : 
    6223          64 :     const std::set<std::string> functionStart{"static", "const", "unsigned", "signed", "void", "bool", "char", "short", "int", "long", "float", "*"};
    6224             : 
    6225          16 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6226          12 :         const bool isIncluded = (tok->fileIndex() != 0);
    6227             : 
    6228             :         // Remove executable code
    6229          12 :         if (isIncluded && !mSettings.checkHeaders && tok->str() == "{") {
    6230             :             // TODO: We probably need to keep the executable code if this function is called from the source file.
    6231           0 :             const Token *prev = tok->previous();
    6232           0 :             while (prev && prev->isName())
    6233           0 :                 prev = prev->previous();
    6234           0 :             if (Token::simpleMatch(prev, ")")) {
    6235             :                 // Replace all tokens from { to } with a ";".
    6236           0 :                 Token::eraseTokens(tok,tok->link()->next());
    6237           0 :                 tok->str(";");
    6238           0 :                 tok->link(nullptr);
    6239             :             }
    6240             :         }
    6241             : 
    6242          12 :         if (!tok->previous() || Token::Match(tok->previous(), "[;{}]")) {
    6243             :             // Remove unused function declarations
    6244           7 :             if (isIncluded && removeUnusedIncludedFunctions) {
    6245             :                 while (true) {
    6246           1 :                     Token *start = tok;
    6247           1 :                     while (start && functionStart.find(start->str()) != functionStart.end())
    6248           0 :                         start = start->next();
    6249           1 :                     if (Token::Match(start, "%name% (") && Token::Match(start->linkAt(1), ") const| ;") && keep.find(start->str()) == keep.end()) {
    6250           0 :                         Token::eraseTokens(tok, start->linkAt(1)->tokAt(2));
    6251           0 :                         tok->deleteThis();
    6252             :                     } else
    6253           1 :                         break;
    6254           0 :                 }
    6255             :             }
    6256             : 
    6257           7 :             if (isIncluded && removeUnusedIncludedClasses) {
    6258           1 :                 if (Token::Match(tok, "class|struct %name% [:{]") && keep.find(tok->strAt(1)) == keep.end()) {
    6259             :                     // Remove this class/struct
    6260           1 :                     const Token *endToken = tok->tokAt(2);
    6261           1 :                     if (endToken->str() == ":") {
    6262           0 :                         endToken = endToken->next();
    6263           0 :                         while (Token::Match(endToken, "%name%|,"))
    6264           0 :                             endToken = endToken->next();
    6265             :                     }
    6266           1 :                     if (endToken && endToken->str() == "{" && Token::simpleMatch(endToken->link(), "} ;")) {
    6267           1 :                         Token::eraseTokens(tok, endToken->link()->next());
    6268           1 :                         tok->deleteThis();
    6269             :                     }
    6270             :                 }
    6271             :             }
    6272             : 
    6273           7 :             if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) {
    6274           7 :                 if (Token::Match(tok, "template < %name%")) {
    6275           3 :                     const Token *closingBracket = tok->next()->findClosingBracket();
    6276           3 :                     if (Token::Match(closingBracket, "> class|struct %name% [;:{]") && keep.find(closingBracket->strAt(2)) == keep.end()) {
    6277           1 :                         const Token *endToken = closingBracket->tokAt(3);
    6278           1 :                         if (endToken->str() == ":") {
    6279           0 :                             endToken = endToken->next();
    6280           0 :                             while (Token::Match(endToken, "%name%|,"))
    6281           0 :                                 endToken = endToken->next();
    6282             :                         }
    6283           1 :                         if (endToken && endToken->str() == "{")
    6284           1 :                             endToken = endToken->link()->next();
    6285           1 :                         if (endToken && endToken->str() == ";") {
    6286           1 :                             Token::eraseTokens(tok, endToken);
    6287           1 :                             tok->deleteThis();
    6288             :                         }
    6289           2 :                     } else if (Token::Match(closingBracket, "> %type% %name% (") && Token::simpleMatch(closingBracket->linkAt(3), ") {") && keep.find(closingBracket->strAt(2)) == keep.end()) {
    6290           2 :                         const Token *endToken = closingBracket->linkAt(3)->linkAt(1)->next();
    6291           2 :                         Token::eraseTokens(tok, endToken);
    6292           2 :                         tok->deleteThis();
    6293             :                     }
    6294             :                 }
    6295             :             }
    6296             :         }
    6297             :     }
    6298             : }
    6299             : 
    6300       23225 : void Tokenizer::removeExtraTemplateKeywords()
    6301             : {
    6302       23225 :     if (isCPP()) {
    6303      747644 :         for (Token *tok = list.front(); tok; tok = tok->next()) {
    6304      730565 :             if (Token::Match(tok, "%name%|>|) .|:: template %name%")) {
    6305          10 :                 tok->next()->deleteNext();
    6306          10 :                 Token* templateName = tok->tokAt(2);
    6307          20 :                 while (Token::Match(templateName, "%name%|::")) {
    6308          10 :                     templateName->isTemplate(true);
    6309          10 :                     templateName = templateName->next();
    6310             :                 }
    6311          10 :                 if (!templateName)
    6312           0 :                     syntaxError(tok);
    6313          10 :                 if (Token::Match(templateName->previous(), "operator %op%|(")) {
    6314           2 :                     templateName->isTemplate(true);
    6315           2 :                     if (templateName->str() == "(" && templateName->link())
    6316           1 :                         templateName->link()->isTemplate(true);
    6317             :                 }
    6318             :             }
    6319             :         }
    6320             :     }
    6321       23223 : }
    6322             : 
    6323           0 : static std::string getExpression(const Token *tok)
    6324             : {
    6325           0 :     std::string line;
    6326           0 :     for (const Token *prev = tok->previous(); prev && !Token::Match(prev, "[;{}]"); prev = prev->previous())
    6327           0 :         line = prev->str() + " " + line;
    6328           0 :     line += "!!!" + tok->str() + "!!!";
    6329           0 :     for (const Token *next = tok->next(); next && !Token::Match(next, "[;{}]"); next = next->next())
    6330           0 :         line += " " + next->str();
    6331           0 :     return line;
    6332             : }
    6333             : 
    6334       17170 : void Tokenizer::splitTemplateRightAngleBrackets(bool check)
    6335             : {
    6336       34342 :     std::vector<std::pair<std::string, int>> vars;
    6337             : 
    6338       17173 :     int scopeLevel = 0;
    6339      749425 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6340      732254 :         if (tok->str() == "{")
    6341       33458 :             ++scopeLevel;
    6342      698793 :         else if (tok->str() == "}") {
    6343           0 :             vars.erase(std::remove_if(vars.begin(), vars.end(), [scopeLevel](const std::pair<std::string, int>& v) {
    6344        9261 :                 return v.second == scopeLevel;
    6345       33459 :             }), vars.end());
    6346       33458 :             --scopeLevel;
    6347             :         }
    6348      732251 :         if (Token::Match(tok, "[;{}] %type% %type% [;,=]") && tok->next()->isStandardType())
    6349        7578 :             vars.emplace_back(tok->strAt(2), scopeLevel);
    6350             : 
    6351             :         // Ticket #6181: normalize C++11 template parameter list closing syntax
    6352      732244 :         if (tok->previous() && tok->str() == "<" && TemplateSimplifier::templateParameters(tok) && std::none_of(vars.begin(), vars.end(), [&](const std::pair<std::string, int>& v) {
    6353          99 :             return v.first == tok->previous()->str();
    6354             :         })) {
    6355        6065 :             Token *endTok = tok->findClosingBracket();
    6356        6065 :             if (check) {
    6357           0 :                 if (Token::Match(endTok, ">>|>>="))
    6358           0 :                     reportError(tok, Severity::debug, "dacaWrongSplitTemplateRightAngleBrackets", "bad closing bracket for !!!<!!!: " + getExpression(tok), false);
    6359           0 :                 continue;
    6360             :             }
    6361        6065 :             if (endTok && endTok->str() == ">>") {
    6362         276 :                 endTok->str(">");
    6363         276 :                 endTok->insertToken(">");
    6364        5789 :             } else if (endTok && endTok->str() == ">>=") {
    6365           1 :                 endTok->str(">");
    6366           1 :                 endTok->insertToken("=");
    6367           1 :                 endTok->insertToken(">");
    6368             :             }
    6369      726177 :         } else if (Token::Match(tok, "class|struct|union|=|:|public|protected|private %name% <") && std::none_of(vars.begin(), vars.end(), [&](const std::pair<std::string, int>& v) {
    6370          60 :             return v.first == tok->next()->str();
    6371             :         })) {
    6372         498 :             Token *endTok = tok->tokAt(2)->findClosingBracket();
    6373         498 :             if (check) {
    6374           0 :                 if (Token::simpleMatch(endTok, ">>"))
    6375           0 :                     reportError(tok, Severity::debug, "dacaWrongSplitTemplateRightAngleBrackets", "bad closing bracket for !!!<!!!: " + getExpression(tok), false);
    6376           0 :                 continue;
    6377             :             }
    6378         498 :             if (Token::Match(endTok, ">> ;|{|%type%")) {
    6379          21 :                 endTok->str(">");
    6380          21 :                 endTok->insertToken(">");
    6381             :             }
    6382             :         }
    6383             :     }
    6384       17170 : }
    6385             : 
    6386       22670 : void Tokenizer::removeMacrosInGlobalScope()
    6387             : {
    6388      239929 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6389      217264 :         if (tok->str() == "(") {
    6390       33817 :             tok = tok->link();
    6391       33817 :             if (Token::Match(tok, ") %type% {") &&
    6392         323 :                 !tok->next()->isStandardType() &&
    6393         321 :                 !tok->next()->isKeyword() &&
    6394       34149 :                 !Token::Match(tok->next(), "override|final") &&
    6395           9 :                 tok->next()->isUpperCaseName())
    6396           9 :                 tok->deleteNext();
    6397             :         }
    6398             : 
    6399      236090 :         if (Token::Match(tok, "%type%") && tok->isUpperCaseName() &&
    6400       18826 :             (!tok->previous() || Token::Match(tok->previous(), "[;{}]") || (tok->previous()->isName() && endsWith(tok->previous()->str(), ':')))) {
    6401        2421 :             const Token *tok2 = tok->next();
    6402        2421 :             if (tok2 && tok2->str() == "(")
    6403         721 :                 tok2 = tok2->link()->next();
    6404             : 
    6405             :             // Several unknown macros...
    6406        2424 :             while (Token::Match(tok2, "%type% (") && tok2->isUpperCaseName())
    6407           3 :                 tok2 = tok2->linkAt(1)->next();
    6408             : 
    6409        2428 :             if (Token::Match(tok, "%name% (") && Token::Match(tok2, "%name% *|&|::|<| %name%") &&
    6410           7 :                 !Token::Match(tok2, "requires|namespace|class|struct|union|private:|protected:|public:"))
    6411           3 :                 unknownMacroError(tok);
    6412             : 
    6413        2420 :             if (Token::Match(tok, "%type% (") && Token::Match(tok2, "%type% (") && !Token::Match(tok2, "noexcept|throw") && isFunctionHead(tok2->next(), ":;{"))
    6414           2 :                 unknownMacroError(tok);
    6415             : 
    6416             :             // remove unknown macros before namespace|class|struct|union
    6417        2416 :             if (Token::Match(tok2, "namespace|class|struct|union")) {
    6418             :                 // is there a "{" for?
    6419           4 :                 const Token *tok3 = tok2;
    6420          12 :                 while (tok3 && !Token::Match(tok3,"[;{}()]"))
    6421           8 :                     tok3 = tok3->next();
    6422           4 :                 if (tok3 && tok3->str() == "{") {
    6423           2 :                     Token::eraseTokens(tok, tok2);
    6424           2 :                     tok->deleteThis();
    6425             :                 }
    6426           4 :                 continue;
    6427             :             }
    6428             : 
    6429             :             // replace unknown macros before foo(
    6430             :             /*
    6431             :                         if (Token::Match(tok2, "%type% (") && isFunctionHead(tok2->next(), "{")) {
    6432             :                             std::string typeName;
    6433             :                             for (const Token* tok3 = tok; tok3 != tok2; tok3 = tok3->next())
    6434             :                                 typeName += tok3->str();
    6435             :                             Token::eraseTokens(tok, tok2);
    6436             :                             tok->str(typeName);
    6437             :                         }
    6438             :              */
    6439             :             // remove unknown macros before foo::foo(
    6440        2412 :             if (Token::Match(tok2, "%type% :: %type%")) {
    6441           3 :                 const Token *tok3 = tok2;
    6442           3 :                 while (Token::Match(tok3, "%type% :: %type% ::"))
    6443           0 :                     tok3 = tok3->tokAt(2);
    6444           3 :                 if (Token::Match(tok3, "%type% :: %type% (") && tok3->str() == tok3->strAt(2)) {
    6445           0 :                     Token::eraseTokens(tok, tok2);
    6446           0 :                     tok->deleteThis();
    6447             :                 }
    6448           3 :                 continue;
    6449             :             }
    6450             :         }
    6451             : 
    6452             :         // Skip executable scopes
    6453      217253 :         if (tok->str() == "{") {
    6454       35417 :             const Token *prev = tok->previous();
    6455       47187 :             while (prev && prev->isName())
    6456       11770 :                 prev = prev->previous();
    6457       35417 :             if (prev && prev->str() == ")")
    6458       28887 :                 tok = tok->link();
    6459             :         }
    6460             :     }
    6461       22666 : }
    6462             : 
    6463             : //---------------------------------------------------------------------------
    6464             : 
    6465       23229 : void Tokenizer::removePragma()
    6466             : {
    6467       23229 :     if (isC() && mSettings.standards.c == Standards::C89)
    6468          50 :         return;
    6469       23177 :     if (isCPP() && mSettings.standards.cpp == Standards::CPP03)
    6470          60 :         return;
    6471     1015957 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6472      992846 :         while (Token::simpleMatch(tok, "_Pragma (")) {
    6473           2 :             Token::eraseTokens(tok, tok->linkAt(1)->next());
    6474           2 :             tok->deleteThis();
    6475             :         }
    6476             :     }
    6477             : }
    6478             : 
    6479             : //---------------------------------------------------------------------------
    6480             : 
    6481       22666 : void Tokenizer::removeMacroInClassDef()
    6482             : {
    6483     1008086 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6484      985419 :         if (!Token::Match(tok, "class|struct %name% %name% final| {|:"))
    6485      985408 :             continue;
    6486             : 
    6487          12 :         const bool nextIsUppercase = tok->next()->isUpperCaseName();
    6488          12 :         const bool afterNextIsUppercase = tok->tokAt(2)->isUpperCaseName();
    6489          12 :         if (nextIsUppercase && !afterNextIsUppercase)
    6490           6 :             tok->deleteNext();
    6491           6 :         else if (!nextIsUppercase && afterNextIsUppercase)
    6492           2 :             tok->next()->deleteNext();
    6493             :     }
    6494       22667 : }
    6495             : 
    6496             : //---------------------------------------------------------------------------
    6497             : 
    6498       22673 : void Tokenizer::addSemicolonAfterUnknownMacro()
    6499             : {
    6500       22673 :     if (!isCPP())
    6501        5928 :         return;
    6502      742121 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6503      725371 :         if (tok->str() != ")")
    6504      651063 :             continue;
    6505       74312 :         const Token *macro = tok->link() ? tok->link()->previous() : nullptr;
    6506       74311 :         if (!macro || !macro->isName())
    6507       12521 :             continue;
    6508       61790 :         if (Token::simpleMatch(tok, ") try") && !Token::Match(macro, "if|for|while"))
    6509           1 :             tok->insertToken(";");
    6510       61789 :         else if (Token::simpleMatch(tok, ") using"))
    6511           3 :             tok->insertToken(";");
    6512             :     }
    6513             : }
    6514             : //---------------------------------------------------------------------------
    6515             : 
    6516       22626 : void Tokenizer::simplifyEmptyNamespaces()
    6517             : {
    6518       22626 :     if (isC())
    6519        5917 :         return;
    6520             : 
    6521       16710 :     bool goback = false;
    6522      145842 :     for (Token *tok = list.front(); tok; tok = tok ? tok->next() : nullptr) {
    6523      129131 :         if (goback) {
    6524          24 :             tok = tok->previous();
    6525          24 :             goback = false;
    6526             :         }
    6527      129131 :         if (Token::Match(tok, "(|[|{")) {
    6528       44358 :             tok = tok->link();
    6529       44358 :             continue;
    6530             :         }
    6531       84772 :         if (!Token::Match(tok, "namespace %name%| {"))
    6532       84274 :             continue;
    6533         500 :         const bool isAnonymousNS = tok->strAt(1) == "{";
    6534         500 :         if (tok->strAt(3 - isAnonymousNS) == "}") {
    6535          40 :             tok->deleteNext(3 - isAnonymousNS); // remove '%name%| { }'
    6536          40 :             if (!tok->previous()) {
    6537             :                 // remove 'namespace' or replace it with ';' if isolated
    6538          19 :                 tok->deleteThis();
    6539          19 :                 goback = true;
    6540             :             } else {                    // '%any% namespace %any%'
    6541          21 :                 tok = tok->previous();  // goto previous token
    6542          21 :                 tok->deleteNext();      // remove next token: 'namespace'
    6543          21 :                 if (tok->str() == "{") {
    6544             :                     // Go back in case we were within a namespace that's empty now
    6545          13 :                     tok = tok->tokAt(-2) ? tok->tokAt(-2) : tok->previous();
    6546          13 :                     goback = true;
    6547             :                 }
    6548             :             }
    6549             :         } else {
    6550         460 :             tok = tok->tokAt(2 - isAnonymousNS);
    6551             :         }
    6552             :     }
    6553             : }
    6554             : 
    6555       22624 : void Tokenizer::removeRedundantSemicolons()
    6556             : {
    6557      628841 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6558      606211 :         if (tok->link() && tok->str() == "(") {
    6559       87749 :             tok = tok->link();
    6560       87749 :             continue;
    6561             :         }
    6562             :         for (;;) {
    6563      518524 :             if (Token::simpleMatch(tok, "; ;")) {
    6564          58 :                 tok->deleteNext();
    6565      518465 :             } else if (Token::simpleMatch(tok, "; { ; }")) {
    6566           1 :                 tok->deleteNext(3);
    6567             :             } else {
    6568      518468 :                 break;
    6569             :             }
    6570             :         }
    6571             :     }
    6572       22626 : }
    6573             : 
    6574             : 
    6575       22700 : bool Tokenizer::simplifyAddBraces()
    6576             : {
    6577     1008079 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6578      985391 :         Token const * tokRet=simplifyAddBracesToCommand(tok);
    6579      985379 :         if (!tokRet)
    6580           0 :             return false;
    6581             :     }
    6582       22687 :     return true;
    6583             : }
    6584             : 
    6585     2988668 : Token *Tokenizer::simplifyAddBracesToCommand(Token *tok)
    6586             : {
    6587     2988668 :     Token * tokEnd=tok;
    6588     2988668 :     if (Token::Match(tok,"for|switch|BOOST_FOREACH")) {
    6589        1196 :         tokEnd=simplifyAddBracesPair(tok,true);
    6590     2987479 :     } else if (tok->str()=="while") {
    6591         359 :         Token *tokPossibleDo=tok->previous();
    6592         359 :         if (Token::simpleMatch(tok->previous(), "{"))
    6593          71 :             tokPossibleDo = nullptr;
    6594         288 :         else if (Token::simpleMatch(tokPossibleDo,"}"))
    6595         106 :             tokPossibleDo = tokPossibleDo->link();
    6596         359 :         if (!tokPossibleDo || tokPossibleDo->strAt(-1) != "do")
    6597         273 :             tokEnd=simplifyAddBracesPair(tok,true);
    6598     2987119 :     } else if (tok->str()=="do") {
    6599          96 :         tokEnd=simplifyAddBracesPair(tok,false);
    6600          93 :         if (tokEnd!=tok) {
    6601             :             // walk on to next token, i.e. "while"
    6602             :             // such that simplifyAddBracesPair does not close other braces
    6603             :             // before the "while"
    6604          93 :             if (tokEnd) {
    6605          93 :                 tokEnd=tokEnd->next();
    6606          93 :                 if (!tokEnd || tokEnd->str()!="while") // no while
    6607           5 :                     syntaxError(tok);
    6608             :             }
    6609             :         }
    6610     2987022 :     } else if (tok->str()=="if" && !Token::simpleMatch(tok->tokAt(-2), "operator \"\"")) {
    6611     2009893 :         tokEnd=simplifyAddBracesPair(tok,true);
    6612     2009890 :         if (!tokEnd)
    6613           0 :             return nullptr;
    6614     2009890 :         if (tokEnd->strAt(1) == "else") {
    6615     2001558 :             Token * tokEndNextNext= tokEnd->tokAt(2);
    6616     2001558 :             if (!tokEndNextNext || tokEndNextNext->str() == "}")
    6617           0 :                 syntaxError(tokEndNextNext);
    6618     2001558 :             if (tokEndNextNext->str() == "if")
    6619             :                 // do not change "else if ..." to "else { if ... }"
    6620     2001125 :                 tokEnd=simplifyAddBracesToCommand(tokEndNextNext);
    6621             :             else
    6622         433 :                 tokEnd=simplifyAddBracesPair(tokEnd->next(),false);
    6623             :         }
    6624             :     }
    6625             : 
    6626     2988657 :     return tokEnd;
    6627             : }
    6628             : 
    6629     2011891 : Token *Tokenizer::simplifyAddBracesPair(Token *tok, bool commandWithCondition)
    6630             : {
    6631     2011891 :     Token * tokCondition=tok->next();
    6632     2011891 :     if (!tokCondition) // Missing condition
    6633           0 :         return tok;
    6634             : 
    6635     2011891 :     Token *tokAfterCondition=tokCondition;
    6636     2011891 :     if (commandWithCondition) {
    6637     2011362 :         if (tokCondition->str()=="(")
    6638     2011362 :             tokAfterCondition=tokCondition->link();
    6639             :         else
    6640           0 :             syntaxError(tok); // Bad condition
    6641             : 
    6642     2011362 :         if (!tokAfterCondition || tokAfterCondition->strAt(1) == "]")
    6643           0 :             syntaxError(tok); // Bad condition
    6644             : 
    6645     2011362 :         tokAfterCondition=tokAfterCondition->next();
    6646     2011362 :         if (!tokAfterCondition || Token::Match(tokAfterCondition, ")|}|,")) {
    6647             :             // No tokens left where to add braces around
    6648           7 :             return tok;
    6649             :         }
    6650             :     }
    6651             :     // Skip labels
    6652     2011884 :     Token * tokStatement = tokAfterCondition;
    6653             :     while (true) {
    6654     2011924 :         if (Token::Match(tokStatement, "%name% :"))
    6655          32 :             tokStatement = tokStatement->tokAt(2);
    6656     2011892 :         else if (tokStatement->str() == "case") {
    6657           8 :             tokStatement = skipCaseLabel(tokStatement);
    6658           8 :             if (!tokStatement)
    6659           0 :                 return tok;
    6660           8 :             if (tokStatement->str() != ":")
    6661           0 :                 syntaxError(tokStatement);
    6662           8 :             tokStatement = tokStatement->next();
    6663             :         } else
    6664     2011884 :             break;
    6665          40 :         if (!tokStatement)
    6666           0 :             return tok;
    6667             :     }
    6668     2011884 :     Token * tokBracesEnd=nullptr;
    6669     2011884 :     if (tokStatement->str() == "{") {
    6670             :         // already surrounded by braces
    6671     2009725 :         if (tokStatement != tokAfterCondition) {
    6672             :             // Move the opening brace before labels
    6673           6 :             Token::move(tokStatement, tokStatement, tokAfterCondition->previous());
    6674             :         }
    6675     2009725 :         tokBracesEnd = tokStatement->link();
    6676        2164 :     } else if (Token::simpleMatch(tokStatement, "try {") &&
    6677           5 :                Token::simpleMatch(tokStatement->linkAt(1), "} catch (")) {
    6678           5 :         tokAfterCondition->previous()->insertToken("{");
    6679           5 :         Token * tokOpenBrace = tokAfterCondition->previous();
    6680           5 :         Token * tokEnd = tokStatement->linkAt(1)->linkAt(2)->linkAt(1);
    6681           5 :         if (!tokEnd) {
    6682           0 :             syntaxError(tokStatement);
    6683             :         }
    6684           5 :         tokEnd->insertToken("}");
    6685           5 :         Token * tokCloseBrace = tokEnd->next();
    6686             : 
    6687           5 :         Token::createMutualLinks(tokOpenBrace, tokCloseBrace);
    6688           5 :         tokBracesEnd = tokCloseBrace;
    6689             :     } else {
    6690        2154 :         Token * tokEnd = simplifyAddBracesToCommand(tokStatement);
    6691        2154 :         if (!tokEnd) // Ticket #4887
    6692           0 :             return tok;
    6693        2154 :         if (tokEnd->str()!="}") {
    6694             :             // Token does not end with brace
    6695             :             // Look for ; to add own closing brace after it
    6696        7319 :             while (tokEnd && !Token::Match(tokEnd, ";|)|}")) {
    6697        5303 :                 if (tokEnd->tokType()==Token::eBracket || tokEnd->str() == "(") {
    6698         450 :                     tokEnd = tokEnd->link();
    6699         450 :                     if (!tokEnd) {
    6700             :                         // Inner bracket does not close
    6701           0 :                         return tok;
    6702             :                     }
    6703             :                 }
    6704        5303 :                 tokEnd=tokEnd->next();
    6705             :             }
    6706        2016 :             if (!tokEnd || tokEnd->str() != ";") {
    6707             :                 // No trailing ;
    6708           8 :                 if (tokStatement->isUpperCaseName())
    6709           3 :                     unknownMacroError(tokStatement);
    6710             :                 else
    6711           5 :                     syntaxError(tokStatement);
    6712             :             }
    6713             :         }
    6714             : 
    6715        2146 :         tokAfterCondition->previous()->insertToken("{");
    6716        2146 :         Token * tokOpenBrace=tokAfterCondition->previous();
    6717             : 
    6718        2146 :         tokEnd->insertToken("}");
    6719        2146 :         Token * tokCloseBrace=tokEnd->next();
    6720             : 
    6721        2146 :         Token::createMutualLinks(tokOpenBrace,tokCloseBrace);
    6722        2146 :         tokBracesEnd=tokCloseBrace;
    6723             :     }
    6724             : 
    6725     2011876 :     return tokBracesEnd;
    6726             : }
    6727             : 
    6728       22685 : void Tokenizer::simplifyFunctionParameters()
    6729             : {
    6730      183578 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6731      160903 :         if (tok->link() && Token::Match(tok, "{|[|(")) {
    6732       57783 :             tok = tok->link();
    6733             :         }
    6734             : 
    6735             :         // Find the function e.g. foo( x ) or foo( x, y )
    6736      106472 :         else if (Token::Match(tok, "%name% ( %name% [,)]") &&
    6737        3354 :                  !(tok->strAt(-1) == ":" || tok->strAt(-1) == "," || tok->strAt(-1) == "::")) {
    6738             :             // We have found old style function, now we need to change it
    6739             : 
    6740             :             // First step: Get list of argument names in parentheses
    6741        3296 :             std::map<std::string, Token *> argumentNames;
    6742        3294 :             bool bailOut = false;
    6743        3294 :             Token * tokparam = nullptr;
    6744             : 
    6745             :             //take count of the function name..
    6746        3294 :             const std::string& funcName(tok->str());
    6747             : 
    6748             :             //floating token used to check for parameters
    6749        3294 :             Token *tok1 = tok;
    6750             : 
    6751        3406 :             while (nullptr != (tok1 = tok1->tokAt(2))) {
    6752        3406 :                 if (!Token::Match(tok1, "%name% [,)]")) {
    6753          39 :                     bailOut = true;
    6754          39 :                     break;
    6755             :                 }
    6756             : 
    6757             :                 //same parameters: take note of the parameter
    6758        3367 :                 if (argumentNames.find(tok1->str()) != argumentNames.end())
    6759          33 :                     tokparam = tok1;
    6760        3334 :                 else if (tok1->str() != funcName)
    6761        3327 :                     argumentNames[tok1->str()] = tok1;
    6762             :                 else {
    6763           7 :                     if (tok1->next()->str() == ")") {
    6764           4 :                         if (tok1->previous()->str() == ",") {
    6765           1 :                             tok1 = tok1->tokAt(-2);
    6766           1 :                             tok1->deleteNext(2);
    6767             :                         } else {
    6768           3 :                             tok1 = tok1->previous();
    6769           3 :                             tok1->deleteNext();
    6770           3 :                             bailOut = true;
    6771           3 :                             break;
    6772             :                         }
    6773             :                     } else {
    6774           3 :                         tok1 = tok1->tokAt(-2);
    6775           3 :                         tok1->next()->deleteNext(2);
    6776             :                     }
    6777             :                 }
    6778             : 
    6779        3364 :                 if (tok1->next()->str() == ")") {
    6780        3252 :                     tok1 = tok1->tokAt(2);
    6781             :                     //expect at least a type name after round brace..
    6782        3252 :                     if (!tok1 || !tok1->isName())
    6783        3219 :                         bailOut = true;
    6784        3252 :                     break;
    6785             :                 }
    6786             :             }
    6787             : 
    6788             :             //goto '('
    6789        3294 :             tok = tok->next();
    6790             : 
    6791        3294 :             if (bailOut) {
    6792        3261 :                 tok = tok->link();
    6793        3261 :                 continue;
    6794             :             }
    6795             : 
    6796          33 :             tok1 = tok->link()->next();
    6797             : 
    6798             :             // there should be the sequence '; {' after the round parentheses
    6799         322 :             for (const Token* tok2 = tok1; tok2; tok2 = tok2->next()) {
    6800         314 :                 if (Token::simpleMatch(tok2, "; {"))
    6801          16 :                     break;
    6802         298 :                 if (tok2->str() == "{") {
    6803           9 :                     bailOut = true;
    6804           9 :                     break;
    6805             :                 }
    6806             :             }
    6807             : 
    6808          33 :             if (bailOut) {
    6809           9 :                 tok = tok->link();
    6810           9 :                 continue;
    6811             :             }
    6812             : 
    6813             :             // Last step: check out if the declarations between ')' and '{' match the parameters list
    6814          26 :             std::map<std::string, Token *> argumentNames2;
    6815             : 
    6816         155 :             while (tok1 && tok1->str() != "{") {
    6817         141 :                 if (Token::Match(tok1, "(|)")) {
    6818           1 :                     bailOut = true;
    6819           1 :                     break;
    6820             :                 }
    6821         140 :                 if (tok1->str() == ";") {
    6822          34 :                     if (tokparam) {
    6823           1 :                         syntaxError(tokparam);
    6824             :                     }
    6825          33 :                     Token *tok2 = tok1->previous();
    6826          35 :                     while (tok2->str() == "]")
    6827           2 :                         tok2 = tok2->link()->previous();
    6828             : 
    6829             :                     //it should be a name..
    6830          33 :                     if (!tok2->isName()) {
    6831           1 :                         bailOut = true;
    6832           1 :                         break;
    6833             :                     }
    6834             : 
    6835          32 :                     if (argumentNames2.find(tok2->str()) != argumentNames2.end()) {
    6836             :                         //same parameter names...
    6837           1 :                         syntaxError(tok1);
    6838             :                     } else
    6839          31 :                         argumentNames2[tok2->str()] = tok2;
    6840             : 
    6841          31 :                     if (argumentNames.find(tok2->str()) == argumentNames.end()) {
    6842             :                         //non-matching parameter... bailout
    6843           6 :                         bailOut = true;
    6844           6 :                         break;
    6845             :                     }
    6846             :                 }
    6847         131 :                 tok1 = tok1->next();
    6848             :             }
    6849             : 
    6850          22 :             if (bailOut || !tok1) {
    6851           8 :                 tok = tok->link();
    6852           8 :                 continue;
    6853             :             }
    6854             : 
    6855             :             //the two containers may not hold the same size...
    6856             :             //in that case, the missing parameters are defined as 'int'
    6857          14 :             if (argumentNames.size() != argumentNames2.size()) {
    6858             :                 //move back 'tok1' to the last ';'
    6859           2 :                 tok1 = tok1->previous();
    6860          10 :                 for (const std::pair<const std::string, Token *>& argumentName : argumentNames) {
    6861           8 :                     if (argumentNames2.find(argumentName.first) == argumentNames2.end()) {
    6862             :                         //add the missing parameter argument declaration
    6863           5 :                         tok1->insertToken(";");
    6864           5 :                         tok1->insertToken(argumentName.first);
    6865             :                         //register the change inside argumentNames2
    6866           5 :                         argumentNames2[argumentName.first] = tok1->next();
    6867           5 :                         tok1->insertToken("int");
    6868             :                     }
    6869             :                 }
    6870             :             }
    6871             : 
    6872          43 :             while (tok->str() != ")") {
    6873             :                 //initialize start and end tokens to be moved
    6874          29 :                 Token *declStart = argumentNames2[tok->next()->str()];
    6875          29 :                 Token *declEnd = declStart;
    6876          71 :                 while (declStart->previous()->str() != ";" && declStart->previous()->str() != ")")
    6877          42 :                     declStart = declStart->previous();
    6878          31 :                 while (declEnd->next()->str() != ";" && declEnd->next()->str() != "{")
    6879           2 :                     declEnd = declEnd->next();
    6880             : 
    6881             :                 //remove ';' after declaration
    6882          29 :                 declEnd->deleteNext();
    6883             : 
    6884             :                 //replace the parameter name in the parentheses with all the declaration
    6885          29 :                 Token::replace(tok->next(), declStart, declEnd);
    6886             : 
    6887             :                 //since there are changes to tokens, put tok where tok1 is
    6888          29 :                 tok = declEnd->next();
    6889             : 
    6890             :                 //fix up line number
    6891          29 :                 if (tok->str() == ",")
    6892          15 :                     tok->linenr(tok->previous()->linenr());
    6893             :             }
    6894             :             //goto forward and continue
    6895          14 :             tok = tok->next()->link();
    6896             :         }
    6897             :     }
    6898       22678 : }
    6899             : 
    6900       22640 : void Tokenizer::simplifyPointerToStandardType()
    6901             : {
    6902       22640 :     if (!isC())
    6903       16716 :         return;
    6904             : 
    6905      264197 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6906      258273 :         if (!Token::Match(tok, "& %name% [ 0 ] !!["))
    6907      258250 :             continue;
    6908             : 
    6909          23 :         if (!Token::Match(tok->previous(), "[,(=]"))
    6910           1 :             continue;
    6911             : 
    6912             :         // Remove '[ 0 ]' suffix
    6913          22 :         Token::eraseTokens(tok->next(), tok->tokAt(5));
    6914             :         // Remove '&' prefix
    6915          22 :         tok = tok->previous();
    6916          22 :         if (!tok)
    6917           0 :             break;
    6918          22 :         tok->deleteNext();
    6919             :     }
    6920             : }
    6921             : 
    6922       22640 : void Tokenizer::simplifyFunctionPointers()
    6923             : {
    6924      911637 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    6925             :         // #2873 - do not simplify function pointer usage here:
    6926             :         // (void)(xy(*p)(0));
    6927      888993 :         if (Token::simpleMatch(tok, ") (")) {
    6928         501 :             tok = tok->next()->link();
    6929         501 :             continue;
    6930             :         }
    6931             : 
    6932             :         // check for function pointer cast
    6933     1776927 :         if (Token::Match(tok, "( %type% %type%| *| *| ( * ) (") ||
    6934      888430 :             Token::Match(tok, "static_cast < %type% %type%| *| *| ( * ) (")) {
    6935          65 :             Token *tok1 = tok;
    6936             : 
    6937          65 :             if (tok1->isCpp() && tok1->str() == "static_cast")
    6938           0 :                 tok1 = tok1->next();
    6939             : 
    6940          65 :             tok1 = tok1->next();
    6941             : 
    6942          65 :             if (Token::Match(tok1->next(), "%type%"))
    6943           0 :                 tok1 = tok1->next();
    6944             : 
    6945          71 :             while (tok1->next()->str() == "*")
    6946           6 :                 tok1 = tok1->next();
    6947             : 
    6948             :             // check that the cast ends
    6949          65 :             if (!Token::Match(tok1->linkAt(4), ") )|>"))
    6950           0 :                 continue;
    6951             : 
    6952             :             // ok simplify this function pointer cast to an ordinary pointer cast
    6953          65 :             tok1->deleteNext();
    6954          65 :             tok1->next()->deleteNext();
    6955          65 :             Token::eraseTokens(tok1->next(), tok1->linkAt(2)->next());
    6956          65 :             continue;
    6957             :         }
    6958             : 
    6959             :         // check for start of statement
    6960      888433 :         if (tok->previous() && !Token::Match(tok->previous(), "{|}|;|,|(|public:|protected:|private:"))
    6961      557124 :             continue;
    6962             : 
    6963      331310 :         if (Token::Match(tok, "delete|else|return|throw|typedef"))
    6964       10295 :             continue;
    6965             : 
    6966      416296 :         while (Token::Match(tok, "%type%|:: %type%|::"))
    6967       95285 :             tok = tok->next();
    6968             : 
    6969      321010 :         Token *tok2 = (tok && tok->isName()) ? tok->next() : nullptr;
    6970      350075 :         while (Token::Match(tok2, "*|&"))
    6971       29063 :             tok2 = tok2->next();
    6972      321013 :         if (!tok2 || tok2->str() != "(")
    6973      264616 :             continue;
    6974       84695 :         while (Token::Match(tok2, "(|:: %type%"))
    6975       28296 :             tok2 = tok2->tokAt(2);
    6976       56399 :         if (!Token::Match(tok2, "(|:: * *| %name%"))
    6977       55919 :             continue;
    6978         479 :         tok2 = tok2->tokAt(2);
    6979         479 :         if (tok2->str() == "*")
    6980          11 :             tok2 = tok2->next();
    6981         505 :         while (Token::Match(tok2, "%type%|:: %type%|::"))
    6982          26 :             tok2 = tok2->next();
    6983             : 
    6984         479 :         if (!Token::Match(tok2, "%name% ) (") &&
    6985         769 :             !Token::Match(tok2, "%name% [ ] ) (") &&
    6986         290 :             !(Token::Match(tok2, "%name% (") && Token::simpleMatch(tok2->linkAt(1), ") ) (")))
    6987         258 :             continue;
    6988             : 
    6989         468 :         while (tok && tok->str() != "(")
    6990         247 :             tok = tok->next();
    6991             : 
    6992             :         // check that the declaration ends
    6993         221 :         if (!tok || !tok->link() || !tok->link()->next()) {
    6994           2 :             syntaxError(nullptr);
    6995             :         }
    6996         219 :         Token *endTok = tok->link()->next()->link();
    6997         219 :         if (Token::simpleMatch(endTok, ") throw ("))
    6998           1 :             endTok = endTok->linkAt(2);
    6999         219 :         if (!Token::Match(endTok, ") const|volatile| const|volatile| ;|,|)|=|[|{"))
    7000          26 :             continue;
    7001             : 
    7002         228 :         while (Token::Match(endTok->next(), "const|volatile"))
    7003          35 :             endTok->deleteNext();
    7004             : 
    7005             :         // ok simplify this function pointer to an ordinary pointer
    7006         193 :         if (Token::simpleMatch(tok->link()->previous(), ") )")) {
    7007             :             // Function returning function pointer
    7008             :             // void (*dostuff(void))(void) {}
    7009          31 :             Token::eraseTokens(tok->link(), endTok->next());
    7010          31 :             tok->link()->deleteThis();
    7011          31 :             tok->deleteThis();
    7012             :         } else {
    7013         162 :             Token::eraseTokens(tok->link()->linkAt(1), endTok->next());
    7014             : 
    7015             :             // remove variable names
    7016         162 :             int indent = 0;
    7017         356 :             for (Token* tok3 = tok->link()->tokAt(2); Token::Match(tok3, "%name%|*|&|[|(|)|::|,|<"); tok3 = tok3->next()) {
    7018         355 :                 if (tok3->str() == ")" && --indent < 0)
    7019         161 :                     break;
    7020         194 :                 if (tok3->str() == "<" && tok3->link())
    7021           0 :                     tok3 = tok3->link();
    7022         194 :                 else if (Token::Match(tok3, "["))
    7023           0 :                     tok3 = tok3->link();
    7024         194 :                 else if (tok3->str() == "(") {
    7025           1 :                     tok3 = tok3->link();
    7026           1 :                     if (Token::simpleMatch(tok3, ") (")) {
    7027           1 :                         tok3 = tok3->next();
    7028           1 :                         ++indent;
    7029             :                     } else
    7030           0 :                         break;
    7031             :                 }
    7032         194 :                 if (Token::Match(tok3, "%type%|*|&|> %name% [,)[]"))
    7033          19 :                     tok3->deleteNext();
    7034             :             }
    7035             : 
    7036             :             // TODO Keep this info
    7037         222 :             while (Token::Match(tok, "( %type% ::"))
    7038          60 :                 tok->deleteNext(2);
    7039             :         }
    7040             :     }
    7041       22638 : }
    7042             : 
    7043       67987 : void Tokenizer::simplifyVarDecl(const bool only_k_r_fpar)
    7044             : {
    7045       67987 :     simplifyVarDecl(list.front(), nullptr, only_k_r_fpar);
    7046       67986 : }
    7047             : 
    7048       68255 : void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, const bool only_k_r_fpar)
    7049             : {
    7050       68255 :     const bool isCPP11 = isCPP() && (mSettings.standards.cpp >= Standards::CPP11);
    7051             : 
    7052             :     // Split up variable declarations..
    7053             :     // "int a=4;" => "int a; a=4;"
    7054       68256 :     bool finishedwithkr = true;
    7055       68256 :     bool scopeDecl = false;
    7056     1427695 :     for (Token *tok = tokBegin; tok != tokEnd; tok = tok->next()) {
    7057     1359437 :         if (Token::Match(tok, "{|;"))
    7058      314309 :             scopeDecl = false;
    7059     1359437 :         if (isCPP()) {
    7060     1023848 :             if (Token::Match(tok, "class|struct|namespace|union"))
    7061       20687 :                 scopeDecl = true;
    7062     1023851 :             if (Token::Match(tok, "decltype|noexcept (")) {
    7063         325 :                 tok = tok->next()->link();
    7064             :                 // skip decltype(...){...}
    7065         325 :                 if (tok && Token::simpleMatch(tok->previous(), ") {"))
    7066           0 :                     tok = tok->link();
    7067     2045990 :             } else if (Token::simpleMatch(tok, "= {") ||
    7068     1022485 :                        (!scopeDecl && Token::Match(tok, "%name%|> {") &&
    7069        4202 :                         !Token::Match(tok, "else|try|do|const|constexpr|override|volatile|noexcept"))) {
    7070        3553 :                 if (!tok->next()->link())
    7071           0 :                     syntaxError(tokBegin);
    7072             :                 // Check for lambdas before skipping
    7073        3553 :                 if (Token::Match(tok->tokAt(-2), ") . %name%")) { // trailing return type
    7074             :                     // TODO: support lambda without parameter clause?
    7075          67 :                     Token* lambdaStart = tok->linkAt(-2)->previous();
    7076          67 :                     if (Token::simpleMatch(lambdaStart, "]"))
    7077          23 :                         lambdaStart = lambdaStart->link();
    7078          67 :                     Token* lambdaEnd = findLambdaEndScope(lambdaStart);
    7079          67 :                     if (lambdaEnd)
    7080          23 :                         simplifyVarDecl(lambdaEnd->link()->next(), lambdaEnd, only_k_r_fpar);
    7081             :                 } else {
    7082       19314 :                     for (Token* tok2 = tok->next(); tok2 != tok->next()->link(); tok2 = tok2->next()) {
    7083       15828 :                         Token* lambdaEnd = findLambdaEndScope(tok2);
    7084       15828 :                         if (!lambdaEnd)
    7085       15783 :                             continue;
    7086          45 :                         simplifyVarDecl(lambdaEnd->link()->next(), lambdaEnd, only_k_r_fpar);
    7087             :                     }
    7088             :                 }
    7089        3553 :                 tok = tok->next()->link();
    7090             :             }
    7091             : 
    7092      335590 :         } else if (Token::simpleMatch(tok, "= {")) {
    7093         191 :             tok = tok->next()->link();
    7094             :         }
    7095     1359419 :         if (!tok) {
    7096           0 :             syntaxError(tokBegin);
    7097             :         }
    7098     1359419 :         if (only_k_r_fpar && finishedwithkr) {
    7099      161344 :             if (Token::Match(tok, "(|[|{")) {
    7100       60190 :                 tok = tok->link();
    7101       60190 :                 if (tok->next() && Token::Match(tok, ") !!{"))
    7102        2162 :                     tok = tok->next();
    7103             :                 else
    7104       58028 :                     continue;
    7105             :             } else
    7106      101156 :                 continue;
    7107     1198075 :         } else if (tok->str() == "(") {
    7108      175156 :             if (isCPP()) {
    7109      667408 :                 for (Token * tok2 = tok; tok2 && tok2 != tok->link(); tok2 = tok2->next()) {
    7110      556349 :                     if (Token::Match(tok2, "[(,] [")) {
    7111             :                         // lambda function at tok2->next()
    7112             :                         // find start of lambda body
    7113         202 :                         Token * lambdaBody = tok2;
    7114        1687 :                         while (lambdaBody && lambdaBody != tok2->link() && lambdaBody->str() != "{")
    7115        1485 :                             lambdaBody = lambdaBody->next();
    7116         202 :                         if (lambdaBody && lambdaBody != tok2->link() && lambdaBody->link())
    7117         200 :                             simplifyVarDecl(lambdaBody, lambdaBody->link()->next(), only_k_r_fpar);
    7118             :                     }
    7119             :                 }
    7120             :             }
    7121      175155 :             tok = tok->link();
    7122             :         }
    7123             : 
    7124     1200238 :         if (!tok)
    7125           0 :             syntaxError(nullptr); // #7043 invalid code
    7126     1200238 :         if (tok->previous() && !Token::Match(tok->previous(), "{|}|;|)|public:|protected:|private:"))
    7127      662019 :             continue;
    7128      538228 :         if (Token::simpleMatch(tok, "template <"))
    7129        2026 :             continue;
    7130             : 
    7131      536200 :         Token *type0 = tok;
    7132      536200 :         if (!Token::Match(type0, "::|extern| %type%"))
    7133      273475 :             continue;
    7134      262736 :         if (Token::Match(type0, "else|return|public:|protected:|private:"))
    7135       22444 :             continue;
    7136      240292 :         if (isCPP11 && type0->str() == "using")
    7137         461 :             continue;
    7138      239830 :         if (type0->isCpp() && Token::Match(type0, "namespace|delete"))
    7139        1532 :             continue;
    7140             : 
    7141      238298 :         bool isconst = false;
    7142      238298 :         bool isstatic = false;
    7143      238298 :         Token *tok2 = type0;
    7144      238298 :         int typelen = 1;
    7145             : 
    7146      238298 :         if (Token::Match(tok2, "::|extern")) {
    7147         292 :             tok2 = tok2->next();
    7148         292 :             typelen++;
    7149             :         }
    7150             : 
    7151             :         //check if variable is declared 'const' or 'static' or both
    7152      260704 :         while (tok2) {
    7153      260704 :             if (!Token::Match(tok2, "const|static|constexpr") && Token::Match(tok2, "%type% const|static")) {
    7154          69 :                 tok2 = tok2->next();
    7155          69 :                 ++typelen;
    7156             :             }
    7157             : 
    7158      260704 :             if (Token::Match(tok2, "const|constexpr"))
    7159        7855 :                 isconst = true;
    7160             : 
    7161      252851 :             else if (Token::Match(tok2, "static|constexpr"))
    7162        1129 :                 isstatic = true;
    7163             : 
    7164      251723 :             else if (Token::Match(tok2, "%type% :: %type%")) {
    7165       13437 :                 tok2 = tok2->next();
    7166       13437 :                 ++typelen;
    7167             :             }
    7168             : 
    7169             :             else
    7170      238286 :                 break;
    7171             : 
    7172       22421 :             if (tok2->strAt(1) == "*")
    7173          15 :                 break;
    7174             : 
    7175       22406 :             if (Token::Match(tok2->next(), "& %name% ,"))
    7176           0 :                 break;
    7177             : 
    7178       22406 :             tok2 = tok2->next();
    7179       22406 :             ++typelen;
    7180             :         }
    7181             : 
    7182             :         // strange looking variable declaration => don't split up.
    7183      238301 :         if (Token::Match(tok2, "%type% *|&| %name% , %type% *|&| %name%"))
    7184           8 :             continue;
    7185             : 
    7186      238290 :         if (Token::Match(tok2, "struct|union|class %type%")) {
    7187       11821 :             tok2 = tok2->next();
    7188       11821 :             ++typelen;
    7189             :         }
    7190             : 
    7191             :         // check for qualification..
    7192      238290 :         if (Token::Match(tok2,  ":: %type%")) {
    7193           7 :             ++typelen;
    7194           7 :             tok2 = tok2->next();
    7195             :         }
    7196             : 
    7197             :         //skip combinations of templates and namespaces
    7198      242593 :         while (!isC() && (Token::Match(tok2, "%type% <") || Token::Match(tok2, "%type% ::"))) {
    7199        4341 :             if (tok2->next()->str() == "<" && !TemplateSimplifier::templateParameters(tok2->next())) {
    7200          38 :                 tok2 = nullptr;
    7201          38 :                 break;
    7202             :             }
    7203        4303 :             typelen += 2;
    7204        4303 :             tok2 = tok2->tokAt(2);
    7205        4303 :             if (tok2 && tok2->previous()->str() == "::")
    7206         321 :                 continue;
    7207        3982 :             int indentlevel = 0;
    7208        3982 :             int parens = 0;
    7209             : 
    7210       12220 :             for (Token *tok3 = tok2; tok3; tok3 = tok3->next()) {
    7211       12220 :                 ++typelen;
    7212             : 
    7213       12220 :                 if (!parens && tok3->str() == "<") {
    7214         386 :                     ++indentlevel;
    7215       11834 :                 } else if (!parens && tok3->str() == ">") {
    7216        4368 :                     if (indentlevel == 0) {
    7217        3982 :                         tok2 = tok3->next();
    7218        3982 :                         break;
    7219             :                     }
    7220         386 :                     --indentlevel;
    7221        7466 :                 } else if (!parens && tok3->str() == ">>") {
    7222           0 :                     if (indentlevel <= 1) {
    7223           0 :                         tok2 = tok3->next();
    7224           0 :                         break;
    7225             :                     }
    7226           0 :                     indentlevel -= 2;
    7227        7466 :                 } else if (tok3->str() == "(") {
    7228         166 :                     ++parens;
    7229        7300 :                 } else if (tok3->str() == ")") {
    7230         166 :                     if (!parens) {
    7231           0 :                         tok2 = nullptr;
    7232           0 :                         break;
    7233             :                     }
    7234         166 :                     --parens;
    7235        7134 :                 } else if (tok3->str() == ";") {
    7236           0 :                     break;
    7237             :                 }
    7238             :             }
    7239             : 
    7240        3982 :             if (Token::Match(tok2,  ":: %type%")) {
    7241         611 :                 ++typelen;
    7242         611 :                 tok2 = tok2->next();
    7243             :             }
    7244             : 
    7245             :             // east const
    7246        3982 :             if (Token::simpleMatch(tok2, "const"))
    7247           7 :                 isconst = true;
    7248             :         }
    7249             : 
    7250             :         //pattern: "%type% *| ... *| const| %name% ,|="
    7251      240025 :         if (Token::Match(tok2, "%type%") ||
    7252        1736 :             (tok2 && tok2->previous() && tok2->previous()->str() == ">")) {
    7253      237048 :             Token *varName = tok2;
    7254      237048 :             if (!tok2->previous() || tok2->previous()->str() != ">")
    7255      233688 :                 varName = varName->next();
    7256             :             else
    7257        3360 :                 --typelen;
    7258      237047 :             if (isCPP() && Token::Match(varName, "public:|private:|protected:|using"))
    7259           5 :                 continue;
    7260             :             //skip all the pointer part
    7261      237046 :             bool isPointerOrRef = false;
    7262      252362 :             while (Token::simpleMatch(varName, "*") || Token::Match(varName, "& %name% ,")) {
    7263       15316 :                 isPointerOrRef = true;
    7264       15316 :                 varName = varName->next();
    7265             :             }
    7266             : 
    7267      241983 :             while (Token::Match(varName, "%type% %type%")) {
    7268        4936 :                 if (varName->str() != "const" && varName->str() != "volatile") {
    7269        4799 :                     ++typelen;
    7270             :                 }
    7271        4936 :                 varName = varName->next();
    7272             :             }
    7273             :             // Function pointer
    7274      237048 :             if (Token::simpleMatch(varName, "( *") &&
    7275      237216 :                 Token::Match(varName->link()->previous(), "%name% ) (") &&
    7276         170 :                 Token::simpleMatch(varName->link()->linkAt(1), ") =")) {
    7277          18 :                 Token *endDecl = varName->link()->linkAt(1);
    7278          18 :                 varName = varName->link()->previous();
    7279          18 :                 endDecl->insertToken(";");
    7280          18 :                 endDecl = endDecl->next();
    7281          18 :                 endDecl->next()->isSplittedVarDeclEq(true);
    7282          18 :                 endDecl->insertToken(varName->str());
    7283          18 :                 endDecl->next()->setMacroName(varName->getMacroName());
    7284          18 :                 continue;
    7285             :             }
    7286             :             //non-VLA case
    7287      237028 :             if (Token::Match(varName, "%name% ,|=")) {
    7288       10174 :                 if (varName->str() != "operator") {
    7289       10163 :                     tok2 = varName->next(); // The ',' or '=' token
    7290             : 
    7291       10163 :                     if (tok2->str() == "=" && (isstatic || (isconst && !isPointerOrRef))) {
    7292             :                         //do not split const non-pointer variables..
    7293        4094 :                         while (tok2 && tok2->str() != "," && tok2->str() != ";") {
    7294        3177 :                             if (Token::Match(tok2, "{|(|["))
    7295         472 :                                 tok2 = tok2->link();
    7296        3177 :                             const Token *tok3 = tok2;
    7297        3177 :                             if (!isC() && tok2->str() == "<" && TemplateSimplifier::templateParameters(tok2) > 0) {
    7298          24 :                                 tok2 = tok2->findClosingBracket();
    7299             :                             }
    7300        3177 :                             if (!tok2)
    7301           0 :                                 syntaxError(tok3); // #6881 invalid code
    7302        3177 :                             tok2 = tok2->next();
    7303             :                         }
    7304         917 :                         if (tok2 && tok2->str() == ";")
    7305         876 :                             tok2 = nullptr;
    7306             :                     }
    7307             :                 } else
    7308          11 :                     tok2 = nullptr;
    7309             :             }
    7310             : 
    7311             :             //VLA case
    7312      226855 :             else if (Token::Match(varName, "%name% [")) {
    7313        4098 :                 tok2 = varName->next();
    7314             : 
    7315        5499 :                 while (Token::Match(tok2->link(), "] ,|=|["))
    7316        1401 :                     tok2 = tok2->link()->next();
    7317        4098 :                 if (!Token::Match(tok2, "=|,"))
    7318        2894 :                     tok2 = nullptr;
    7319        4098 :                 if (tok2 && tok2->str() == "=") {
    7320        3515 :                     while (tok2 && tok2->str() != "," && tok2->str() != ";") {
    7321        2348 :                         if (Token::Match(tok2, "{|(|["))
    7322         815 :                             tok2 = tok2->link();
    7323        2348 :                         tok2 = tok2->next();
    7324             :                     }
    7325        1167 :                     if (tok2 && tok2->str() == ";")
    7326        1154 :                         tok2 = nullptr;
    7327             :                 }
    7328             :             }
    7329             : 
    7330             :             // brace initialization
    7331      222756 :             else if (Token::Match(varName, "%name% {")) {
    7332        1629 :                 tok2 = varName->next();
    7333        1629 :                 tok2 = tok2->link();
    7334        1629 :                 if (tok2)
    7335        1629 :                     tok2 = tok2->next();
    7336        1629 :                 if (tok2 && tok2->str() != ",")
    7337        1614 :                     tok2 = nullptr;
    7338             :             }
    7339             : 
    7340             :             // function declaration
    7341      221127 :             else if (Token::Match(varName, "%name% (")) {
    7342       60232 :                 Token* commaTok = varName->linkAt(1)->next();
    7343       61286 :                 while (Token::Match(commaTok, "const|noexcept|override|final")) {
    7344        1053 :                     commaTok = commaTok->next();
    7345        1053 :                     if (Token::Match(commaTok, "( true|false )"))
    7346         104 :                         commaTok = commaTok->link()->next();
    7347             :                 }
    7348       60232 :                 tok2 = Token::simpleMatch(commaTok, ",") ? commaTok : nullptr;
    7349             :             }
    7350             : 
    7351             :             else
    7352      160896 :                 tok2 = nullptr;
    7353             :         } else {
    7354        1239 :             tok2 = nullptr;
    7355             :         }
    7356             : 
    7357      238268 :         if (!tok2) {
    7358      228921 :             if (only_k_r_fpar)
    7359         378 :                 finishedwithkr = false;
    7360      228921 :             continue;
    7361             :         }
    7362             : 
    7363        9347 :         if (tok2->str() == ",") {
    7364        2060 :             tok2->str(";");
    7365        2060 :             tok2->isSplittedVarDeclComma(true);
    7366             :             //TODO: should we have to add also template '<>' links?
    7367        2060 :             TokenList::insertTokens(tok2, type0, typelen);
    7368             :         }
    7369             : 
    7370             :         else {
    7371        7287 :             Token *eq = tok2;
    7372             : 
    7373       30099 :             while (tok2) {
    7374       30052 :                 if (Token::Match(tok2, "{|(|["))
    7375        4811 :                     tok2 = tok2->link();
    7376             : 
    7377       25240 :                 else if (!isC() && tok2->str() == "<" && ((tok2->previous()->isName() && !tok2->previous()->varId()) || tok2->strAt(-1) == "]"))
    7378         156 :                     tok2 = tok2->findClosingBracket();
    7379             : 
    7380       25085 :                 else if (std::strchr(";,", tok2->str()[0])) {
    7381             :                     // "type var ="   =>   "type var; var ="
    7382        7241 :                     const Token *varTok = type0->tokAt(typelen);
    7383        9213 :                     while (Token::Match(varTok, "%name%|*|& %name%|*|&"))
    7384        1972 :                         varTok = varTok->next();
    7385        7241 :                     if (!varTok)
    7386           0 :                         syntaxError(tok2); // invalid code
    7387        7241 :                     TokenList::insertTokens(eq, varTok, 2);
    7388        7242 :                     eq->str(";");
    7389        7241 :                     eq->isSplittedVarDeclEq(true);
    7390             : 
    7391             :                     // "= x, "   =>   "= x; type "
    7392        7241 :                     if (tok2->str() == ",") {
    7393          65 :                         tok2->str(";");
    7394          65 :                         tok2->isSplittedVarDeclComma(true);
    7395          65 :                         TokenList::insertTokens(tok2, type0, typelen);
    7396             :                     }
    7397        7241 :                     break;
    7398             :                 }
    7399       22811 :                 if (tok2)
    7400       22782 :                     tok2 = tok2->next();
    7401             :             }
    7402             :         }
    7403        9346 :         finishedwithkr = (only_k_r_fpar && tok2 && tok2->strAt(1) == "{");
    7404             :     }
    7405       68254 : }
    7406             : 
    7407       22642 : void Tokenizer::simplifyStaticConst()
    7408             : {
    7409             :     // This function will simplify the token list so that the qualifiers "extern", "static"
    7410             :     // and "const" appear in the same order as in the array below.
    7411      158476 :     const std::string qualifiers[] = {"extern", "static", "const"};
    7412             : 
    7413             :     // Move 'const' before all other qualifiers and types and then
    7414             :     // move 'static' before all other qualifiers and types, ...
    7415     1021842 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7416      999201 :         bool continue2 = false;
    7417     3996513 :         for (int i = 0; i < sizeof(qualifiers)/sizeof(qualifiers[0]); i++) {
    7418             : 
    7419             :             // Keep searching for a qualifier
    7420     2997358 :             if (!tok->next() || tok->next()->str() != qualifiers[i])
    7421     2988367 :                 continue;
    7422             : 
    7423             :             // Look backwards to find the beginning of the declaration
    7424        8990 :             Token* leftTok = tok;
    7425        8990 :             bool behindOther = false;
    7426        9302 :             for (; leftTok; leftTok = leftTok->previous()) {
    7427       36357 :                 for (int j = 0; j <= i; j++) {
    7428       27170 :                     if (leftTok->str() == qualifiers[j]) {
    7429         104 :                         behindOther = true;
    7430         104 :                         break;
    7431             :                     }
    7432             :                 }
    7433        9291 :                 if (behindOther)
    7434         104 :                     break;
    7435        9187 :                 if (isCPP() && Token::simpleMatch(leftTok, ">")) {
    7436          50 :                     Token* opening = leftTok->findOpeningBracket();
    7437          50 :                     if (opening) {
    7438          50 :                         leftTok = opening;
    7439          50 :                         continue;
    7440             :                     }
    7441             :                 }
    7442        9491 :                 if (!Token::Match(leftTok, "%type%|struct|::") ||
    7443         354 :                     (isCPP() && Token::Match(leftTok, "private:|protected:|public:|operator|template"))) {
    7444        8875 :                     break;
    7445             :                 }
    7446             :             }
    7447             : 
    7448             :             // The token preceding the declaration should indicate the start of a declaration
    7449        8992 :             if (leftTok == tok)
    7450        8804 :                 continue;
    7451             : 
    7452         188 :             if (leftTok && !behindOther && !Token::Match(leftTok, ";|{|}|(|,|private:|protected:|public:")) {
    7453          47 :                 continue2 = true;
    7454          47 :                 break;
    7455             :             }
    7456             : 
    7457             :             // Move the qualifier to the left-most position in the declaration
    7458         141 :             tok->deleteNext();
    7459         141 :             if (!leftTok) {
    7460          13 :                 list.front()->insertToken(qualifiers[i]);
    7461          13 :                 list.front()->swapWithNext();
    7462          13 :                 tok = list.front();
    7463         128 :             } else if (leftTok->next()) {
    7464         128 :                 leftTok->next()->insertTokenBefore(qualifiers[i]);
    7465         128 :                 tok = leftTok->next();
    7466             :             } else {
    7467           0 :                 leftTok->insertToken(qualifiers[i]);
    7468           0 :                 tok = leftTok;
    7469             :             }
    7470             :         }
    7471      999202 :         if (continue2)
    7472          47 :             continue;
    7473             :     }
    7474       22638 : }
    7475             : 
    7476       22638 : void Tokenizer::simplifyVariableMultipleAssign()
    7477             : {
    7478     1013689 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7479      991055 :         if (Token::Match(tok, "%name% = %name% = %num%|%name% ;")) {
    7480             :             // skip intermediate assignments
    7481          11 :             Token *tok2 = tok->previous();
    7482          24 :             while (tok2 &&
    7483          49 :                    tok2->str() == "=" &&
    7484          14 :                    Token::Match(tok2->previous(), "%name%")) {
    7485          14 :                 tok2 = tok2->tokAt(-2);
    7486             :             }
    7487             : 
    7488          11 :             if (!tok2 || tok2->str() != ";") {
    7489           6 :                 continue;
    7490             :             }
    7491             : 
    7492           5 :             Token *stopAt = tok->tokAt(2);
    7493           5 :             const Token *valueTok = stopAt->tokAt(2);
    7494           5 :             const std::string& value(valueTok->str());
    7495           5 :             tok2 = tok2->next();
    7496             : 
    7497          23 :             while (tok2 != stopAt) {
    7498          18 :                 tok2->next()->insertToken(";");
    7499          18 :                 tok2->next()->insertToken(value);
    7500          18 :                 tok2 = tok2->tokAt(4);
    7501             :             }
    7502             :         }
    7503             :     }
    7504       22641 : }
    7505             : 
    7506             : // Binary operators simplification map
    7507             : static const std::unordered_map<std::string, std::string> cAlternativeTokens = {
    7508             :     std::make_pair("and", "&&")
    7509             :     , std::make_pair("and_eq", "&=")
    7510             :     , std::make_pair("bitand", "&")
    7511             :     , std::make_pair("bitor", "|")
    7512             :     , std::make_pair("not_eq", "!=")
    7513             :     , std::make_pair("or", "||")
    7514             :     , std::make_pair("or_eq", "|=")
    7515             :     , std::make_pair("xor", "^")
    7516             :     , std::make_pair("xor_eq", "^=")
    7517             : };
    7518             : 
    7519             : // Simplify the C alternative tokens:
    7520             : //  and      =>     &&
    7521             : //  and_eq   =>     &=
    7522             : //  bitand   =>     &
    7523             : //  bitor    =>     |
    7524             : //  compl    =>     ~
    7525             : //  not      =>     !
    7526             : //  not_eq   =>     !=
    7527             : //  or       =>     ||
    7528             : //  or_eq    =>     |=
    7529             : //  xor      =>     ^
    7530             : //  xor_eq   =>     ^=
    7531       23229 : bool Tokenizer::simplifyCAlternativeTokens()
    7532             : {
    7533             :     /* executable scope level */
    7534       23229 :     int executableScopeLevel = 0;
    7535             : 
    7536       46456 :     std::vector<Token *> alt;
    7537       23229 :     bool replaceAll = false;  // replace all or none
    7538             : 
    7539      979694 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7540      956469 :         if (tok->str() == ")") {
    7541      107715 :             if (const Token *end = isFunctionHead(tok, "{")) {
    7542       37618 :                 ++executableScopeLevel;
    7543       37618 :                 tok = const_cast<Token *>(end);
    7544      557175 :                 continue;
    7545             :             }
    7546             :         }
    7547             : 
    7548      918848 :         if (tok->str() == "{") {
    7549        9314 :             if (executableScopeLevel > 0)
    7550        2220 :                 ++executableScopeLevel;
    7551        9314 :             continue;
    7552             :         }
    7553             : 
    7554      909535 :         if (tok->str() == "}") {
    7555       46927 :             if (executableScopeLevel > 0)
    7556       39833 :                 --executableScopeLevel;
    7557       46927 :             continue;
    7558             :         }
    7559             : 
    7560      862602 :         if (!tok->isName())
    7561      463297 :             continue;
    7562             : 
    7563      399307 :         const std::unordered_map<std::string, std::string>::const_iterator cOpIt = cAlternativeTokens.find(tok->str());
    7564      399311 :         if (cOpIt != cAlternativeTokens.end()) {
    7565          44 :             alt.push_back(tok);
    7566             : 
    7567             :             // Is this a variable declaration..
    7568          44 :             if (isC() && Token::Match(tok->previous(), "%type%|* %name% [;,=]"))
    7569           1 :                 return false;
    7570             : 
    7571          43 :             if (!Token::Match(tok->previous(), "%name%|%num%|%char%|)|]|> %name% %name%|%num%|%char%|%op%|("))
    7572           5 :                 continue;
    7573          38 :             if (Token::Match(tok->next(), "%assign%|%or%|%oror%|&&|*|/|%|^") && !Token::Match(tok->previous(), "%num%|%char%|) %name% *"))
    7574           1 :                 continue;
    7575          37 :             if (executableScopeLevel == 0 && Token::Match(tok, "%name% (")) {
    7576           1 :                 const Token *start = tok;
    7577           3 :                 while (Token::Match(start, "%name%|*"))
    7578           2 :                     start = start->previous();
    7579           1 :                 if (!start || Token::Match(start, "[;}]"))
    7580           1 :                     continue;
    7581             :             }
    7582          36 :             replaceAll = true;
    7583      399264 :         } else if (Token::Match(tok, "not|compl")) {
    7584          28 :             alt.push_back(tok);
    7585             : 
    7586          28 :             if ((Token::Match(tok->previous(), "%assign%") || Token::Match(tok->next(), "%num%")) && !Token::Match(tok->next(), ".|->")) {
    7587           2 :                 replaceAll = true;
    7588           2 :                 continue;
    7589             :             }
    7590             : 
    7591             :             // Don't simplify 'not p;' (in case 'not' is a type)
    7592          26 :             if (!Token::Match(tok->next(), "%name%|(") ||
    7593          30 :                 Token::Match(tok->previous(), "[;{}]") ||
    7594           4 :                 (executableScopeLevel == 0U && tok->strAt(-1) == "("))
    7595          10 :                 continue;
    7596             : 
    7597          16 :             replaceAll = true;
    7598             :         }
    7599             :     }
    7600             : 
    7601       23226 :     if (!replaceAll)
    7602       23179 :         return false;
    7603             : 
    7604         101 :     for (Token *tok: alt) {
    7605          54 :         const std::unordered_map<std::string, std::string>::const_iterator cOpIt = cAlternativeTokens.find(tok->str());
    7606          54 :         if (cOpIt != cAlternativeTokens.end())
    7607          36 :             tok->str(cOpIt->second);
    7608          18 :         else if (tok->str() == "not")
    7609          15 :             tok->str("!");
    7610             :         else
    7611           3 :             tok->str("~");
    7612             :     }
    7613             : 
    7614          47 :     return !alt.empty();
    7615             : }
    7616             : 
    7617             : // int i(0); => int i; i = 0;
    7618             : // int i(0), j; => int i; i = 0; int j;
    7619       67931 : void Tokenizer::simplifyInitVar()
    7620             : {
    7621       67931 :     if (isC())
    7622       17767 :         return;
    7623             : 
    7624     2233150 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7625     2182975 :         if (!tok->isName() || (tok->previous() && !Token::Match(tok->previous(), "[;{}]")))
    7626     1917162 :             continue;
    7627             : 
    7628      265826 :         if (tok->str() == "return")
    7629       20076 :             continue;
    7630             : 
    7631      245751 :         if (Token::Match(tok, "class|struct|union| %type% *| %name% ( &| %any% ) ;")) {
    7632        2311 :             tok = initVar(tok);
    7633      243438 :         } else if (Token::Match(tok, "%type% *| %name% ( %type% (")) {
    7634         210 :             const Token* tok2 = tok->tokAt(2);
    7635         210 :             if (!tok2->link())
    7636           3 :                 tok2 = tok2->next();
    7637         210 :             if (!tok2->link() || (tok2->link()->strAt(1) == ";" && !Token::simpleMatch(tok2->linkAt(2), ") (")))
    7638         130 :                 tok = initVar(tok);
    7639      243230 :         } else if (Token::Match(tok, "class|struct|union| %type% *| %name% ( &| %any% ) ,") && tok->str() != "new") {
    7640           4 :             Token *tok1 = tok->tokAt(5);
    7641           5 :             while (tok1->str() != ",")
    7642           1 :                 tok1 = tok1->next();
    7643           4 :             tok1->str(";");
    7644             : 
    7645           4 :             const int numTokens = (Token::Match(tok, "class|struct|union")) ? 2U : 1U;
    7646           4 :             TokenList::insertTokens(tok1, tok, numTokens);
    7647           4 :             tok = initVar(tok);
    7648             :         }
    7649             :     }
    7650             : }
    7651             : 
    7652        2445 : Token * Tokenizer::initVar(Token * tok)
    7653             : {
    7654             :     // call constructor of class => no simplification
    7655        2445 :     if (Token::Match(tok, "class|struct|union")) {
    7656           9 :         if (tok->strAt(2) != "*")
    7657           6 :             return tok;
    7658             : 
    7659           3 :         tok = tok->next();
    7660        2436 :     } else if (!tok->isStandardType() && tok->str() != "auto" && tok->next()->str() != "*")
    7661        1597 :         return tok;
    7662             : 
    7663             :     // goto variable name..
    7664         842 :     tok = tok->next();
    7665         842 :     if (tok->str() == "*")
    7666          63 :         tok = tok->next();
    7667             : 
    7668             :     // sizeof is not a variable name..
    7669         842 :     if (tok->str() == "sizeof")
    7670           3 :         return tok;
    7671             : 
    7672             :     // check initializer..
    7673         839 :     if (tok->tokAt(2)->isStandardType() || tok->strAt(2) == "void")
    7674         701 :         return tok;
    7675         138 :     if (!tok->tokAt(2)->isNumber() && !Token::Match(tok->tokAt(2), "%type% (") && tok->strAt(2) != "&" && tok->tokAt(2)->varId() == 0)
    7676          91 :         return tok;
    7677             : 
    7678             :     // insert '; var ='
    7679          47 :     tok->insertToken(";");
    7680          47 :     tok->next()->insertToken(tok->str());
    7681          47 :     tok->tokAt(2)->varId(tok->varId());
    7682          47 :     tok = tok->tokAt(2);
    7683          47 :     tok->insertToken("=");
    7684             : 
    7685             :     // goto '('..
    7686          47 :     tok = tok->tokAt(2);
    7687             : 
    7688             :     // delete ')'
    7689          47 :     tok->link()->deleteThis();
    7690             : 
    7691             :     // delete this
    7692          47 :     tok->deleteThis();
    7693             : 
    7694          47 :     return tok;
    7695             : }
    7696             : 
    7697       22638 : void Tokenizer::elseif()
    7698             : {
    7699     1014449 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7700      991818 :         if (tok->str() != "else")
    7701      989314 :             continue;
    7702             : 
    7703        2497 :         if (!Token::Match(tok->previous(), ";|}"))
    7704           0 :             syntaxError(tok->previous());
    7705             : 
    7706        2497 :         if (!Token::Match(tok->next(), "%name%"))
    7707         388 :             continue;
    7708             : 
    7709        2109 :         if (tok->strAt(1) != "if")
    7710           0 :             unknownMacroError(tok->next());
    7711             : 
    7712     8004558 :         for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    7713     8004558 :             if (Token::Match(tok2, "(|{|["))
    7714     4002279 :                 tok2 = tok2->link();
    7715             : 
    7716     8004558 :             if (Token::Match(tok2, "}|;")) {
    7717     2001156 :                 if (tok2->next() && tok2->next()->str() != "else") {
    7718        2109 :                     tok->insertToken("{");
    7719        2109 :                     tok2->insertToken("}");
    7720        2109 :                     Token::createMutualLinks(tok->next(), tok2->next());
    7721        2109 :                     break;
    7722             :                 }
    7723             :             }
    7724             :         }
    7725             :     }
    7726       22638 : }
    7727             : 
    7728             : 
    7729       22627 : void Tokenizer::simplifyIfSwitchForInit()
    7730             : {
    7731       22627 :     if (!isCPP() || mSettings.standards.cpp < Standards::CPP17)
    7732        7172 :         return;
    7733             : 
    7734       15455 :     const bool forInit = (mSettings.standards.cpp >= Standards::CPP20);
    7735             : 
    7736      652714 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7737      637261 :         if (!Token::Match(tok, "if|switch|for ("))
    7738      632085 :             continue;
    7739             : 
    7740        5174 :         Token *semicolon = tok->tokAt(2);
    7741       25011 :         while (!Token::Match(semicolon, "[;)]")) {
    7742       19837 :             if (Token::Match(semicolon, "(|{|[") && semicolon->link())
    7743        1891 :                 semicolon = semicolon->link();
    7744       19837 :             semicolon = semicolon->next();
    7745             :         }
    7746        5174 :         if (semicolon->str() != ";")
    7747        4453 :             continue;
    7748             : 
    7749         721 :         if (tok->str() ==  "for") {
    7750         713 :             if (!forInit)
    7751           0 :                 continue;
    7752             : 
    7753             :             // Is it a for range..
    7754         713 :             const Token *tok2 = semicolon->next();
    7755         713 :             bool rangeFor = false;
    7756        3451 :             while (!Token::Match(tok2, "[;)]")) {
    7757        2742 :                 if (tok2->str() == "(")
    7758         259 :                     tok2 = tok2->link();
    7759        2483 :                 else if (!rangeFor && tok2->str() == "?")
    7760           4 :                     break;
    7761        2479 :                 else if (tok2->str() == ":")
    7762           1 :                     rangeFor = true;
    7763        2738 :                 tok2 = tok2->next();
    7764             :             }
    7765         713 :             if (!rangeFor || tok2->str() != ")")
    7766         712 :                 continue;
    7767             :         }
    7768             : 
    7769           9 :         Token *endpar = tok->linkAt(1);
    7770           9 :         if (!Token::simpleMatch(endpar, ") {"))
    7771           0 :             continue;
    7772             : 
    7773           9 :         Token *endscope = endpar->linkAt(1);
    7774           9 :         if (Token::simpleMatch(endscope, "} else {"))
    7775           2 :             endscope = endscope->linkAt(2);
    7776             : 
    7777             :         // Simplify, the initialization expression is broken out..
    7778           9 :         semicolon->insertToken(tok->str());
    7779           9 :         semicolon->next()->insertToken("(");
    7780           9 :         Token::createMutualLinks(semicolon->next()->next(), endpar);
    7781           9 :         tok->deleteNext();
    7782           9 :         tok->str("{");
    7783           9 :         endscope->insertToken("}");
    7784           9 :         Token::createMutualLinks(tok, endscope->next());
    7785           9 :         tok->isSimplifiedScope(true);
    7786             :     }
    7787             : }
    7788             : 
    7789             : 
    7790       22641 : bool Tokenizer::simplifyRedundantParentheses()
    7791             : {
    7792       22641 :     bool ret = false;
    7793     1005208 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7794      982565 :         if (tok->str() != "(")
    7795      876035 :             continue;
    7796             : 
    7797      106531 :         if (tok->isCpp() && Token::simpleMatch(tok->previous(), "} (")) {
    7798          39 :             const Token* plp = tok->previous()->link()->previous();
    7799          39 :             if (Token::Match(plp, "%name%|>|] {") || (Token::simpleMatch(plp, ")") && Token::simpleMatch(plp->link()->previous(), "]")))
    7800          25 :                 continue;
    7801             :         }
    7802             : 
    7803      106506 :         if (Token::simpleMatch(tok, "( {"))
    7804          43 :             continue;
    7805             : 
    7806      106467 :         if (Token::Match(tok->link(), ") %num%")) {
    7807        2092 :             tok = tok->link();
    7808        2092 :             continue;
    7809             :         }
    7810             : 
    7811             :         // Do not simplify if there is comma inside parentheses..
    7812      104375 :         if (Token::Match(tok->previous(), "%op% (") || Token::Match(tok->link(), ") %op%")) {
    7813        6199 :             bool innerComma = false;
    7814       18328 :             for (const Token *inner = tok->link()->previous(); inner != tok; inner = inner->previous()) {
    7815       12352 :                 if (inner->str() == ")")
    7816        2841 :                     inner = inner->link();
    7817       12350 :                 if (inner->str() == ",") {
    7818         220 :                     innerComma = true;
    7819         220 :                     break;
    7820             :                 }
    7821             :             }
    7822        6196 :             if (innerComma)
    7823         220 :                 continue;
    7824             :         }
    7825             : 
    7826             :         // !!operator = ( x ) ;
    7827      208299 :         if (tok->strAt(-2) != "operator" &&
    7828      208864 :             tok->previous() && tok->previous()->str() == "=" &&
    7829      209490 :             tok->next() && tok->next()->str() != "{" &&
    7830         597 :             Token::simpleMatch(tok->link(), ") ;")) {
    7831         149 :             tok->link()->deleteThis();
    7832         149 :             tok->deleteThis();
    7833         149 :             continue;
    7834             :         }
    7835             : 
    7836      106902 :         while (Token::simpleMatch(tok, "( (") &&
    7837      106902 :                tok->link() && tok->link()->previous() == tok->next()->link()) {
    7838             :             // We have "(( *something* ))", remove the inner
    7839             :             // parentheses
    7840          75 :             tok->deleteNext();
    7841          75 :             tok->link()->tokAt(-2)->deleteNext();
    7842          75 :             ret = true;
    7843             :         }
    7844             : 
    7845      104000 :         if (isCPP() && Token::Match(tok->tokAt(-2), "[;{}=(] new (") && Token::Match(tok->link(), ") [;,{}[]")) {
    7846             :             // Remove the parentheses in "new (type)" constructs
    7847           5 :             tok->link()->deleteThis();
    7848           5 :             tok->deleteThis();
    7849           5 :             ret = true;
    7850             :         }
    7851             : 
    7852      104001 :         if (Token::Match(tok->previous(), "! ( %name% )")) {
    7853             :             // Remove the parentheses
    7854          17 :             tok->deleteThis();
    7855          17 :             tok->deleteNext();
    7856          17 :             ret = true;
    7857             :         }
    7858             : 
    7859      104001 :         if (Token::Match(tok->previous(), "[(,;{}] ( %name% ) .")) {
    7860             :             // Remove the parentheses
    7861          11 :             tok->deleteThis();
    7862          11 :             tok->deleteNext();
    7863          11 :             ret = true;
    7864             :         }
    7865             : 
    7866      104065 :         if (Token::Match(tok->previous(), "[(,;{}] ( %name% (") && !tok->next()->isKeyword() &&
    7867          63 :             tok->link()->previous() == tok->linkAt(2)) {
    7868             :             // We have "( func ( *something* ))", remove the outer
    7869             :             // parentheses
    7870           6 :             tok->link()->deleteThis();
    7871           6 :             tok->deleteThis();
    7872           6 :             ret = true;
    7873             :         }
    7874             : 
    7875      104003 :         if (Token::Match(tok->previous(), "[,;{}] ( delete [| ]| %name% ) ;")) {
    7876             :             // We have "( delete [| ]| var )", remove the outer
    7877             :             // parentheses
    7878           2 :             tok->link()->deleteThis();
    7879           2 :             tok->deleteThis();
    7880           2 :             ret = true;
    7881             :         }
    7882             : 
    7883      104002 :         if (!Token::simpleMatch(tok->tokAt(-2), "operator delete") &&
    7884      112195 :             Token::Match(tok->previous(), "delete|; (") &&
    7885      216198 :             (tok->previous()->str() != "delete" || tok->next()->varId() > 0) &&
    7886        8185 :             Token::Match(tok->link(), ") ;|,")) {
    7887          24 :             tok->link()->deleteThis();
    7888          24 :             tok->deleteThis();
    7889          24 :             ret = true;
    7890             :         }
    7891             : 
    7892      113258 :         if (Token::Match(tok->previous(), "[(!*;{}] ( %name% )") &&
    7893      113259 :             (tok->next()->varId() != 0 || Token::Match(tok->tokAt(3), "[+-/=]")) && !tok->next()->isStandardType()) {
    7894             :             // We have "( var )", remove the parentheses
    7895           6 :             tok->deleteThis();
    7896           6 :             tok->deleteNext();
    7897           6 :             ret = true;
    7898             :         }
    7899             : 
    7900      104011 :         while (Token::Match(tok->previous(), "[;{}[(,!*] ( %name% .")) {
    7901          45 :             Token *tok2 = tok->tokAt(2);
    7902          86 :             while (Token::Match(tok2, ". %name%")) {
    7903          41 :                 tok2 = tok2->tokAt(2);
    7904             :             }
    7905          45 :             if (tok2 != tok->link())
    7906          38 :                 break;
    7907             :             // We have "( var . var . ... . var )", remove the parentheses
    7908           7 :             tok = tok->previous();
    7909           7 :             tok->deleteNext();
    7910           7 :             tok2->deleteThis();
    7911           7 :             ret = true;
    7912             :         }
    7913             : 
    7914      104445 :         while (Token::Match(tok->previous(), "[{([,] ( !!{") &&
    7915        2150 :                Token::Match(tok->link(), ") [;,])]") &&
    7916      107042 :                !Token::simpleMatch(tok->tokAt(-2), "operator ,") && // Ticket #5709
    7917         446 :                !Token::findsimplematch(tok, ",", tok->link())) {
    7918             :             // We have "( ... )", remove the parentheses
    7919         441 :             tok->link()->deleteThis();
    7920         441 :             tok->deleteThis();
    7921         441 :             ret = true;
    7922             :         }
    7923             : 
    7924      104101 :         if (Token::simpleMatch(tok->previous(), ", (") &&
    7925          96 :             Token::simpleMatch(tok->link(), ") =")) {
    7926           4 :             tok->link()->deleteThis();
    7927           4 :             tok->deleteThis();
    7928           4 :             ret = true;
    7929             :         }
    7930             : 
    7931             :         // Simplify "!!operator !!%name%|)|]|>|>> ( %num%|%bool% ) %op%|;|,|)"
    7932      106388 :         if (Token::Match(tok, "( %bool%|%num% ) %cop%|;|,|)") &&
    7933        4766 :             tok->strAt(-2) != "operator" &&
    7934        2383 :             tok->previous() &&
    7935      106497 :             !Token::Match(tok->previous(), "%name%|)|]") &&
    7936         110 :             (!(isCPP() && Token::Match(tok->previous(),">|>>")))) {
    7937          53 :             tok->link()->deleteThis();
    7938          53 :             tok->deleteThis();
    7939          53 :             ret = true;
    7940             :         }
    7941             : 
    7942      104004 :         if (Token::Match(tok->previous(), "*|& ( %name% )")) {
    7943             :             // We may have a variable declaration looking like "type_name *(var_name)"
    7944          20 :             Token *tok2 = tok->tokAt(-2);
    7945          27 :             while (Token::Match(tok2, "%type%|static|const|extern") && tok2->str() != "operator") {
    7946           7 :                 tok2 = tok2->previous();
    7947             :             }
    7948          20 :             if (tok2 && !Token::Match(tok2, "[;,{]")) {
    7949             :                 // Not a variable declaration
    7950             :             } else {
    7951           5 :                 tok->deleteThis();
    7952           5 :                 tok->deleteNext();
    7953             :             }
    7954             :         }
    7955             :     }
    7956       22636 :     return ret;
    7957             : }
    7958             : 
    7959       16713 : void Tokenizer::simplifyTypeIntrinsics()
    7960             : {
    7961             :     static const std::unordered_map<std::string, std::string> intrinsics = {
    7962             :         { "__has_nothrow_assign", "has_nothrow_assign" },
    7963             :         { "__has_nothrow_constructor", "has_nothrow_constructor" },
    7964             :         { "__has_nothrow_copy", "has_nothrow_copy" },
    7965             :         { "__has_trivial_assign", "has_trivial_assign" },
    7966             :         { "__has_trivial_constructor", "has_trivial_constructor" },
    7967             :         { "__has_trivial_copy", "has_trivial_copy" },
    7968             :         { "__has_trivial_destructor", "has_trivial_destructor" },
    7969             :         { "__has_virtual_destructor", "has_virtual_destructor" },
    7970             :         { "__is_abstract", "is_abstract" },
    7971             :         { "__is_aggregate", "is_aggregate" },
    7972             :         { "__is_assignable", "is_assignable" },
    7973             :         { "__is_base_of", "is_base_of" },
    7974             :         { "__is_class", "is_class" },
    7975             :         { "__is_constructible", "is_constructible" },
    7976             :         { "__is_convertible_to", "is_convertible_to" },
    7977             :         { "__is_destructible", "is_destructible" },
    7978             :         { "__is_empty", "is_empty" },
    7979             :         { "__is_enum", "is_enum" },
    7980             :         { "__is_final", "is_final" },
    7981             :         { "__is_nothrow_assignable", "is_nothrow_assignable" },
    7982             :         { "__is_nothrow_constructible", "is_nothrow_constructible" },
    7983             :         { "__is_nothrow_destructible", "is_nothrow_destructible" },
    7984             :         { "__is_pod", "is_pod" },
    7985             :         { "__is_polymorphic", "is_polymorphic" },
    7986             :         { "__is_trivially_assignable", "is_trivially_assignable" },
    7987             :         { "__is_trivially_constructible", "is_trivially_constructible" },
    7988             :         { "__is_union", "is_union" },
    7989       17105 :     };
    7990      747185 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    7991      730469 :         if (!Token::Match(tok, "%name% ("))
    7992      730461 :             continue;
    7993       61893 :         auto p = intrinsics.find(tok->str());
    7994       61896 :         if (p == intrinsics.end())
    7995       61888 :             continue;
    7996          11 :         Token * end = tok->next()->link();
    7997          11 :         Token * prev = tok->previous();
    7998          11 :         tok->str(p->second);
    7999          11 :         prev->insertToken("::");
    8000          11 :         prev->insertToken("std");
    8001          11 :         tok->next()->str("<");
    8002          11 :         end->str(">");
    8003          11 :         end->insertToken("}");
    8004          11 :         end->insertToken("{");
    8005          11 :         Token::createMutualLinks(end->tokAt(1), end->tokAt(2));
    8006             :     }
    8007       16715 : }
    8008             : 
    8009             : //---------------------------------------------------------------------------
    8010             : // Helper functions for handling the tokens list
    8011             : //---------------------------------------------------------------------------
    8012             : 
    8013             : //---------------------------------------------------------------------------
    8014             : 
    8015         624 : bool Tokenizer::isScopeNoReturn(const Token *endScopeToken, bool *unknown) const
    8016             : {
    8017        1248 :     std::string unknownFunc;
    8018         624 :     const bool ret = mSettings.library.isScopeNoReturn(endScopeToken,&unknownFunc);
    8019         624 :     if (!unknownFunc.empty() && mSettings.summaryReturn.find(unknownFunc) != mSettings.summaryReturn.end()) {
    8020           0 :         return false;
    8021             :     }
    8022         624 :     if (unknown)
    8023         452 :         *unknown = !unknownFunc.empty();
    8024         624 :     if (!unknownFunc.empty() && mSettings.checkLibrary) {
    8025          38 :         bool warn = true;
    8026          38 :         if (Token::simpleMatch(endScopeToken->tokAt(-2), ") ; }")) {
    8027          38 :             const Token * const ftok = endScopeToken->linkAt(-2)->previous();
    8028          38 :             if (ftok && (ftok->type() || ftok->function() || ftok->variable())) // constructor call
    8029          23 :                 warn = false;
    8030             :         }
    8031             : 
    8032          38 :         if (warn) {
    8033          15 :             reportError(endScopeToken->previous(),
    8034             :                         Severity::information,
    8035             :                         "checkLibraryNoReturn",
    8036          30 :                         "--check-library: Function " + unknownFunc + "() should have <noreturn> configuration");
    8037             :         }
    8038             :     }
    8039         624 :     return ret;
    8040             : }
    8041             : 
    8042             : //---------------------------------------------------------------------------
    8043             : 
    8044         575 : void Tokenizer::syntaxError(const Token *tok, const std::string &code) const
    8045             : {
    8046         575 :     printDebugOutput(0);
    8047        1069 :     throw InternalError(tok, code.empty() ? "syntax error" : "syntax error: " + code, InternalError::SYNTAX);
    8048             : }
    8049             : 
    8050          22 : void Tokenizer::unmatchedToken(const Token *tok) const
    8051             : {
    8052          22 :     printDebugOutput(0);
    8053          22 :     throw InternalError(tok,
    8054          44 :                         "Unmatched '" + tok->str() + "'. Configuration: '" + mConfiguration + "'.",
    8055          44 :                         InternalError::SYNTAX);
    8056             : }
    8057             : 
    8058          38 : void Tokenizer::syntaxErrorC(const Token *tok, const std::string &what) const
    8059             : {
    8060          38 :     printDebugOutput(0);
    8061          38 :     throw InternalError(tok, "Code '"+what+"' is invalid C code. Use --std or --language to configure the language.", InternalError::SYNTAX);
    8062             : }
    8063             : 
    8064          44 : void Tokenizer::unknownMacroError(const Token *tok1) const
    8065             : {
    8066          44 :     printDebugOutput(0);
    8067          44 :     throw InternalError(tok1, "There is an unknown macro here somewhere. Configuration is required. If " + tok1->str() + " is a macro then please configure it.", InternalError::UNKNOWN_MACRO);
    8068             : }
    8069             : 
    8070           1 : void Tokenizer::unhandled_macro_class_x_y(const Token *tok) const
    8071             : {
    8072           1 :     reportError(tok,
    8073             :                 Severity::information,
    8074             :                 "class_X_Y",
    8075           0 :                 "The code '" +
    8076           2 :                 tok->str() + " " +
    8077           3 :                 tok->strAt(1) + " " +
    8078           3 :                 tok->strAt(2) + " " +
    8079           3 :                 tok->strAt(3) + "' is not handled. You can use -I or --include to add handling of this code.");
    8080           1 : }
    8081             : 
    8082           0 : void Tokenizer::macroWithSemicolonError(const Token *tok, const std::string &macroName) const
    8083             : {
    8084           0 :     reportError(tok,
    8085             :                 Severity::information,
    8086             :                 "macroWithSemicolon",
    8087           0 :                 "Ensure that '" + macroName + "' is defined either using -I, --include or -D.");
    8088           0 : }
    8089             : 
    8090           1 : void Tokenizer::cppcheckError(const Token *tok) const
    8091             : {
    8092           1 :     printDebugOutput(0);
    8093           1 :     throw InternalError(tok, "Analysis failed. If the code is valid then please report this failure.", InternalError::INTERNAL);
    8094             : }
    8095             : 
    8096           0 : void Tokenizer::unhandledCharLiteral(const Token *tok, const std::string& msg) const
    8097             : {
    8098           0 :     std::string s = tok ? (" " + tok->str()) : "";
    8099           0 :     for (int i = 0; i < s.size(); ++i) {
    8100           0 :         if ((unsigned char)s[i] >= 0x80)
    8101           0 :             s.clear();
    8102             :     }
    8103             : 
    8104           0 :     reportError(tok,
    8105             :                 Severity::portability,
    8106             :                 "nonStandardCharLiteral",
    8107           0 :                 "Non-standard character literal" + s + ". " + msg);
    8108           0 : }
    8109             : 
    8110             : /**
    8111             :  * Helper function to check whether number is equal to integer constant X
    8112             :  * or floating point pattern X.0
    8113             :  * @param s the string to check
    8114             :  * @param intConstant the integer constant to check against
    8115             :  * @param floatConstant the string with stringified float constant to check against
    8116             :  * @return true in case s is equal to X or X.0 and false otherwise.
    8117             :  */
    8118          22 : static bool isNumberOneOf(const std::string &s, MathLib::bigint intConstant, const char* floatConstant)
    8119             : {
    8120          22 :     if (MathLib::isInt(s)) {
    8121          11 :         if (MathLib::toBigNumber(s) == intConstant)
    8122          11 :             return true;
    8123          11 :     } else if (MathLib::isFloat(s)) {
    8124           9 :         if (MathLib::toString(MathLib::toDoubleNumber(s)) == floatConstant)
    8125           7 :             return true;
    8126             :     }
    8127           4 :     return false;
    8128             : }
    8129             : 
    8130             : // ------------------------------------------------------------------------
    8131             : // Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not?
    8132             : // @param s the string to check
    8133             : // @return true in case s is one and false otherwise.
    8134             : // ------------------------------------------------------------------------
    8135          24 : bool Tokenizer::isOneNumber(const std::string &s)
    8136             : {
    8137          24 :     if (!MathLib::isPositive(s))
    8138           2 :         return false;
    8139          22 :     return isNumberOneOf(s, 1L, "1.0");
    8140             : }
    8141             : // ------------------------------------------------------------------------
    8142       22707 : void Tokenizer::checkConfiguration() const
    8143             : {
    8144       22707 :     if (!mSettings.checkConfiguration)
    8145       22706 :         return;
    8146           1 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8147           0 :         if (!Token::Match(tok, "%name% ("))
    8148           0 :             continue;
    8149           0 :         if (tok->isControlFlowKeyword())
    8150           0 :             continue;
    8151           0 :         for (const Token *tok2 = tok->tokAt(2); tok2 && tok2->str() != ")"; tok2 = tok2->next()) {
    8152           0 :             if (tok2->str() == ";") {
    8153           0 :                 macroWithSemicolonError(tok, tok->str());
    8154           0 :                 break;
    8155             :             }
    8156           0 :             if (Token::Match(tok2, "(|{"))
    8157           0 :                 tok2 = tok2->link();
    8158             :         }
    8159             :     }
    8160             : }
    8161             : 
    8162       23289 : void Tokenizer::validateC() const
    8163             : {
    8164       23289 :     if (isCPP())
    8165       17106 :         return;
    8166      271318 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8167             :         // That might trigger false positives, but it's much faster to have this truncated pattern
    8168      265170 :         if (Token::Match(tok, "const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
    8169           4 :             syntaxErrorC(tok, "C++ cast <...");
    8170             :         // Template function..
    8171      265168 :         if (Token::Match(tok, "%name% < %name% > (")) {
    8172           6 :             const Token *tok2 = tok->tokAt(5);
    8173           6 :             while (tok2 && !Token::Match(tok2, "[()]"))
    8174           0 :                 tok2 = tok2->next();
    8175           6 :             if (Token::simpleMatch(tok2, ") {"))
    8176           4 :                 syntaxErrorC(tok, tok->str() + '<' + tok->strAt(2) + ">() {}");
    8177             :         }
    8178      265167 :         if (tok->previous() && !Token::Match(tok->previous(), "[;{}]"))
    8179      215209 :             continue;
    8180       49958 :         if (Token::Match(tok, "using namespace %name% ;"))
    8181           2 :             syntaxErrorC(tok, "using namespace " + tok->strAt(2));
    8182       49957 :         if (Token::Match(tok, "template < class|typename %name% [,>]"))
    8183          18 :             syntaxErrorC(tok, "template<...");
    8184       49948 :         if (Token::Match(tok, "%name% :: %name%"))
    8185          15 :             syntaxErrorC(tok, tok->str() + tok->strAt(1) + tok->strAt(2));
    8186       49943 :         if (Token::Match(tok, "class|namespace %name% [:{]"))
    8187          32 :             syntaxErrorC(tok, tok->str() + tok->strAt(1) + tok->strAt(2));
    8188             :     }
    8189             : }
    8190             : 
    8191      146740 : void Tokenizer::validate() const
    8192             : {
    8193      293471 :     std::stack<const Token *> linkTokens;
    8194      146747 :     const Token *lastTok = nullptr;
    8195     6552966 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8196     6406185 :         lastTok = tok;
    8197     6406185 :         if (Token::Match(tok, "[{([]") || (tok->str() == "<" && tok->link())) {
    8198     1038143 :             if (tok->link() == nullptr)
    8199           0 :                 cppcheckError(tok);
    8200             : 
    8201     1038143 :             linkTokens.push(tok);
    8202             :         }
    8203             : 
    8204     5368051 :         else if (Token::Match(tok, "[})]]") || (Token::Match(tok, ">|>>") && tok->link())) {
    8205     1038112 :             if (tok->link() == nullptr)
    8206           0 :                 cppcheckError(tok);
    8207             : 
    8208     1038112 :             if (linkTokens.empty())
    8209           0 :                 cppcheckError(tok);
    8210             : 
    8211     1038111 :             if (tok->link() != linkTokens.top())
    8212           0 :                 cppcheckError(tok);
    8213             : 
    8214     1038135 :             if (tok != tok->link()->link())
    8215           0 :                 cppcheckError(tok);
    8216             : 
    8217     1038122 :             linkTokens.pop();
    8218             :         }
    8219             : 
    8220     4329849 :         else if (tok->link() != nullptr)
    8221           0 :             cppcheckError(tok);
    8222             :     }
    8223             : 
    8224      146731 :     if (!linkTokens.empty())
    8225           0 :         cppcheckError(linkTokens.top());
    8226             : 
    8227             :     // Validate that the Tokenizer::list.back() is updated correctly during simplifications
    8228      146731 :     if (lastTok != list.back())
    8229           0 :         cppcheckError(lastTok);
    8230      146743 : }
    8231             : 
    8232       61345 : static const Token *findUnmatchedTernaryOp(const Token * const begin, const Token * const end, int depth = 0)
    8233             : {
    8234      122688 :     std::stack<const Token *> ternaryOp;
    8235      389369 :     for (const Token *tok = begin; tok != end && tok->str() != ";"; tok = tok->next()) {
    8236      328046 :         if (tok->str() == "?")
    8237         349 :             ternaryOp.push(tok);
    8238      327695 :         else if (!ternaryOp.empty() && tok->str() == ":")
    8239         321 :             ternaryOp.pop();
    8240      327374 :         else if (depth < 100 && Token::Match(tok,"(|[")) {
    8241       38543 :             const Token *inner = findUnmatchedTernaryOp(tok->next(), tok->link(), depth+1);
    8242       38542 :             if (inner)
    8243          22 :                 return inner;
    8244       38520 :             tok = tok->link();
    8245             :         }
    8246             :     }
    8247       61320 :     return ternaryOp.empty() ? nullptr : ternaryOp.top();
    8248             : }
    8249             : 
    8250     1714591 : static bool isCPPAttribute(const Token * tok)
    8251             : {
    8252     1714591 :     return Token::simpleMatch(tok, "[ [") && tok->link() && tok->link()->previous() == tok->linkAt(1);
    8253             : }
    8254             : 
    8255     1714199 : static bool isAlignAttribute(const Token * tok)
    8256             : {
    8257     1714199 :     return Token::simpleMatch(tok, "alignas (") && tok->next()->link();
    8258             : }
    8259             : 
    8260             : template<typename T>
    8261         192 : static T* skipCPPOrAlignAttribute(T * tok)
    8262             : {
    8263         192 :     if (isCPPAttribute(tok))
    8264         180 :         return tok->link();
    8265          12 :     if (isAlignAttribute(tok)) {
    8266          12 :         return tok->next()->link();
    8267             :     }
    8268           0 :     return tok;
    8269             : }
    8270             : 
    8271       88540 : static bool isNonMacro(const Token* tok)
    8272             : {
    8273       88540 :     if (tok->isKeyword() || tok->isStandardType())
    8274       12420 :         return true;
    8275       76120 :     if (cAlternativeTokens.count(tok->str()) > 0)
    8276           1 :         return true;
    8277       76122 :     if (startsWith(tok->str(), "__")) // attribute/annotation
    8278          70 :         return true;
    8279       76052 :     if (Token::simpleMatch(tok, "alignas ("))
    8280           2 :         return true;
    8281       76050 :     return false;
    8282             : }
    8283             : 
    8284       22665 : void Tokenizer::reportUnknownMacros() const
    8285             : {
    8286             :     // Report unknown macros used in expressions "%name% %num%"
    8287     1024654 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8288     1001989 :         if (Token::Match(tok, "%name% %num%")) {
    8289             :             // A keyword is not an unknown macro
    8290        3075 :             if (tok->isKeyword())
    8291        3074 :                 continue;
    8292             : 
    8293           1 :             if (Token::Match(tok->previous(), "%op%|("))
    8294           1 :                 unknownMacroError(tok);
    8295             :         }
    8296             :     }
    8297             : 
    8298             :     // Report unknown macros before } "{ .. if (x) MACRO }"
    8299     1024652 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8300     1001986 :         if (Token::Match(tok, ")|; %name% } !!)")) {
    8301           5 :             if (tok->link() && !Token::simpleMatch(tok->link()->tokAt(-1), "if"))
    8302           2 :                 continue;
    8303           3 :             const Token* prev = tok->linkAt(2);
    8304           6 :             while (Token::simpleMatch(prev, "{"))
    8305           3 :                 prev = prev->previous();
    8306           3 :             if (Token::Match(prev, ";|)"))
    8307           1 :                 unknownMacroError(tok->next());
    8308             :         }
    8309             :     }
    8310             : 
    8311             :     // Report unknown macros that contain several statements "MACRO(a;b;c)"
    8312     1024648 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8313     1001985 :         if (!Token::Match(tok, "%name% ("))
    8314      913494 :             continue;
    8315       88488 :         if (!tok->isUpperCaseName())
    8316       77143 :             continue;
    8317       11347 :         const Token *endTok = tok->linkAt(1);
    8318       63369 :         for (const Token *inner = tok->tokAt(2); inner != endTok; inner = inner->next()) {
    8319       52022 :             if (Token::Match(inner, "[[({]"))
    8320       10057 :                 inner = inner->link();
    8321       41965 :             else if (inner->str() == ";")
    8322           0 :                 unknownMacroError(tok);
    8323             :         }
    8324             :     }
    8325             : 
    8326             :     // Report unknown macros that contain struct initialization "MACRO(a, .b=3)"
    8327     1024621 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8328     1001952 :         if (!Token::Match(tok, "%name% ("))
    8329      913471 :             continue;
    8330       88484 :         const Token *endTok = tok->linkAt(1);
    8331      338790 :         for (const Token *inner = tok->tokAt(2); inner != endTok; inner = inner->next()) {
    8332      250303 :             if (Token::Match(inner, "[[({]"))
    8333       16741 :                 inner = inner->link();
    8334      233562 :             else if (Token::Match(inner->previous(), "[,(] . %name% =|{"))
    8335           1 :                 unknownMacroError(tok);
    8336             :         }
    8337             :     }
    8338             : 
    8339             :     // Report unknown macros in non-executable scopes..
    8340       45327 :     std::set<std::string> possible;
    8341      406329 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8342             :         // Skip executable scopes..
    8343      383673 :         if (tok->str() == "{") {
    8344       35456 :             const Token *prev = tok->previous();
    8345       47239 :             while (prev && prev->isName())
    8346       11783 :                 prev = prev->previous();
    8347       35456 :             if (prev && prev->str() == ")")
    8348       28893 :                 tok = tok->link();
    8349             :             else
    8350        6563 :                 possible.clear();
    8351      348217 :         } else if (tok->str() == "}")
    8352        6560 :             possible.clear();
    8353             : 
    8354      383673 :         if (Token::Match(tok, "%name% (") && tok->isUpperCaseName() && Token::simpleMatch(tok->linkAt(1), ") (") && Token::simpleMatch(tok->linkAt(1)->linkAt(1), ") {")) {
    8355             :             // A keyword is not an unknown macro
    8356           2 :             if (tok->isKeyword())
    8357           0 :                 continue;
    8358             : 
    8359           2 :             const Token *bodyStart = tok->linkAt(1)->linkAt(1)->tokAt(2);
    8360           2 :             const Token *bodyEnd = tok->link();
    8361           2 :             for (const Token *tok2 = bodyStart; tok2 && tok2 != bodyEnd; tok2 = tok2->next()) {
    8362           2 :                 if (Token::Match(tok2, "if|switch|for|while|return"))
    8363           2 :                     unknownMacroError(tok);
    8364             :             }
    8365      383668 :         } else if (Token::Match(tok, "%name% (") && tok->isUpperCaseName() && Token::Match(tok->linkAt(1), ") %name% (") && Token::Match(tok->linkAt(1)->linkAt(2), ") [;{]")) {
    8366           9 :             if (!(tok->linkAt(1)->next() && tok->linkAt(1)->next()->isKeyword())) { // e.g. noexcept(true)
    8367           2 :                 if (possible.count(tok->str()) == 0)
    8368           1 :                     possible.insert(tok->str());
    8369             :                 else
    8370           1 :                     unknownMacroError(tok);
    8371             :             }
    8372      383661 :         } else if (isCPP() && Token::Match(tok, "public|private|protected %name% :")) {
    8373           2 :             unknownMacroError(tok->next());
    8374             :         }
    8375             :     }
    8376             : 
    8377             :     // String concatenation with unknown macros
    8378     1024407 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8379     2003529 :         if ((Token::Match(tok, "%str% %name% (") && Token::Match(tok->linkAt(2), ") %str%")) ||
    8380     1001768 :             (Token::Match(tok, "%str% %name% %str%") && !(startsWith(tok->strAt(1), "PRI") || startsWith(tok->strAt(1), "SCN")))) { // TODO: implement macros in std.cfg
    8381           4 :             if (tok->next()->isKeyword())
    8382           0 :                 continue;
    8383           4 :             unknownMacroError(tok->next());
    8384             :         }
    8385     1001765 :         if (Token::Match(tok, "[(,] %name% (") && Token::Match(tok->linkAt(2), ") %name% %name%|,|)")) {
    8386           4 :             if (tok->next()->isKeyword() || tok->linkAt(2)->next()->isKeyword())
    8387           3 :                 continue;
    8388           1 :             if (cAlternativeTokens.count(tok->linkAt(2)->next()->str()) > 0)
    8389           0 :                 continue;
    8390           1 :             if (startsWith(tok->next()->str(), "__")) // attribute/annotation
    8391           0 :                 continue;
    8392           1 :             unknownMacroError(tok->next());
    8393             :         }
    8394             :     }
    8395             : 
    8396             :     // Report unknown macros without commas or operators inbetween statements: MACRO1() MACRO2()
    8397     1024322 :     for (const Token* tok = tokens(); tok; tok = tok->next()) {
    8398     1001669 :         if (!Token::Match(tok, "%name% ("))
    8399      913219 :             continue;
    8400       88449 :         if (isNonMacro(tok) && !tok->isStandardType())
    8401       11980 :             continue;
    8402             : 
    8403       76475 :         const Token* endTok = tok->linkAt(1);
    8404       76475 :         if (!Token::Match(endTok, ") %name% (|."))
    8405       76387 :             continue;
    8406             : 
    8407          88 :         const Token* tok2 = endTok->next();
    8408          88 :         if (isNonMacro(tok2))
    8409          83 :             continue;
    8410             : 
    8411           5 :         if (tok2->next()->str() == "(") {
    8412           4 :             if (Token::Match(tok->previous(), "%name%|::|>"))
    8413           2 :                 continue;
    8414             :         }
    8415             : 
    8416           3 :         unknownMacroError(tok->isStandardType() ? tok2 : tok);
    8417             :     }
    8418       22651 : }
    8419             : 
    8420       23218 : void Tokenizer::findGarbageCode() const
    8421             : {
    8422       23218 :     const bool isCPP11 = isCPP() && mSettings.standards.cpp >= Standards::CPP11;
    8423             : 
    8424             :     static const std::unordered_set<std::string> nonConsecutiveKeywords{ "break",
    8425             :                                                                          "continue",
    8426             :                                                                          "for",
    8427             :                                                                          "goto",
    8428             :                                                                          "if",
    8429             :                                                                          "return",
    8430             :                                                                          "switch",
    8431             :                                                                          "throw",
    8432             :                                                                          "typedef",
    8433       23503 :                                                                          "while" };
    8434             : 
    8435     1014640 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8436             :         // initialization: = {
    8437      991566 :         if (Token::simpleMatch(tok, "= {") && Token::simpleMatch(tok->linkAt(1), "} ("))
    8438           4 :             syntaxError(tok->linkAt(1));
    8439             : 
    8440             :         // Inside [] there can't be ; or various keywords
    8441      991545 :         else if (tok->str() == "[") {
    8442       10935 :             for (const Token* inner = tok->next(); inner != tok->link(); inner = inner->next()) {
    8443        5391 :                 if (Token::Match(inner, "(|[|{"))
    8444         128 :                     inner = inner->link();
    8445        5263 :                 else if (Token::Match(inner, ";|goto|return|typedef"))
    8446          12 :                     syntaxError(inner);
    8447             :             }
    8448             :         }
    8449             : 
    8450             :         // array assignment
    8451      985989 :         else if (Token::Match(tok, "%assign% [") && Token::simpleMatch(tok->linkAt(1), "] ;"))
    8452          12 :             syntaxError(tok, tok->str() + "[...];");
    8453             : 
    8454      986003 :         else if (Token::Match(tok, "[({<] %assign%"))
    8455          21 :             syntaxError(tok);
    8456             : 
    8457      985976 :         else if (Token::Match(tok, "[`\\@]"))
    8458           9 :             syntaxError(tok);
    8459             : 
    8460             :         // UNKNOWN_MACRO(return)
    8461      991496 :         if (tok->isKeyword() && Token::Match(tok, "throw|return )") && Token::Match(tok->linkAt(1)->previous(), "%name% ("))
    8462           3 :             unknownMacroError(tok->linkAt(1)->previous());
    8463             : 
    8464             :         // UNKNOWN_MACRO(return)
    8465      991494 :         else if (Token::Match(tok, "%name% throw|return") && std::isupper(tok->str()[0]))
    8466           1 :             unknownMacroError(tok);
    8467             : 
    8468             :         // Assign/increment/decrement literal
    8469      991506 :         else if (Token::Match(tok, "!!) %num%|%str%|%char% %assign%|++|--")) {
    8470           5 :             if (!isCPP() || mSettings.standards.cpp < Standards::CPP20 || !Token::Match(tok->previous(), "%name% : %num% ="))
    8471          12 :                 syntaxError(tok, tok->next()->str() + " " + tok->strAt(2));
    8472             :         }
    8473      991492 :         else if (Token::simpleMatch(tok, ") return") && !Token::Match(tok->link()->previous(), "if|while|for (")) {
    8474           4 :             if (tok->link()->previous() && tok->link()->previous()->isUpperCaseName())
    8475           1 :                 unknownMacroError(tok->link()->previous());
    8476             :             else
    8477           3 :                 syntaxError(tok);
    8478             :         }
    8479             : 
    8480      991492 :         if (tok->isControlFlowKeyword() && Token::Match(tok, "if|while|for|switch")) { // if|while|for|switch (EXPR) { ... }
    8481       10277 :             if (tok->previous() && !Token::Match(tok->previous(), "%name%|:|;|{|}|)")) {
    8482          16 :                 if (Token::Match(tok->previous(), "[,(]")) {
    8483          12 :                     const Token *prev = tok->previous();
    8484          32 :                     while (prev && prev->str() != "(") {
    8485          20 :                         if (prev->str() == ")")
    8486           2 :                             prev = prev->link();
    8487          20 :                         prev = prev->previous();
    8488             :                     }
    8489          12 :                     if (prev && Token::Match(prev->previous(), "%name% ("))
    8490           5 :                         unknownMacroError(prev->previous());
    8491             :                 }
    8492          11 :                 if (!Token::simpleMatch(tok->tokAt(-2), "operator \"\" if"))
    8493           9 :                     syntaxError(tok);
    8494             :             }
    8495       10263 :             if (!Token::Match(tok->next(), "( !!)"))
    8496          32 :                 syntaxError(tok);
    8497       10231 :             if (tok->str() != "for") {
    8498        9229 :                 if (isGarbageExpr(tok->next(), tok->linkAt(1), isCPP() && (mSettings.standards.cpp>=Standards::cppstd_t::CPP17)))
    8499           0 :                     syntaxError(tok);
    8500             :             }
    8501             :         }
    8502             : 
    8503             :         // keyword keyword
    8504      991449 :         if (tok->isKeyword() && nonConsecutiveKeywords.count(tok->str()) != 0) {
    8505       18808 :             if (Token::Match(tok, "%name% %name%") && nonConsecutiveKeywords.count(tok->next()->str()) == 1)
    8506          14 :                 syntaxError(tok);
    8507       18794 :             const Token* prev = tok;
    8508       39812 :             while (prev && prev->isName())
    8509       21016 :                 prev = prev->previous();
    8510       18794 :             if (Token::Match(prev, "%op%|%num%|%str%|%char%")) {
    8511          21 :                 if (!Token::simpleMatch(tok->tokAt(-2), "operator \"\" if") &&
    8512          39 :                     !Token::simpleMatch(tok->tokAt(-2), "extern \"C\"") &&
    8513          18 :                     !Token::simpleMatch(prev, "> typedef"))
    8514          60 :                     syntaxError(tok, prev == tok->previous() ? (prev->str() + " " + tok->str()) : (prev->str() + " .. " + tok->str()));
    8515             :             }
    8516             :         }
    8517             :     }
    8518             : 
    8519             :     // invalid struct declaration
    8520     1013218 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8521      990154 :         if (Token::Match(tok, "struct|class|enum %name%| {") && (!tok->previous() || Token::Match(tok->previous(), "[;{}]"))) {
    8522        4062 :             const Token *tok2 = tok->linkAt(tok->next()->isName() ? 2 : 1);
    8523        4062 :             if (Token::Match(tok2, "} %op%")) {
    8524          17 :                 tok2 = tok2->next();
    8525          17 :                 if (!Token::Match(tok2, "*|&|&&"))
    8526          12 :                     syntaxError(tok2, "Unexpected token '" + tok2->str() + "'");
    8527          26 :                 while (Token::Match(tok2, "*|&|&&"))
    8528          13 :                     tok2 = tok2->next();
    8529          13 :                 if (!Token::Match(tok2, "%name%"))
    8530          16 :                     syntaxError(tok2, "Unexpected token '" + (tok2 ? tok2->str() : "") + "'");
    8531             :             }
    8532             :         }
    8533      990133 :         if (Token::Match(tok, "enum : %num%| {"))
    8534           6 :             syntaxError(tok->tokAt(2), "Unexpected token '" + tok->strAt(2) + "'");
    8535             :     }
    8536             : 
    8537             :     // Keywords in global scope
    8538             :     static const std::unordered_set<std::string> nonGlobalKeywords{"break",
    8539             :                                                                    "continue",
    8540             :                                                                    "for",
    8541             :                                                                    "goto",
    8542             :                                                                    "if",
    8543             :                                                                    "return",
    8544             :                                                                    "switch",
    8545             :                                                                    "while",
    8546             :                                                                    "try",
    8547       23354 :                                                                    "catch"};
    8548      343387 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8549      320341 :         if (tok->str() == "{")
    8550       32321 :             tok = tok->link();
    8551      288017 :         else if (tok->isKeyword() && nonGlobalKeywords.count(tok->str()) && !Token::Match(tok->tokAt(-2), "operator %str%"))
    8552          42 :             syntaxError(tok, "keyword '" + tok->str() + "' is not allowed in global scope");
    8553             :     }
    8554             : 
    8555             :     // case keyword must be inside switch
    8556      615499 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8557      592441 :         if (Token::simpleMatch(tok, "switch (")) {
    8558         203 :             if (Token::simpleMatch(tok->linkAt(1), ") {")) {
    8559         193 :                 tok = tok->linkAt(1)->linkAt(1);
    8560         193 :                 continue;
    8561             :             }
    8562          10 :             const Token *switchToken = tok;
    8563          10 :             tok = tok->linkAt(1);
    8564          10 :             if (!tok)
    8565           0 :                 syntaxError(switchToken);
    8566             :             // Look for the end of the switch statement, i.e. the first semi-colon or '}'
    8567          86 :             for (; tok; tok = tok->next()) {
    8568          86 :                 if (tok->str() == "{") {
    8569           5 :                     tok = tok->link();
    8570             :                 }
    8571          86 :                 if (Token::Match(tok, ";|}")) {
    8572             :                     // We're at the end of the switch block
    8573          10 :                     if (tok->str() == "}" && tok->strAt(-1) == ":") // Invalid case
    8574           2 :                         syntaxError(switchToken);
    8575           8 :                     break;
    8576             :                 }
    8577             :             }
    8578           8 :             if (!tok)
    8579           0 :                 break;
    8580      592243 :         } else if (tok->str() == "(") {
    8581       87920 :             tok = tok->link();
    8582      504331 :         } else if (tok->str() == "case") {
    8583           7 :             syntaxError(tok);
    8584             :         }
    8585             :     }
    8586             : 
    8587     1012643 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8588      989603 :         if (!Token::simpleMatch(tok, "for (")) // find for loops
    8589      988614 :             continue;
    8590             :         // count number of semicolons
    8591         989 :         int semicolons = 0, colons = 0;
    8592         989 :         const Token* const startTok = tok;
    8593         989 :         tok = tok->next()->link()->previous(); // find ")" of the for-loop
    8594             :         // walk backwards until we find the beginning (startTok) of the for() again
    8595       13304 :         for (; tok != startTok; tok = tok->previous()) {
    8596       12316 :             if (tok->str() == ";") { // do the counting
    8597        1553 :                 semicolons++;
    8598       10763 :             } else if (tok->str() == ":") {
    8599         214 :                 colons++;
    8600       10549 :             } else if (tok->str() == ")") { // skip pairs of ( )
    8601         519 :                 tok = tok->link();
    8602             :             }
    8603             :         }
    8604             :         // if we have an invalid number of semicolons inside for( ), assume syntax error
    8605         988 :         if (semicolons > 2)
    8606           0 :             syntaxError(tok);
    8607         988 :         if (semicolons == 1 && !(isCPP() && mSettings.standards.cpp >= Standards::CPP20))
    8608           1 :             syntaxError(tok);
    8609         987 :         if (semicolons == 0 && colons == 0)
    8610           5 :             syntaxError(tok);
    8611             :     }
    8612             : 
    8613             :     // Operators without operands..
    8614       23040 :     const Token *templateEndToken = nullptr;
    8615     1010023 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8616      987221 :         if (!templateEndToken) {
    8617      968613 :             if (tok->str() == "<" && isCPP())
    8618        6433 :                 templateEndToken = tok->findClosingBracket();
    8619             :         } else {
    8620       18608 :             if (templateEndToken == tok)
    8621        5497 :                 templateEndToken = nullptr;
    8622       18608 :             if (Token::Match(tok, "> %cop%"))
    8623        1072 :                 continue;
    8624             :         }
    8625             :         // skip C++ attributes [[...]]
    8626      986149 :         if (isCPP11 && (isCPPAttribute(tok) || isAlignAttribute(tok))) {
    8627           0 :             tok = skipCPPOrAlignAttribute(tok);
    8628           0 :             continue;
    8629             :         }
    8630             :         {
    8631      986150 :             bool match1 = Token::Match(tok, "%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|++|--|::|sizeof");
    8632      986166 :             bool match2 = Token::Match(tok->next(), "{|if|else|while|do|for|return|switch|break");
    8633      986165 :             if (isCPP()) {
    8634      724276 :                 match1 = match1 || Token::Match(tok, "throw|decltype|typeof");
    8635      724277 :                 match2 = match2 || Token::Match(tok->next(), "try|catch|namespace");
    8636             :             }
    8637      986172 :             if (match1 && !tok->isIncDecOp()) {
    8638       23018 :                 match2 = match2 || Token::Match(tok->next(), "%assign%");
    8639             :             }
    8640      986172 :             if (match1 && match2)
    8641          23 :                 syntaxError(tok);
    8642             :         }
    8643      986149 :         if (Token::Match(tok, "%or%|%oror%|~|^|!|%comp%|+|-|/|%")) {
    8644       41752 :             std::string code;
    8645       20876 :             if (Token::Match(tok->next(), ")|]|}"))
    8646          75 :                 code = tok->str() + tok->next()->str();
    8647       20876 :             if (Token::simpleMatch(tok->next(), "( )"))
    8648         191 :                 code = tok->str() + "()";
    8649       20876 :             if (!code.empty()) {
    8650         266 :                 if (isC() || (tok->str() != ">" && !Token::simpleMatch(tok->previous(), "operator")))
    8651          26 :                     syntaxError(tok, code);
    8652             :             }
    8653             :         }
    8654      986099 :         if (Token::Match(tok, "%num%|%bool%|%char%|%str% %num%|%bool%|%char%|%str%") && !Token::Match(tok, "%str% %str%"))
    8655          12 :             syntaxError(tok);
    8656      986084 :         if (Token::Match(tok, "%assign% typename|class %assign%"))
    8657           8 :             syntaxError(tok);
    8658      986087 :         if (Token::Match(tok, "%assign% [;)}]") && (!isCPP() || !Token::simpleMatch(tok->previous(), "operator")))
    8659          36 :             syntaxError(tok);
    8660      986052 :         if (Token::Match(tok, "%cop%|=|,|[ %or%|%oror%|/|%"))
    8661           7 :             syntaxError(tok);
    8662      986037 :         if (Token::Match(tok, "[;([{] %comp%|%oror%|%or%|%|/"))
    8663          41 :             syntaxError(tok);
    8664      985991 :         if (Token::Match(tok, "%cop%|= ]") && !(isCPP() && Token::Match(tok->previous(), "%type%|[|,|%num% &|=|> ]")))
    8665           0 :             syntaxError(tok);
    8666      985998 :         if (Token::Match(tok, "[+-] [;,)]}]") && !(isCPP() && Token::simpleMatch(tok->previous(), "operator")))
    8667           8 :             syntaxError(tok);
    8668     1024420 :         if (Token::simpleMatch(tok, ",") &&
    8669       38436 :             !Token::Match(tok->tokAt(-2), "[ = , &|%name%")) {
    8670       38431 :             if (Token::Match(tok->previous(), "(|[|{|<|%assign%|%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|::|sizeof"))
    8671          16 :                 syntaxError(tok);
    8672       38415 :             if (isCPP() && Token::Match(tok->previous(), "throw|decltype|typeof"))
    8673           0 :                 syntaxError(tok);
    8674       38415 :             if (Token::Match(tok->next(), ")|]|>|%assign%|%or%|%oror%|==|!=|/|>=|<=|&&"))
    8675           6 :                 syntaxError(tok);
    8676             :         }
    8677      985961 :         if ((!isCPP() || !Token::simpleMatch(tok->previous(), "operator")) && Token::Match(tok, "[,;] ,"))
    8678           4 :             syntaxError(tok);
    8679      985950 :         if (Token::simpleMatch(tok, ".") &&
    8680        5332 :             !Token::simpleMatch(tok->previous(), ".") &&
    8681        5332 :             !Token::simpleMatch(tok->next(), ".") &&
    8682      996570 :             !Token::Match(tok->previous(), "{|, . %name% =|.|[|{") &&
    8683        5288 :             !Token::Match(tok->previous(), ", . %name%")) {
    8684        5288 :             if (!Token::Match(tok->previous(), "%name%|)|]|>|}"))
    8685          20 :                 syntaxError(tok, tok->strAt(-1) + " " + tok->str() + " " + tok->strAt(1));
    8686        5284 :             if (!Token::Match(tok->next(), "%name%|*|~"))
    8687           0 :                 syntaxError(tok, tok->strAt(-1) + " " + tok->str() + " " + tok->strAt(1));
    8688             :         }
    8689      985946 :         if (Token::Match(tok, "[!|+-/%^~] )|]"))
    8690           0 :             syntaxError(tok);
    8691      985949 :         if (Token::Match(tok, "==|!=|<=|>= %comp%") && tok->strAt(-1) != "operator")
    8692           2 :             syntaxError(tok, tok->str() + " " + tok->strAt(1));
    8693      999639 :         if (Token::simpleMatch(tok, "::") && (!Token::Match(tok->next(), "%name%|*|~") ||
    8694       13692 :                                               (tok->next()->isKeyword() && !Token::Match(tok->next(), "new|delete|operator"))))
    8695           4 :             syntaxError(tok);
    8696      985946 :         if (Token::Match(tok, "& %comp%|&&|%oror%|&|%or%") && tok->strAt(1) != ">")
    8697           0 :             syntaxError(tok);
    8698      985944 :         if (Token::Match(tok, "^ %op%") && !Token::Match(tok->next(), "[>*+-!~]"))
    8699           0 :             syntaxError(tok);
    8700      985948 :         if (Token::Match(tok, ": [)]=]"))
    8701           3 :             syntaxError(tok);
    8702      985945 :         if (Token::Match(tok, "typedef [,;]"))
    8703           0 :             syntaxError(tok);
    8704      985957 :         if (Token::Match(tok, "! %comp%"))
    8705           0 :             syntaxError(tok);
    8706      985954 :         if (Token::Match(tok, "] %name%") && (!isCPP() || !(tok->tokAt(-1) && Token::simpleMatch(tok->tokAt(-2), "delete ["))))
    8707           9 :             syntaxError(tok);
    8708             : 
    8709      985943 :         if (tok->link() && Token::Match(tok, "[([]") && (!tok->tokAt(-1) || !tok->tokAt(-1)->isControlFlowKeyword())) {
    8710      102611 :             const Token* const end = tok->link();
    8711   300340918 :             for (const Token* inner = tok->next(); inner != end; inner = inner->next()) {
    8712   300238340 :                 if (inner->str() == "{")
    8713         260 :                     inner = inner->link();
    8714   300238077 :                 else if (inner->str() == ";") {
    8715          30 :                     if (tok->tokAt(-1) && tok->tokAt(-1)->isUpperCaseName())
    8716           7 :                         unknownMacroError(tok->tokAt(-1));
    8717             :                     else
    8718          23 :                         syntaxError(inner);
    8719             :                 }
    8720             :             }
    8721             :         }
    8722             :     }
    8723             : 
    8724             :     // ternary operator without :
    8725       22801 :     if (const Token *ternaryOp = findUnmatchedTernaryOp(tokens(), nullptr))
    8726          12 :         syntaxError(ternaryOp);
    8727             : 
    8728             :     // Code must not start with an arithmetical operand
    8729       22791 :     if (Token::Match(list.front(), "%cop%"))
    8730          11 :         syntaxError(list.front());
    8731             : 
    8732             :     // Code must end with } ; ) NAME
    8733       22780 :     if (!Token::Match(list.back(), "%name%|;|}|)"))
    8734          42 :         syntaxError(list.back());
    8735       22738 :     if (list.back()->str() == ")" && !Token::Match(list.back()->link()->previous(), "%name%|> ("))
    8736           6 :         syntaxError(list.back());
    8737       22800 :     for (const Token *end = list.back(); end && end->isName(); end = end->previous()) {
    8738          86 :         if (Token::Match(end, "void|char|short|int|long|float|double|const|volatile|static|inline|struct|class|enum|union|template|sizeof|case|break|continue|typedef"))
    8739          18 :             syntaxError(list.back());
    8740             :     }
    8741       22713 :     if ((list.back()->str()==")" || list.back()->str()=="}") && list.back()->previous() && list.back()->previous()->isControlFlowKeyword())
    8742           1 :         syntaxError(list.back()->previous());
    8743             : 
    8744             :     // Garbage templates..
    8745       22707 :     if (isCPP()) {
    8746      733920 :         for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8747      717162 :             if (!Token::simpleMatch(tok, "template <"))
    8748      715860 :                 continue;
    8749        1297 :             if (tok->previous() && !Token::Match(tok->previous(), ":|;|{|}|)|>|\"C++\"")) {
    8750           5 :                 if (tok->previous()->isUpperCaseName())
    8751           2 :                     unknownMacroError(tok->previous());
    8752             :                 else
    8753           3 :                     syntaxError(tok);
    8754             :             }
    8755        1292 :             const Token * const tok1 = tok;
    8756        1292 :             tok = tok->next()->findClosingBracket();
    8757        1292 :             if (!tok)
    8758           1 :                 syntaxError(tok1);
    8759        1291 :             if (!Token::Match(tok, ">|>> ::|...| %name%") &&
    8760        1293 :                 !Token::Match(tok, ">|>> [ [ %name%") &&
    8761           2 :                 !Token::Match(tok, "> >|*"))
    8762           0 :                 syntaxError(tok->next() ? tok->next() : tok1);
    8763             :         }
    8764             :     }
    8765             : 
    8766             :     // Objective C/C++
    8767     1006571 :     for (const Token *tok = tokens(); tok; tok = tok->next()) {
    8768      983873 :         if (Token::Match(tok, "[;{}] [ %name% %name% ] ;"))
    8769           1 :             syntaxError(tok->next());
    8770             :     }
    8771       22703 : }
    8772             : 
    8773             : 
    8774        9229 : bool Tokenizer::isGarbageExpr(const Token *start, const Token *end, bool allowSemicolon)
    8775             : {
    8776       47354 :     for (const Token *tok = start; tok != end; tok = tok->next()) {
    8777       38125 :         if (tok->isControlFlowKeyword())
    8778           0 :             return true;
    8779       38125 :         if (!allowSemicolon && tok->str() == ";")
    8780           0 :             return true;
    8781       38125 :         if (tok->str() == "{")
    8782          19 :             tok = tok->link();
    8783             :     }
    8784        9229 :     return false;
    8785             : }
    8786             : 
    8787       10499 : std::string Tokenizer::simplifyString(const std::string &source)
    8788             : {
    8789       10499 :     std::string str = source;
    8790             : 
    8791       60798 :     for (std::string::size_type i = 0; i + 1U < str.size(); ++i) {
    8792       50299 :         if (str[i] != '\\')
    8793       50101 :             continue;
    8794             : 
    8795         217 :         int c = 'a';   // char
    8796         217 :         int sz = 0;    // size of stringdata
    8797         217 :         if (str[i+1] == 'x') {
    8798          17 :             sz = 2;
    8799          43 :             while (sz < 4 && std::isxdigit((unsigned char)str[i+sz]))
    8800          26 :                 sz++;
    8801          17 :             if (sz > 2) {
    8802          34 :                 std::istringstream istr(str.substr(i+2, sz-2));
    8803          17 :                 istr >> std::hex >> c;
    8804             :             }
    8805         200 :         } else if (MathLib::isOctalDigit(str[i+1])) {
    8806          19 :             sz = 2;
    8807          31 :             while (sz < 4 && MathLib::isOctalDigit(str[i+sz]))
    8808          12 :                 sz++;
    8809          38 :             std::istringstream istr(str.substr(i+1, sz-1));
    8810          19 :             istr >> std::oct >> c;
    8811          19 :             str = str.replace(i, sz, std::string(1U, (char)c));
    8812          19 :             continue;
    8813             :         }
    8814             : 
    8815         198 :         if (sz <= 2)
    8816         181 :             i++;
    8817          17 :         else if (i+sz < str.size())
    8818          17 :             str.replace(i, sz, std::string(1U, (char)c));
    8819             :         else
    8820           0 :             str.replace(i, str.size() - i - 1U, "a");
    8821             :     }
    8822             : 
    8823       10499 :     return str;
    8824             : }
    8825             : 
    8826       23227 : void Tokenizer::simplifyFunctionTryCatch()
    8827             : {
    8828       23227 :     if (!isCPP())
    8829        6143 :         return;
    8830             : 
    8831      747660 :     for (Token * tok = list.front(); tok; tok = tok->next()) {
    8832      730578 :         if (!Token::Match(tok, "try {|:"))
    8833      730493 :             continue;
    8834          84 :         if (!isFunctionHead(tok->previous(), "try"))
    8835          74 :             continue;
    8836             : 
    8837          10 :         Token* tryStartToken = skipInitializerList(tok->next());
    8838             : 
    8839          10 :         if (!Token::simpleMatch(tryStartToken, "{"))
    8840           0 :             syntaxError(tryStartToken, "Invalid function-try-catch block code. Did not find '{' for try body.");
    8841             : 
    8842             :         // find the end of the last catch block
    8843          10 :         Token * const tryEndToken = tryStartToken->link();
    8844          10 :         Token * endToken = tryEndToken;
    8845          21 :         while (Token::simpleMatch(endToken, "} catch (")) {
    8846          13 :             endToken = endToken->linkAt(2)->next();
    8847          13 :             if (!endToken)
    8848           0 :                 break;
    8849          13 :             if (endToken->str() != "{") {
    8850           2 :                 endToken = nullptr;
    8851           2 :                 break;
    8852             :             }
    8853          11 :             endToken = endToken->link();
    8854             :         }
    8855          10 :         if (!endToken || endToken == tryEndToken)
    8856           3 :             continue;
    8857             : 
    8858           7 :         tok->previous()->insertToken("{");
    8859           7 :         endToken->insertToken("}");
    8860           7 :         Token::createMutualLinks(tok->previous(), endToken->next());
    8861             :     }
    8862             : }
    8863             : 
    8864      395802 : static bool isAnonymousEnum(const Token* tok)
    8865             : {
    8866      395802 :     if (!Token::Match(tok, "enum {|:"))
    8867      395734 :         return false;
    8868          71 :     if (tok->index() > 2 && Token::Match(tok->tokAt(-3), "using %name% ="))
    8869           0 :         return false;
    8870          71 :     const Token* end = tok->next();
    8871          71 :     if (end->str() == ":") {
    8872           3 :         end = end->next();
    8873           8 :         while (Token::Match(end, "%name%|::"))
    8874           5 :             end = end->next();
    8875             :     }
    8876          71 :     return end && Token::Match(end->link(), "} (| %type%| )| [,;[({=]");
    8877             : }
    8878             : 
    8879       22638 : void Tokenizer::simplifyStructDecl()
    8880             : {
    8881       22638 :     const bool cpp = isCPP();
    8882             : 
    8883             :     // A counter that is used when giving unique names for anonymous structs.
    8884       22640 :     int count = 0;
    8885             : 
    8886             :     // Add names for anonymous structs
    8887     1013167 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    8888      990516 :         if (!tok->isName())
    8889      594597 :             continue;
    8890             :         // check for anonymous struct/union
    8891      395913 :         if (Token::Match(tok, "struct|union {")) {
    8892         123 :             if (Token::Match(tok->next()->link(), "} const| *|&| const| %type% ,|;|[|(|{|=")) {
    8893          65 :                 tok->insertToken("Anonymous" + std::to_string(count++));
    8894             :             }
    8895             :         }
    8896             :         // check for derived anonymous class/struct
    8897      395803 :         else if (cpp && Token::Match(tok, "class|struct :")) {
    8898           1 :             const Token *tok1 = Token::findsimplematch(tok, "{");
    8899           1 :             if (tok1 && Token::Match(tok1->link(), "} const| *|&| const| %type% ,|;|[|(|{")) {
    8900           1 :                 tok->insertToken("Anonymous" + std::to_string(count++));
    8901             :             }
    8902             :         }
    8903             :         // check for anonymous enum
    8904      395799 :         else if (isAnonymousEnum(tok)) {
    8905          66 :             Token *start = tok->strAt(1) == ":" ? tok->linkAt(3) : tok->linkAt(1);
    8906          66 :             if (start && Token::Match(start->next(), "( %type% )")) {
    8907           0 :                 start->next()->link()->deleteThis();
    8908           0 :                 start->next()->deleteThis();
    8909             :             }
    8910          66 :             tok->insertToken("Anonymous" + std::to_string(count++));
    8911             :         }
    8912             :     }
    8913             : 
    8914             :     // "{" token for current scope
    8915       45281 :     std::stack<const Token*> scopeStart;
    8916       22642 :     const Token* functionEnd = nullptr;
    8917             : 
    8918     1013812 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    8919             : 
    8920             :         // check for start of scope and determine if it is in a function
    8921      991172 :         if (tok->str() == "{") {
    8922       48120 :             scopeStart.push(tok);
    8923       48120 :             if (!functionEnd && Token::Match(tok->previous(), "const|)"))
    8924       28817 :                 functionEnd = tok->link();
    8925             :         }
    8926             : 
    8927             :         // end of scope
    8928      943052 :         else if (tok->str() == "}") {
    8929       48119 :             if (!scopeStart.empty())
    8930       48119 :                 scopeStart.pop();
    8931       48119 :             if (tok == functionEnd)
    8932       28817 :                 functionEnd = nullptr;
    8933             :         }
    8934             : 
    8935             :         // check for named struct/union
    8936      894932 :         else if (Token::Match(tok, "class|struct|union|enum %type% :|{")) {
    8937        5330 :             Token *start = tok;
    8938        5488 :             while (Token::Match(start->previous(), "%type%"))
    8939         158 :                 start = start->previous();
    8940        5330 :             const Token * const type = tok->next();
    8941        5330 :             Token *next = tok->tokAt(2);
    8942             : 
    8943        7660 :             while (next && !Token::Match(next, "[{;]"))
    8944        2330 :                 next = next->next();
    8945        5330 :             if (!next || next->str() == ";")
    8946          12 :                 continue;
    8947        5318 :             Token* after = next->link();
    8948        5318 :             if (!after)
    8949           0 :                 break; // see #4869 segmentation fault in Tokenizer::simplifyStructDecl (invalid code)
    8950             : 
    8951             :             // check for named type
    8952        5318 :             if (Token::Match(after->next(), "const|static|volatile| *|&| const| (| %type% )| ,|;|[|=|(|{")) {
    8953         214 :                 after->insertToken(";");
    8954         214 :                 after = after->next();
    8955         227 :                 while (!Token::Match(start, "struct|class|union|enum")) {
    8956          13 :                     after->insertToken(start->str());
    8957          13 :                     after = after->next();
    8958          13 :                     start->deleteThis();
    8959             :                 }
    8960         214 :                 tok = start;
    8961         214 :                 if (!after)
    8962           0 :                     break; // see #4869 segmentation fault in Tokenizer::simplifyStructDecl (invalid code)
    8963         214 :                 after->insertToken(type->str());
    8964         214 :                 if (start->str() != "class") {
    8965         188 :                     after->insertToken(start->str());
    8966         188 :                     after = after->next();
    8967             :                 }
    8968             : 
    8969         214 :                 after = after->tokAt(2);
    8970             : 
    8971         214 :                 if (Token::Match(after, "( %type% )")) {
    8972           1 :                     after->link()->deleteThis();
    8973           1 :                     after->deleteThis();
    8974             :                 }
    8975             : 
    8976             :                 // check for initialization
    8977         214 :                 if (Token::Match(after, "%any% (|{")) {
    8978          16 :                     after->insertToken("=");
    8979          16 :                     after = after->next();
    8980          16 :                     const bool isEnum = start->str() == "enum";
    8981          16 :                     if (!isEnum && cpp) {
    8982           7 :                         after->insertToken(type->str());
    8983           7 :                         after = after->next();
    8984             :                     }
    8985             : 
    8986          16 :                     if (isEnum) {
    8987           9 :                         if (Token::Match(after->next(), "{ !!}")) {
    8988           4 :                             after->next()->str("(");
    8989           4 :                             after->linkAt(1)->str(")");
    8990             :                         }
    8991             :                     }
    8992             :                 }
    8993             :             }
    8994             :         }
    8995             : 
    8996             :         // check for anonymous struct/union
    8997             :         else {
    8998             :             // unnamed anonymous struct/union so possibly remove it
    8999      889602 :             bool done = false;
    9000      889656 :             while (!done && Token::Match(tok, "struct|union {") && Token::simpleMatch(tok->linkAt(1), "} ;")) {
    9001          54 :                 done = true;
    9002             : 
    9003             :                 // is this a class/struct/union scope?
    9004          54 :                 bool isClassStructUnionScope = false;
    9005          54 :                 if (!scopeStart.empty()) {
    9006          99 :                     for (const Token* tok2 = scopeStart.top()->previous(); tok2 && !Token::Match(tok2, "[;{}]"); tok2 = tok2->previous()) {
    9007          89 :                         if (Token::Match(tok2, "class|struct|union")) {
    9008          36 :                             isClassStructUnionScope = true;
    9009          36 :                             break;
    9010             :                         }
    9011             :                     }
    9012             :                 }
    9013             : 
    9014             :                 // remove unnamed anonymous struct/union
    9015             :                 // * not in class/struct/union scopes
    9016          54 :                 if (Token::simpleMatch(tok->linkAt(1), "} ;") && !isClassStructUnionScope && tok->str() != "union") {
    9017          10 :                     tok->linkAt(1)->previous()->deleteNext(2);
    9018          10 :                     tok->deleteNext();
    9019          10 :                     tok->deleteThis();
    9020          10 :                     done = false;
    9021             :                 }
    9022             :             }
    9023             :         }
    9024             :     }
    9025       22642 : }
    9026             : 
    9027       22671 : void Tokenizer::simplifyCallingConvention()
    9028             : {
    9029       22671 :     const bool windows = mSettings.platform.isWindows();
    9030             : 
    9031     1008229 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9032      985590 :         while (Token::Match(tok, "__cdecl|__stdcall|__fastcall|__thiscall|__clrcall|__syscall|__pascal|__fortran|__far|__near") || (windows && Token::Match(tok, "WINAPI|APIENTRY|CALLBACK"))) {
    9033          33 :             tok->deleteThis();
    9034             :         }
    9035             :     }
    9036       22674 : }
    9037             : 
    9038     1989761 : static bool isAttribute(const Token* tok, bool gcc) {
    9039     1989761 :     return gcc ? Token::Match(tok, "__attribute__|__attribute (") : Token::Match(tok, "__declspec|_declspec (");
    9040             : }
    9041             : 
    9042         169 : static Token* getTokenAfterAttributes(Token* tok, bool gccattr) {
    9043         169 :     Token* after = tok;
    9044         375 :     while (isAttribute(after, gccattr))
    9045         206 :         after = after->linkAt(1)->next();
    9046         169 :     return after;
    9047             : }
    9048             : 
    9049         155 : Token* Tokenizer::getAttributeFuncTok(Token* tok, bool gccattr) const {
    9050         155 :     if (!Token::Match(tok, "%name% ("))
    9051           0 :         return nullptr;
    9052         155 :     Token* const after = getTokenAfterAttributes(tok, gccattr);
    9053         155 :     if (!after)
    9054           2 :         syntaxError(tok);
    9055             : 
    9056         153 :     if (Token::Match(after, "%name%|*|&|(")) {
    9057          68 :         Token *ftok = after;
    9058         103 :         while (Token::Match(ftok, "%name%|::|<|*|& !!(")) {
    9059          35 :             if (ftok->str() == "<") {
    9060           2 :                 ftok = ftok->findClosingBracket();
    9061           2 :                 if (!ftok)
    9062           0 :                     break;
    9063             :             }
    9064          35 :             ftok = ftok->next();
    9065             :         }
    9066          68 :         if (Token::simpleMatch(ftok, "( *"))
    9067           1 :             ftok = ftok->tokAt(2);
    9068          68 :         if (Token::Match(ftok, "%name% (|)"))
    9069          52 :             return ftok;
    9070          85 :     } else if (Token::Match(after, "[;{=:]")) {
    9071          79 :         Token *prev = tok->previous();
    9072          93 :         while (Token::Match(prev, "%name%"))
    9073          14 :             prev = prev->previous();
    9074          79 :         if (Token::simpleMatch(prev, ")")) {
    9075          64 :             if (Token::Match(prev->link()->previous(), "%name% ("))
    9076          60 :                 return prev->link()->previous();
    9077           4 :             if (Token::Match(prev->link()->tokAt(-2), "%name% ) ("))
    9078           1 :                 return prev->link()->tokAt(-2);
    9079             :         }
    9080          18 :         if (Token::simpleMatch(prev, ")") && Token::Match(prev->link()->tokAt(-2), "operator %op% (") && isCPP())
    9081           1 :             return prev->link()->tokAt(-2);
    9082          17 :         if ((!prev || Token::Match(prev, "[;{}*]")) && Token::Match(tok->previous(), "%name%"))
    9083           8 :             return tok->previous();
    9084             :     }
    9085          31 :     return nullptr;
    9086             : }
    9087             : 
    9088       23226 : void Tokenizer::simplifyDeclspec()
    9089             : {
    9090     1018672 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9091      995460 :         while (isAttribute(tok, false)) {
    9092          14 :             if (Token::Match(tok->tokAt(2), "noreturn|nothrow|dllexport")) {
    9093           9 :                 Token *functok = getAttributeFuncTok(tok, false);
    9094           9 :                 if (functok) {
    9095           5 :                     if (tok->strAt(2) == "noreturn")
    9096           0 :                         functok->isAttributeNoreturn(true);
    9097           5 :                     else if (tok->strAt(2) == "nothrow")
    9098           4 :                         functok->isAttributeNothrow(true);
    9099             :                     else
    9100           1 :                         functok->isAttributeExport(true);
    9101             :                 }
    9102           5 :             } else if (tok->strAt(2) == "property")
    9103           1 :                 tok->next()->link()->insertToken("__property");
    9104             : 
    9105          14 :             Token::eraseTokens(tok, tok->next()->link()->next());
    9106          14 :             tok->deleteThis();
    9107             :         }
    9108             :     }
    9109       23228 : }
    9110             : 
    9111       23224 : void Tokenizer::simplifyAttribute()
    9112             : {
    9113     1017023 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9114      993806 :         if (!tok->isKeyword() && Token::Match(tok, "%type% (") && !mSettings.library.isNotLibraryFunction(tok)) {
    9115       23245 :             if (mSettings.library.isFunctionConst(tok->str(), true))
    9116        4918 :                 tok->isAttributePure(true);
    9117       23245 :             if (mSettings.library.isFunctionConst(tok->str(), false))
    9118          18 :                 tok->isAttributeConst(true);
    9119             :         }
    9120      993936 :         while (isAttribute(tok, true)) {
    9121         146 :             Token *functok = getAttributeFuncTok(tok, true);
    9122             : 
    9123         466 :             for (Token *attr = tok->tokAt(2); attr->str() != ")"; attr = attr->next()) {
    9124         328 :                 if (Token::Match(attr, "%name% ("))
    9125          20 :                     attr = attr->linkAt(1);
    9126             : 
    9127         328 :                 if (Token::Match(attr, "[(,] constructor|__constructor__ [,()]")) {
    9128          11 :                     if (!functok)
    9129           4 :                         syntaxError(tok);
    9130           7 :                     functok->isAttributeConstructor(true);
    9131             :                 }
    9132             : 
    9133         317 :                 else if (Token::Match(attr, "[(,] destructor|__destructor__ [,()]")) {
    9134           9 :                     if (!functok)
    9135           2 :                         syntaxError(tok);
    9136           7 :                     functok->isAttributeDestructor(true);
    9137             :                 }
    9138             : 
    9139         308 :                 else if (Token::Match(attr, "[(,] unused|__unused__|used|__used__ [,)]")) {
    9140          14 :                     Token *vartok = nullptr;
    9141          14 :                     Token *after = getTokenAfterAttributes(tok, true);
    9142             : 
    9143             :                     // check if after variable name
    9144          14 :                     if (Token::Match(after, ";|=")) {
    9145           9 :                         Token *prev = tok->previous();
    9146          12 :                         while (Token::simpleMatch(prev, "]"))
    9147           3 :                             prev = prev->link()->previous();
    9148           9 :                         if (Token::Match(prev, "%type%"))
    9149           5 :                             vartok = prev;
    9150             :                     }
    9151             : 
    9152             :                     // check if before variable name
    9153           5 :                     else if (Token::Match(after, "%type%"))
    9154           3 :                         vartok = after;
    9155             : 
    9156          14 :                     if (vartok) {
    9157           8 :                         const std::string &attribute(attr->next()->str());
    9158           8 :                         if (attribute.find("unused") != std::string::npos)
    9159           6 :                             vartok->isAttributeUnused(true);
    9160             :                         else
    9161           2 :                             vartok->isAttributeUsed(true);
    9162             :                     }
    9163             :                 }
    9164             : 
    9165         294 :                 else if (Token::Match(attr, "[(,] pure|__pure__|const|__const__|noreturn|__noreturn__|nothrow|__nothrow__|warn_unused_result [,)]")) {
    9166         107 :                     if (!functok)
    9167           0 :                         syntaxError(tok);
    9168             : 
    9169         107 :                     const std::string &attribute(attr->next()->str());
    9170         107 :                     if (attribute.find("pure") != std::string::npos)
    9171          42 :                         functok->isAttributePure(true);
    9172          65 :                     else if (attribute.find("const") != std::string::npos)
    9173          25 :                         functok->isAttributeConst(true);
    9174          40 :                     else if (attribute.find("noreturn") != std::string::npos)
    9175           9 :                         functok->isAttributeNoreturn(true);
    9176          31 :                     else if (attribute.find("nothrow") != std::string::npos)
    9177          27 :                         functok->isAttributeNothrow(true);
    9178           4 :                     else if (attribute.find("warn_unused_result") != std::string::npos)
    9179           4 :                         functok->isAttributeNodiscard(true);
    9180             :                 }
    9181             : 
    9182         187 :                 else if (Token::Match(attr, "[(,] packed [,)]") && Token::simpleMatch(tok->previous(), "}"))
    9183           1 :                     tok->previous()->isAttributePacked(true);
    9184             : 
    9185         186 :                 else if (functok && Token::simpleMatch(attr, "( __visibility__ ( \"default\" ) )"))
    9186           1 :                     functok->isAttributeExport(true);
    9187             :             }
    9188             : 
    9189         138 :             Token::eraseTokens(tok, tok->linkAt(1)->next());
    9190         138 :             tok->deleteThis();
    9191             :         }
    9192             :     }
    9193       23220 : }
    9194             : 
    9195       22702 : void Tokenizer::simplifyCppcheckAttribute()
    9196             : {
    9197     1006371 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9198      983651 :         if (tok->str() != "(")
    9199      876498 :             continue;
    9200      107172 :         if (!tok->previous())
    9201          49 :             continue;
    9202      107123 :         const std::string &attr = tok->previous()->str();
    9203      107120 :         if (!startsWith(attr, "__cppcheck_"))
    9204      107120 :             continue;
    9205           2 :         if (attr.compare(attr.size()-2, 2, "__") != 0) // TODO: ends_with("__")
    9206           0 :             continue;
    9207             : 
    9208           2 :         Token *vartok = tok->link();
    9209           7 :         while (Token::Match(vartok->next(), "%name%|*|&|::")) {
    9210           5 :             vartok = vartok->next();
    9211           5 :             if (Token::Match(vartok, "%name% (") && startsWith(vartok->str(),"__cppcheck_"))
    9212           1 :                 vartok = vartok->linkAt(1);
    9213             :         }
    9214             : 
    9215           2 :         if (vartok->isName()) {
    9216           2 :             if (Token::Match(tok->previous(), "__cppcheck_low__ ( %num% )"))
    9217           1 :                 vartok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW,
    9218             :                                              MathLib::toBigNumber(tok->next()->str()));
    9219           1 :             else if (Token::Match(tok->previous(), "__cppcheck_high__ ( %num% )"))
    9220           1 :                 vartok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH,
    9221             :                                              MathLib::toBigNumber(tok->next()->str()));
    9222             :         }
    9223             : 
    9224             :         // Delete cppcheck attribute..
    9225           2 :         if (tok->tokAt(-2)) {
    9226           2 :             tok = tok->tokAt(-2);
    9227           2 :             Token::eraseTokens(tok, tok->linkAt(2)->next());
    9228             :         } else {
    9229           0 :             tok = tok->previous();
    9230           0 :             Token::eraseTokens(tok, tok->linkAt(1)->next());
    9231           0 :             tok->str(";");
    9232             :         }
    9233             :     }
    9234       22700 : }
    9235             : 
    9236       23226 : void Tokenizer::simplifyCPPAttribute()
    9237             : {
    9238       23226 :     if ((isCPP() && mSettings.standards.cpp < Standards::CPP11) || (isC() && mSettings.standards.c < Standards::C23))
    9239         154 :         return;
    9240             : 
    9241     1014689 :     for (Token *tok = list.front(); tok;) {
    9242      991621 :         if (!isCPPAttribute(tok) && !isAlignAttribute(tok)) {
    9243      991510 :             tok = tok->next();
    9244      991511 :             continue;
    9245             :         }
    9246         107 :         if (isCPPAttribute(tok)) {
    9247          96 :             if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) {
    9248          16 :                 Token * head = skipCPPOrAlignAttribute(tok)->next();
    9249          18 :                 while (isCPPAttribute(head) || isAlignAttribute(head))
    9250           2 :                     head = skipCPPOrAlignAttribute(head)->next();
    9251          48 :                 while (Token::Match(head, "%name%|::|*|&|<|>|,")) // skip return type
    9252          32 :                     head = head->next();
    9253          32 :                 if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
    9254          16 :                     head->previous()->isAttributeNoreturn(true);
    9255             :                 }
    9256          80 :             } else if (Token::findsimplematch(tok->tokAt(2), "nodiscard", tok->link())) {
    9257          13 :                 Token * head = skipCPPOrAlignAttribute(tok)->next();
    9258          14 :                 while (isCPPAttribute(head) || isAlignAttribute(head))
    9259           1 :                     head = skipCPPOrAlignAttribute(head)->next();
    9260          45 :                 while (Token::Match(head, "%name%|::|*|&|<|>|,"))
    9261          32 :                     head = head->next();
    9262          26 :                 if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
    9263          13 :                     head->previous()->isAttributeNodiscard(true);
    9264             :                 }
    9265          67 :             } else if (Token::findsimplematch(tok->tokAt(2), "maybe_unused", tok->link())) {
    9266          50 :                 Token* head = skipCPPOrAlignAttribute(tok)->next();
    9267          53 :                 while (isCPPAttribute(head) || isAlignAttribute(head))
    9268           3 :                     head = skipCPPOrAlignAttribute(head)->next();
    9269          50 :                 head->isAttributeMaybeUnused(true);
    9270          17 :             } else if (Token::Match(tok->previous(), ") [ [ expects|ensures|assert default|audit|axiom| : %name% <|<=|>|>= %num% ] ]")) {
    9271           1 :                 const Token *vartok = tok->tokAt(4);
    9272           1 :                 if (vartok->str() == ":")
    9273           0 :                     vartok = vartok->next();
    9274           1 :                 Token *argtok = tok->tokAt(-2);
    9275           1 :                 while (argtok && argtok->str() != "(") {
    9276           1 :                     if (argtok->str() == vartok->str())
    9277           1 :                         break;
    9278           0 :                     if (argtok->str() == ")")
    9279           0 :                         argtok = argtok->link();
    9280           0 :                     argtok = argtok->previous();
    9281             :                 }
    9282           1 :                 if (argtok && argtok->str() == vartok->str()) {
    9283           1 :                     if (vartok->next()->str() == ">=")
    9284           0 :                         argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW,
    9285             :                                                      MathLib::toBigNumber(vartok->strAt(2)));
    9286           1 :                     else if (vartok->next()->str() == ">")
    9287           0 :                         argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW,
    9288           0 :                                                      MathLib::toBigNumber(vartok->strAt(2)) + 1);
    9289           1 :                     else if (vartok->next()->str() == "<=")
    9290           1 :                         argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH,
    9291             :                                                      MathLib::toBigNumber(vartok->strAt(2)));
    9292           0 :                     else if (vartok->next()->str() == "<")
    9293           0 :                         argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH,
    9294           0 :                                                      MathLib::toBigNumber(vartok->strAt(2)) - 1);
    9295             :                 }
    9296             :             }
    9297             :         } else {
    9298          11 :             if (Token::simpleMatch(tok, "alignas (")) {
    9299             :                 // alignment requirements could be checked here
    9300             :             }
    9301             :         }
    9302         107 :         Token::eraseTokens(tok, skipCPPOrAlignAttribute(tok)->next());
    9303         107 :         tok->deleteThis();
    9304             :     }
    9305             : }
    9306             : 
    9307       23603 : void Tokenizer::simplifySpaceshipOperator()
    9308             : {
    9309       23603 :     if (isCPP() && mSettings.standards.cpp >= Standards::CPP20) {
    9310      642709 :         for (Token *tok = list.front(); tok && tok->next(); tok = tok->next()) {
    9311      626554 :             if (Token::simpleMatch(tok, "<= >")) {
    9312           6 :                 tok->str("<=>");
    9313           6 :                 tok->deleteNext();
    9314             :             }
    9315             :         }
    9316             :     }
    9317       23601 : }
    9318             : 
    9319             : static const std::unordered_set<std::string> keywords = {
    9320             :     "inline"
    9321             :     , "_inline"
    9322             :     , "__inline"
    9323             :     , "__forceinline"
    9324             :     , "register"
    9325             :     , "__restrict"
    9326             :     , "__restrict__"
    9327             :     , "__thread"
    9328             : };
    9329             : // Remove "inline", "register", "restrict", "override", "static" and "constexpr"
    9330             : // "restrict" keyword
    9331             : //   - New to 1999 ANSI/ISO C standard
    9332             : //   - Not in C++ standard yet
    9333       23227 : void Tokenizer::simplifyKeyword()
    9334             : {
    9335             :     // FIXME: There is a risk that "keywords" are removed by mistake. This
    9336             :     // code should be fixed so it doesn't remove variables etc. Nonstandard
    9337             :     // keywords should be defined with a library instead. For instance the
    9338             :     // linux kernel code at least uses "_inline" as struct member name at some
    9339             :     // places.
    9340             : 
    9341       23227 :     const bool c99 = isC() && mSettings.standards.c >= Standards::C99;
    9342       23228 :     const bool cpp11 = isCPP() && mSettings.standards.cpp >= Standards::CPP11;
    9343       23228 :     const bool cpp20 = isCPP() && mSettings.standards.cpp >= Standards::CPP20;
    9344             : 
    9345     1018313 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9346      995086 :         if (keywords.find(tok->str()) != keywords.end()) {
    9347             :             // Don't remove struct members
    9348          59 :             if (!Token::simpleMatch(tok->previous(), ".")) {
    9349          58 :                 const bool isinline = (tok->str().find("inline") != std::string::npos);
    9350          58 :                 const bool isrestrict = (tok->str().find("restrict") != std::string::npos);
    9351          58 :                 if (isinline || isrestrict) {
    9352         133 :                     for (Token *temp = tok->next(); Token::Match(temp, "%name%"); temp = temp->next()) {
    9353          83 :                         if (isinline)
    9354          79 :                             temp->isInline(true);
    9355          83 :                         if (isrestrict)
    9356           4 :                             temp->isRestrict(true);
    9357             :                     }
    9358             :                 }
    9359          58 :                 tok->deleteThis(); // Simplify..
    9360             :             }
    9361             :         }
    9362             : 
    9363      995080 :         if (isC() || mSettings.standards.cpp == Standards::CPP03) {
    9364      266439 :             if (tok->str() == "auto")
    9365          10 :                 tok->deleteThis();
    9366             :         }
    9367             : 
    9368             :         // simplify static keyword:
    9369             :         // void foo( int [ static 5 ] ); ==> void foo( int [ 5 ] );
    9370      995082 :         if (Token::Match(tok, "[ static %num%"))
    9371           2 :             tok->deleteNext();
    9372             : 
    9373      995082 :         if (c99) {
    9374         417 :             auto getTypeTokens = [tok]() {
    9375         139 :                 std::vector<Token*> ret;
    9376         278 :                 for (Token *temp = tok; Token::Match(temp, "%name%"); temp = temp->previous()) {
    9377         139 :                     if (!temp->isKeyword())
    9378           0 :                         ret.emplace_back(temp);
    9379             :                 }
    9380         277 :                 for (Token *temp = tok->next(); Token::Match(temp, "%name%"); temp = temp->next()) {
    9381         138 :                     if (!temp->isKeyword())
    9382         138 :                         ret.emplace_back(temp);
    9383             :                 }
    9384         139 :                 return ret;
    9385      263842 :             };
    9386             : 
    9387      263842 :             if (tok->str() == "restrict") {
    9388         277 :                 for (Token* temp: getTypeTokens())
    9389         138 :                     temp->isRestrict(true);
    9390         139 :                 tok->deleteThis();
    9391             :             }
    9392             : 
    9393      263842 :             if (mSettings.standards.c >= Standards::C11) {
    9394      263835 :                 while (tok->str() == "_Atomic") {
    9395           0 :                     for (Token* temp: getTypeTokens())
    9396           0 :                         temp->isAtomic(true);
    9397           0 :                     tok->deleteThis();
    9398             :                 }
    9399             :             }
    9400             :         }
    9401             : 
    9402      731240 :         else if (cpp11) {
    9403      728644 :             if (cpp20 && tok->str() == "consteval") {
    9404           1 :                 tok->originalName(tok->str());
    9405           1 :                 tok->str("constexpr");
    9406      728641 :             } else if (cpp20 && tok->str() == "constinit") {
    9407           1 :                 tok->deleteThis();
    9408             :             }
    9409             : 
    9410             :             // final:
    9411             :             // 1) struct name final { };   <- struct is final
    9412      728643 :             if (Token::Match(tok->previous(), "struct|class|union %type%")) {
    9413        6346 :                 Token* finalTok = tok->next();
    9414        6346 :                 if (tok->isUpperCaseName() && Token::Match(finalTok, "%type%") && finalTok->str() != "final") {
    9415         150 :                     tok = finalTok;
    9416         150 :                     finalTok = finalTok->next();
    9417             :                 }
    9418        6346 :                 if (Token::simpleMatch(finalTok, "<")) { // specialization
    9419         131 :                     finalTok = finalTok->findClosingBracket();
    9420         131 :                     if (finalTok)
    9421         129 :                         finalTok = finalTok->next();
    9422             :                 }
    9423        6346 :                 if (Token::Match(finalTok, "final [:{]")) {
    9424          14 :                     finalTok->deleteThis();
    9425          14 :                     tok->previous()->isFinalType(true);
    9426             :                 }
    9427             :             }
    9428             : 
    9429             :             // noexcept -> noexcept(true)
    9430             :             // 2) void f() noexcept; -> void f() noexcept(true);
    9431      722300 :             else if (Token::Match(tok, ") const|override|final| noexcept :|{|;|,|const|override|final")) {
    9432             :                 // Insertion is done in inverse order
    9433             :                 // The brackets are linked together accordingly afterwards
    9434          48 :                 Token* tokNoExcept = tok->next();
    9435          69 :                 while (tokNoExcept->str() != "noexcept")
    9436          21 :                     tokNoExcept = tokNoExcept->next();
    9437          48 :                 tokNoExcept->insertToken(")");
    9438          48 :                 Token * braceEnd = tokNoExcept->next();
    9439          48 :                 tokNoExcept->insertToken("true");
    9440          48 :                 tokNoExcept->insertToken("(");
    9441          48 :                 Token * braceStart = tokNoExcept->next();
    9442          48 :                 tok = tok->tokAt(3);
    9443          48 :                 Token::createMutualLinks(braceStart, braceEnd);
    9444             :             }
    9445             : 
    9446             :             // 3) thread_local -> static
    9447             :             //    on single thread thread_local has the effect of static
    9448      722256 :             else if (tok->str() == "thread_local") {
    9449           3 :                 tok->originalName(tok->str());
    9450           3 :                 tok->str("static");
    9451             :             }
    9452             :         }
    9453             :     }
    9454       23226 : }
    9455             : 
    9456           0 : static Token* setTokenDebug(Token* start, TokenDebug td)
    9457             : {
    9458           0 :     if (!start->link())
    9459           0 :         return nullptr;
    9460           0 :     Token* end = start->link();
    9461           0 :     start->deleteThis();
    9462           0 :     for (Token* tok = start; tok != end; tok = tok->next()) {
    9463           0 :         tok->setTokenDebug(td);
    9464             :     }
    9465           0 :     end->deleteThis();
    9466           0 :     return end;
    9467             : }
    9468             : 
    9469       23229 : void Tokenizer::simplifyDebug()
    9470             : {
    9471       23229 :     if (!mSettings.debugnormal && !mSettings.debugwarnings)
    9472       21201 :         return;
    9473           0 :     static const std::unordered_map<std::string, TokenDebug> m = {{"debug_valueflow", TokenDebug::ValueFlow},
    9474        2106 :         {"debug_valuetype", TokenDebug::ValueType}};
    9475      394874 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    9476      392846 :         if (!Token::Match(tok, "%name% ("))
    9477      355973 :             continue;
    9478       36873 :         auto it = m.find(tok->str());
    9479       36873 :         if (it != m.end()) {
    9480           0 :             tok->deleteThis();
    9481           0 :             tok = setTokenDebug(tok, it->second);
    9482             :         }
    9483             :     }
    9484             : }
    9485             : 
    9486       22642 : void Tokenizer::simplifyAssignmentBlock()
    9487             : {
    9488     1013712 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9489      991073 :         if (Token::Match(tok, "[;{}] %name% = ( {")) {
    9490           6 :             const std::string &varname = tok->next()->str();
    9491             : 
    9492             :             // goto the "} )"
    9493           6 :             int indentlevel = 0;
    9494           6 :             Token *tok2 = tok;
    9495          75 :             while (nullptr != (tok2 = tok2->next())) {
    9496          75 :                 if (Token::Match(tok2, "(|{"))
    9497          17 :                     ++indentlevel;
    9498          58 :                 else if (Token::Match(tok2, ")|}")) {
    9499          11 :                     if (indentlevel <= 2)
    9500           6 :                         break;
    9501           5 :                     --indentlevel;
    9502          47 :                 } else if (indentlevel == 2 && tok2->str() == varname && Token::Match(tok2->previous(), "%type%|*"))
    9503             :                     // declaring variable in inner scope with same name as lhs variable
    9504           0 :                     break;
    9505             :             }
    9506           6 :             if (indentlevel == 2 && Token::simpleMatch(tok2, "} )")) {
    9507           6 :                 tok2 = tok2->tokAt(-3);
    9508           6 :                 if (Token::Match(tok2, "[;{}] %num%|%name% ;")) {
    9509           0 :                     tok2->insertToken("=");
    9510           0 :                     tok2->insertToken(tok->next()->str());
    9511           0 :                     tok2->next()->varId(tok->next()->varId());
    9512           0 :                     tok->deleteNext(3);
    9513           0 :                     tok2->tokAt(5)->deleteNext();
    9514             :                 }
    9515             :             }
    9516             :         }
    9517             :     }
    9518       22638 : }
    9519             : 
    9520             : // Remove __asm..
    9521       23229 : void Tokenizer::simplifyAsm()
    9522             : {
    9523       46456 :     std::string instruction;
    9524     1018385 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9525      995167 :         if (Token::Match(tok, "__asm|_asm|asm {") &&
    9526          11 :             tok->next()->link()->next()) {
    9527           9 :             instruction = tok->tokAt(2)->stringifyList(tok->next()->link());
    9528           9 :             Token::eraseTokens(tok, tok->next()->link()->next());
    9529             :         }
    9530             : 
    9531      995143 :         else if (Token::Match(tok, "asm|__asm|__asm__ volatile|__volatile|__volatile__| (")) {
    9532             :             // Goto "("
    9533          35 :             Token *partok = tok->next();
    9534          35 :             if (partok->str() != "(")
    9535           7 :                 partok = partok->next();
    9536          35 :             instruction = partok->next()->stringifyList(partok->link());
    9537          35 :             Token::eraseTokens(tok, partok->link()->next());
    9538             :         }
    9539             : 
    9540      995107 :         else if (Token::Match(tok, "_asm|__asm")) {
    9541           7 :             Token *endasm = tok->next();
    9542           7 :             const Token *firstSemiColon = nullptr;
    9543           7 :             int comment = 0;
    9544          28 :             while (Token::Match(endasm, "%num%|%name%|,|:|;") || (endasm && endasm->linenr() == comment)) {
    9545          23 :                 if (Token::Match(endasm, "_asm|__asm|__endasm"))
    9546           2 :                     break;
    9547          21 :                 if (endasm->str() == ";") {
    9548           3 :                     comment = endasm->linenr();
    9549           3 :                     if (!firstSemiColon)
    9550           3 :                         firstSemiColon = endasm;
    9551             :                 }
    9552          21 :                 endasm = endasm->next();
    9553             :             }
    9554           7 :             if (Token::simpleMatch(endasm, "__endasm")) {
    9555           2 :                 instruction = tok->next()->stringifyList(endasm);
    9556           2 :                 Token::eraseTokens(tok, endasm->next());
    9557           2 :                 if (!Token::simpleMatch(tok->next(), ";"))
    9558           0 :                     tok->insertToken(";");
    9559           5 :             } else if (firstSemiColon) {
    9560           2 :                 instruction = tok->next()->stringifyList(firstSemiColon);
    9561           2 :                 Token::eraseTokens(tok, firstSemiColon);
    9562           3 :             } else if (!endasm) {
    9563           1 :                 instruction = tok->next()->stringifyList(endasm);
    9564           1 :                 Token::eraseTokens(tok, endasm);
    9565           1 :                 tok->insertToken(";");
    9566             :             } else
    9567           2 :                 continue;
    9568             :         }
    9569             : 
    9570             :         else
    9571      995105 :             continue;
    9572             : 
    9573          49 :         if (Token::Match(tok->previous(), ") %name% %name% (")) {
    9574           1 :             tok->deleteThis();
    9575           1 :             continue;
    9576             :         }
    9577             : 
    9578             :         // insert "asm ( "instruction" )"
    9579          48 :         tok->str("asm");
    9580          48 :         if (tok->strAt(1) != ";" && tok->strAt(1) != "{")
    9581           6 :             tok->insertToken(";");
    9582          48 :         tok->insertToken(")");
    9583          48 :         tok->insertToken("\"" + instruction + "\"");
    9584          48 :         tok->insertToken("(");
    9585             : 
    9586          48 :         tok = tok->next();
    9587          48 :         Token::createMutualLinks(tok, tok->tokAt(2));
    9588             : 
    9589             :         //move the new tokens in the same line as ";" if available
    9590          48 :         tok = tok->tokAt(2);
    9591          94 :         if (tok->next() && tok->next()->str() == ";" &&
    9592          46 :             tok->next()->linenr() != tok->linenr()) {
    9593           2 :             const int endposition = tok->next()->linenr();
    9594           2 :             tok = tok->tokAt(-3);
    9595          10 :             for (int i = 0; i < 4; ++i) {
    9596           8 :                 tok = tok->next();
    9597           8 :                 tok->linenr(endposition);
    9598             :             }
    9599             :         }
    9600             :     }
    9601       23227 : }
    9602             : 
    9603       22642 : void Tokenizer::simplifyAsm2()
    9604             : {
    9605             :     // Block declarations: ^{}
    9606             :     // A C extension used to create lambda like closures.
    9607             : 
    9608             :     // Put ^{} statements in asm()
    9609     1021678 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9610      999040 :         if (tok->str() != "^")
    9611      999008 :             continue;
    9612             : 
    9613          28 :         if (Token::simpleMatch(tok, "^ {") || (Token::simpleMatch(tok->linkAt(1), ") {") && tok->strAt(-1) != "operator")) {
    9614           1 :             Token * start = tok;
    9615           2 :             while (start && !Token::Match(start, "[,(;{}=]")) {
    9616           1 :                 if (start->link() && Token::Match(start, ")|]|>"))
    9617           0 :                     start = start->link();
    9618           1 :                 start = start->previous();
    9619             :             }
    9620             : 
    9621           1 :             const Token *last = tok->next()->link();
    9622           1 :             if (Token::simpleMatch(last, ") {"))
    9623           1 :                 last = last->linkAt(1);
    9624           1 :             last = last->next();
    9625           1 :             while (last && !Token::Match(last, "%cop%|,|;|{|}|)")) {
    9626           0 :                 if (Token::Match(last, "(|["))
    9627           0 :                     last = last->link();
    9628           0 :                 last = last->next();
    9629             :             }
    9630             : 
    9631           1 :             if (start && last) {
    9632           1 :                 std::string asmcode;
    9633           8 :                 while (start->next() != last) {
    9634           7 :                     asmcode += start->next()->str();
    9635           7 :                     start->deleteNext();
    9636             :                 }
    9637           1 :                 if (last->str() == "}")
    9638           0 :                     start->insertToken(";");
    9639           1 :                 start->insertToken(")");
    9640           1 :                 start->insertToken("\"" + asmcode + "\"");
    9641           1 :                 start->insertToken("(");
    9642           1 :                 start->insertToken("asm");
    9643           1 :                 start->tokAt(2)->link(start->tokAt(4));
    9644           1 :                 start->tokAt(4)->link(start->tokAt(2));
    9645           1 :                 tok = start->tokAt(4);
    9646             :             }
    9647             :         }
    9648             :     }
    9649       22641 : }
    9650             : 
    9651       23228 : void Tokenizer::simplifyAt()
    9652             : {
    9653       46455 :     std::set<std::string> var;
    9654             : 
    9655     1018762 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9656      995538 :         if (Token::Match(tok, "%name%|] @ %num%|%name%|%str%|(")) {
    9657           9 :             const Token *end = tok->tokAt(2);
    9658           9 :             if (end->isLiteral())
    9659           5 :                 end = end->next();
    9660           4 :             else if (end->str() == "(") {
    9661           1 :                 int par = 0;
    9662           4 :                 while ((end = end->next()) != nullptr) {
    9663           4 :                     if (end->str() == "(")
    9664           0 :                         par++;
    9665           4 :                     else if (end->str() == ")") {
    9666           1 :                         if (--par < 0)
    9667           1 :                             break;
    9668             :                     }
    9669             :                 }
    9670           1 :                 end = end ? end->next() : nullptr;
    9671           3 :             } else if (var.find(end->str()) != var.end())
    9672           1 :                 end = end->next();
    9673             :             else
    9674           2 :                 continue;
    9675             : 
    9676           7 :             if (Token::Match(end, ": %num% ;"))
    9677           2 :                 end = end->tokAt(2);
    9678             : 
    9679           7 :             if (Token::Match(end, "[;=]")) {
    9680           7 :                 if (tok->isName())
    9681           6 :                     var.insert(tok->str());
    9682           7 :                 tok->isAtAddress(true);
    9683           7 :                 Token::eraseTokens(tok, end);
    9684             :             }
    9685             :         }
    9686             : 
    9687             :         // keywords in compiler from cosmic software for STM8
    9688             :         // TODO: Should use platform configuration.
    9689      995541 :         if (Token::Match(tok, "@ builtin|eeprom|far|inline|interrupt|near|noprd|nostack|nosvf|packed|stack|svlreg|tiny|vector")) {
    9690           1 :             tok->str(tok->next()->str() + "@");
    9691           1 :             tok->deleteNext();
    9692             :         }
    9693             :     }
    9694       23224 : }
    9695             : 
    9696             : // Simplify bitfields
    9697       22642 : void Tokenizer::simplifyBitfields()
    9698             : {
    9699       22642 :     bool goback = false;
    9700      998913 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9701      976277 :         if (goback) {
    9702           3 :             goback = false;
    9703           3 :             tok = tok->previous();
    9704             :         }
    9705      976277 :         Token *last = nullptr;
    9706             : 
    9707      976277 :         if (Token::simpleMatch(tok, "for ("))
    9708         972 :             tok = tok->linkAt(1);
    9709             : 
    9710      976277 :         if (!Token::Match(tok, ";|{|}|public:|protected:|private:"))
    9711      788598 :             continue;
    9712             : 
    9713      187673 :         bool isEnum = false;
    9714      187673 :         if (tok->str() == "}") {
    9715       48112 :             const Token *type = tok->link()->previous();
    9716       61412 :             while (type && type->isName()) {
    9717       13524 :                 if (type->str() == "enum") {
    9718         224 :                     isEnum = true;
    9719         224 :                     break;
    9720             :                 }
    9721       13300 :                 type = type->previous();
    9722             :             }
    9723             :         }
    9724             : 
    9725      187681 :         if (Token::Match(tok->next(), "const| %type% %name% :") &&
    9726      187757 :             !Token::Match(tok->next(), "case|public|protected|private|class|struct") &&
    9727          73 :             !Token::simpleMatch(tok->tokAt(2), "default :")) {
    9728          72 :             Token *tok1 = (tok->next()->str() == "const") ? tok->tokAt(3) : tok->tokAt(2);
    9729          72 :             if (Token::Match(tok1, "%name% : %num% [;=]"))
    9730          55 :                 tok1->setBits(MathLib::toBigNumber(tok1->strAt(2)));
    9731         144 :             if (tok1 && tok1->tokAt(2) &&
    9732          72 :                 (Token::Match(tok1->tokAt(2), "%bool%|%num%") ||
    9733          11 :                  !Token::Match(tok1->tokAt(2), "public|protected|private| %type% ::|<|,|{|;"))) {
    9734         195 :                 while (tok1->next() && !Token::Match(tok1->next(), "[;,)]{}=]")) {
    9735         130 :                     if (Token::Match(tok1->next(), "[([]"))
    9736           2 :                         Token::eraseTokens(tok1, tok1->next()->link());
    9737         130 :                     tok1->deleteNext();
    9738             :                 }
    9739             : 
    9740          65 :                 last = tok1->next();
    9741             :             }
    9742      187612 :         } else if (isEnum && Token::Match(tok, "} %name%| : %num% ;")) {
    9743           2 :             if (tok->next()->str() == ":") {
    9744           1 :                 tok->deleteNext(2);
    9745           1 :                 tok->insertToken("Anonymous");
    9746             :             } else {
    9747           1 :                 tok->next()->deleteNext(2);
    9748             :             }
    9749      187613 :         } else if (Token::Match(tok->next(), "const| %type% : %num%|%bool% ;") &&
    9750           3 :                    tok->next()->str() != "default") {
    9751           3 :             const int offset = (tok->next()->str() == "const") ? 1 : 0;
    9752           3 :             if (!Token::Match(tok->tokAt(3 + offset), "[{};()]")) {
    9753           3 :                 tok->deleteNext(4 + offset);
    9754           3 :                 goback = true;
    9755             :             }
    9756             :         }
    9757             : 
    9758      187673 :         if (last && last->str() == ",") {
    9759           3 :             Token * tok1 = last;
    9760           3 :             tok1->str(";");
    9761             : 
    9762           3 :             const Token *const tok2 = tok->next();
    9763           3 :             tok1->insertToken(tok2->str());
    9764           3 :             tok1 = tok1->next();
    9765           3 :             tok1->isSigned(tok2->isSigned());
    9766           3 :             tok1->isUnsigned(tok2->isUnsigned());
    9767           3 :             tok1->isLong(tok2->isLong());
    9768             :         }
    9769             :     }
    9770       22638 : }
    9771             : 
    9772         323 : static bool isStdContainerOrIterator(const Token* tok, const Settings& settings)
    9773             : {
    9774         323 :     const Library::Container* ctr = settings.library.detectContainerOrIterator(tok, nullptr, /*withoutStd*/ true);
    9775         323 :     return ctr && startsWith(ctr->startPattern, "std ::");
    9776             : }
    9777             : 
    9778          72 : static bool isStdSmartPointer(const Token* tok, const Settings& settings)
    9779             : {
    9780          72 :     const Library::SmartPointer* ptr = settings.library.detectSmartPointer(tok, /*withoutStd*/ true);
    9781          72 :     return ptr && startsWith(ptr->name, "std::");
    9782             : }
    9783             : 
    9784             : // Add std:: in front of std classes, when using namespace std; was given
    9785       22624 : void Tokenizer::simplifyNamespaceStd()
    9786             : {
    9787       22624 :     if (!isCPP())
    9788        5917 :         return;
    9789             : 
    9790       33416 :     std::set<std::string> userFunctions;
    9791             : 
    9792       20708 :     for (Token* tok = Token::findsimplematch(list.front(), "using namespace std ;"); tok; tok = tok->next()) {
    9793        4001 :         bool insert = false;
    9794        4001 :         if (Token::Match(tok, "enum class|struct| %name%| :|{")) { // Don't replace within enum definitions
    9795           8 :             skipEnumBody(tok);
    9796             :         }
    9797        4001 :         if (!tok->isName() || tok->isKeyword() || tok->isStandardType() || tok->varId())
    9798        3364 :             continue;
    9799         637 :         if (Token::Match(tok->previous(), ".|::|namespace"))
    9800         223 :             continue;
    9801         414 :         if (Token::simpleMatch(tok->next(), "(")) {
    9802         146 :             if (isFunctionHead(tok->next(), "{"))
    9803          83 :                 userFunctions.insert(tok->str());
    9804          63 :             else if (isFunctionHead(tok->next(), ";")) {
    9805          61 :                 const Token *start = tok;
    9806         141 :                 while (Token::Match(start->previous(), "%type%|*|&"))
    9807          80 :                     start = start->previous();
    9808          61 :                 if (start != tok && start->isName() && !start->isKeyword() && (!start->previous() || Token::Match(start->previous(), "[;{}]")))
    9809          15 :                     userFunctions.insert(tok->str());
    9810             :             }
    9811         146 :             if (userFunctions.find(tok->str()) == userFunctions.end() && mSettings.library.matchArguments(tok, "std::" + tok->str()))
    9812          10 :                 insert = true;
    9813         356 :         } else if (Token::simpleMatch(tok->next(), "<") &&
    9814          88 :                    (isStdContainerOrIterator(tok, mSettings) || isStdSmartPointer(tok, mSettings)))
    9815          21 :             insert = true;
    9816         494 :         else if (mSettings.library.hasAnyTypeCheck("std::" + tok->str()) ||
    9817         729 :                  mSettings.library.podtype("std::" + tok->str()) ||
    9818         235 :                  isStdContainerOrIterator(tok, mSettings))
    9819          20 :             insert = true;
    9820             : 
    9821         414 :         if (insert) {
    9822          51 :             tok->previous()->insertToken("std");
    9823          51 :             tok->previous()->linenr(tok->linenr()); // For stylistic reasons we put the std:: in the same line as the following token
    9824          51 :             tok->previous()->fileIndex(tok->fileIndex());
    9825          51 :             tok->previous()->insertToken("::");
    9826             :         }
    9827             :     }
    9828             : 
    9829      746625 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
    9830      729927 :         if (Token::simpleMatch(tok, "using namespace std ;")) {
    9831          51 :             Token::eraseTokens(tok, tok->tokAt(4));
    9832          51 :             tok->deleteThis();
    9833             :         }
    9834             :     }
    9835             : }
    9836             : 
    9837             : 
    9838       22669 : void Tokenizer::simplifyMicrosoftMemoryFunctions()
    9839             : {
    9840             :     // skip if not Windows
    9841       22669 :     if (!mSettings.platform.isWindows())
    9842       19129 :         return;
    9843             : 
    9844       99918 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9845       96381 :         if (tok->strAt(1) != "(")
    9846       84651 :             continue;
    9847             : 
    9848       11730 :         if (Token::Match(tok, "CopyMemory|RtlCopyMemory|RtlCopyBytes")) {
    9849           3 :             tok->str("memcpy");
    9850       11727 :         } else if (Token::Match(tok, "MoveMemory|RtlMoveMemory")) {
    9851           2 :             tok->str("memmove");
    9852       11725 :         } else if (Token::Match(tok, "FillMemory|RtlFillMemory|RtlFillBytes")) {
    9853             :             // FillMemory(dst, len, val) -> memset(dst, val, len)
    9854           4 :             tok->str("memset");
    9855             : 
    9856           4 :             Token *tok1 = tok->tokAt(2);
    9857           4 :             if (tok1)
    9858           4 :                 tok1 = tok1->nextArgument(); // Second argument
    9859           4 :             if (tok1) {
    9860           4 :                 Token *tok2 = tok1->nextArgument(); // Third argument
    9861             : 
    9862           4 :                 if (tok2)
    9863           4 :                     Token::move(tok1->previous(), tok2->tokAt(-2), tok->next()->link()->previous()); // Swap third with second argument
    9864             :             }
    9865       11721 :         } else if (Token::Match(tok, "ZeroMemory|RtlZeroMemory|RtlZeroBytes|RtlSecureZeroMemory")) {
    9866             :             // ZeroMemory(dst, len) -> memset(dst, 0, len)
    9867          29 :             tok->str("memset");
    9868             : 
    9869          29 :             Token *tok1 = tok->tokAt(2);
    9870          29 :             if (tok1)
    9871          29 :                 tok1 = tok1->nextArgument(); // Second argument
    9872             : 
    9873          29 :             if (tok1) {
    9874          29 :                 tok1 = tok1->previous();
    9875          29 :                 tok1->insertToken("0");
    9876          29 :                 tok1 = tok1->next();
    9877          29 :                 tok1->insertToken(",");
    9878             :             }
    9879       11692 :         } else if (Token::simpleMatch(tok, "RtlCompareMemory")) {
    9880             :             // RtlCompareMemory(src1, src2, len) -> memcmp(src1, src2, len)
    9881          13 :             tok->str("memcmp");
    9882             :             // For the record, when memcmp returns 0, both strings are equal.
    9883             :             // When RtlCompareMemory returns len, both strings are equal.
    9884             :             // It might be needed to improve this replacement by something
    9885             :             // like ((len - memcmp(src1, src2, len)) % (len + 1)) to
    9886             :             // respect execution path (if required)
    9887             :         }
    9888             :     }
    9889             : }
    9890             : 
    9891             : namespace {
    9892             :     struct triplet {
    9893        2496 :         triplet(const char* m, const char* u) :  mbcs(m), unicode(u) {}
    9894             :         std::string mbcs, unicode;
    9895             :     };
    9896             : 
    9897             :     const std::map<std::string, triplet> apis = {
    9898             :         std::make_pair("_topen", triplet("open", "_wopen")),
    9899             :         std::make_pair("_tsopen_s", triplet("_sopen_s", "_wsopen_s")),
    9900             :         std::make_pair("_tfopen", triplet("fopen", "_wfopen")),
    9901             :         std::make_pair("_tfopen_s", triplet("fopen_s", "_wfopen_s")),
    9902             :         std::make_pair("_tfreopen", triplet("freopen", "_wfreopen")),
    9903             :         std::make_pair("_tfreopen_s", triplet("freopen_s", "_wfreopen_s")),
    9904             :         std::make_pair("_tcscat", triplet("strcat", "wcscat")),
    9905             :         std::make_pair("_tcschr", triplet("strchr", "wcschr")),
    9906             :         std::make_pair("_tcscmp", triplet("strcmp", "wcscmp")),
    9907             :         std::make_pair("_tcsdup", triplet("strdup", "wcsdup")),
    9908             :         std::make_pair("_tcscpy", triplet("strcpy", "wcscpy")),
    9909             :         std::make_pair("_tcslen", triplet("strlen", "wcslen")),
    9910             :         std::make_pair("_tcsncat", triplet("strncat", "wcsncat")),
    9911             :         std::make_pair("_tcsncpy", triplet("strncpy", "wcsncpy")),
    9912             :         std::make_pair("_tcsnlen", triplet("strnlen", "wcsnlen")),
    9913             :         std::make_pair("_tcsrchr", triplet("strrchr", "wcsrchr")),
    9914             :         std::make_pair("_tcsstr", triplet("strstr", "wcsstr")),
    9915             :         std::make_pair("_tcstok", triplet("strtok", "wcstok")),
    9916             :         std::make_pair("_ftprintf", triplet("fprintf", "fwprintf")),
    9917             :         std::make_pair("_tprintf", triplet("printf", "wprintf")),
    9918             :         std::make_pair("_stprintf", triplet("sprintf", "swprintf")),
    9919             :         std::make_pair("_sntprintf", triplet("_snprintf", "_snwprintf")),
    9920             :         std::make_pair("_ftscanf", triplet("fscanf", "fwscanf")),
    9921             :         std::make_pair("_tscanf", triplet("scanf", "wscanf")),
    9922             :         std::make_pair("_stscanf", triplet("sscanf", "swscanf")),
    9923             :         std::make_pair("_ftprintf_s", triplet("fprintf_s", "fwprintf_s")),
    9924             :         std::make_pair("_tprintf_s", triplet("printf_s", "wprintf_s")),
    9925             :         std::make_pair("_stprintf_s", triplet("sprintf_s", "swprintf_s")),
    9926             :         std::make_pair("_sntprintf_s", triplet("_snprintf_s", "_snwprintf_s")),
    9927             :         std::make_pair("_ftscanf_s", triplet("fscanf_s", "fwscanf_s")),
    9928             :         std::make_pair("_tscanf_s", triplet("scanf_s", "wscanf_s")),
    9929             :         std::make_pair("_stscanf_s", triplet("sscanf_s", "swscanf_s"))
    9930             :     };
    9931             : }
    9932             : 
    9933       22669 : void Tokenizer::simplifyMicrosoftStringFunctions()
    9934             : {
    9935             :     // skip if not Windows
    9936       22669 :     if (!mSettings.platform.isWindows())
    9937       19130 :         return;
    9938             : 
    9939        3537 :     const bool ansi = mSettings.platform.type == Platform::Type::Win32A;
    9940       99098 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9941       95561 :         if (tok->strAt(1) != "(")
    9942       83844 :             continue;
    9943             : 
    9944       11717 :         const std::map<std::string, triplet>::const_iterator match = apis.find(tok->str());
    9945       11717 :         if (match!=apis.end()) {
    9946         177 :             tok->str(ansi ? match->second.mbcs : match->second.unicode);
    9947         177 :             tok->originalName(match->first);
    9948       11540 :         } else if (Token::Match(tok, "_T|_TEXT|TEXT ( %char%|%str% )")) {
    9949         256 :             tok->deleteNext();
    9950         256 :             tok->deleteThis();
    9951         256 :             tok->deleteNext();
    9952         256 :             if (!ansi) {
    9953         164 :                 tok->isLong(true);
    9954         164 :                 if (tok->str()[0] != 'L')
    9955         164 :                     tok->str("L" + tok->str());
    9956             :             }
    9957         269 :             while (Token::Match(tok->next(), "_T|_TEXT|TEXT ( %char%|%str% )")) {
    9958          13 :                 tok->next()->deleteNext();
    9959          13 :                 tok->next()->deleteThis();
    9960          13 :                 tok->next()->deleteNext();
    9961          13 :                 tok->concatStr(tok->next()->str());
    9962          13 :                 tok->deleteNext();
    9963             :             }
    9964             :         }
    9965             :     }
    9966             : }
    9967             : 
    9968             : // Remove Borland code
    9969       22669 : void Tokenizer::simplifyBorland()
    9970             : {
    9971             :     // skip if not Windows
    9972       22669 :     if (!mSettings.platform.isWindows())
    9973       19132 :         return;
    9974        3537 :     if (isC())
    9975        2656 :         return;
    9976       51789 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9977       50908 :         if (Token::Match(tok, "( __closure * %name% )")) {
    9978           1 :             tok->deleteNext();
    9979             :         }
    9980             :     }
    9981             : 
    9982             :     // I think that these classes are always declared at the outer scope
    9983             :     // I save some time by ignoring inner classes.
    9984       11165 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
    9985       10284 :         if (tok->str() == "{" && !Token::Match(tok->tokAt(-2), "namespace %type%")) {
    9986        1230 :             tok = tok->link();
    9987        1230 :             if (!tok)
    9988           0 :                 break;
    9989        9054 :         } else if (Token::Match(tok, "class %name% :|{")) {
    9990          33 :             while (tok && tok->str() != "{" && tok->str() != ";")
    9991          25 :                 tok = tok->next();
    9992           8 :             if (!tok)
    9993           0 :                 break;
    9994           8 :             if (tok->str() == ";")
    9995           0 :                 continue;
    9996             : 
    9997           8 :             const Token* end = tok->link()->next();
    9998          79 :             for (Token *tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) {
    9999          73 :                 if (tok2->str() == "__property" &&
   10000           2 :                     Token::Match(tok2->previous(), ";|{|}|protected:|public:|__published:")) {
   10001           8 :                     while (tok2->next() && !Token::Match(tok2->next(), "{|;"))
   10002           6 :                         tok2->deleteNext();
   10003           2 :                     tok2->deleteThis();
   10004           2 :                     if (tok2->str() == "{") {
   10005           2 :                         Token::eraseTokens(tok2, tok2->link());
   10006           2 :                         tok2->deleteNext();
   10007           2 :                         tok2->deleteThis();
   10008             : 
   10009             :                         // insert "; __property ;"
   10010           2 :                         tok2->previous()->insertToken(";");
   10011           2 :                         tok2->previous()->insertToken("__property");
   10012           2 :                         tok2->previous()->insertToken(";");
   10013             :                     }
   10014             :                 }
   10015             :             }
   10016             :         }
   10017             :     }
   10018             : }
   10019             : 
   10020       22733 : void Tokenizer::createSymbolDatabase()
   10021             : {
   10022       22733 :     if (!mSymbolDatabase)
   10023       22695 :         mSymbolDatabase = new SymbolDatabase(*this, mSettings, mErrorLogger);
   10024       22708 :     mSymbolDatabase->validate();
   10025       22704 : }
   10026             : 
   10027         548 : bool Tokenizer::operatorEnd(const Token * tok)
   10028             : {
   10029         548 :     if (tok && tok->str() == ")") {
   10030         547 :         if (isFunctionHead(tok, "{|;|?|:|["))
   10031         481 :             return true;
   10032             : 
   10033          66 :         tok = tok->next();
   10034          66 :         while (tok && !Token::Match(tok, "[=;{),]")) {
   10035          64 :             if (Token::Match(tok, "const|volatile|override")) {
   10036           0 :                 tok = tok->next();
   10037          64 :             } else if (tok->str() == "noexcept") {
   10038           0 :                 tok = tok->next();
   10039           0 :                 if (tok && tok->str() == "(") {
   10040           0 :                     tok = tok->link()->next();
   10041             :                 }
   10042          64 :             } else if (tok->str() == "throw" && tok->next() && tok->next()->str() == "(") {
   10043           0 :                 tok = tok->next()->link()->next();
   10044             :             }
   10045             :             // unknown macros ") MACRO {" and ") MACRO(...) {"
   10046          64 :             else if (tok->isUpperCaseName()) {
   10047           0 :                 tok = tok->next();
   10048           0 :                 if (tok && tok->str() == "(") {
   10049           0 :                     tok = tok->link()->next();
   10050             :                 }
   10051         184 :             } else if (Token::Match(tok, "%op% !!(") ||
   10052         120 :                        (Token::Match(tok, "%op% (") && !isFunctionHead(tok->next(), "{")))
   10053          14 :                 break;
   10054             :             else
   10055          50 :                 return false;
   10056             :         }
   10057             : 
   10058          16 :         return true;
   10059             :     }
   10060             : 
   10061           1 :     return false;
   10062             : }
   10063             : 
   10064       22641 : void Tokenizer::simplifyOperatorName()
   10065             : {
   10066       22641 :     if (isC())
   10067        5924 :         return;
   10068             : 
   10069      748640 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10070      731925 :         if (Token::Match(tok, "using|:: operator %op%|%name% ;")) {
   10071           4 :             tok->next()->str("operator" + tok->strAt(2));
   10072           4 :             tok->next()->deleteNext();
   10073      731348 :             continue;
   10074             :         }
   10075             : 
   10076      731924 :         if (tok->str() != "operator")
   10077      731341 :             continue;
   10078             :         // operator op
   10079         579 :         if (Token::Match(tok, "operator %op% (") && !operatorEnd(tok->linkAt(2))) {
   10080           3 :             tok->str(tok->str() + tok->next()->str());
   10081           3 :             tok->deleteNext();
   10082           3 :             continue;
   10083             :         }
   10084        1152 :         std::string op;
   10085         576 :         Token *par = tok->next();
   10086         576 :         bool done = false;
   10087        1671 :         while (!done && par) {
   10088        1176 :             done = true;
   10089        1176 :             if (par->isName()) {
   10090          66 :                 op += par->str();
   10091          66 :                 par = par->next();
   10092             :                 // merge namespaces eg. 'operator std :: string () const {'
   10093          66 :                 if (Token::Match(par, ":: %name%|%op%|.")) {
   10094           7 :                     op += par->str();
   10095           7 :                     par = par->next();
   10096             :                 }
   10097          66 :                 done = false;
   10098        1110 :             } else if (Token::Match(par, ".|%op%|,")) {
   10099             :                 // check for operator in template
   10100         476 :                 if (par->str() == "," && !op.empty())
   10101           2 :                     break;
   10102         474 :                 if (!(Token::Match(par, "<|>") && !op.empty())) {
   10103         468 :                     op += par->str() == "." ? par->originalName() : par->str();
   10104         468 :                     par = par->next();
   10105         468 :                     done = false;
   10106             :                 }
   10107         634 :             } else if (Token::simpleMatch(par, "[ ]")) {
   10108          19 :                 op += "[]";
   10109          19 :                 par = par->tokAt(2);
   10110          19 :                 done = false;
   10111         615 :             } else if (Token::Match(par, "( *| )")) {
   10112             :                 // break out and simplify..
   10113         125 :                 if (operatorEnd(par->next()))
   10114          77 :                     break;
   10115             : 
   10116          97 :                 while (par->str() != ")") {
   10117          49 :                     op += par->str();
   10118          49 :                     par = par->next();
   10119             :                 }
   10120          48 :                 op += ")";
   10121          48 :                 par = par->next();
   10122          48 :                 if (Token::simpleMatch(par, "...")) {
   10123           1 :                     op.clear();
   10124           1 :                     par = nullptr;
   10125           1 :                     break;
   10126             :                 }
   10127          47 :                 done = false;
   10128         490 :             } else if (Token::Match(par, "\"\" %name% )| (|;|<")) {
   10129          12 :                 op += "\"\"";
   10130          12 :                 op += par->strAt(1);
   10131          12 :                 par = par->tokAt(2);
   10132          12 :                 if (par->str() == ")") {
   10133           1 :                     par->link()->deleteThis();
   10134           1 :                     par = par->next();
   10135           1 :                     par->deletePrevious();
   10136           1 :                     tok = par->tokAt(-3);
   10137             :                 }
   10138          12 :                 done = true;
   10139         478 :             } else if (par->str() == "::") {
   10140           1 :                 op += par->str();
   10141           1 :                 par = par->next();
   10142           1 :                 done = false;
   10143         477 :             } else if (par->str() == ";" || par->str() == ")") {
   10144           4 :                 done = true;
   10145         473 :             } else if (par->str() != "(") {
   10146           2 :                 syntaxError(par, "operator");
   10147             :             }
   10148             :         }
   10149             : 
   10150         575 :         const bool returnsRef = Token::simpleMatch(par, "( & (") && tok->next()->isName();
   10151         575 :         if (par && !op.empty()) {
   10152         569 :             if (returnsRef) {
   10153           3 :                 par->next()->insertToken("operator" + op)->isOperatorKeyword(true);
   10154           3 :                 tok->deleteThis();
   10155             :             }
   10156             :             else {
   10157         566 :                 tok->str("operator" + op);
   10158         566 :                 Token::eraseTokens(tok, par);
   10159             :             }
   10160             :         }
   10161             : 
   10162         575 :         if (!op.empty() && !returnsRef)
   10163         566 :             tok->isOperatorKeyword(true);
   10164             :     }
   10165             : 
   10166      748593 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10167      731873 :         if (Token::Match(tok, "%op% %str% %name%")) {
   10168           2 :             const std::string name = tok->strAt(2);
   10169           1 :             Token * const str = tok->next();
   10170           1 :             str->deleteNext();
   10171           1 :             tok->insertToken("operator\"\"" + name);
   10172           1 :             tok = tok->next();
   10173           1 :             tok->isOperatorKeyword(true);
   10174           1 :             tok->insertToken("(");
   10175           1 :             str->insertToken(")");
   10176           1 :             Token::createMutualLinks(tok->next(), str->next());
   10177           1 :             str->insertToken(std::to_string(Token::getStrLength(str)));
   10178           1 :             str->insertToken(",");
   10179             :         }
   10180             :     }
   10181             : 
   10182       16717 :     if (mSettings.debugwarnings) {
   10183        1362 :         const Token *tok = list.front();
   10184             : 
   10185        1365 :         while ((tok = Token::findsimplematch(tok, "operator")) != nullptr) {
   10186           3 :             reportError(tok, Severity::debug, "debug",
   10187           6 :                         "simplifyOperatorName: found unsimplified operator name");
   10188           3 :             tok = tok->next();
   10189             :         }
   10190             :     }
   10191             : }
   10192             : 
   10193       22628 : void Tokenizer::simplifyOverloadedOperators()
   10194             : {
   10195       22628 :     if (isC())
   10196        5917 :         return;
   10197       33416 :     std::set<std::string> classNames;
   10198       33417 :     std::set<nonneg int> classVars;
   10199      744967 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10200      728244 :         if (!tok->isName())
   10201      432763 :             continue;
   10202             : 
   10203      295477 :         if (Token::simpleMatch(tok, "this ) (") && Token::simpleMatch(tok->tokAt(-2), "( *")) {
   10204           1 :             tok = tok->next();
   10205           1 :             tok->insertToken("operator()");
   10206           1 :             tok->insertToken(".");
   10207           1 :             continue;
   10208             :         }
   10209             : 
   10210             :         // Get classes that have operator() member
   10211      295490 :         if (Token::Match(tok, "class|struct %name% [:{]")) {
   10212        5180 :             int indent = 0;
   10213       66399 :             for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
   10214       66394 :                 if (tok2->str() == "}")
   10215        5131 :                     break;
   10216       61263 :                 if (indent == 0 && tok2->str() == ";")
   10217           2 :                     break;
   10218       61261 :                 if (tok2->str() == "{") {
   10219        8008 :                     if (indent == 0)
   10220        5172 :                         ++indent;
   10221             :                     else
   10222        2836 :                         tok2 = tok2->link();
   10223       53295 :                 } else if (indent == 1 && Token::simpleMatch(tok2, "operator() (") && isFunctionHead(tok2->next(), ";{")) {
   10224          42 :                     classNames.insert(tok->strAt(1));
   10225          42 :                     break;
   10226             :                 }
   10227             :             }
   10228             :         }
   10229             : 
   10230             :         // Get variables that have operator() member
   10231      295490 :         if (Token::Match(tok, "%type% &| %var%") && classNames.find(tok->str()) != classNames.end()) {
   10232           6 :             tok = tok->next();
   10233           6 :             while (!tok->isName())
   10234           0 :                 tok = tok->next();
   10235           6 :             classVars.insert(tok->varId());
   10236             :         }
   10237             : 
   10238             :         // Simplify operator() calls
   10239      295492 :         if (Token::Match(tok, "%var% (") && classVars.find(tok->varId()) != classVars.end()) {
   10240             :             // constructor init list..
   10241           5 :             if (Token::Match(tok->previous(), "[:,]")) {
   10242           1 :                 const Token *start = tok->previous();
   10243           1 :                 while (Token::simpleMatch(start, ",")) {
   10244           1 :                     if (Token::simpleMatch(start->previous(), ")"))
   10245           0 :                         start = start->linkAt(-1);
   10246             :                     else
   10247           1 :                         break;
   10248           0 :                     if (Token::Match(start->previous(), "%name%"))
   10249           0 :                         start = start->tokAt(-2);
   10250             :                     else
   10251           0 :                         break;
   10252             :                 }
   10253           1 :                 const Token *after = tok->linkAt(1);
   10254           1 :                 while (Token::Match(after, ")|} , %name% (|{"))
   10255           0 :                     after = after->linkAt(3);
   10256             : 
   10257             :                 // Do not simplify initlist
   10258           1 :                 if (Token::simpleMatch(start, ":") && Token::simpleMatch(after, ") {"))
   10259           0 :                     continue;
   10260             :             }
   10261             : 
   10262           5 :             tok->insertToken("operator()");
   10263           5 :             tok->insertToken(".");
   10264             :         }
   10265             :     }
   10266             : }
   10267             : 
   10268             : // remove unnecessary member qualification..
   10269       22669 : void Tokenizer::removeUnnecessaryQualification()
   10270             : {
   10271       22669 :     if (isC())
   10272        5935 :         return;
   10273             : 
   10274       16740 :     std::vector<Space> classInfo;
   10275      729712 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10276      720299 :         if (Token::Match(tok, "class|struct|namespace %type% :|{") &&
   10277        7322 :             (!tok->previous() || tok->previous()->str() != "enum")) {
   10278        5168 :             Space info;
   10279        5168 :             info.isNamespace = tok->str() == "namespace";
   10280        5168 :             tok = tok->next();
   10281        5168 :             info.className = tok->str();
   10282        5168 :             tok = tok->next();
   10283        7204 :             while (tok && tok->str() != "{")
   10284        2036 :                 tok = tok->next();
   10285        5168 :             if (!tok)
   10286           7 :                 return;
   10287        5161 :             info.bodyEnd = tok->link();
   10288        5161 :             classInfo.push_back(std::move(info));
   10289      707813 :         } else if (!classInfo.empty()) {
   10290       74345 :             if (tok == classInfo.back().bodyEnd)
   10291        5161 :                 classInfo.pop_back();
   10292       69184 :             else if (tok->str() == classInfo.back().className &&
   10293       71362 :                      !classInfo.back().isNamespace && tok->previous()->str() != ":" &&
   10294        2178 :                      (Token::Match(tok, "%type% :: ~| %type% (") ||
   10295        2173 :                       Token::Match(tok, "%type% :: operator"))) {
   10296           5 :                 const Token *tok1 = tok->tokAt(3);
   10297           5 :                 if (tok->strAt(2) == "operator") {
   10298             :                     // check for operator ()
   10299           0 :                     if (tok1->str() == "(")
   10300           0 :                         tok1 = tok1->next();
   10301             : 
   10302           0 :                     while (tok1 && tok1->str() != "(") {
   10303           0 :                         if (tok1->str() == ";")
   10304           0 :                             break;
   10305           0 :                         tok1 = tok1->next();
   10306             :                     }
   10307           0 :                     if (!tok1 || tok1->str() != "(")
   10308           0 :                         continue;
   10309           5 :                 } else if (tok->strAt(2) == "~")
   10310           0 :                     tok1 = tok1->next();
   10311             : 
   10312           5 :                 if (!tok1 || !Token::Match(tok1->link(), ") const| {|;|:")) {
   10313           0 :                     continue;
   10314             :                 }
   10315             : 
   10316             :                 const bool isConstructorOrDestructor =
   10317           5 :                     Token::Match(tok, "%type% :: ~| %type%") && (tok->strAt(2) == tok->str() || (tok->strAt(2) == "~" && tok->strAt(3) == tok->str()));
   10318           5 :                 if (!isConstructorOrDestructor) {
   10319           5 :                     bool isPrependedByType = Token::Match(tok->previous(), "%type%");
   10320           5 :                     if (!isPrependedByType) {
   10321           1 :                         const Token* tok2 = tok->tokAt(-2);
   10322           1 :                         isPrependedByType = Token::Match(tok2, "%type% *|&");
   10323             :                     }
   10324           5 :                     if (!isPrependedByType) {
   10325           1 :                         const Token* tok3 = tok->tokAt(-3);
   10326           1 :                         isPrependedByType = Token::Match(tok3, "%type% * *|&");
   10327             :                     }
   10328           5 :                     if (!isPrependedByType) {
   10329             :                         // It's not a constructor declaration and it's not a function declaration so
   10330             :                         // this is a function call which can have all the qualifiers just fine - skip.
   10331           1 :                         continue;
   10332             :                     }
   10333             :                 }
   10334             :             }
   10335             :         }
   10336             :     }
   10337             : }
   10338             : 
   10339           1 : void Tokenizer::printUnknownTypes() const
   10340             : {
   10341           1 :     if (!mSymbolDatabase)
   10342           0 :         return;
   10343             : 
   10344           2 :     std::vector<std::pair<std::string, const Token *>> unknowns;
   10345             : 
   10346           2 :     for (int i = 1; i <= mVarId; ++i) {
   10347           1 :         const Variable *var = mSymbolDatabase->getVariableFromVarId(i);
   10348           1 :         if (!var)
   10349           1 :             continue;
   10350             :         // is unknown type?
   10351           1 :         if (var->type() || var->typeStartToken()->isStandardType())
   10352           1 :             continue;
   10353             : 
   10354           0 :         std::string name;
   10355             :         const Token * nameTok;
   10356             : 
   10357             :         // single token type?
   10358           0 :         if (var->typeStartToken() == var->typeEndToken()) {
   10359           0 :             nameTok = var->typeStartToken();
   10360           0 :             name = nameTok->str();
   10361             :         }
   10362             : 
   10363             :         // complicated type
   10364             :         else {
   10365           0 :             const Token *tok = var->typeStartToken();
   10366           0 :             int level = 0;
   10367             : 
   10368           0 :             nameTok =  tok;
   10369             : 
   10370           0 :             while (tok) {
   10371             :                 // skip pointer and reference part of type
   10372           0 :                 if (level == 0 && Token::Match(tok, "*|&"))
   10373           0 :                     break;
   10374             : 
   10375           0 :                 name += tok->str();
   10376             : 
   10377           0 :                 if (Token::Match(tok, "struct|union|enum"))
   10378           0 :                     name += " ";
   10379             : 
   10380             :                 // pointers and references are OK in template
   10381           0 :                 else if (tok->str() == "<")
   10382           0 :                     ++level;
   10383           0 :                 else if (tok->str() == ">")
   10384           0 :                     --level;
   10385             : 
   10386           0 :                 if (tok == var->typeEndToken())
   10387           0 :                     break;
   10388             : 
   10389           0 :                 tok = tok->next();
   10390             :             }
   10391             :         }
   10392             : 
   10393           0 :         unknowns.emplace_back(std::move(name), nameTok);
   10394             :     }
   10395             : 
   10396           1 :     if (!unknowns.empty()) {
   10397           0 :         std::string last;
   10398           0 :         int count = 0;
   10399             : 
   10400           0 :         for (auto it = unknowns.cbegin(); it != unknowns.cend(); ++it) {
   10401             :             // skip types is std namespace because they are not interesting
   10402           0 :             if (it->first.find("std::") != 0) {
   10403           0 :                 if (it->first != last) {
   10404           0 :                     last = it->first;
   10405           0 :                     count = 1;
   10406           0 :                     reportError(it->second, Severity::debug, "debug", "Unknown type \'" + it->first + "\'.");
   10407             :                 } else {
   10408           0 :                     if (count < 3) // limit same type to 3
   10409           0 :                         reportError(it->second, Severity::debug, "debug", "Unknown type \'" + it->first + "\'.");
   10410           0 :                     count++;
   10411             :                 }
   10412             :             }
   10413             :         }
   10414             :     }
   10415             : }
   10416             : 
   10417       45683 : void Tokenizer::prepareTernaryOpForAST()
   10418             : {
   10419             :     // http://en.cppreference.com/w/cpp/language/operator_precedence says about ternary operator:
   10420             :     //       "The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored."
   10421             :     // The AST parser relies on this function to add such parentheses where necessary.
   10422     2034124 :     for (Token* tok = list.front(); tok; tok = tok->next()) {
   10423     1988454 :         if (tok->str() == "?") {
   10424        1202 :             bool parenthesesNeeded = false;
   10425        1202 :             int depth = 0;
   10426        1202 :             Token* tok2 = tok->next();
   10427        2846 :             for (; tok2; tok2 = tok2->next()) {
   10428        2846 :                 if (tok2->link() && Token::Match(tok2, "[|(|<"))
   10429         196 :                     tok2 = tok2->link();
   10430        2650 :                 else if (tok2->str() == ":") {
   10431        1181 :                     if (depth == 0)
   10432        1178 :                         break;
   10433           3 :                     depth--;
   10434        1469 :                 } else if (tok2->str() == ";" || (tok2->link() && tok2->str() != "{" && tok2->str() != "}"))
   10435          24 :                     break;
   10436        1445 :                 else if (tok2->str() == ",")
   10437          11 :                     parenthesesNeeded = true;
   10438        1434 :                 else if (tok2->str() == "<")
   10439           5 :                     parenthesesNeeded = true;
   10440        1429 :                 else if (tok2->str() == "?") {
   10441          19 :                     depth++;
   10442          19 :                     parenthesesNeeded = true;
   10443             :                 }
   10444             :             }
   10445        1202 :             if (parenthesesNeeded && tok2 && tok2->str() == ":") {
   10446          17 :                 tok->insertToken("(");
   10447          17 :                 tok2->insertTokenBefore(")");
   10448          17 :                 Token::createMutualLinks(tok->next(), tok2->previous());
   10449             :             }
   10450             :         }
   10451             :     }
   10452       45677 : }
   10453             : 
   10454          23 : void Tokenizer::reportError(const Token* tok, const Severity severity, const std::string& id, const std::string& msg, bool inconclusive) const
   10455             : {
   10456          46 :     const std::list<const Token*> callstack(1, tok);
   10457          23 :     reportError(callstack, severity, id, msg, inconclusive);
   10458          23 : }
   10459             : 
   10460          23 : void Tokenizer::reportError(const std::list<const Token*>& callstack, Severity severity, const std::string& id, const std::string& msg, bool inconclusive) const
   10461             : {
   10462          46 :     const ErrorMessage errmsg(callstack, &list, severity, id, msg, inconclusive ? Certainty::inconclusive : Certainty::normal);
   10463          23 :     mErrorLogger.reportErr(errmsg);
   10464          23 : }
   10465             : 
   10466       22633 : void Tokenizer::setPodTypes()
   10467             : {
   10468     1014357 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10469      991717 :         if (!tok->isName() || tok->varId())
   10470      715555 :             continue;
   10471             : 
   10472             :         // pod type
   10473      276167 :         const Library::PodType *podType = mSettings.library.podtype(tok->str());
   10474      276169 :         if (podType) {
   10475        2278 :             const Token *prev = tok->previous();
   10476        2814 :             while (prev && prev->isName())
   10477         536 :                 prev = prev->previous();
   10478        2278 :             if (prev && !Token::Match(prev, ";|{|}|,|("))
   10479          71 :                 continue;
   10480        2207 :             tok->isStandardType(true);
   10481             :         }
   10482             :     }
   10483       22629 : }
   10484             : 
   10485          12 : const Token *Tokenizer::findSQLBlockEnd(const Token *tokSQLStart)
   10486             : {
   10487          12 :     const Token *tokLastEnd = nullptr;
   10488          76 :     for (const Token *tok = tokSQLStart->tokAt(2); tok != nullptr; tok = tok->next()) {
   10489          71 :         if (tokLastEnd == nullptr && tok->str() == ";")
   10490           8 :             tokLastEnd = tok;
   10491          63 :         else if (tok->str() == "__CPPCHECK_EMBEDDED_SQL_EXEC__") {
   10492           5 :             if (Token::simpleMatch(tok->tokAt(-2), "END - __CPPCHECK_EMBEDDED_SQL_EXEC__ ;"))
   10493           2 :                 return tok->next();
   10494           3 :             return tokLastEnd;
   10495          58 :         } else if (Token::Match(tok, "{|}|==|&&|!|^|<<|>>|++|+=|-=|/=|*=|>>=|<<=|~"))
   10496           2 :             break; // We are obviously outside the SQL block
   10497             :     }
   10498             : 
   10499           7 :     return tokLastEnd;
   10500             : }
   10501             : 
   10502       22703 : void Tokenizer::simplifyNestedNamespace()
   10503             : {
   10504       22703 :     if (!isCPP())
   10505        5936 :         return;
   10506             : 
   10507      740147 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10508      723379 :         if (Token::Match(tok, "namespace %name% ::") && tok->strAt(-1) != "using") {
   10509           7 :             Token * tok2 = tok->tokAt(2);
   10510             : 
   10511             :             // validate syntax
   10512          15 :             while (Token::Match(tok2, ":: %name%"))
   10513           8 :                 tok2 = tok2->tokAt(2);
   10514             : 
   10515           7 :             if (!tok2 || tok2->str() != "{")
   10516           1 :                 return; // syntax error
   10517             : 
   10518          12 :             std::stack<Token *> links;
   10519           6 :             tok2 = tok->tokAt(2);
   10520             : 
   10521          13 :             while (tok2->str() == "::") {
   10522           7 :                 links.push(tok2);
   10523           7 :                 tok2->str("{");
   10524           7 :                 tok2->insertToken("namespace");
   10525           7 :                 tok2 = tok2->tokAt(3);
   10526             :             }
   10527             : 
   10528           6 :             tok = tok2;
   10529             : 
   10530           6 :             if (!links.empty() && tok2->str() == "{") {
   10531           6 :                 tok2 = tok2->link();
   10532          13 :                 while (!links.empty()) {
   10533           7 :                     tok2->insertToken("}");
   10534           7 :                     tok2 = tok2->next();
   10535           7 :                     Token::createMutualLinks(links.top(), tok2);
   10536           7 :                     links.pop();
   10537             :                 }
   10538             :             }
   10539             :         }
   10540             :     }
   10541             : }
   10542             : 
   10543       22703 : void Tokenizer::simplifyCoroutines()
   10544             : {
   10545       22703 :     if (!isCPP() || mSettings.standards.cpp < Standards::CPP20)
   10546        7219 :         return;
   10547      647099 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10548      631612 :         if (!tok->isName() || !Token::Match(tok, "co_return|co_yield|co_await"))
   10549      631613 :             continue;
   10550           3 :         Token *end = tok->next();
   10551           8 :         while (end && end->str() != ";") {
   10552           5 :             if (Token::Match(end, "[({[]"))
   10553           1 :                 end = end->link();
   10554           4 :             else if (Token::Match(end, "[)]}]"))
   10555           0 :                 break;
   10556           5 :             end = end->next();
   10557             :         }
   10558           3 :         if (Token::simpleMatch(end, ";")) {
   10559           3 :             tok->insertToken("(");
   10560           3 :             end->previous()->insertToken(")");
   10561           3 :             Token::createMutualLinks(tok->next(), end->previous());
   10562             :         }
   10563             :     }
   10564             : }
   10565             : 
   10566          23 : static bool sameTokens(const Token *first, const Token *last, const Token *other)
   10567             : {
   10568          23 :     while (other && first->str() == other->str()) {
   10569          22 :         if (first == last)
   10570           7 :             return true;
   10571          15 :         first = first->next();
   10572          15 :         other = other->next();
   10573             :     }
   10574             : 
   10575           1 :     return false;
   10576             : }
   10577             : 
   10578          21 : static bool alreadyHasNamespace(const Token *first, const Token *last, const Token *end)
   10579             : {
   10580          21 :     while (end && last->str() == end->str()) {
   10581          10 :         if (first == last)
   10582           1 :             return true;
   10583           9 :         last = last->previous();
   10584           9 :         end = end->previous();
   10585             :     }
   10586             : 
   10587          11 :     return false;
   10588             : }
   10589             : 
   10590           8 : static Token * deleteAlias(Token * tok)
   10591             : {
   10592           8 :     Token::eraseTokens(tok, Token::findsimplematch(tok, ";"));
   10593             : 
   10594             :     // delete first token
   10595           8 :     tok->deleteThis();
   10596             : 
   10597             :     // delete ';' if not last token
   10598           8 :     tok->deleteThis();
   10599             : 
   10600           8 :     return tok;
   10601             : }
   10602             : 
   10603       22703 : void Tokenizer::simplifyNamespaceAliases()
   10604             : {
   10605       22703 :     if (!isCPP())
   10606        5936 :         return;
   10607             : 
   10608       16767 :     int scope = 0;
   10609             : 
   10610      740071 :     for (Token *tok = list.front(); tok; tok = tok->next()) {
   10611      723299 :         bool isPrev{};
   10612      723299 :         if (tok->str() == "{")
   10613       32955 :             scope++;
   10614      690334 :         else if (tok->str() == "}")
   10615       32956 :             scope--;
   10616      657376 :         else if (Token::Match(tok, "namespace %name% =") || (isPrev = Token::Match(tok->previous(), "namespace %name% ="))) {
   10617          17 :             if (isPrev)
   10618           1 :                 tok = tok->previous();
   10619          17 :             if (tok->tokAt(-1) && !Token::Match(tok->tokAt(-1), "[;{}]"))
   10620           0 :                 syntaxError(tok->tokAt(-1));
   10621          18 :             const std::string name(tok->next()->str());
   10622          17 :             Token * tokNameStart = tok->tokAt(3);
   10623          17 :             Token * tokNameEnd = tokNameStart;
   10624             : 
   10625          52 :             while (tokNameEnd && tokNameEnd->next() && tokNameEnd->next()->str() != ";") {
   10626          36 :                 if (tokNameEnd->str() == "(") {
   10627           1 :                     if (tokNameEnd->previous()->isName())
   10628           1 :                         unknownMacroError(tokNameEnd->previous());
   10629             :                     else
   10630           0 :                         syntaxError(tokNameEnd);
   10631             :                 }
   10632          35 :                 tokNameEnd = tokNameEnd->next();
   10633             :             }
   10634             : 
   10635          16 :             if (!tokNameEnd)
   10636           0 :                 return; // syntax error
   10637             : 
   10638          16 :             int endScope = scope;
   10639          16 :             Token * tokLast = tokNameEnd->next();
   10640          16 :             if (!tokLast)
   10641           0 :                 return;
   10642          16 :             Token * tokNext = tokLast->next();
   10643          16 :             Token * tok2 = tokNext;
   10644             : 
   10645         246 :             while (tok2 && endScope >= scope) {
   10646         230 :                 if (Token::simpleMatch(tok2, "{"))
   10647           9 :                     endScope++;
   10648         221 :                 else if (Token::simpleMatch(tok2, "}"))
   10649          12 :                     endScope--;
   10650         209 :                 else if (tok2->str() == name) {
   10651          21 :                     if (Token::Match(tok2->previous(), "namespace %name% =")) {
   10652             :                         // check for possible duplicate aliases
   10653           8 :                         if (sameTokens(tokNameStart, tokNameEnd, tok2->tokAt(2))) {
   10654             :                             // delete duplicate
   10655           7 :                             tok2 = deleteAlias(tok2->previous());
   10656           7 :                             continue;
   10657             :                         }
   10658             :                         // conflicting declaration (syntax error)
   10659             :                         // cppcheck-suppress duplicateBranch - remove when TODO below is addressed
   10660           1 :                         if (endScope == scope) {
   10661             :                             // delete conflicting declaration
   10662           0 :                             tok2 = deleteAlias(tok2->previous());
   10663             :                         }
   10664             : 
   10665             :                         // new declaration
   10666             :                         else {
   10667             :                             // TODO: use the new alias in this scope
   10668           1 :                             tok2 = deleteAlias(tok2->previous());
   10669             :                         }
   10670           1 :                         continue;
   10671             :                     }
   10672             : 
   10673          13 :                     if (tok2->strAt(1) == "::" && !alreadyHasNamespace(tokNameStart, tokNameEnd, tok2)) {
   10674          11 :                         if (Token::simpleMatch(tok2->tokAt(-1), "::") && tokNameStart->str() == "::")
   10675           1 :                             tok2->deletePrevious();
   10676          11 :                         tok2->str(tokNameStart->str());
   10677          11 :                         Token * tok3 = tokNameStart;
   10678          28 :                         while (tok3 != tokNameEnd) {
   10679          17 :                             tok2->insertToken(tok3->next()->str());
   10680          17 :                             tok2 = tok2->next();
   10681          17 :                             tok3 = tok3->next();
   10682             :                         }
   10683             :                     }
   10684             :                 }
   10685         222 :                 tok2 = tok2->next();
   10686             :             }
   10687             : 
   10688          16 :             if (tok->previous() && tokNext) {
   10689           8 :                 Token::eraseTokens(tok->previous(), tokNext);
   10690           8 :                 tok = tokNext->previous();
   10691           8 :             } else if (tok->previous()) {
   10692           1 :                 Token::eraseTokens(tok->previous(), tokLast);
   10693           1 :                 tok = tokLast;
   10694           7 :             } else if (tokNext) {
   10695           5 :                 Token::eraseTokens(tok, tokNext);
   10696           5 :                 tok->deleteThis();
   10697             :             } else {
   10698           2 :                 Token::eraseTokens(tok, tokLast);
   10699           2 :                 tok->deleteThis();
   10700             :             }
   10701             :         }
   10702             :     }
   10703             : }
   10704             : 
   10705        3441 : void Tokenizer::setDirectives(std::list<Directive> directives)
   10706             : {
   10707        3441 :     mDirectives = std::move(directives);
   10708        3442 : }
   10709             : 
   10710       18331 : bool Tokenizer::hasIfdef(const Token *start, const Token *end) const
   10711             : {
   10712       18331 :     const auto& directives = mDirectives;
   10713       18331 :     return std::any_of(directives.cbegin(), directives.cend(), [&](const Directive& d) {
   10714      759285 :         return startsWith(d.str, "#if") &&
   10715      115741 :         d.linenr >= start->linenr() &&
   10716       46568 :         d.linenr <= end->linenr() &&
   10717      875138 :         start->fileIndex() < list.getFiles().size() &&
   10718      759397 :         d.file == list.getFiles()[start->fileIndex()];
   10719       18331 :     });
   10720             : }
   10721             : 
   10722         164 : bool Tokenizer::isPacked(const Token * bodyStart) const
   10723             : {
   10724         164 :     const auto& directives = mDirectives;
   10725             :     // TODO: should this return true if the #pragma exists in any line before the start token?
   10726         164 :     return std::any_of(directives.cbegin(), directives.cend(), [&](const Directive& d) {
   10727         932 :         return d.linenr < bodyStart->linenr() && d.str == "#pragma pack(1)" && d.file == list.getFiles().front();
   10728         164 :     });
   10729             : }

Generated by: LCOV version 1.14