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)