40 #include <unordered_set> 
   42 #include <simplecpp.h> 
   48 #define ASSERT_LANG(x) assert(x) 
   50 #define ASSERT_LANG(x) 
   60     : mTokensFrontBack(*this)
 
   97     if (
mLang == Standards::Language::None) {
 
  102         if (
mLang == Standards::Language::None) {
 
  105             mLang = Standards::Language::CPP;
 
  113     for (
int i = 0; i < 
mFiles.size(); ++i)
 
  118     mFiles.push_back(std::move(fileName));
 
  154         while ((end = str.find(
"##", begin)) != std::string::npos) {
 
  155             addtoken(str.substr(begin, end - begin), lineno, fileno, 
false);
 
  156             addtoken(
"##", lineno, column, fileno, 
false);
 
  160             addtoken(str.substr(begin), lineno, column, fileno, 
false);
 
  219     if (tok == 
nullptr || locationTok == 
nullptr)
 
  266     std::stack<Token *> links;
 
  268     int linenr = dest->
linenr();
 
  269     const int commonFileIndex = dest->
fileIndex();
 
  270     for (
const Token *tok = first; tok != last->
next(); tok = tok->
next()) {
 
  276         tok2->
flags(tok->flags());
 
  277         tok2->
varId(tok->varId());
 
  287             Token * link = links.top();
 
  294         if (!one_line && tok->next())
 
  295             linenr += tok->next()->linenr() - tok->linenr();
 
  306     std::stack<Token *> link;
 
  315         else if (!link.empty() && 
Token::Match(dest, 
")|]|}")) {
 
  350     if (
mLang == Standards::Language::None) {
 
  363     simplecpp::OutputList outputList;
 
  364     simplecpp::TokenList tokens(code, 
mFiles, file0, &outputList);
 
  368     return outputList.empty();
 
  377     if (!tokenList.getFiles().empty()) {
 
  387     for (
const simplecpp::Token *tok = tokenList.cfront(); tok;) {
 
  390         std::string str = tok->str();
 
  393         if (str.size() > 1 && str[0] == 
'.' && std::isdigit(str[1]))
 
  411             tokenList.deleteToken(tok->previous);
 
  415         for (std::string & mFile : 
mFiles)
 
  426     std::string hashData;
 
  428         hashData += std::to_string(tok->flags());
 
  429         hashData += std::to_string(tok->varId());
 
  430         hashData += std::to_string(tok->tokType());
 
  431         hashData += tok->str();
 
  432         hashData += tok->originalName();
 
  434     return (std::hash<std::string>{})(hashData);
 
  442         std::stack<Token*> op;
 
  444         int inArrayAssignment{};
 
  449         const Token* functionCallEndPar{};
 
  450         explicit AST_state(
bool cpp) : cpp(cpp) {}
 
  456     auto isDecltypeFuncParam = [](
const Token* tok) -> 
bool {
 
  463             tok = tok->
link()->next();
 
  471         if (vartok->
str() == 
"<") {
 
  473                 vartok = vartok->
link();
 
  478         } 
else if (
Token::Match(vartok, 
"decltype|typeof (") && !isDecltypeFuncParam(tok->
linkAt(1))) {
 
  480                 inner->push_back(vartok->
tokAt(2));
 
  483         vartok = vartok->
next();
 
  519     for (
const Token *tok2 = tok->
next(); tok2; tok2 = tok2->
next()) {
 
  520         if (tok2->varId() != 0)
 
  522         if (cpp && !type && tok2->str() == 
"new")
 
  526             tok2 = tok2->link()->next();
 
  528         if (tok2->str() == 
")") {
 
  535                 return tok3->
str() != 
";";
 
  539                               (!tok2->next()->isOp() || 
Token::Match(tok2->next(), 
"!|~|++|--")) &&
 
  550         if (tok2->isStandardType() && (tok2->next()->str() != 
"(" || 
Token::Match(tok2->next(), 
"( * *| )")))
 
  564         if (tok->
str() == 
"<") {
 
  578     return (tok && tok->
str() == 
"(") ? tok : 
nullptr;
 
  582 static bool iscpp11init_impl(
const Token * 
const tok);
 
  583 static bool iscpp11init(
const Token * 
const tok)
 
  590 static bool iscpp11init_impl(
const Token * 
const tok)
 
  594     const Token *nameToken = tok;
 
  595     while (nameToken && nameToken->
str() == 
"{") {
 
  600             nameToken = nameToken->
linkAt(-1);
 
  606         nameToken = nameToken->
link()->previous();
 
  609     if (nameToken->
str() == 
">" && nameToken->
link())
 
  610         nameToken = nameToken->
link()->previous();
 
  619     auto isCaseStmt = [](
const Token* colonTok) {
 
  620         if (!
Token::Match(colonTok->tokAt(-1), 
"%name%|%num%|%char%|) :"))
 
  628             caseTok = caseTok->
tokAt(-1);
 
  632     const Token *endtok = 
nullptr;
 
  633     if (
Token::Match(nameToken, 
"%name%|return|: {") && !isCaseStmt(nameToken) &&
 
  635         endtok = nameToken->
linkAt(1);
 
  639         endtok = nameToken->
linkAt(1);
 
  644     if (
Token::Match(nameToken, 
"else|try|do|const|constexpr|override|volatile|&|&&"))
 
  652         for (
const Token *tok2 = nameToken->
next(); tok2 != endtok; tok2 = tok2->
next()) {
 
  653             if (tok2->str() == 
";")
 
  663     const Token *prev = nameToken;
 
  664     while (
Token::Match(prev, 
"%name%|::|:|<|>|(|)|,|%num%|%cop%|...")) {
 
  673 static bool isQualifier(
const Token* tok)
 
  680 static void compileUnaryOp(
Token *&tok, AST_state& state, 
void (*f)(
Token *&tok, AST_state& state))
 
  682     Token *unaryop = tok;
 
  697     state.op.push(unaryop);
 
  700 static void compileBinOp(
Token *&tok, AST_state& state, 
void (*f)(
Token *&tok, AST_state& state))
 
  718     if (!state.op.empty()) {
 
  722     if (!state.op.empty()) {
 
  726     state.op.push(binop);
 
  729 static void compileExpression(
Token *&tok, AST_state& state);
 
  731 static void compileTerm(
Token *&tok, AST_state& state)
 
  752     } 
else if (tok->
isName()) {
 
  753         if (
Token::Match(tok, 
"return|case") || (state.cpp && (tok->
str() == 
"throw"))) {
 
  754             if (tok->
str() == 
"case")
 
  756             const bool tokIsReturn = tok->
str() == 
"return";
 
  757             const bool stopAtColon = state.stopAtColon;
 
  758             state.stopAtColon=
true;
 
  759             compileUnaryOp(tok, state, compileExpression);
 
  760             state.stopAtColon=stopAtColon;
 
  764                 state.inCase = 
false;
 
  768             compileUnaryOp(tok, state, compileExpression);
 
  770         } 
else if (state.cpp && findCppTypeInitPar(tok)) {  
 
  771             tok = findCppTypeInitPar(tok);
 
  774         } 
else if (state.cpp && iscpp11init(tok)) { 
 
  777             if (tok->
str() == 
"<")
 
  778                 tok = tok->
link()->next();
 
  782                 const int inArrayAssignment = state.inArrayAssignment;
 
  783                 state.inArrayAssignment = 1;
 
  784                 compileBinOp(tok, state, compileExpression);
 
  785                 state.inArrayAssignment = inArrayAssignment;
 
  791         } 
else if (!state.cpp || !
Token::Match(tok, 
"new|delete %name%|*|&|::|(|[")) {
 
  792             std::vector<Token*> inner;
 
  794             for (
Token* tok3 : inner) {
 
  795                 AST_state state1(state.cpp);
 
  796                 compileExpression(tok3, state1);
 
  813             else if (
Token::Match(tok, 
"%name% ...") || (state.op.size() == 1 && state.depth == 0 && 
Token::Match(tok->
tokAt(-3), 
"!!& ) ( %name% ) =")))
 
  823     } 
else if (tok->
str() == 
"{") {
 
  826             prev = prev->
link()->previous();
 
  833                     const int inArrayAssignment = state.inArrayAssignment;
 
  834                     state.inArrayAssignment = 1;
 
  835                     compileBinOp(tok, state, compileExpression);
 
  836                     state.inArrayAssignment = inArrayAssignment;
 
  841                     compileUnaryOp(tok, state, compileExpression);
 
  846                 compileBinOp(tok, state, compileExpression);
 
  856                 state.inArrayAssignment++;
 
  857                 compileUnaryOp(tok, state, compileExpression);
 
  858                 state.inArrayAssignment--;
 
  859                 tok = tok1->
link()->next();
 
  863             tok = tok->
link()->next();
 
  866                 state.inArrayAssignment++;
 
  867                 compileUnaryOp(tok, state, compileExpression);
 
  868                 if (
Token::Match(tok, 
"} [,};]") && state.inArrayAssignment > 0) {
 
  870                     state.inArrayAssignment--;
 
  880 static void compileScope(
Token *&tok, AST_state& state)
 
  882     compileTerm(tok, state);
 
  884         if (tok->
str() == 
"::") {
 
  885             const Token *lastOp = state.op.empty() ? nullptr : state.op.top();
 
  887                 lastOp = lastOp->
next();
 
  890                 compileBinOp(tok, state, compileTerm);
 
  892                 compileUnaryOp(tok, state, compileTerm);
 
  897 static bool isPrefixUnary(
const Token* tok, 
bool cpp)
 
  906             if (prev->
str() == 
"new")
 
  926 static void compilePrecedence2(
Token *&tok, AST_state& state)
 
  928     auto doCompileScope = [&](
const Token* tok) -> 
bool {
 
  929         const bool isStartOfCpp11Init = state.cpp && tok && tok->
str() == 
"{" && iscpp11init(tok);
 
  935                 tok = tok->
tokAt(-2);
 
  944     if (doCompileScope(tok)) {
 
  945         compileScope(tok, state);
 
  950             compileUnaryOp(tok, state, compileScope);
 
  951         } 
else if (tok->
str() == 
"...") {
 
  956         } 
else if (tok->
str() == 
"." && tok->
strAt(1) != 
"*") {
 
  957             if (tok->
strAt(1) == 
".") {
 
  962             compileBinOp(tok, state, compileScope);
 
  963         } 
else if (tok->
str() == 
"[") {
 
  964             if (state.cpp && isPrefixUnary(tok,  
true) && 
Token::Match(tok->
link(), 
"] (|{|<")) { 
 
  970                 Token* 
const squareBracket = tok;
 
  972                 if (tok->
strAt(1) != 
"]") {
 
  974                     AST_state state2(state.cpp);
 
  975                     compileExpression(tok2, state2);
 
  976                     if (!state2.op.empty()) {
 
  984                     Token* 
const roundBracket = hasTemplateArg ? squareBracket->
link()->next()->link()->next() : squareBracket->
link()->next();
 
  985                     Token* curlyBracket = roundBracket->
link()->next();
 
  986                     while (
Token::Match(curlyBracket, 
"mutable|const|constexpr|consteval"))
 
  987                         curlyBracket = curlyBracket->
next();
 
  990                             curlyBracket = curlyBracket->
linkAt(1)->
next();
 
  992                             curlyBracket = curlyBracket->
next();
 
  994                     if (curlyBracket && curlyBracket->
originalName() == 
"->")
 
  996                     if (curlyBracket && curlyBracket->
str() == 
"{") {
 
  999                         state.op.push(squareBracket);
 
 1000                         tok = curlyBracket->
link()->next();
 
 1004                     Token* 
const curlyBracket = squareBracket->
link()->next();
 
 1006                     state.op.push(squareBracket);
 
 1007                     tok = curlyBracket->
link() ? curlyBracket->
link()->next() : 
nullptr;
 
 1012             Token* 
const tok2 = tok;
 
 1013             if (tok->
strAt(1) != 
"]") {
 
 1014                 compileBinOp(tok, state, compileExpression);
 
 1017                     Token* 
const tok3 = tok;
 
 1018                     compileBinOp(tok, state, compileExpression);
 
 1019                     if (tok != tok3->
link())
 
 1026                 compileUnaryOp(tok, state, compileExpression);
 
 1027             tok = tok2->
link()->next();
 
 1029             state.op.push(tok->
next());
 
 1030             tok = tok->
link()->next();
 
 1035             const bool opPrevTopSquare = !state.op.empty() && state.op.top() && state.op.top()->
str() == 
"[";
 
 1036             const std::size_t oldOpSize = state.op.size();
 
 1037             compileExpression(tok, state);
 
 1044                 || (tok->
strAt(-1) == 
"}" && opPrevTopSquare)) {
 
 1045                 const bool operandInside = oldOpSize < state.op.size();
 
 1047                     compileBinOp(tok, state, 
nullptr);
 
 1049                     compileUnaryOp(tok, state, 
nullptr);
 
 1051             tok = tok->
link()->next();
 
 1053                 compileBinOp(tok, state, compileTerm);
 
 1056             tok = tok->
link()->next();
 
 1058             compileUnaryOp(tok, state, compileExpression);
 
 1060             tok = tok1->
link()->next();
 
 1061         } 
else if (state.cpp && tok->
str() == 
"{" && iscpp11init(tok)) {
 
 1065                 compileUnaryOp(tok, state, 
nullptr);
 
 1070                 compileBinOp(tok, state, compileExpression);
 
 1080 static void compilePrecedence3(
Token *&tok, AST_state& state)
 
 1082     compilePrecedence2(tok, state);
 
 1085             isPrefixUnary(tok, state.cpp)) {
 
 1088                 while (tok2->
next() && tok2->
str() == 
"*")
 
 1089                     tok2 = tok2->
next();
 
 1095             compileUnaryOp(tok, state, compilePrecedence3);
 
 1096         } 
else if (tok->
str() == 
"(" && 
iscast(tok, state.cpp)) {
 
 1097             Token* castTok = tok;
 
 1099             tok = tok->
link()->next();
 
 1100             const int inArrayAssignment = state.inArrayAssignment;
 
 1101             if (tok && tok->
str() == 
"{")
 
 1102                 state.inArrayAssignment = 1;
 
 1103             compilePrecedence3(tok, state);
 
 1104             state.inArrayAssignment = inArrayAssignment;
 
 1105             compileUnaryOp(castTok, state, 
nullptr);
 
 1106         } 
else if (state.cpp && 
Token::Match(tok, 
"new %name%|::|(")) {
 
 1107             Token* newtok = tok;
 
 1109             bool innertype = 
false;
 
 1110             if (tok->
str() == 
"(") {
 
 1112                     tok = tok->
link()->next();
 
 1116                         AST_state innerState(
true);
 
 1117                         compileExpression(innerTok, innerState);
 
 1119                     tok = tok->
link()->next();
 
 1132             Token* leftToken = tok;
 
 1142                     leftToken = scopeToken;
 
 1143                     tok = scopeToken->
next();
 
 1154                 state.op.push(tok->
next());
 
 1155                 tok = tok->
link()->next();
 
 1156                 compileBinOp(tok, state, compilePrecedence2);
 
 1158                 compilePrecedence2(tok, state);
 
 1161                 compilePrecedence2(tok, state);
 
 1163             compileUnaryOp(newtok, state, 
nullptr);
 
 1170         } 
else if (state.cpp && 
Token::Match(tok, 
"delete %name%|*|&|::|(|[")) {
 
 1173             if (tok && tok->
str() == 
"[")
 
 1174                 tok = tok->
link()->next();
 
 1175             compilePrecedence3(tok, state);
 
 1176             compileUnaryOp(tok2, state, 
nullptr);
 
 1187 static void compilePointerToElem(
Token *&tok, AST_state& state)
 
 1189     compilePrecedence3(tok, state);
 
 1192             compileBinOp(tok, state, compilePrecedence3);
 
 1197 static void compileMulDiv(
Token *&tok, AST_state& state)
 
 1199     compilePointerToElem(tok, state);
 
 1204                 while (tok2->
next() && tok2->
str() == 
"*")
 
 1205                     tok2 = tok2->
next();
 
 1211             compileBinOp(tok, state, compilePointerToElem);
 
 1216 static void compileAddSub(
Token *&tok, AST_state& state)
 
 1218     compileMulDiv(tok, state);
 
 1221             compileBinOp(tok, state, compileMulDiv);
 
 1226 static void compileShift(
Token *&tok, AST_state& state)
 
 1228     compileAddSub(tok, state);
 
 1231             compileBinOp(tok, state, compileAddSub);
 
 1236 static void compileThreewayComp(
Token *&tok, AST_state& state)
 
 1238     compileShift(tok, state);
 
 1240         if (tok->
str() == 
"<=>") {
 
 1241             compileBinOp(tok, state, compileShift);
 
 1246 static void compileRelComp(
Token *&tok, AST_state& state)
 
 1248     compileThreewayComp(tok, state);
 
 1251             compileBinOp(tok, state, compileThreewayComp);
 
 1256 static void compileEqComp(
Token *&tok, AST_state& state)
 
 1258     compileRelComp(tok, state);
 
 1261             compileBinOp(tok, state, compileRelComp);
 
 1266 static void compileAnd(
Token *&tok, AST_state& state)
 
 1268     compileEqComp(tok, state);
 
 1270         if (tok->
str() == 
"&" && !tok->
astOperand1() && !isQualifier(tok)) {
 
 1274             if (tok2->
str() == 
"&")
 
 1275                 tok2 = tok2->
next();
 
 1280             compileBinOp(tok, state, compileEqComp);
 
 1285 static void compileXor(
Token *&tok, AST_state& state)
 
 1287     compileAnd(tok, state);
 
 1289         if (tok->
str() == 
"^") {
 
 1290             compileBinOp(tok, state, compileAnd);
 
 1295 static void compileOr(
Token *&tok, AST_state& state)
 
 1297     compileXor(tok, state);
 
 1299         if (tok->
str() == 
"|") {
 
 1300             compileBinOp(tok, state, compileXor);
 
 1305 static void compileLogicAnd(
Token *&tok, AST_state& state)
 
 1307     compileOr(tok, state);
 
 1309         if (tok->
str() == 
"&&" && !isQualifier(tok)) {
 
 1319             compileBinOp(tok, state, compileOr);
 
 1324 static void compileLogicOr(
Token *&tok, AST_state& state)
 
 1326     compileLogicAnd(tok, state);
 
 1328         if (tok->
str() == 
"||") {
 
 1329             compileBinOp(tok, state, compileLogicAnd);
 
 1334 static void compileAssignTernary(
Token *&tok, AST_state& state)
 
 1336     compileLogicOr(tok, state);
 
 1341             compileBinOp(tok, state, compileAssignTernary);
 
 1344             if (state.assign > 0)
 
 1346         } 
else if (tok->
str() == 
"?") {
 
 1350             const bool stopAtColon = state.stopAtColon;
 
 1351             state.stopAtColon = 
false;
 
 1352             if (tok->
strAt(1) == 
":") {
 
 1353                 state.op.push(
nullptr);
 
 1355             const int assign = state.assign;
 
 1357             compileBinOp(tok, state, compileAssignTernary);
 
 1358             state.assign = assign;
 
 1359             state.stopAtColon = stopAtColon;
 
 1360         } 
else if (tok->
str() == 
":") {
 
 1361             if (state.depth == 1U && state.inCase) {
 
 1362                 state.inCase = 
false;
 
 1366             if (state.stopAtColon)
 
 1368             if (state.assign > 0)
 
 1370             compileBinOp(tok, state, compileAssignTernary);
 
 1375 static void compileComma(
Token *&tok, AST_state& state)
 
 1377     compileAssignTernary(tok, state);
 
 1379         if (tok->
str() == 
",") {
 
 1383                 compileBinOp(tok, state, compileAssignTernary);
 
 1384         } 
else if (tok->
str() == 
";" && state.functionCallEndPar && tok->
index() < state.functionCallEndPar->index()) {
 
 1385             compileBinOp(tok, state, compileAssignTernary);
 
 1390 static void compileExpression(
Token *&tok, AST_state& state)
 
 1395         compileComma(tok, state);
 
 1422     tok = tok->
link()->next();
 
 1424         tok = tok->
link()->next();
 
 1427         while (
Token::Match(tok, 
"%type%|%name%|::|&|&&|*|<|(")) {
 
 1429                 tok = tok->
link()->next();
 
 1436     return tok->
link()->next();
 
 1442 static void createAstAtTokenInner(
Token * 
const tok1, 
const Token *endToken, 
bool cpp)
 
 1444     for (
Token* tok = tok1; 
precedes(tok, endToken); tok = tok ? tok->
next() : 
nullptr) {
 
 1445         if (tok->
str() == 
"{" && !iscpp11init(tok)) {
 
 1446             const Token * 
const endToken2 = tok->
link();
 
 1447             bool hasAst = 
false;
 
 1448             for (
const Token *inner = tok->
next(); inner != endToken2; inner = inner->
next()) {
 
 1449                 if (inner->astOperand1()) {
 
 1455                 if (inner->str() == 
"{")
 
 1456                     inner = inner->link();
 
 1459                 for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->
next() : 
nullptr)
 
 1460                     tok = createAstAtToken(tok);
 
 1462         } 
else if (cpp && tok->
str() == 
"[") {
 
 1465                 if (tok->
str() == 
"(")
 
 1467                 const Token * 
const endToken2 = tok->
link();
 
 1469                 for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->
next() : 
nullptr)
 
 1470                     tok = createAstAtToken(tok);
 
 1474             bool hasAst = 
false;
 
 1484                 AST_state state(cpp);
 
 1485                 compileExpression(tok, state);
 
 1486                 createAstAtTokenInner(startTok, endtok, cpp);
 
 1494     for (
Token *tok = tok1; tok && (tok != tok2); tok = tok->
next()) {
 
 1495         if (tok->astParent() || tok->astOperand1() || tok->astOperand2()) {
 
 1496             while (tok->astParent() && tok->astParent()->index() >= tok1->
index() && tok->astParent()->index() <= tok2->
index())
 
 1503     for (
Token *tok = tok1; tok && (tok != tok2); tok = tok->
next()) {
 
 1504         if (tok->isName() || tok->isNumber())
 
 1514     const bool cpp = tok->
isCpp();
 
 1520             tok2 = tok2->
next();
 
 1525         bool isStandardTypeOrQualifier = 
false;
 
 1529                 isStandardTypeOrQualifier = 
true;
 
 1530             if (type->
str() == 
"<") {
 
 1532                     type = type->
link();
 
 1536             type = type->
next();
 
 1538         if (isStandardTypeOrQualifier && 
Token::Match(type, 
"%var% [;,)]"))
 
 1543             return type->
link()->linkAt(1)->next();
 
 1547         if (cpp && 
Token::Match(tok, 
"for ( const| auto &|&&| [")) {
 
 1550                 AST_state state1(cpp);
 
 1551                 while (decl->
str() != 
"]") {
 
 1553                         state1.op.push(decl);
 
 1554                     } 
else if (decl->
str() == 
",") {
 
 1555                         if (!state1.op.empty()) {
 
 1559                         if (!state1.op.empty()) {
 
 1560                             state1.op.top()->astOperand2(decl);
 
 1563                         state1.op.push(decl);
 
 1565                     decl = decl->
next();
 
 1567                 if (state1.op.size() > 1) {
 
 1568                     Token *lastName = state1.op.top();
 
 1572                 decl = decl->
next();
 
 1574                 Token *colon = decl;
 
 1575                 compileExpression(decl, state1);
 
 1584         std::vector<Token*> inner;
 
 1586         for (
Token* tok3 : inner) {
 
 1587             AST_state state1(cpp);
 
 1588             compileExpression(tok3, state1);
 
 1590         Token *init1 = 
nullptr;
 
 1594             AST_state state1(cpp);
 
 1595             compileExpression(tok2, state1);
 
 1597                 for (
Token *tok3 = init1; tok3 && tok3 != tok3->
link(); tok3 = tok3->
next()) {
 
 1609             while (tok2 && tok2 != endPar && tok2->
str() != 
";") {
 
 1610                 if (tok2->
str() == 
"<" && tok2->
link()) {
 
 1611                     tok2 = tok2->
link();
 
 1614                     AST_state state1(cpp);
 
 1615                     compileExpression(tok2, state1);
 
 1622                 tok2 = tok2->
next();
 
 1625         if (!tok2 || tok2->
str() != 
";") {
 
 1626             if (tok2 == endPar && init1) {
 
 1627                 createAstAtTokenInner(init1->
next(), endPar, cpp);
 
 1634         Token * 
const init = init1 ? init1 : tok2;
 
 1636         Token * 
const semicolon1 = tok2;
 
 1637         tok2 = tok2->
next();
 
 1638         AST_state state2(cpp);
 
 1639         compileExpression(tok2, state2);
 
 1641         Token * 
const semicolon2 = tok2;
 
 1645         if (semicolon2->
str() == 
";") {
 
 1646             tok2 = tok2->
next();
 
 1647             AST_state state3(cpp);
 
 1649                 state3.op.push(tok2->
next());
 
 1650                 tok2 = tok2->
link()->next();
 
 1652             compileExpression(tok2, state3);
 
 1654             tok2 = findAstTop(semicolon1->
next(), semicolon2);
 
 1657             tok2 = findAstTop(semicolon2->
next(), endPar);
 
 1660             else if (!state3.op.empty())
 
 1670         if (init != semicolon1)
 
 1675         createAstAtTokenInner(endPar->
link(), endPar, cpp);
 
 1690                 tok2 = tok2->
tokAt(2);
 
 1698             AST_state state(cpp);
 
 1699             compileExpression(tok, state);
 
 1700             createAstAtTokenInner(tok1->
next(), tok1->
linkAt(1), cpp);
 
 1707         Token *typetok = tok;
 
 1711             typetok = typetok->
next();
 
 1728         (cpp && tok->
str() == 
"throw") ||
 
 1738         Token * 
const tok1 = tok;
 
 1739         AST_state state(cpp);
 
 1741             state.functionCallEndPar = tok->
linkAt(1);
 
 1743             tok = tok->
tokAt(-1);
 
 1744         compileExpression(tok, state);
 
 1745         Token * 
const endToken = tok;
 
 1746         if (endToken == tok1 || !endToken)
 
 1749         createAstAtTokenInner(tok1->
next(), endToken, cpp);
 
 1754     if (cpp && tok->
str() == 
"{" && iscpp11init(tok)) {
 
 1755         Token * 
const tok1 = tok;
 
 1756         AST_state state(cpp);
 
 1757         compileExpression(tok, state);
 
 1758         Token* 
const endToken = tok;
 
 1759         if (endToken == tok1 || !endToken)
 
 1762         createAstAtTokenInner(tok1->
next(), endToken, cpp);
 
 1772         Token* 
const nextTok = createAstAtToken(tok);
 
 1780     struct OnException {
 
 1781         std::function<void()> f;
 
 1785             if (std::uncaught_exception())
 
 1794     OnException oe{[&] {
 
 1799     std::set<const Token*> safeAstTokens;    
 
 1806         if (tok->
str() == 
"?") {
 
 1816             std::set<const Token*> astTokens;    
 
 1817             astTokens.insert(tok);
 
 1819                 if (safeAstTokens.find(parent) != safeAstTokens.end())
 
 1821                 if (astTokens.find(parent) != astTokens.end())
 
 1823                 astTokens.insert(parent);
 
 1824             } 
while ((parent = parent->
astParent()) != 
nullptr);
 
 1825             safeAstTokens.insert(astTokens.cbegin(), astTokens.cend());
 
 1826         } 
else if (tok->
str() == 
";") {
 
 1827             safeAstTokens.clear();
 
 1829             safeAstTokens.insert(tok);
 
 1833         if (tok->
str() == 
"<" && tok->
link()) {
 
 1852         if (
Token::Match(tok, 
"%or%|%oror%|%assign%|%comp%")) {
 
 1876                                     "Syntax Error: AST broken, '" + tok->
previous()->
str() +
 
 1877                                     "' doesn't have two operands.",
 
 1888                 const std::string& op =
 
 1891                           tok, 
"Syntax Error: AST broken, '" + op + 
"' doesn't have two operands.", 
InternalError::AST);
 
 1930     enum { isLongLong, isLong, isInt } type;
 
 1948         if (
Token::Match(tok, 
"std| ::| size_t|uintptr_t|uintmax_t")) {
 
 1949             if (isCPP11 && tok->
strAt(-1) == 
"using" && tok->
strAt(1) == 
"=")
 
 1952         } 
else if (
Token::Match(tok, 
"std| ::| ssize_t|ptrdiff_t|intptr_t|intmax_t")) {
 
 1953             if (isCPP11 && tok->
strAt(-1) == 
"using" && tok->
strAt(1) == 
"=")
 
 1960         if (tok->
str() == 
"::") {
 
 1962         } 
else if (tok->
str() == 
"std") {
 
 1963             if (tok->
next()->
str() != 
"::")
 
 2001             if (tok->
strAt(-1) == 
"::") {
 
 2017             } 
else if (platformtype->
mPointer) {
 
 2022             } 
else if (platformtype->
mPtrPtr) {
 
 2037             if (platformtype->
mLong)
 
 2045     auto isVarDeclC = [](
const Token* tok) -> 
bool {
 
 2048         tok = tok->
link()->previous();
 
 2071             bool isFloat= 
false;
 
 2072             bool isSigned = 
false;
 
 2073             bool isUnsigned = 
false;
 
 2074             bool isComplex = 
false;
 
 2076             Token* typeSpec = 
nullptr;
 
 2079             for (; tok2->
next(); tok2 = tok2->
next()) {
 
 2080                 if (tok2->
str() == 
"long") {
 
 2084                 } 
else if (tok2->
str() == 
"short") {
 
 2086                 } 
else if (tok2->
str() == 
"unsigned")
 
 2088                 else if (tok2->
str() == 
"signed")
 
 2094                     isComplex = !isFloat || tok2->
str() == 
"_Complex" || 
Token::Match(tok2->
next(), 
"*|&|%name%"); 
 
 2110                 typeSpec->
isLong(typeSpec->
isLong() || (isFloat && countLong == 1) || countLong > 1);
 
 2118                 while (tok3 != tok2) {
 
 2119                     if (tok2 != typeSpec &&
 
 2120                         (isComplex || !
Token::Match(tok2, 
"complex|_Complex")))  
 
 2134         static const std::unordered_set<std::string> cpp_types = {
"bool", 
"false", 
"true"};
 
 2135         if (cpp_types.find(str) != cpp_types.end())
 
 2140             return cpp_keywords.find(str) != cpp_keywords.end();
 
 2143         static const auto& latest_cpp_keywords = 
Keywords::getAll(Standards::cppstd_t::CPPLatest);
 
 2144         return latest_cpp_keywords.find(str) != latest_cpp_keywords.end();
 
 2149     static const std::unordered_set<std::string> c_types = {
"char", 
"double", 
"float", 
"int", 
"long", 
"short"};
 
 2150     if (c_types.find(str) != c_types.end())
 
 2155         return c_keywords.find(str) != c_keywords.end();
 
 2158     static const auto& latest_c_keywords = 
Keywords::getAll(Standards::cstd_t::CLatest);
 
 2159     return latest_c_keywords.find(str) != latest_c_keywords.end();
 
 2167     if (
mLang == Standards::Language::None)
 
 2170     return mLang == Standards::Language::C;
 
 2178     if (
mLang == Standards::Language::None)
 
 2181     return mLang == Standards::Language::CPP;
 
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
 
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
 
File name and line number.
 
std::string stringify() const
 
static const std::unordered_set< std::string > & getAll(Standards::cstd_t cStd)
 
const PlatformType * platform_type(const std::string &name, const std::string &platform) const
 
static Standards::Language identify(const std::string &path, bool *header=nullptr)
Identify the language based on the file extension.
 
static bool sameFileName(const std::string &fname1, const std::string &fname2)
Compare filenames to see if they are the same.
 
static std::string getRelativePath(const std::string &absolutePath, const std::vector< std::string > &basePaths)
Create a relative path from an absolute one, if absolute path is inside the basePaths.
 
This is just a container for general settings so that we don't need to pass individual values to func...
 
std::vector< std::string > basePaths
Paths used as base for conversion to relative paths.
 
Standards::Language enforcedLang
Name of the language that is enforced.
 
bool relativePaths
Use relative paths in output.
 
Standards standards
Struct contains standards settings.
 
static Token * copyTokens(Token *dest, const Token *first, const Token *last, bool one_line=true)
Copy tokens.
 
TokensFrontBack mTokensFrontBack
Token list.
 
std::string fileLine(const Token *tok) const
Get file:line for a given token.
 
void deallocateTokens()
Deallocate list.
 
void createAst() const
Create abstract syntax tree.
 
static void deleteTokens(Token *tok)
Delete all tokens in given token list.
 
TokenList(const Settings *settings)
 
void simplifyPlatformTypes()
Convert platform dependent types to standard types.
 
bool validateToken(const Token *tok) const
Verify that the given token is an element of the tokenlist.
 
bool isKeyword(const std::string &str) const
 
const std::string & getSourceFilePath() const
 
std::size_t calculateHash() const
Calculates a hash of the token list used to compare multiple token lists with each other as quickly a...
 
void setLang(Standards::Language lang)
 
const std::string & file(const Token *tok) const
get filename for given token
 
static void insertTokens(Token *dest, const Token *src, nonneg int n)
 
void simplifyStdType()
Collapse compound standard types into a single token.
 
bool createTokensInternal(std::istream &code, const std::string &file0)
 
const std::vector< std::string > & getFiles() const
Get filenames (the sourcefile + the files it include).
 
void addtoken(const std::string &str, const nonneg int lineno, const nonneg int column, const nonneg int fileno, bool split=false)
 
const Token * front() const
get first token of list
 
bool createTokens(std::istream &code, const std::string &file0)
Create tokens from code.
 
std::vector< std::string > mOrigFiles
Original filenames for the tokenized source code (source + included)
 
int appendFileIfNew(std::string fileName)
append file name if seen the first time; return its index in any case
 
Standards::Language mLang
File is known to be C/C++ code.
 
std::vector< std::string > mFiles
filenames for the tokenized source code (source + included)
 
std::string getOrigFile(const Token *tok) const
 
const Settings *const mSettings
settings
 
void validateAst(bool print) const
Check abstract syntax tree.
 
The token list that the TokenList generates is a linked-list of this class.
 
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
 
void deleteThis()
Remove the contents for this token from the token list.
 
void setMacroName(std::string name)
 
const std::string & originalName() const
 
void printOut(const char *title=nullptr) const
For debugging purposes, prints token and all tokens followed by it.
 
TokenImpl::Cpp11init isCpp11init() const
 
bool isSimplifiedTypedef() const
 
void setTokenDebug(TokenDebug td)
 
static void createMutualLinks(Token *begin, Token *end)
Links two elements against each other.
 
bool isImplicitInt() const
 
const std::string & strAt(int index) const
 
static void assignProgressValues(Token *tok)
Calculate progress values for all tokens.
 
void astOperand1(Token *tok)
 
void setCpp11init(bool cpp11init) const
 
static const Token * findsimplematch(const Token *const startTok, const char(&pattern)[count])
 
const Token * tokAt(int index) const
 
void deleteNext(nonneg int count=1)
Unlink and delete the next 'count' tokens.
 
Token * insertToken(const std::string &tokenStr, const std::string &originalNameStr=emptyString, const std::string ¯oNameStr=emptyString, bool prepend=false)
Insert new token after this token.
 
Token::Type tokType() const
 
void astOperand2(Token *tok)
 
void link(Token *linkToToken)
Create link to given token.
 
const Token * linkAt(int index) const
 
bool isAssignmentOp() const
 
nonneg int linenr() const
 
bool isStandardType() const
 
bool isComparisonOp() const
 
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
 
nonneg int fileIndex() const
 
std::string getMacroName() const
 
nonneg int column() const
 
void astParent(Token *tok)
 
static const std::string emptyString
 
static std::vector< std::string > split(const std::string &str, const std::string &sep=" ")
 
Token * findTypeEnd(Token *tok)
 
Token * findLambdaEndScope(Token *tok)
 
Simple container to be thrown when internal error is detected.
 
enum Standards::cppstd_t cpp
 
static Token * skipDecl(Token *tok, std::vector< Token * > *inner=nullptr)
 
static constexpr int AST_MAX_DEPTH
 
static bool iscast(const Token *tok, bool cpp)
 
const Token * findLambdaEndTokenWithoutAST(const Token *tok)
 
const Token * isLambdaCaptureList(const Token *tok)