54 #include <unordered_map>
55 #include <unordered_set>
59 #include <simplecpp.h>
66 struct VarIdScopeInfo {
67 VarIdScopeInfo() =
default;
68 VarIdScopeInfo(
bool isExecutable,
bool isStructInit,
bool isEnum,
nonneg int startVarid)
69 : isExecutable(isExecutable), isStructInit(isStructInit), isEnum(isEnum), startVarid(startVarid) {}
71 const bool isExecutable{};
72 const bool isStructInit{};
74 const nonneg int startVarid{};
81 if (!tok || tok->
str() !=
"{")
91 defStart = defStart->next();
92 if (defStart && defStart->str() ==
"{")
93 tok = defStart->link()->next();
100 if (tok->
str() ==
"(")
102 if (tok->
str() !=
")")
108 while (tok && tok->
str() ==
"[" && tok->
link()) {
109 if (
endsWith.find(tok->
str()) != std::string::npos)
111 tok = tok->
link()->next();
113 return (tok &&
endsWith.find(tok->
str()) != std::string::npos) ? tok :
nullptr;
115 if (tok->
isCpp() && tok->
str() ==
")") {
117 while (
Token::Match(tok,
"const|noexcept|override|final|volatile|mutable|&|&& !!(") ||
120 if (tok && tok->
str() ==
")")
122 while (tok && tok->
str() ==
"[")
123 tok = tok->
link()->next();
140 return (tok &&
endsWith.find(tok->
str()) != std::string::npos) ? tok :
nullptr;
153 while (tok2 && !
Token::Match(tok2,
"class|struct|union|enum|{|}|;"))
163 mErrorLogger(errorLogger),
180 const std::map<std::string, int>::const_iterator it =
mTypeSize.find(type);
186 return podtype->
size;
193 if (!type || type->
str().empty())
199 const std::map<std::string, int>::const_iterator it =
mTypeSize.find(type->
str());
205 return podtype->
size;
208 if (type->
str() ==
"double")
210 if (type->
str() ==
"long")
222 Token * tok = tokPtr;
226 if (end->
str() ==
"[") {
229 end = end->
link()->next();
230 }
else if (end->
str() ==
",") {
240 end = (end)?end->
next():
nullptr;
244 }
else if (end->
str() ==
"(") {
260 tokPtr = end->
link();
274 }
else if (end->
str() ==
">") {
279 while (end && end->
str() !=
"{")
282 tokPtr = end->
link();
292 (!
Token::Match(tok->
previous(),
"return|new|const|friend|public|private|protected|throw|extern") &&
303 if (tok->
strAt(-2) ==
"typedef" &&
305 typeDef->
strAt(3) !=
"{") {
319 return tok->
next()->
str() !=
";";
321 return tok->
next()->
str() !=
";";
342 std::ostringstream str;
343 const Token *tok1 = tok;
346 if (level == 0 && tok->
str() ==
";")
348 if (tok->
str() ==
"{")
350 else if (tok->
str() ==
"}") {
365 "Failed to parse \'" + str.str() +
"\'. The checking continues anyway.");
370 Token *tok =
nullptr;
373 while (typeDef->
next()) {
374 if (typeDef->
next()->
str() ==
";") {
378 if (typeDef->
next()->
str() ==
"{")
380 else if (typeDef->
next()->
str() ==
"}")
398 std::string className;
399 const Token* bodyEnd{};
400 const Token* bodyEnd2{};
402 std::set<std::string> recordTypes;
409 std::set<std::string> qualifiers;
412 qualifiers.insert(tok->
next()->
str());
428 if (tok1->
str() ==
":") {
430 while (tok1 && tok1->
str() !=
"{")
445 name =
"Unnamed" + std::to_string((*unnamedCount)++);
462 for (
const std::string &qualifier : qualifiers) {
490 tok2 = tok2->
tokAt(5);
500 if (tok2->
next()->
str() ==
"(")
511 tok2 = tok2->
tokAt(2);
516 if (tok2->
str() ==
"(" &&
517 tok2->
link()->next() &&
518 tok2->
link()->next()->str() ==
"(") {
521 if (tok2->
next()->
str() ==
"(")
531 if (tok2->
next()->
str() ==
"(")
552 if ((
Token::Match(tok,
"[;{}] using %name% :: %name% ::|;") && !tok->tokAt(2)->isKeyword()) ||
553 (
Token::Match(tok,
"[;{}] using :: %name% :: %name% ::|;") && !tok->tokAt(3)->isKeyword())) {
556 endtok = endtok->
next();
558 endtok = endtok->
tokAt(2);
559 if (endtok && endtok->
str() ==
";") {
574 if (tok->str() ==
"typedef") {
575 bool doSimplify = !
Token::Match(tok->previous(),
";|{|}|:|public:|private:|protected:");
578 bool haveStart =
false;
599 start = start->
next();
610 class TypedefSimplifier {
612 Token* mTypedefToken;
613 Token* mEndToken{
nullptr};
614 std::pair<Token*, Token*> mRangeType;
615 std::pair<Token*, Token*> mRangeTypeQualifiers;
616 std::pair<Token*, Token*> mRangeAfterVar;
617 Token* mNameToken{
nullptr};
619 bool mReplaceFailed =
false;
623 explicit TypedefSimplifier(
Token* typedefToken) : mTypedefToken(typedefToken) {
626 start = start->
next();
629 if (
Token::Match(start,
"const| enum|struct|union|class %name%| {")) {
633 Token* nameToken = rangeBefore.second->
link()->next();
635 nameToken = nameToken->
next();
636 const std::pair<Token*, Token*> rangeQualifiers(rangeBefore.second->link()->next(), nameToken);
639 if (
Token::Match(rangeBefore.second->previous(),
"enum|struct|union|class {"))
640 rangeBefore.second->previous()->insertToken(nameToken->
str());
641 mRangeType = rangeBefore;
642 mRangeTypeQualifiers = rangeQualifiers;
648 mNameToken = nameToken;
649 mEndToken = nameToken->
next();
654 for (
Token* type = start;
Token::Match(type,
"%name%|*|&|&&"); type = type->next()) {
655 if (type != start &&
Token::Match(type,
"%name% ;") && !type->isStandardType()) {
656 mRangeType.first = start;
657 mRangeType.second = type;
659 mEndToken = mNameToken->
next();
668 mRangeType.first = start;
669 mRangeType.second = type;
671 mEndToken = end->
next();
672 mRangeAfterVar.first = mNameToken->
next();
673 mRangeAfterVar.second = mEndToken;
679 mRangeType.first = start;
680 mRangeType.second = mNameToken;
681 mRangeAfterVar.first = mNameToken->
next();
682 mRangeAfterVar.second = mEndToken;
688 mRangeType.first = start;
689 mRangeType.second = type;
690 mRangeAfterVar.first = mNameToken->
next();
691 mRangeAfterVar.second = mEndToken;
697 printTypedef(typedefToken);
701 const Token* getTypedefToken()
const {
702 return mTypedefToken;
705 bool isUsed()
const {
709 bool isInvalidConstFunctionType(
const std::map<std::string, TypedefSimplifier>& m)
const {
710 if (!
Token::Match(mTypedefToken,
"typedef const %name% %name% ;"))
712 const auto it = m.find(mTypedefToken->
strAt(2));
722 bool replaceFailed()
const {
723 return mReplaceFailed;
726 bool isStructEtc()
const {
727 return mRangeType.second && mRangeType.second->str() ==
"{";
730 std::string name()
const {
731 return mNameToken ? mNameToken->str() :
"";
735 if (tok == mNameToken)
742 bool pointerType =
false;
743 for (
const Token* type = mRangeType.first; type != mRangeType.second; type = type->
next()) {
744 if (type->str() ==
"*" || type->str() ==
"&") {
749 for (
const Token* type = mRangeTypeQualifiers.first; type != mRangeTypeQualifiers.second; type = type->
next()) {
750 if (type->str() ==
"*" || type->str() ==
"&") {
758 Token* tok2 = insertTokens(tok, mRangeType);
759 insertTokens(tok2, mRangeTypeQualifiers);
765 const bool isFunctionPointer =
Token::Match(mNameToken,
"%name% )");
766 if (isFunctionPointer && isCast(tok->
previous())) {
768 insertTokens(tok, std::pair<Token*, Token*>(mRangeType.first, mNameToken->linkAt(1)));
776 tok->
str(mRangeType.second->previous()->str());
781 if (
Token::Match(mRangeType.first,
"const| struct|class %name% %name% ;")) {
783 tok->
str(mRangeType.second->previous()->str());
785 mReplaceFailed =
true;
792 bool pointerType =
false;
793 for (
const Token* type = mRangeType.first; type != mRangeType.second; type = type->
next()) {
794 if (type->str() ==
"*") {
811 for (
const Token* type = mRangeType.first; type != mRangeType.second; type = type->
next()) {
812 if (type->str() == kw) {
820 mReplaceFailed =
true;
826 auto rangeType = mRangeType;
828 while (
Token::Match(rangeType.first,
"const|class|struct|union"))
829 rangeType.first = rangeType.first->next();
832 Token*
const tok2 = insertTokens(tok, rangeType);
833 Token*
const tok3 = insertTokens(tok2, mRangeTypeQualifiers);
839 after = after->
next();
842 after = after->
link()->next();
850 bool useAfterVarRange =
true;
853 useAfterVarRange =
false;
861 if (prev->
isName() && prev != tok3)
872 if (isFunctionPointer) {
874 after = after->
link()->linkAt(1)->next();
875 else if (after->
str() ==
"(") {
876 useAfterVarRange =
false;
880 else if (after->
str() ==
"[") {
881 while (after && after->
str() ==
"[")
882 after = after->
link()->next();
887 after = after->
link()->next();
891 throw InternalError(tok,
"Failed to simplify typedef. Is the code valid?");
893 Token*
const tok4 = useAfterVarRange ? insertTokens(after->
previous(), mRangeAfterVar)->
next() : tok3->
next();
905 std::stack<Token*> brackets;
906 for (; tok != tok4; tok = tok->
next()) {
916 void removeDeclaration() {
927 static int canReplaceStatic(
const Token* tok) {
928 if (!
Token::Match(tok,
"%name% %name%|*|&|&&|;|(|)|,|::")) {
943 if (prev->
str() ==
")")
951 bool isGeneric =
false;
952 for (; tok; tok = tok->
previous()) {
967 bool canReplace(
const Token* tok) {
968 if (mNameToken == tok)
973 const int res = canReplaceStatic(tok);
974 if (res == 0 || res == 1)
983 tok->
str() != mRangeType.second->previous()->str())
989 for (
const Token* after = tok->
next(); after; after = after->
next()) {
992 if (after->
str() ==
"<" && after->
link())
1003 if (
Token::Match(before,
"struct|union|class|enum") || before->isStandardType())
1005 if (before->str() ==
"::")
1007 if (before->isName())
1014 Token* endToken()
const {
1019 static bool isCast(
const Token* tok) {
1027 static Token* insertTokens(
Token* to, std::pair<Token*,Token*> range) {
1028 for (
const Token* from = range.first; from != range.second; from = from->
next()) {
1038 static void printTypedef(
const Token *tok) {
1040 while (tok && (
indent > 0 || tok->
str() !=
";")) {
1041 if (tok->
str() ==
"{")
1043 else if (tok->
str() ==
"}")
1045 std::cout <<
" " << tok->
str();
1057 std::map<std::string, int> numberOfTypedefs;
1059 if (tok->
str() ==
"typedef") {
1060 TypedefSimplifier ts(tok);
1062 numberOfTypedefs[ts.name()]++;
1067 int indentlevel = 0;
1068 std::map<std::string, TypedefSimplifier> typedefs;
1071 if (tok->
str()[0] ==
'{')
1073 else if (tok->
str()[0] ==
'}')
1078 if (indentlevel == 0 && tok->
str() ==
"typedef") {
1079 TypedefSimplifier ts(tok);
1080 if (!ts.fail() && numberOfTypedefs[ts.name()] == 1) {
1083 "It is unspecified behavior to const qualify a function type.");
1084 typedefs.emplace(ts.name(), ts);
1085 if (!ts.isStructEtc())
1086 tok = ts.endToken();
1091 auto it = typedefs.find(tok->
str());
1092 if (it != typedefs.end() && it->second.canReplace(tok)) {
1093 std::set<std::string> r;
1094 while (it != typedefs.end() && r.insert(tok->
str()).second) {
1096 it = typedefs.find(tok->
str());
1098 }
else if (tok->
str() ==
"enum") {
1103 if (tok->
str() ==
"{")
1108 if (!typedefs.empty())
1111 for (
auto &t: typedefs) {
1112 if (!t.second.replaceFailed()) {
1113 const Token*
const typedefToken = t.second.getTypedefToken();
1115 typedefInfo.
name = t.second.name();
1119 typedefInfo.
used = t.second.isUsed();
1122 t.second.removeDeclaration();
1147 bool isNamespace =
false;
1148 std::string className, fullClassName;
1149 bool hasClass =
false;
1150 bool goback =
false;
1153 std::vector<Space> spaceInfo(1);
1167 if (maxTime > 0 && std::time(
nullptr) > maxTime) {
1173 "Typedef simplification instantiation maximum time exceeded",
1187 if (tok->
str() !=
"typedef") {
1191 }
else if (
Token::Match(tok,
"class|struct|namespace %any%") &&
1193 isNamespace = (tok->
str() ==
"namespace");
1195 className = tok->
next()->
str();
1197 fullClassName = className;
1199 tok1 = tok1->
tokAt(2);
1200 fullClassName +=
" :: " + tok1->
str();
1202 }
else if (hasClass && tok->
str() ==
";") {
1204 }
else if (hasClass && tok->
str() ==
"{") {
1206 spaceInfo.back().recordTypes.insert(fullClassName);
1209 info.isNamespace = isNamespace;
1210 info.className = className;
1211 info.bodyEnd = tok->
link();
1212 info.bodyEnd2 = tok->
link();
1213 spaceInfo.push_back(std::move(info));
1216 }
else if (spaceInfo.size() > 1 && tok->
str() ==
"}" && spaceInfo.back().bodyEnd == tok) {
1217 spaceInfo.pop_back();
1226 tokClass = tokClass->
next();
1227 if (
Token::Match(tokClass,
"struct|enum|union|class %type%| {|:")) {
1246 Token *typeStart =
nullptr;
1247 Token *typeEnd =
nullptr;
1248 Token *argStart =
nullptr;
1249 Token *argEnd =
nullptr;
1250 Token *arrayStart =
nullptr;
1251 Token *arrayEnd =
nullptr;
1252 Token *specStart =
nullptr;
1253 Token *specEnd =
nullptr;
1254 Token *typeDef = tok;
1255 Token *argFuncRetStart =
nullptr;
1256 Token *argFuncRetEnd =
nullptr;
1257 Token *funcStart =
nullptr;
1258 Token *funcEnd =
nullptr;
1260 bool function =
false;
1261 bool functionPtr =
false;
1262 bool functionRetFuncPtr =
false;
1263 bool functionPtrRetFuncPtr =
false;
1264 bool ptrToArray =
false;
1265 bool refToArray =
false;
1266 bool ptrMember =
false;
1267 bool typeOf =
false;
1268 Token *namespaceStart =
nullptr;
1269 Token *namespaceEnd =
nullptr;
1275 if (tokOffset->
str() ==
"::") {
1276 typeStart = tokOffset;
1277 tokOffset = tokOffset->
next();
1280 tokOffset = tokOffset->
tokAt(2);
1282 typeEnd = tokOffset;
1285 tokOffset = tokOffset->
next();
1287 typeStart = tokOffset;
1290 tokOffset = tokOffset->
tokAt(2);
1293 typeEnd = tokOffset;
1296 tokOffset = tokOffset->
next();
1298 typeStart = tokOffset;
1300 while (
Token::Match(tokOffset,
"const|struct|enum %type%") ||
1302 tokOffset = tokOffset->
next();
1304 typeEnd = tokOffset;
1306 tokOffset = tokOffset->
next();
1311 typeEnd = tokOffset;
1312 tokOffset = tokOffset->
next();
1317 if (tokOffset && tokOffset->
str() ==
"::") {
1318 typeEnd = tokOffset;
1319 tokOffset = tokOffset->
next();
1324 typeEnd = tokOffset;
1325 tokOffset = tokOffset->
next();
1327 typeEnd = tokOffset;
1328 tokOffset = tokOffset->
next();
1341 if (!
isC() && tokOffset->
str() ==
"<") {
1345 typeEnd = typeEnd->
tokAt(2);
1353 typeEnd = typeEnd->
next();
1356 tokOffset = tok->
next();
1359 std::list<std::string> pointers;
1362 pointers.push_back(tokOffset->
str());
1363 tokOffset = tokOffset->
next();
1372 typeName = tokOffset;
1373 tokOffset = tokOffset->
next();
1376 while (tokOffset && tokOffset->
str() ==
"[") {
1378 arrayStart = tokOffset;
1379 arrayEnd = tokOffset->
link();
1380 tokOffset = arrayEnd->
next();
1388 else if (tokOffset && tokOffset->
str() ==
"(") {
1389 Token *tokOffset2 =
nullptr;
1391 tokOffset2 = tokOffset->
next();
1392 if (tokOffset2->
str() ==
"typename")
1393 tokOffset2 = tokOffset2->
next();
1395 tokOffset2 = tokOffset2->
tokAt(2);
1399 if (typeName->
str() ==
"void") {
1411 typeEnd = typeEnd->
next();
1413 funcStart = funcEnd = tokOffset2;
1414 tokOffset = tokOffset2->
tokAt(3);
1415 typeName = tokOffset->
tokAt(-2);
1416 argStart = tokOffset;
1417 argEnd = tokOffset->
link();
1418 tok = argEnd->
next();
1424 if (tokOffset->
link()->next()->str() ==
"const") {
1425 specStart = tokOffset->
link()->next();
1426 specEnd = specStart;
1428 argStart = tokOffset;
1429 argEnd = tokOffset->
link();
1430 tok = argEnd->
next();
1454 argStart = tokOffset;
1455 argEnd = tokOffset->
link();
1456 typeName = tokOffset->
link()->next();
1457 tok = typeName->
next();
1464 else if (tokOffset->
str() ==
"(" && (
1473 if (tokOffset->
next()->
str() ==
"(")
1474 tokOffset = tokOffset->
next();
1476 pointers.emplace_back(
"*");
1477 tokOffset = tokOffset->
tokAt(2);
1480 if (tokOffset->
link()->strAt(-2) ==
"*")
1484 funcStart = tokOffset->
next();
1485 tokOffset = tokOffset->
link();
1486 funcEnd = tokOffset->
tokAt(-2);
1488 argStart = tokOffset->
next();
1489 argEnd = tokOffset->
next()->
link();
1493 tok = argEnd->
next();
1499 specEnd = spec->
next();
1502 tok = specEnd->
next();
1507 if (tok->
str() ==
")")
1513 if (tokOffset->
link()->next()) {
1514 tok = tokOffset->
link()->next();
1515 tokOffset = tokOffset->
tokAt(2);
1517 argStart = tokOffset;
1518 argEnd = tokOffset->
link();
1526 else if (
Token::Match(tokOffset,
"( * ( * %type% ) (") &&
1529 functionPtrRetFuncPtr =
true;
1531 tokOffset = tokOffset->
tokAt(6);
1532 typeName = tokOffset->
tokAt(-2);
1533 argStart = tokOffset;
1534 argEnd = tokOffset->
link();
1538 argFuncRetStart = argEnd->
tokAt(2);
1539 argFuncRetEnd = argFuncRetStart->
link();
1543 tok = argFuncRetEnd->
next();
1550 functionRetFuncPtr =
true;
1552 tokOffset = tokOffset->
tokAt(3);
1554 argStart = tokOffset;
1555 argEnd = tokOffset->
link();
1557 argFuncRetStart = argEnd->
tokAt(2);
1558 if (!argFuncRetStart)
1561 argFuncRetEnd = argFuncRetStart->
link();
1565 tok = argFuncRetEnd->
next();
1566 }
else if (
Token::Match(tokOffset,
"( * ( %type% ) (")) {
1567 functionRetFuncPtr =
true;
1569 tokOffset = tokOffset->
tokAt(5);
1570 typeName = tokOffset->
tokAt(-2);
1571 argStart = tokOffset;
1572 argEnd = tokOffset->
link();
1576 argFuncRetStart = argEnd->
tokAt(2);
1577 if (!argFuncRetStart)
1580 argFuncRetEnd = argFuncRetStart->
link();
1584 tok = argFuncRetEnd->
next();
1588 else if (
Token::Match(tokOffset,
"( *|& %type% ) [")) {
1589 ptrToArray = (tokOffset->
next()->
str() ==
"*");
1590 refToArray = !ptrToArray;
1591 tokOffset = tokOffset->
tokAt(2);
1592 typeName = tokOffset;
1593 arrayStart = tokOffset->
tokAt(2);
1594 arrayEnd = arrayStart->
link();
1598 tok = arrayEnd->
next();
1602 else if (
Token::Match(tokOffset,
"( %type% :: * %type% ) ;")) {
1603 tokOffset = tokOffset->
tokAt(2);
1604 namespaceStart = tokOffset->
previous();
1605 namespaceEnd = tokOffset;
1607 tokOffset = tokOffset->
tokAt(2);
1608 typeName = tokOffset;
1609 tok = tokOffset->
tokAt(2);
1626 typedefInfo.
name = typeName->
str();
1630 typedefInfo.
used =
false;
1634 std::string pattern = typeName->
str();
1636 bool simplifyType =
false;
1637 bool inMemberFunc =
false;
1638 int memberScope = 0;
1639 bool globalScope =
false;
1640 int classLevel = spaceInfo.size();
1641 bool inTypeDef =
false;
1642 bool inEnum =
false;
1643 std::string removed;
1644 std::string classPath;
1645 for (
size_t i = 1; i < spaceInfo.size(); ++i) {
1646 if (!classPath.empty())
1647 classPath +=
" :: ";
1648 classPath += spaceInfo[i].className;
1651 for (
Token *tok2 = tok; tok2; tok2 = tok2->
next()) {
1666 Token* varDecl = tok2;
1668 varDecl = varDecl->
next();
1677 tok2 = tok2->
link();
1678 tok2 = tok2->
next();
1689 if (tok2->
str() ==
"}") {
1693 if (memberScope == 0)
1694 inMemberFunc =
false;
1698 if (classLevel > 1 && tok2 == spaceInfo[classLevel - 1].bodyEnd2) {
1702 for (
int i = classLevel; i < spaceInfo.size(); ++i)
1703 pattern += (spaceInfo[i].className +
" :: ");
1705 pattern += typeName->
str();
1707 if (scope == 0 && !(classLevel > 1 && tok2 == spaceInfo[classLevel - 1].bodyEnd))
1709 scope = std::max(scope - 1, 0);
1730 if (spaceInfo.size() > 1 && classLevel < spaceInfo.size() &&
1731 func->
strAt(offset) == spaceInfo[classLevel].className) {
1733 inMemberFunc =
true;
1739 else if (tok2->
str() ==
"{") {
1741 if (tok2->
isCpp()) {
1742 if (tok2->
strAt(-2) ==
"namespace") {
1743 if (classLevel < spaceInfo.size() &&
1744 spaceInfo[classLevel].isNamespace &&
1745 spaceInfo[classLevel].className == tok2->
previous()->
str()) {
1746 spaceInfo[classLevel].bodyEnd2 = tok2->
link();
1749 for (
int i = classLevel; i < spaceInfo.size(); ++i)
1750 pattern += spaceInfo[i].className +
" :: ";
1752 pattern += typeName->
str();
1770 else if (tok2->
isCpp() &&
1771 tok2->
str() ==
"operator" &&
1775 tok2->
strAt(2) ==
"(" &&
1780 if (spaceInfo.size() > 1 && classLevel < spaceInfo.size() &&
1781 tok2->
strAt(-2) == spaceInfo[classLevel].className) {
1782 tok2 = tok2->
next();
1783 simplifyType =
true;
1795 (inMemberFunc && tok2->
str() == typeName->
str()))) {
1797 if (!(inMemberFunc && tok2->
str() == typeName->
str()) && pattern.find(
"::") != std::string::npos) {
1798 Token *start = tok2;
1800 int back = classLevel - 1;
1807 if (qualificationTok->
str() == spaceInfo[back].className) {
1808 start = qualificationTok;
1817 if (good && back == 1 && start->
strAt(-1) ==
"::")
1823 if (!removed.empty())
1824 removed.insert(0,
" ");
1825 removed.insert(0, tok2->
strAt(-2) +
" " + tok2->
strAt(-1));
1831 if (tok2->
strAt(-1) ==
"::") {
1832 removed.insert(0,
":: ");
1838 for (
int i = classLevel; i < spaceInfo.size(); ++i) {
1839 if (!removed.empty())
1841 removed += (tok2->
str() +
" " + tok2->
strAt(1));
1845 simplifyType =
true;
1848 if (tok2->
strAt(-1) ==
"::") {
1849 int relativeSpaceInfoSize = spaceInfo.size();
1851 while (relativeSpaceInfoSize > 1 &&
1852 tokBeforeType && tokBeforeType->
str() ==
"::" &&
1853 tokBeforeType->
strAt(-1) == spaceInfo[relativeSpaceInfoSize-1].className) {
1854 tokBeforeType = tokBeforeType->
tokAt(-2);
1855 --relativeSpaceInfoSize;
1857 if (tokBeforeType && tokBeforeType->
str() !=
"::") {
1859 simplifyType =
true;
1862 tok2 = tok2->
next();
1865 if (tok2->
str() !=
"}") {
1866 while (tok2->
next()) {
1867 if (tok2->
next()->
str() ==
"{")
1869 else if (tok2->
next()->
str() ==
"}")
1872 tok2 = tok2->
next();
1878 simplifyType = (TypedefSimplifier::canReplaceStatic(tok2) != 0);
1890 if (functionPtr && (tok2->
previous()->
str() ==
"operator" ||
1891 (tok2->
next() && tok2->
next()->
str() ==
"operator"))) {
1892 simplifyType =
false;
1893 tok2 = tok2->
next();
1904 bool inCast =
false;
1905 bool inTemplate =
false;
1906 bool inOperator =
false;
1907 bool inSizeof =
false;
1909 const bool sameStartEnd = (typeStart == typeEnd);
1912 const bool isDerived =
Token::Match(tok2->
previous(),
"public|protected|private|: %type% {|,");
1930 if (tok2->
strAt(-1) ==
"operator" ||
1934 if (typeStart->
str() ==
"typename" && tok2->
strAt(-1)==
"typename") {
1936 typeStart = typeStart->
next();
1940 bool structRemoved =
false;
1941 if ((isDerived || inTemplate) &&
Token::Match(typeStart,
"class|struct")) {
1942 if (typeStart->
str() ==
"struct")
1943 structRemoved =
true;
1944 typeStart = typeStart->
next();
1947 typeStart = typeStart->
next();
1950 typeEnd = typeStart;
1953 const bool isPointerTypeCall = !inOperator &&
Token::Match(tok2,
"%name% ( )") && !pointers.empty();
1956 Token* replStart = tok2;
1957 for (
Token* tok3 = typeStart; tok3 && (tok3->
str() !=
";"); tok3 = tok3->
next())
1959 if (isPointerTypeCall) {
1962 tok2 = tok2->
next();
1967 tok2->
str(typeStart->
str());
1970 if (
Token::Match(typeStart,
"class|struct|union") || structRemoved) {
1976 tok2 = tok2->
next();
1979 for (
int i = classLevel; i < spaceInfo.size(); ++i) {
1981 tok2 = tok2->
next();
1983 tok2 = tok2->
next();
1988 Token *start = tok2;
1989 std::string removed1 = removed;
1990 std::string::size_type idx = removed1.rfind(
" ::");
1992 if (idx != std::string::npos)
1993 removed1.resize(idx);
1994 if (removed1 == classPath && !removed1.empty()) {
1995 for (std::vector<Space>::const_reverse_iterator it = spaceInfo.crbegin(); it != spaceInfo.crend(); ++it) {
1996 if (it->recordTypes.find(start->
str()) != it->recordTypes.end()) {
1997 std::string::size_type spaceIdx = 0;
1998 std::string::size_type startIdx = 0;
1999 while ((spaceIdx = removed1.find(
' ', startIdx)) != std::string::npos) {
2001 startIdx = spaceIdx + 1;
2007 idx = removed1.rfind(
" ::");
2008 if (idx == std::string::npos)
2011 removed1.resize(idx);
2019 if (!pointers.empty()) {
2020 for (
const std::string &p : pointers) {
2023 tok2 = tok2->
next();
2029 tok2 = tok2->
next();
2033 if (funcStart && funcEnd) {
2035 tok2 = tok2->
next();
2036 Token *paren = tok2;
2049 tok2 = tok2->
next();
2055 Token *spec = specStart;
2057 tok2 = tok2->
next();
2058 while (spec != specEnd) {
2059 spec = spec->
next();
2061 tok2 = tok2->
next();
2066 else if (functionPtr ||
function) {
2069 bool needParen =
true;
2070 if (!inTemplate &&
function && tok2->
next() && tok2->
next()->
str() !=
"*")
2074 tok2 = tok2->
next();
2077 if (namespaceStart) {
2078 const Token *tok4 = namespaceStart;
2080 while (tok4 != namespaceEnd) {
2082 tok2 = tok2->
next();
2083 tok4 = tok4->
next();
2086 tok2 = tok2->
next();
2090 tok2 = tok2->
next();
2101 tok2 = tok2->
next();
2112 tok2 = tok2->
next();
2116 Token *spec = specStart;
2118 tok2 = tok2->
next();
2119 while (spec != specEnd) {
2120 spec = spec->
next();
2122 tok2 = tok2->
next();
2125 }
else if (functionRetFuncPtr || functionPtrRetFuncPtr) {
2127 tok2 = tok2->
next();
2130 tok2 = tok2->
next();
2132 Token * tok4 =
nullptr;
2133 if (functionPtrRetFuncPtr) {
2135 tok2 = tok2->
next();
2138 tok2 = tok2->
next();
2143 if (!tok2 || !tok2->
next())
2146 if (tok2->
next()->
str() !=
")")
2147 tok2 = tok2->
next();
2150 if (tok4 && functionPtrRetFuncPtr) {
2152 tok2 = tok2->
next();
2159 tok2 = tok2->
next();
2163 }
else if (ptrToArray || refToArray) {
2165 tok2 = tok2->
next();
2172 tok2 = tok2->
next();
2174 bool hasName =
false;
2179 if (tok2->
next()->
str() !=
"(")
2180 tok2 = tok2->
next();
2183 if (tok2 && tok2->
next() && tok2->
next()->
str() ==
"(")
2187 if (tok2 && tok2->
next() && tok2->
next()->
str() ==
"[")
2195 tok2 = tok2->
next();
2196 }
else if (ptrMember) {
2199 tok2 = tok2->
next();
2204 const bool castOperator = inOperator &&
Token::Match(tok2,
"%type% (");
2205 Token *openParenthesis =
nullptr;
2207 if (!castOperator) {
2209 tok2 = tok2->
next();
2211 openParenthesis = tok2;
2214 const Token *tok4 = namespaceStart;
2216 while (tok4 != namespaceEnd) {
2218 tok2 = tok2->
next();
2219 tok4 = tok4->
next();
2222 tok2 = tok2->
next();
2225 tok2 = tok2->
next();
2227 if (openParenthesis) {
2230 tok2 = tok2->
next();
2233 tok2 = tok2->
next();
2238 }
else if (typeOf) {
2247 if (arrayStart && arrayEnd) {
2252 if (!inCast && !inSizeof && !inTemplate)
2253 tok2 = tok2->
next();
2255 if (tok2->
str() ==
"const")
2256 tok2 = tok2->
next();
2266 tok2 = tok3->
tokAt(3);
2268 tok2 = tok2->
tokAt(2);
2270 tok2 = tok2->
tokAt(2);
2272 tok2 = tok2->
tokAt(3);
2276 while (tok2->
strAt(1) ==
"::")
2277 tok2 = tok2->
tokAt(2);
2280 if (tok2->
str() ==
"(")
2281 tok2 = tok2->
link();
2283 if (tok2->
strAt(1) ==
"(")
2288 tok2 = tok2->
next();
2290 tok2 = tok2->
tokAt(3);
2294 tok2 = tok2->
next();
2302 while (tok2->
next()->
str() ==
"[")
2309 if (tok2->
str() ==
"=") {
2310 if (tok2->
next()->
str() ==
"{")
2311 tok2 = tok2->
next()->
link()->next();
2312 else if (tok2->
next()->
str().at(0) ==
'\"')
2313 tok2 = tok2->
tokAt(2);
2318 simplifyType =
false;
2327 if (tok->
str() ==
";")
2329 else if (tok->
str() ==
",") {
2330 arrayStart =
nullptr;
2332 tokOffset = tok->
next();
2336 pointers.push_back(tokOffset->
str());
2337 tokOffset = tokOffset->
next();
2341 typeName = tokOffset;
2342 tokOffset = tokOffset->
next();
2344 if (tokOffset && tokOffset->
str() ==
"[") {
2345 arrayStart = tokOffset;
2349 tokOffset = tokOffset->
next();
2351 if (!tokOffset->
next())
2353 if (tokOffset->
next()->
str() ==
";")
2355 if (tokOffset->
str() ==
"]")
2357 tokOffset = tokOffset->
next();
2360 arrayEnd = tokOffset;
2361 tokOffset = tokOffset->
next();
2409 ScopeInfo3() : parent(nullptr), type(
Global), bodyStart(nullptr), bodyEnd(nullptr) {}
2410 ScopeInfo3(ScopeInfo3 *parent_,
Type type_, std::string name_,
const Token *bodyStart_,
const Token *bodyEnd_)
2411 : parent(parent_), type(type_), name(std::move(name_)), bodyStart(bodyStart_), bodyEnd(bodyEnd_) {
2415 ScopeInfo3 *scope = parent;
2416 while (scope && scope->parent) {
2417 if (scope->name.empty())
2419 fullName = scope->name +
" :: " + fullName;
2420 scope = scope->parent;
2424 std::list<ScopeInfo3> children;
2426 std::string fullName;
2428 const Token * bodyStart;
2429 const Token * bodyEnd;
2430 std::set<std::string> usingNamespaces;
2431 std::set<std::string> recordTypes;
2432 std::set<std::string> baseTypes;
2434 ScopeInfo3 *addChild(
Type scopeType,
const std::string &scopeName,
const Token *bodyStartToken,
const Token *bodyEndToken) {
2435 children.emplace_back(
this, scopeType, scopeName, bodyStartToken, bodyEndToken);
2436 return &children.back();
2439 bool hasChild(
const std::string &childName)
const {
2440 return std::any_of(children.cbegin(), children.cend(), [&](
const ScopeInfo3& child) {
2441 return child.name == childName;
2445 const ScopeInfo3 * findInChildren(
const std::string & scope)
const {
2446 for (
const auto & child : children) {
2447 if (child.type == Record && (child.name == scope || child.fullName == scope))
2450 const ScopeInfo3 * temp = child.findInChildren(scope);
2457 const ScopeInfo3 * findScope(
const std::string & scope)
const {
2458 const ScopeInfo3 * tempScope =
this;
2461 auto it = std::find_if(tempScope->children.cbegin(), tempScope->children.cend(), [&](
const ScopeInfo3& child) {
2462 return &child != this && child.type == Record && (child.name == scope || child.fullName == scope);
2464 if (it != tempScope->children.end())
2467 if (tempScope->parent) {
2468 for (
const auto &sibling : tempScope->parent->children) {
2469 if (sibling.name == tempScope->name && &sibling !=
this) {
2470 const ScopeInfo3 * temp = sibling.findInChildren(scope);
2476 tempScope = tempScope->parent;
2481 bool findTypeInBase(
const std::string &scope)
const {
2485 if (baseTypes.find(scope) != baseTypes.end())
2488 for (
const std::string & base : baseTypes) {
2489 const ScopeInfo3 * baseScope = findScope(base);
2491 if (baseScope ==
this)
2493 if (baseScope && baseScope->fullName == scope)
2495 if (baseScope && baseScope->findTypeInBase(scope))
2501 ScopeInfo3 * findScope(
const ScopeInfo3 * scope) {
2502 if (scope->bodyStart == bodyStart)
2504 for (
auto & child : children) {
2505 ScopeInfo3 * temp = child.findScope(scope);
2513 void setScopeInfo(
Token *tok, ScopeInfo3 *&scopeInfo,
bool debug=
false)
2517 if (tok->
str() ==
"{" && scopeInfo->parent && tok == scopeInfo->bodyStart)
2519 if (tok->
str() ==
"}") {
2520 if (scopeInfo->parent && tok == scopeInfo->bodyEnd)
2521 scopeInfo = scopeInfo->parent;
2524 ScopeInfo3 *parent = scopeInfo->parent;
2525 while (parent && parent->bodyEnd != tok)
2526 parent = parent->parent;
2530 throw std::runtime_error(
"Internal error: unmatched }");
2535 if (!
Token::Match(tok,
"namespace|class|struct|union %name% {|:|::|<")) {
2537 if (
Token::Match(tok,
"using namespace %name% ;|::")) {
2539 std::string nameSpace;
2540 while (tok1 && tok1->
str() !=
";") {
2541 if (!nameSpace.empty())
2543 nameSpace += tok1->
str();
2544 tok1 = tok1->
next();
2546 scopeInfo->usingNamespaces.insert(std::move(nameSpace));
2549 else if (tok->
str() ==
"{") {
2560 if (tok1->
strAt(-1) !=
")")
2565 tok1 = tok1->
tokAt(-2);
2566 if (tok1->
strAt(-1) !=
")" && tok1->
strAt(-1) !=
"}")
2571 if (tok1->
strAt(-1) ==
">")
2575 tok1 = tok1->
tokAt(-2);
2576 if (tok1->
str() ==
"~")
2578 std::string scope = tok1->
strAt(-1);
2580 scope = tok1->
strAt(-3) +
" :: " + scope;
2581 tok1 = tok1->
tokAt(-2);
2583 scopeInfo = scopeInfo->addChild(ScopeInfo3::MemberFunction, scope, tok, tok->
link());
2589 scopeInfo = scopeInfo->addChild(ScopeInfo3::Other,
emptyString, tok, tok->
link());
2594 const bool record =
Token::Match(tok,
"class|struct|union %name%");
2596 std::string classname = tok->
str();
2598 tok = tok->
tokAt(2);
2599 classname +=
" :: " + tok->
str();
2604 scopeInfo->recordTypes.insert(classname);
2608 if (tok && tok->
str() ==
"<") {
2615 std::set<std::string> baseTypes;
2616 if (tok && tok->
str() ==
":") {
2619 while (
Token::Match(tok,
"public|protected|private|virtual"))
2628 if (tok && tok->
str() ==
"<") {
2631 endTok = endTok->
next();
2632 while (tok != endTok) {
2639 baseTypes.insert(std::move(base));
2643 if (tok && tok->
str() ==
"{") {
2644 scopeInfo = scopeInfo->addChild(record ? ScopeInfo3::Record : ScopeInfo3::Namespace, classname, tok, tok->
link());
2645 scopeInfo->baseTypes = std::move(baseTypes);
2653 for (; tok && (level > 0 || tok->
str() !=
";"); tok = tok->
next()) {
2654 if (tok->
str() ==
"{")
2656 else if (level > 0 && tok->
str() ==
"}")
2664 const Token *nameToken,
2665 const std::string &scope,
2667 const std::string &scope1,
2668 const ScopeInfo3 *currentScope,
2669 const ScopeInfo3 *memberClassScope)
2673 if (tok1 && tok1->
str() != nameToken->
str())
2677 if (tok1 == nameToken) {
2678 tok = findSemicolon(tok1);
2683 if (tok1->
strAt(-1) ==
"using") {
2686 if (currentScope->bodyEnd)
2687 tok =
const_cast<Token*
>(currentScope->bodyEnd->previous());
2697 std::string qualification;
2698 const Token* tok2 = tok1;
2699 std::string::size_type index = scope.size();
2700 std::string::size_type new_index = std::string::npos;
2704 if (
match && !scope1.empty()) {
2705 new_index = scope1.rfind(
' ', index - 1);
2706 if (new_index != std::string::npos)
2707 last = scope1.substr(new_index, index - new_index);
2708 else if (!qualification.empty())
2717 if (!qualification.empty())
2718 qualification =
" :: " + qualification;
2719 qualification = tok2->
strAt(-2) + qualification;
2721 tok2 = tok2->
tokAt(-2);
2724 std::string fullScope1 = scope1;
2725 if (!scope1.empty() && !qualification.empty())
2726 fullScope1 +=
" :: ";
2727 fullScope1 += qualification;
2729 if (scope == fullScope1)
2732 const ScopeInfo3 *scopeInfo = memberClassScope ? memberClassScope : currentScope;
2735 if (qualification.empty() && scopeInfo->findTypeInBase(scope))
2739 const ScopeInfo3 * tempScope = scopeInfo;
2742 const std::set<std::string>& usingNS = tempScope->usingNamespaces;
2743 if (!usingNS.empty()) {
2744 if (qualification.empty()) {
2745 if (usingNS.find(scope) != usingNS.end())
2748 const std::string suffix =
" :: " + qualification;
2749 if (std::any_of(usingNS.cbegin(), usingNS.cend(), [&](
const std::string& ns) {
2750 return scope == ns + suffix;
2755 tempScope = tempScope->parent;
2758 std::string newScope1 = scope1;
2761 index = newScope1.size();
2762 while (!newScope1.empty()) {
2763 const std::string::size_type separator = newScope1.rfind(
" :: ", index - 1);
2764 if (separator != std::string::npos)
2765 newScope1.resize(separator);
2769 std::string newFullScope1 = newScope1;
2770 if (!newScope1.empty() && !qualification.empty())
2771 newFullScope1 +=
" :: ";
2772 newFullScope1 += qualification;
2774 if (scope == newFullScope1)
2781 std::string memberFunctionScope(
const Token *tok)
2783 std::string qualification;
2786 if (!qualification.empty())
2787 qualification =
" :: " + qualification;
2788 qualification = qualTok->
str() + qualification;
2789 qualTok = qualTok->
tokAt(-2);
2791 return qualification;
2794 const Token * memberFunctionEnd(
const Token *tok)
2796 if (tok->
str() !=
"(")
2802 if (end->
str() ==
";")
2817 static bool scopesMatch(
const std::string &scope1,
const std::string &scope2,
const ScopeInfo3 *globalScope)
2819 if (scope1.empty() || scope2.empty())
2823 if (scope1 == scope2)
2827 if (scope1 == (
":: " + scope2)) {
2828 std::string::size_type end = scope2.find_first_of(
' ');
2829 if (end == std::string::npos)
2830 end = scope2.size();
2831 if (globalScope->hasChild(scope2.substr(0, end)))
2833 }
else if (scope2 == (
":: " + scope1)) {
2834 std::string::size_type end = scope1.find_first_of(
' ');
2835 if (end == std::string::npos)
2836 end = scope1.size();
2837 if (globalScope->hasChild(scope1.substr(0, end)))
2845 unsigned int dist = 0;
2846 const Token* tok = tok1;
2847 while (tok != tok2) {
2868 if (end->
str() ==
"<")
2878 if (end->
str() ==
",") {
2885 const unsigned int maxReplacementTokens = 1000;
2887 bool substitute =
false;
2888 ScopeInfo3 scopeInfo;
2889 ScopeInfo3 *currentScope = &scopeInfo;
2891 Using(
Token *start,
Token *end) : startTok(start), endTok(end) {}
2895 std::list<Using> usingList;
2905 Token *bodyStart = tok;
2907 if (bodyStart->
str() ==
"<")
2909 bodyStart = bodyStart ? bodyStart->
next() :
nullptr;
2912 tok = bodyStart->
link();
2916 if (
Token::Match(tok,
"{|}|namespace|class|struct|union") ||
2920 }
catch (
const std::runtime_error &) {
2922 "simplifyUsing: unmatched body end");
2932 currentScope->recordTypes.insert(end->
strAt(2));
2941 if (!(tok->
strAt(-1) !=
">" &&
2947 const std::string& name = tok->
strAt(1);
2949 std::string scope = currentScope->fullName;
2950 Token *usingStart = tok;
2952 if (tok->
strAt(2) ==
"=") {
2955 start = tok->
tokAt(3);
2959 Token *usingEnd = findSemicolon(start);
2966 if (
Token::Match(start,
"class|struct|union|enum %name%| {|:")) {
2968 const bool hasName =
Token::Match(structEnd,
"%name%");
2972 structEnd = structEnd->
next();
2975 if (structEnd->
str() ==
":") {
2976 structEnd = structEnd->
next();
2977 while (structEnd && structEnd->
str() !=
"{")
2978 structEnd = structEnd->
next();
2984 structEnd = structEnd->
link();
2991 std::string newName;
2992 if (structEnd->
strAt(2) ==
";")
3003 usingStart = structEnd->
tokAt(2);
3004 nameToken = usingStart->
next();
3005 if (usingStart->
strAt(2) ==
"=")
3006 start = usingStart->
tokAt(3);
3009 usingEnd = findSemicolon(start);
3019 else if (start->
str() ==
"typename") {
3021 Token *temp = start;
3023 temp = temp->
tokAt(2);
3034 ScopeInfo3 scopeInfo1;
3035 ScopeInfo3 *currentScope1 = &scopeInfo1;
3037 Token *endToken =
nullptr;
3038 bool inMemberFunc =
false;
3039 const ScopeInfo3 * memberFuncScope =
nullptr;
3040 const Token * memberFuncEnd =
nullptr;
3044 if (currentScope->type == ScopeInfo3::Other ||
3045 currentScope->type == ScopeInfo3::MemberFunction) {
3046 scopeInfo1 = scopeInfo;
3047 currentScope1 = scopeInfo1.findScope(currentScope);
3050 startToken = usingEnd->
next();
3051 endToken =
const_cast<Token*
>(currentScope->bodyEnd->next());
3052 if (currentScope->type == ScopeInfo3::MemberFunction) {
3053 const ScopeInfo3 * temp = currentScope->findScope(currentScope->fullName);
3055 inMemberFunc =
true;
3056 memberFuncScope = temp;
3057 memberFuncEnd = endToken;
3062 std::string scope1 = currentScope1->fullName;
3064 Token *enumOpenBrace =
nullptr;
3065 for (
Token* tok1 = startToken; !skip && tok1 && tok1 != endToken; tok1 = tok1->
next()) {
3067 if (tok1 && tok1 == enumOpenBrace) {
3068 tok1 = tok1->
link();
3069 enumOpenBrace =
nullptr;
3073 if ((
Token::Match(tok1,
"{|}|namespace|class|struct|union") && tok1->
strAt(-1) !=
"using") ||
3077 }
catch (
const std::runtime_error &) {
3079 "simplifyUsing: unmatched body end");
3081 scope1 = currentScope1->fullName;
3082 if (inMemberFunc && memberFuncEnd && tok1 == memberFuncEnd) {
3083 inMemberFunc =
false;
3084 memberFuncScope =
nullptr;
3085 memberFuncEnd =
nullptr;
3094 tok1 = declEndToken;
3099 if (tok1->
str() ==
"enum") {
3101 tok1 = tok1->
next();
3102 Token *defStart = tok1;
3104 defStart = defStart->
next();
3106 enumOpenBrace = defStart;
3112 if (!scope1.empty())
3114 scope1 += memberFunctionScope(tok1);
3115 const ScopeInfo3 * temp = currentScope1->findScope(scope1);
3117 const Token *end = memberFunctionEnd(tok1);
3119 inMemberFunc =
true;
3120 memberFuncScope = temp;
3121 memberFuncEnd = end;
3126 if (inMemberFunc && memberFuncScope) {
3127 if (!usingMatch(nameToken, scope, tok1, scope1, currentScope1, memberFuncScope))
3129 }
else if (!usingMatch(nameToken, scope, tok1, scope1, currentScope1,
nullptr))
3132 const auto nReplace =
tokDistance(start, usingEnd);
3133 if (nReplace > maxReplacementTokens) {
3139 std::string fullScope = scope;
3140 std::string removed;
3142 removed = (tok1->
strAt(-2) +
" :: ") + removed;
3143 if (fullScope == tok1->
strAt(-2)) {
3148 const std::string::size_type idx = fullScope.rfind(
"::");
3150 if (idx == std::string::npos)
3153 if (tok1->
strAt(-2) == fullScope.substr(idx + 3)) {
3156 fullScope.resize(idx - 1);
3162 if (tok1->
strAt(-1) ==
"::") {
3163 removed.insert(0,
":: ");
3167 Token * arrayStart =
nullptr;
3170 Token *type = start;
3171 if (type->
str() ==
"::") {
3172 type = type->
next();
3174 type = type->
tokAt(2);
3176 type = type->
next();
3179 type = type->
tokAt(2);
3182 type = type->
next();
3184 while (
Token::Match(type,
"const|class|struct|union|enum %type%") ||
3186 type = type->
next();
3188 type = type->
next();
3192 type = type->
next();
3197 if (type && type->
str() ==
"::") {
3198 type = type->
next();
3203 type = type->
next();
3205 type = type->
next();
3218 if (type->
str() ==
"<") {
3222 type = type->
tokAt(2);
3229 type = type->
next();
3231 type = type->
next();
3235 std::list<std::string> pointers;
3237 pointers.push_back(type->
str());
3238 type = type->
next();
3242 if (type && type->
str() ==
"[") {
3250 type = type->
next();
3255 else if (type->
next()->
str() ==
";")
3257 else if (type->
str() ==
"]")
3260 type = type->
next();
3263 type = type->
next();
3264 }
while (type && type->
str() ==
"[");
3268 if (!tok1 || !tok1->
next())
3273 if (type && type == usingEnd) {
3284 std::string removed1 = std::move(removed);
3285 std::string::size_type idx = removed1.rfind(
" ::");
3286 if (idx != std::string::npos)
3287 removed1.resize(idx);
3289 ScopeInfo3 * tempScope = currentScope;
3290 while (tempScope->parent) {
3291 if (tempScope->recordTypes.find(start->
str()) != tempScope->recordTypes.end()) {
3292 std::string::size_type spaceIdx = 0;
3293 std::string::size_type startIdx = 0;
3294 while ((spaceIdx = removed1.find(
' ', startIdx)) != std::string::npos) {
3296 startIdx = spaceIdx + 1;
3302 idx = removed1.rfind(
" ::");
3303 if (idx == std::string::npos)
3306 removed1.resize(idx);
3307 tempScope = tempScope->parent;
3312 if (
Token::Match(tok1,
"%name% ( )") && !pointers.empty()) {
3317 after = tok2->
next();
3333 usingList.emplace_back(usingStart, usingEnd);
3337 for (std::list<Using>::reverse_iterator it = usingList.rbegin(); it != usingList.rend(); ++it) {
3338 Token *usingStart = it->startTok;
3339 Token *usingEnd = it->endTok;
3341 if (usingEnd->
next())
3348 if (usingEnd->
next()) {
3366 for (
const Token *tok = usingStart; tok && tok != usingEnd; tok = tok->
next()) {
3372 std::list<const Token *> callstack(1, usingStart);
3374 "Failed to parse \'" + str +
"\'. The checking continues anyway.",
Certainty::normal));
3423 const char* disableValueflowEnv = std::getenv(
"DISABLE_VALUEFLOW");
3424 const bool doValueFlow = !disableValueflowEnv || (std::strcmp(disableValueflowEnv,
"1") != 0);
3442 simplecpp::characterLiteralToLL(tok->
str());
3443 }
catch (
const std::exception &e) {
3471 tok = tok->
tokAt(2);
3500 const bool cpp =
isCPP();
3504 const char c1 = tok->
str()[0];
3506 if (tok->
str().length() == 1 && tok->
next()->
str().length() == 1) {
3507 const char c2 = tok->
next()->
str()[0];
3510 if (c2 ==
'=' && (std::strchr(
"+-*/%|^=!<>", c1)) && !
Token::Match(tok->
previous(),
"%type% *")) {
3513 const Token* opening =
3518 tok->
str(tok->
str() + c2);
3522 }
else if (tok->
next()->
str() ==
"=") {
3523 if (tok->
str() ==
">>") {
3526 }
else if (tok->
str() ==
"<<") {
3530 }
else if (cpp && (c1 ==
'p' || c1 ==
'_') &&
3531 Token::Match(tok,
"private|protected|public|__published : !!:")) {
3532 bool simplify =
false;
3535 if (prev->
str() ==
")") {
3537 }
else if (prev->
str() ==
"(") {
3542 if (par != 0U || prev->
str() ==
"(")
3555 tok->
str(tok->
str() +
":");
3558 }
else if (tok->
str() ==
"->") {
3622 const bool isExtC = tok->
next()->
str().size() == 3;
3623 if (tok->
strAt(2) ==
"{") {
3624 tok2 = tok2->
next();
3625 while ((tok2 = tok2->
next()) && tok2 != tok->
linkAt(2))
3652 if (
Token::Match(tok,
"( { %bool%|%char%|%num%|%str%|%name% ; } )")) {
3683 tok = tok->
tokAt(3);
3692 const std::string number(tok->
str());
3694 tok->
str(indexTok->
str());
3696 indexTok->
str(number);
3730 while (tok->
next()) {
3731 if (tok->
str() ==
"+") {
3732 if (tok->
next()->
str()[0] ==
'-') {
3734 if (tok->
str().size() == 1) {
3739 tok->
str(tok->
str().substr(1));
3745 }
else if (tok->
str() ==
"-") {
3746 if (tok->
next()->
str()[0] ==
'-') {
3748 if (tok->
str().size() == 1) {
3753 tok->
str(tok->
str().substr(1));
3770 auto getStrTok = [](
Token* tok,
bool addLength,
Token*& endStmt) ->
Token* {
3772 endStmt = tok->
tokAt(5);
3773 return tok->
tokAt(4);
3776 tok = tok->
tokAt(4);
3783 endStmt = tok->
tokAt(parCount + 1);
3793 bool addlength =
false;
3802 if (
const Token* strTok = getStrTok(tok, addlength, endStmt)) {
3812 for (
Token *tok2 = tok->
tokAt(4); tok2 && tok2 != end; tok2 = tok2->
next()) {
3814 if (tok2->
str() ==
"[" && tok2->
link()->strAt(1) ==
"=") {
3822 tok2 = tok2->
link();
3823 }
else if (tok2->
str() ==
",") {
3836 tok = end->
next() ? end->
next() : end;
3845 if (!var || !var->isArray())
3847 if (!
Token::Match(var->nameToken(),
"%name% [ ] = { ["))
3850 const Token*
const startToken = var->nameToken()->
tokAt(4);
3851 const Token*
const endToken = startToken->
link();
3852 for (
const Token* tok = startToken; tok != endToken; tok = tok->
next()) {
3859 if (maxIndex >= 0) {
3861 Token* tok =
const_cast<Token*
>(var->nameToken()->next());
3873 d.
num = maxIndex + 1;
3874 std::vector<Dimension> dimensions{d};
3875 const_cast<Variable*
>(var)->setDimensions(dimensions);
3883 while (
nullptr != (tok = tok->
next())) {
3884 if (tok->
str() ==
"?") {
3886 }
else if (tok->
str() ==
":") {
3888 if (colonLevel == 0) {
3908 assert(tok->
str() ==
"case");
3909 while (
nullptr != (tok = tok->
next())) {
3912 else if (tok->
str() ==
"?") {
3926 if (tok->
str() !=
")")
3936 return (tok && tok->
str() ==
"{") ? tok :
nullptr;
3944 const bool cpp =
isCPP();
3945 bool executablescope =
false;
3946 int indentLevel = 0;
3952 executablescope =
true;
3955 if (!executablescope)
3958 if (tok->
str() ==
"{") {
3963 }
else if (tok->
str() ==
"}") {
3965 if (indentLevel == 0) {
3966 executablescope =
false;
3976 if (tok->
str() !=
":" || tok->
strAt(-1) ==
"case" || !tok->
next())
3984 tok = tok->
tokAt(2);
3995 if (
Token::Match(tok,
"case %num%|%char% ... %num%|%char% :")) {
3998 end = std::min(start + 50, end);
4000 tok = tok->
tokAt(2);
4018 std::string nextScopeNameAddition;
4019 std::shared_ptr<ScopeInfo2> primaryScope = std::make_shared<ScopeInfo2>(
"",
nullptr);
4027 if (
Token::Match(tok,
"using namespace %name% ::|<|;")) {
4028 std::string usingNamespaceName;
4029 for (
const Token* namespaceNameToken = tok->
tokAt(2);
4030 namespaceNameToken && namespaceNameToken->
str() !=
";";
4031 namespaceNameToken = namespaceNameToken->next()) {
4032 usingNamespaceName += namespaceNameToken->str();
4033 usingNamespaceName +=
" ";
4035 if (!usingNamespaceName.empty())
4036 usingNamespaceName.pop_back();
4037 tok->
scopeInfo()->usingNamespaces.insert(std::move(usingNamespaceName));
4038 }
else if (
Token::Match(tok,
"namespace|class|struct|union %name% {|::|:|<")) {
4039 for (
Token* nameTok = tok->
next(); nameTok && !
Token::Match(nameTok,
"{|:"); nameTok = nameTok->next()) {
4041 nextScopeNameAddition =
"";
4044 nextScopeNameAddition.append(nameTok->str());
4045 nextScopeNameAddition.append(
" ");
4047 if (!nextScopeNameAddition.empty())
4048 nextScopeNameAddition.pop_back();
4063 if (tok1->
strAt(-1) !=
")")
4066 tok1 = tok1->
tokAt(-2);
4067 if (tok1->
strAt(-1) !=
")")
4071 if (tok1->
strAt(-1) ==
">")
4074 tok1 = tok1->
tokAt(-2);
4075 std::string scope = tok1->
strAt(-1);
4077 scope = tok1->
strAt(-3) +
" :: " + scope;
4078 tok1 = tok1->
tokAt(-2);
4081 if (!nextScopeNameAddition.empty() && !scope.empty())
4082 nextScopeNameAddition +=
" :: ";
4083 nextScopeNameAddition += scope;
4089 std::shared_ptr<ScopeInfo2> newScopeInfo = std::make_shared<ScopeInfo2>(tok->
scopeInfo()->name, tok->
link(), tok->
scopeInfo()->usingNamespaces);
4091 if (!newScopeInfo->name.empty() && !nextScopeNameAddition.empty())
4092 newScopeInfo->name.append(
" :: ");
4093 newScopeInfo->name.append(nextScopeNameAddition);
4094 nextScopeNameAddition =
"";
4098 tok->
scopeInfo(std::move(newScopeInfo));
4120 std::unordered_map<std::string, nonneg int> mVariableId;
4121 std::unordered_map<std::string, nonneg int> mVariableId_global;
4122 std::stack<std::vector<std::pair<std::string, nonneg int>>> mScopeInfo;
4123 mutable nonneg int mVarId{};
4125 VariableMap() =
default;
4128 void addVariable(
const std::string& varname,
bool globalNamespace);
4129 bool hasVariable(
const std::string& varname)
const {
4130 return mVariableId.find(varname) != mVariableId.end();
4133 const std::unordered_map<std::string, nonneg int>& map(
bool global)
const {
4134 return global ? mVariableId_global : mVariableId;
4143 void VariableMap::enterScope()
4145 mScopeInfo.emplace();
4148 bool VariableMap::leaveScope()
4150 if (mScopeInfo.empty())
4153 for (
const std::pair<std::string, nonneg int>& outerVariable : mScopeInfo.top()) {
4154 if (outerVariable.second != 0)
4155 mVariableId[outerVariable.first] = outerVariable.second;
4157 mVariableId.erase(outerVariable.first);
4163 void VariableMap::addVariable(
const std::string& varname,
bool globalNamespace)
4165 if (mScopeInfo.empty()) {
4166 mVariableId[varname] = ++mVarId;
4167 if (globalNamespace)
4168 mVariableId_global[varname] = mVariableId[varname];
4171 std::unordered_map<std::string, nonneg int>::iterator it = mVariableId.find(varname);
4172 if (it == mVariableId.end()) {
4173 mScopeInfo.top().emplace_back(varname, 0);
4174 mVariableId[varname] = ++mVarId;
4175 if (globalNamespace)
4176 mVariableId_global[varname] = mVariableId[varname];
4179 mScopeInfo.top().emplace_back(varname, it->second);
4180 it->second = ++mVarId;
4185 const Token*
const tok1 = tok;
4190 nonneg int typeCount = 0;
4191 nonneg int singleNameCount = 0;
4192 bool hasstruct =
false;
4193 bool bracket =
false;
4211 singleNameCount = 0;
4214 }
else if (!hasstruct && variableMap.map(
false).count(tok2->
str()) && tok2->
previous()->
str() !=
"::") {
4216 tok2 = tok2->
next();
4217 if (!tok2 || tok2->
str() !=
"::")
4226 const Token *start = tok;
4230 if (closingBracket ==
nullptr) {
4233 tok2 = closingBracket;
4234 if (tok2->
str() !=
">")
4236 singleNameCount = 1;
4250 tok3 = tok3->
link();
4251 if (tok3->
str() ==
",")
4259 }
else if (tok2->
str() ==
"::") {
4260 singleNameCount = 0;
4261 }
else if (tok2->
str() !=
"*" && tok2->
str() !=
"...") {
4264 tok2 = tok2->
next();
4268 bool isLambdaArg =
false;
4271 if (tok3 && tok3->
str() ==
",") {
4274 tok3 = tok3->
link();
4285 if (!
Token::Match(fdecl,
"[;{}] %name%") || count <= 1)
4300 if (executableScope && ref && !isLambdaArg) {
4303 else if (tok2->
str() !=
")" || tok2->
link()->strAt(-1) !=
"catch")
4310 if (typeCount >= 2 && executableScope &&
Token::Match(tok2,
")| [")) {
4311 const Token *tok3 = tok2->
str() ==
")" ? tok2->
next() : tok2;
4312 while (tok3 && tok3->
str() ==
"[") {
4313 tok3 = tok3->
link()->next();
4321 return (typeCount >= 2 && tok2 &&
Token::Match(tok2->
tokAt(-2),
"!!:: %type%"));
4326 std::map<
nonneg int, std::map<std::string, nonneg int>>& structMembers,
4333 if (struct_varid == 0)
4336 std::map<std::string, nonneg int>& members = structMembers[struct_varid];
4338 tok = tok->
tokAt(3);
4339 while (tok->
str() !=
"}") {
4344 const std::map<std::string, nonneg int>::iterator it = members.find(tok->
str());
4345 if (it == members.end()) {
4346 members[tok->
str()] = ++varId;
4349 tok->
varId(it->second);
4362 tok = tok->
tokAt(3);
4366 tok = tok->
tokAt(2);
4367 if (struct_varid == 0)
4370 if (tok->
str() ==
".")
4377 std::map<std::string, nonneg int>& members = structMembers[struct_varid];
4378 const std::map<std::string, nonneg int>::iterator it = members.find(tok->
str());
4379 if (it == members.end()) {
4380 members[tok->
str()] = ++varId;
4383 tok->
varId(it->second);
4391 VariableMap& variableMap,
4392 const nonneg int scopeStartVarId,
4393 std::map<
nonneg int, std::map<std::string, nonneg int>>& structMembers)
4396 const Token*
const endToken = startToken->
link();
4399 std::string className;
4401 if (!tok->
isName() && tok->
str() !=
":")
4403 if (
Token::Match(tok,
"class|struct|enum %type% [:{]")) {
4404 className = tok->
next()->
str();
4410 int indentlevel = 0;
4411 bool initList =
false;
4412 bool inEnum =
false;
4413 const Token *initListArgLastToken =
nullptr;
4414 for (
Token *tok = startToken->
next(); tok != endToken; tok = tok->
next()) {
4418 if (tok == initListArgLastToken)
4419 initListArgLastToken =
nullptr;
4420 else if (!initListArgLastToken &&
4423 initListArgLastToken = tok->
link();
4425 if (tok->
str() ==
"{") {
4427 if (initList && !initListArgLastToken)
4430 }
else if (tok->
str() ==
"}") {
4433 }
else if (initList && indentlevel == 0 &&
Token::Match(tok->
previous(),
"[,:] %name% [({]")) {
4434 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(
false).find(tok->
str());
4435 if (it != variableMap.map(
false).end()) {
4436 tok->
varId(it->second);
4438 }
else if (tok->
isName() && tok->
varId() <= scopeStartVarId) {
4439 if (indentlevel > 0 || initList) {
4444 if (tok->
next()->
str() ==
"::") {
4445 if (tok->
str() == className)
4446 tok = tok->
tokAt(2);
4452 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(
false).find(tok->
str());
4453 if (it != variableMap.map(
false).end()) {
4454 tok->
varId(it->second);
4459 }
else if (indentlevel == 0 && tok->
str() ==
":" && !initListArgLastToken)
4470 Token *
const startToken,
4471 const Token *
const endToken,
4472 const std::map<std::string, nonneg int> &varlist,
4473 std::map<
nonneg int, std::map<std::string, nonneg int>>& structMembers,
4476 const auto pos = classname.rfind(
' ');
4477 const std::string lastScope = classname.substr(pos == std::string::npos ? 0 : pos + 1);
4478 for (
Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->
next()) {
4490 const std::map<std::string, nonneg int>::const_iterator it = varlist.find(tok2->
str());
4491 if (it != varlist.end()) {
4492 tok2->
varId(it->second);
4517 #define NOTSTART_C "NOT", "case", "default", "goto", "not", "return", "sizeof", "typedef"
4520 "delete",
"friend",
"new",
"throw",
"using",
"virtual",
"explicit",
"const_cast",
"dynamic_cast",
"reinterpret_cast",
"static_cast",
"template"
4528 VariableMap variableMap;
4529 std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
4531 std::stack<VarIdScopeInfo> scopeStack;
4533 scopeStack.emplace();
4534 std::stack<const Token *> functionDeclEndStack;
4535 const Token *functionDeclEndToken =
nullptr;
4536 bool initlist =
false;
4537 bool inlineFunction =
false;
4544 tok = closingBracket;
4548 if (tok == functionDeclEndToken) {
4549 functionDeclEndStack.pop();
4550 functionDeclEndToken = functionDeclEndStack.empty() ? nullptr : functionDeclEndStack.top();
4551 if (tok->
str() ==
":")
4553 else if (tok->
str() ==
";") {
4554 if (!variableMap.leaveScope())
4556 }
else if (tok->
str() ==
"{") {
4557 scopeStack.emplace(
true, scopeStack.top().isStructInit || tok->
strAt(-1) ==
"=",
false, variableMap.getVarId());
4561 if (ifToken && ifToken->
str() ==
")")
4562 ifToken = ifToken->
link();
4567 if (ifToken && ifToken->
str() ==
"if") {
4569 variableMap.enterScope();
4572 }
else if (!initlist && tok->
str()==
"(") {
4573 const Token * newFunctionDeclEnd =
nullptr;
4574 if (!scopeStack.top().isExecutable)
4577 const Token* tokenLinkNext = tok->
link()->next();
4579 tokenLinkNext = tokenLinkNext->
next();
4581 tokenLinkNext = tokenLinkNext->
next();
4583 tokenLinkNext = tokenLinkNext->
link()->next();
4586 if (tokenLinkNext && tokenLinkNext->
str() ==
"{")
4587 newFunctionDeclEnd = tokenLinkNext;
4589 if (newFunctionDeclEnd && newFunctionDeclEnd != functionDeclEndToken) {
4590 functionDeclEndStack.push(newFunctionDeclEnd);
4591 functionDeclEndToken = newFunctionDeclEnd;
4592 variableMap.enterScope();
4595 inlineFunction =
false;
4597 const Token *
const startToken = (tok->
str() ==
"{") ? tok : tok->
link();
4603 if (tok->
str() ==
"{") {
4610 (initlist && tok->
strAt(-1) ==
"}")) {
4611 isExecutable =
true;
4613 isExecutable = ((scopeStack.top().isExecutable || initlist || tok->
strAt(-1) ==
"else") &&
4615 if (!(scopeStack.top().isStructInit || tok->
strAt(-1) ==
"="))
4616 variableMap.enterScope();
4619 scopeStack.emplace(isExecutable, scopeStack.top().isStructInit || tok->
strAt(-1) ==
"=",
isEnumStart(tok), variableMap.getVarId());
4621 bool isNamespace =
false;
4623 if (tok1->
str() ==
"namespace") {
4629 if (!initlist && !
isC() && !scopeStack.top().isExecutable && tok->
link() && !isNamespace) {
4632 scopeStack.top().startVarid,
4638 if (!scopeStack.top().isStructInit) {
4639 variableMap.leaveScope();
4643 if (ifToken && ifToken->
str() ==
")")
4644 ifToken = ifToken->
link()->previous();
4647 if (startToken->
strAt(-1) ==
"else" || (ifToken && ifToken->
str() ==
"if" && tok->
strAt(1) !=
"else")) {
4649 variableMap.leaveScope();
4654 if (scopeStack.empty()) {
4655 scopeStack.emplace();
4661 if ((!scopeStack.top().isStructInit &&
4664 (tok->
str() ==
"(" && !scopeStack.top().isExecutable &&
isFunctionHead(tok,
";:")) ||
4665 (tok->
str() ==
"," && (!scopeStack.top().isExecutable || inlineFunction || !tok->
previous()->
varId())) ||
4682 tok2 = tok2->
next();
4688 if (notstart.find(tok2->
str()) != notstart.end())
4700 while (tok2 && tok2->
str() !=
"]") {
4702 variableMap.addVariable(tok2->
str(),
false);
4703 tok2 = tok2->
next();
4711 }
catch (
const Token * errTok) {
4715 if (tok->
str() ==
"(" &&
isFunctionHead(tok,
"{") && scopeStack.top().isExecutable)
4716 inlineFunction =
true;
4721 for (
Token *declTok = declTypeTok->
linkAt(1); declTok != declTypeTok; declTok = declTok->
previous()) {
4722 if (declTok->isName() && !
Token::Match(declTok->previous(),
"::|.") && variableMap.hasVariable(declTok->str()))
4723 declTok->varId(variableMap.map(
false).find(declTok->str())->second);
4735 if (prev2->
isCpp() &&
4741 if (!scopeStack.top().isExecutable) {
4746 if (tok3->
str() ==
"=") {
4751 if (tok3->
str() ==
",") {
4760 (tok3->
isName() && (variableMap.hasVariable(tok3->
str()) ||
4763 tok3->
str() ==
"(" ||
4764 notstart.find(tok3->
str()) != notstart.end()) {
4773 if (tok2->
link() != tok2->
next() &&
4782 variableMap.addVariable(prev2->
str(), scopeStack.size() <= 1);
4785 for (
const Token *tok3 = prev2->
next(); tok3 && tok3->
str() !=
";"; tok3 = tok3->
next()) {
4787 tok3 = tok3->
link();
4789 variableMap.addVariable(tok3->
next()->
str(),
false);
4797 if (tok && tok->
str() ==
"<") {
4799 while (tok != end) {
4802 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(
false).find(tok->
str());
4803 if (it != variableMap.map(
false).end())
4804 tok->
varId(it->second);
4820 bool globalNamespace =
false;
4825 globalNamespace =
true;
4834 if (scopeStack.top().isExecutable &&
Token::Match(tok,
"%name% [,)[]")) {
4841 if (start->
str() ==
"(") {
4850 if (start->
varId() > 0)
4858 const bool isNotstartKeyword = start->
next() && notstart.find(start->
next()->
str()) != notstart.end();
4870 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(globalNamespace).find(tok->
str());
4871 if (it != variableMap.map(globalNamespace).end()) {
4872 tok->
varId(it->second);
4882 }
while (tok && (tok->
isName() || tok->
str() ==
","));
4889 mVarId = variableMap.getVarId();
4894 Member(std::list<std::string> s, std::list<const Token *> ns,
Token *t) : usingnamespaces(std::move(ns)), scope(std::move(s)), tok(t) {}
4895 std::list<const Token *> usingnamespaces;
4896 std::list<std::string> scope;
4905 ret += (ret.empty() ?
"" :
" :: ") + (si.name);
4911 std::list<ScopeInfo2>::const_iterator scopeIt = scopeInfo.cbegin();
4914 for (std::list<std::string>::const_iterator it = scope.cbegin(); it != scope.cend(); ++it) {
4915 if (scopeIt == scopeInfo.cend() || scopeIt->name != *it)
4923 if (scopeIt != scopeInfo.end() && nsToken->
str() == scopeIt->name) {
4924 nsToken = nsToken->
tokAt(2);
4932 if (scopeIt == scopeInfo.end() || nsToken->
str() != scopeIt->name)
4938 while (scopeIt != scopeInfo.end()) {
4941 if (memberToken->
str() != scopeIt->name)
4943 if (memberToken->
next()->
str() ==
"<") {
4948 memberToken = memberToken->
tokAt(2);
4952 return Token::Match(memberToken,
"~| %name%") ? memberToken :
nullptr;
4957 if (scopeInfo.empty())
4966 for (
const Token *ns : member.usingnamespaces) {
4988 return Token::Match(tok,
"~| %name% (") ? tok :
nullptr;
4991 template<
typename T>
4994 T*
const start = tok;
4996 tok = tok->
tokAt(tok->strAt(1) ==
"::" ? 1 : 2);
4998 tok = tok->
tokAt(2);
5001 const bool isTemplate = tok->
str() ==
"<";
5002 tok = tok->link()->next();
5003 if (isTemplate && tok && tok->link())
5004 tok = tok->link()->next();
5011 std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
5014 std::list<Member> allMemberFunctions;
5015 std::list<Member> allMemberVars;
5017 std::map<const Token *, std::string> endOfScope;
5018 std::list<std::string> scope;
5019 std::list<const Token *> usingnamespaces;
5022 if (
Token::Match(tok,
"using namespace %name% ::|;")) {
5025 endtok = endtok->
tokAt(2);
5027 usingnamespaces.push_back(tok->
tokAt(2));
5032 scope.push_back(tok->
strAt(1));
5037 if (tok->
str() ==
"}") {
5038 const std::map<const Token *, std::string>::iterator it = endOfScope.find(tok);
5039 if (it != endOfScope.end())
5040 scope.remove(it->second);
5043 Token*
const tok1 = tok;
5058 if (tok->
str() ==
"~")
5070 allMemberFunctions.emplace_back(scope, usingnamespaces, tok1);
5072 allMemberVars.emplace_back(scope, usingnamespaces, tok1);
5076 std::list<ScopeInfo2> scopeInfo;
5079 std::map<std::string, std::map<std::string, nonneg int>> varsByClass;
5081 while (tok->
str() ==
"}" && !scopeInfo.empty() && tok == scopeInfo.back().bodyEnd)
5082 scopeInfo.pop_back();
5084 if (!
Token::Match(tok,
"namespace|class|struct %name% {|:|::|<"))
5088 const std::string scopeName2(scopeName.empty() ? std::string() : (scopeName +
" :: "));
5090 std::list<const Token*> classnameTokens{ tok->
next() };
5092 while (
Token::Match(tokStart,
":: %name%") || tokStart->
str() ==
"<") {
5093 if (tokStart->
str() ==
"<") {
5098 tokStart = closeTok->
next();
5100 classnameTokens.push_back(tokStart->
next());
5101 tokStart = tokStart->
tokAt(2);
5105 std::string classname;
5106 for (
const Token *it : classnameTokens)
5107 classname += (classname.empty() ?
"" :
" :: ") + it->
str();
5109 std::map<std::string, nonneg int> &thisClassVars = varsByClass[scopeName2 + classname];
5114 tokStart = tokStart->
next();
5118 std::string baseClassName = tokStart->
str();
5119 const Token* baseStart = tokStart;
5121 baseClassName.insert(0, baseStart->
strAt(-2) +
" :: ");
5122 baseStart = baseStart->
tokAt(-2);
5124 std::string scopeName3(scopeName2);
5125 while (!scopeName3.empty()) {
5126 const std::string name = scopeName3 + baseClassName;
5127 if (varsByClass.find(name) != varsByClass.end()) {
5128 baseClassName = name;
5132 if (scopeName3.size() <= 8)
5134 scopeName3.erase(scopeName3.size() - 4);
5135 const std::string::size_type pos = scopeName3.rfind(
" :: ");
5136 if (pos == std::string::npos)
5138 scopeName3.erase(pos + 4);
5140 const std::map<std::string, nonneg int>& baseClassVars = varsByClass[baseClassName];
5141 thisClassVars.insert(baseClassVars.cbegin(), baseClassVars.cend());
5143 tokStart = tokStart->
next();
5149 std::transform(classnameTokens.cbegin(), classnameTokens.cend(), std::back_inserter(scopeInfo), [&](
const Token* tok) {
5150 return ScopeInfo2(tok->str(), tokStart->link());
5153 for (
Token *tok2 = tokStart->
next(); tok2 && tok2 != tokStart->
link(); tok2 = tok2->
next()) {
5156 if (tok2->
str() ==
"(") {
5160 tok2 = funcstart->
link();
5165 if (tok2->
strAt(-1) ==
")")
5167 tok2 = tok2->
link();
5169 tok2 = tok2->
link();
5178 else if (tok2->
varId() > 0)
5179 thisClassVars[tok2->
str()] = tok2->
varId();
5183 if (thisClassVars.empty())
5187 for (
const Member &var : allMemberVars) {
5191 if (tok2->
varId() == 0)
5192 tok2->
varId(thisClassVars[tok2->
str()]);
5195 if (
isC() || tok->
str() ==
"namespace")
5199 for (
const Member &func : allMemberFunctions) {
5204 if (tok2->
str() ==
"~")
5224 tok3 = tok3->
tokAt(2);
5226 tok3 = tok3->
next();
5228 tok3 = tok3->
tokAt(2);
5233 const std::map<std::string, nonneg int>::const_iterator varpos = thisClassVars.find(tok3->
str());
5234 if (varpos != thisClassVars.end())
5235 tok3->
varId(varpos->second);
5238 if (tok3->
strAt(1) ==
"<") {
5252 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 if (token->
str()[0] == open) {
5257 }
else if (token->
str()[0] == close) {
5258 if (links.empty()) {
5262 if (type.top()->str()[0] != open) {
5274 std::stack<const Token*> type;
5275 std::stack<Token*> links1;
5276 std::stack<Token*> links2;
5277 std::stack<Token*> links3;
5279 if (token->link()) {
5280 token->link(
nullptr);
5290 if (!links1.empty()) {
5295 if (!links2.empty()) {
5300 if (!links3.empty()) {
5311 bool isStruct =
false;
5313 std::stack<Token*> type;
5314 std::stack<Token*> templateTokens;
5321 if (token->link()) {
5324 else if (!type.empty() &&
Token::Match(token,
"}|]|)")) {
5325 while (type.top()->str() ==
"<") {
5326 if (!templateTokens.empty() && templateTokens.top()->next() == type.top())
5327 templateTokens.pop();
5332 }
else if (templateTokens.empty() && !isStruct &&
Token::Match(token,
"%oror%|&&|;")) {
5337 if (token->tokType() ==
Token::eLogicalOp && !type.empty() && type.top()->str() ==
"<") {
5339 bool foundComparison =
false;
5340 while (
Token::Match(prev,
"%name%|%num%|%str%|%cop%|)|]") && prev != type.top()) {
5341 if (prev->
str() ==
")" || prev->
str() ==
"]")
5342 prev = prev->
link();
5346 foundComparison =
true;
5349 if (prev == type.top() && foundComparison)
5352 foundComparison =
false;
5353 while (
Token::Match(next,
"%name%|%num%|%str%|%cop%|(|[") && next->
str() !=
">") {
5354 if (next->
str() ==
"(" || next->
str() ==
"[")
5355 next = next->
link();
5359 foundComparison =
true;
5360 next = next->
next();
5362 if (next && next->
str() ==
">" && foundComparison)
5366 while (!type.empty() && type.top()->str() ==
"<") {
5371 if (
Token::Match(end,
"> %var% ;") && (type.top()->tokAt(-2) ==
nullptr ||
Token::Match(type.top()->tokAt(-2),
";|}|{")))
5375 }
else if (token->str() ==
"<" &&
5376 ((token->previous() && (token->previous()->isTemplate() ||
5377 (token->previous()->isName() && !token->previous()->varId()) ||
5378 (token->strAt(-1) ==
"]" && (!
Token::Match(token->linkAt(-1)->previous(),
"%name%|)") || token->linkAt(-1)->previous()->isKeyword())) ||
5379 (token->strAt(-1) ==
")" && token->linkAt(-1)->strAt(-1) ==
"operator"))) ||
5382 if (token->previous()->str() ==
"template")
5383 templateTokens.push(token);
5384 }
else if (token->str() ==
">" || token->str() ==
">>") {
5385 if (type.empty() || type.top()->str() !=
"<")
5387 Token *
const top1 = type.top();
5389 Token *
const top2 = type.empty() ? nullptr : type.top();
5391 if (!top2 || top2->
str() !=
"<") {
5392 if (token->str() ==
">>")
5394 if (!
Token::Match(token->next(),
"%name%|%cop%|%assign%|::|,|(|)|{|}|;|[|]|:|.|=|?|...") &&
5399 if (token->str() ==
">>" && top1 && top2) {
5406 if (templateTokens.size() == 2 && (top1 == templateTokens.top() || top2 == templateTokens.top())) {
5407 templateTokens.pop();
5408 templateTokens.pop();
5412 if (
Token::Match(token,
"> %name%") && !token->next()->isKeyword() &&
5414 (templateTokens.empty() || top1 != templateTokens.top()))
5417 if (!templateTokens.empty() && top1 == templateTokens.top())
5418 templateTokens.pop();
5429 if (
Token::Match(tok,
"const_cast|dynamic_cast|reinterpret_cast|static_cast")) {
5447 endToken = endToken->
next();
5448 while (
Token::Match(endToken->
next(),
"%name%|%num%|%str%|[|(|.|::|++|--|!|~") || (
Token::Match(endToken,
"%type% * %op%|?|:|const|;|,"))) {
5450 endToken = endToken->
linkAt(1);
5452 endToken = endToken->
next();
5470 if (
Token::Match(tok,
"if|for|while|BOOST_FOREACH %name% (")) {
5475 }
else if (tok->
strAt(1) ==
"constexpr") {
5613 Token *lt =
nullptr;
5619 else if (lt &&
Token::Match(tok,
">|>> %name%|::|(")) {
5620 const Token *
const end = tok;
5621 for (tok = lt; tok != end; tok = tok->
next()) {
5736 if (tok->
str() ==
"(") {
5737 const Token *tok1 = tok;
5741 }
else if (tok->
str() ==
"@") {
5883 std::cout <<
"<debug>" << std::endl;
5899 std::cout <<
"</debug>" << std::endl;
5910 const Token * typetok = var->typeStartToken();
5911 while (typetok && typetok != var->typeEndToken())
5912 typetok = typetok->
next();
5914 if (typetok != var->typeEndToken()) {
5918 "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()));
5932 std::set<const Library::Container*> containers;
5934 outs +=
" <directivelist>";
5937 outs +=
" <directive ";
5941 outs +=
"linenr=\"";
5942 outs += std::to_string(dir.linenr);
5951 outs +=
" </directivelist>";
5955 outs +=
" <tokenlist>";
5958 outs +=
" <token id=\"";
5960 outs +=
"\" file=\"";
5962 outs +=
"\" linenr=\"";
5963 outs += std::to_string(tok->
linenr());
5964 outs +=
"\" column=\"";
5965 outs += std::to_string(tok->
column());
5972 outs +=
" scope=\"";
5976 outs +=
" type=\"name\"";
5978 outs +=
" isUnsigned=\"true\"";
5980 outs +=
" isSigned=\"true\"";
5982 outs +=
" type=\"number\"";
5984 outs +=
" isInt=\"true\"";
5986 outs +=
" isFloat=\"true\"";
5988 outs +=
" type=\"string\" strlen=\"";
5993 outs +=
" type=\"char\"";
5995 outs +=
" type=\"boolean\"";
5996 else if (tok->
isOp()) {
5997 outs +=
" type=\"op\"";
5999 outs +=
" isArithmeticalOp=\"true\"";
6001 outs +=
" isAssignmentOp=\"true\"";
6003 outs +=
" isComparisonOp=\"true\"";
6005 outs +=
" isLogicalOp=\"true\"";
6008 outs +=
" isCast=\"true\"";
6010 outs +=
" externLang=\"C\"";
6014 outs +=
" isTemplateArg=\"true\"";
6016 outs +=
" isRemovedVoidParameter=\"true\"";
6018 outs +=
" isSplittedVarDeclComma=\"true\"";
6020 outs +=
" isSplittedVarDeclEq=\"true\"";
6022 outs +=
" isImplicitInt=\"true\"";
6024 outs +=
" isComplex=\"true\"";
6026 outs +=
" isRestrict=\"true\"";
6028 outs +=
" isAtomic=\"true\"";
6030 outs +=
" isAttributeExport=\"true\"";
6032 outs +=
" isAttributeMaybeUnused=\"true\"";
6034 outs +=
" isAttributeUnused=\"true\"";
6040 if (tok->
varId() > 0) {
6041 outs +=
" varId=\"";
6042 outs += std::to_string(tok->
varId());
6046 outs +=
" exprId=\"";
6047 outs += std::to_string(tok->
exprId());
6051 outs +=
" variable=\"";
6056 outs +=
" function=\"";
6060 if (!tok->
values().empty()) {
6061 outs +=
" values=\"";
6066 outs +=
" type-scope=\"";
6071 outs +=
" astParent=\"";
6076 outs +=
" astOperand1=\"";
6081 outs +=
" astOperand2=\"";
6086 outs +=
" originalName=\"";
6100 outs +=
" noreturn=\"true\"";
6106 outs +=
" </tokenlist>";
6115 containers.erase(
nullptr);
6116 if (!containers.empty()) {
6117 outs +=
" <containers>";
6120 outs +=
" <container id=\"";
6122 outs +=
"\" array-like-index-op=\"";
6125 outs +=
"std-string-like=\"";
6130 outs +=
" </containers>";
6138 outs +=
" <typedef-info>";
6144 outs += typedefInfo.name;
6152 outs += std::to_string(typedefInfo.lineNumber);
6155 outs +=
" column=\"";
6156 outs += std::to_string(typedefInfo.column);
6160 outs += std::to_string(typedefInfo.used?1:0);
6166 outs +=
" </typedef-info>";
6198 std::set<std::string> keep;
6202 if (
Token::Match(closingBracket,
"> class|struct %name% {"))
6203 tok = closingBracket->
linkAt(3);
6209 if (!checkHeaders && tok->
fileIndex() != 0)
6213 keep.insert(tok->
str());
6218 keep.insert(tok->
str());
6222 const std::set<std::string> functionStart{
"static",
"const",
"unsigned",
"signed",
"void",
"bool",
"char",
"short",
"int",
"long",
"float",
"*"};
6225 const bool isIncluded = (tok->
fileIndex() != 0);
6231 while (prev && prev->
isName())
6243 if (isIncluded && removeUnusedIncludedFunctions) {
6246 while (start && functionStart.find(start->
str()) != functionStart.end())
6247 start = start->
next();
6256 if (isIncluded && removeUnusedIncludedClasses) {
6257 if (
Token::Match(tok,
"class|struct %name% [:{]") && keep.find(tok->
strAt(1)) == keep.end()) {
6260 if (endToken->
str() ==
":") {
6261 endToken = endToken->
next();
6263 endToken = endToken->
next();
6272 if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) {
6275 if (
Token::Match(closingBracket,
"> class|struct %name% [;:{]") && keep.find(closingBracket->
strAt(2)) == keep.end()) {
6276 const Token *endToken = closingBracket->
tokAt(3);
6277 if (endToken->
str() ==
":") {
6278 endToken = endToken->
next();
6280 endToken = endToken->
next();
6282 if (endToken && endToken->
str() ==
"{")
6283 endToken = endToken->
link()->next();
6284 if (endToken && endToken->
str() ==
";") {
6303 if (
Token::Match(tok,
"%name%|>|) .|:: template %name%")) {
6308 templateName = templateName->
next();
6314 if (templateName->
str() ==
"(" && templateName->
link())
6315 templateName->
link()->isTemplate(
true);
6326 line = prev->
str() +
" " + line;
6327 line +=
"!!!" + tok->
str() +
"!!!";
6329 line +=
" " + next->str();
6335 std::vector<std::pair<std::string, int>> vars;
6339 if (tok->
str() ==
"{")
6341 else if (tok->
str() ==
"}") {
6342 vars.erase(std::remove_if(vars.begin(), vars.end(), [scopeLevel](
const std::pair<std::string, int>& v) {
6343 return v.second == scopeLevel;
6348 vars.emplace_back(tok->
strAt(2), scopeLevel);
6352 return v.first == tok->previous()->str();
6360 if (endTok && endTok->
str() ==
">>") {
6363 }
else if (endTok && endTok->
str() ==
">>=") {
6368 }
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) {
6369 return v.first == tok->next()->str();
6388 if (tok->
str() ==
"(") {
6401 if (tok2 && tok2->
str() ==
"(")
6402 tok2 = tok2->
link()->next();
6409 !
Token::Match(tok2,
"requires|namespace|class|struct|union|private:|protected:|public:"))
6416 if (
Token::Match(tok2,
"namespace|class|struct|union")) {
6418 const Token *tok3 = tok2;
6420 tok3 = tok3->
next();
6421 if (tok3 && tok3->
str() ==
"{") {
6440 const Token *tok3 = tok2;
6442 tok3 = tok3->
tokAt(2);
6452 if (tok->
str() ==
"{") {
6454 while (prev && prev->
isName())
6456 if (prev && prev->
str() ==
")")
6483 if (!
Token::Match(tok,
"class|struct %name% %name% final| {|:"))
6488 if (nextIsUppercase && !afterNextIsUppercase)
6490 else if (!nextIsUppercase && afterNextIsUppercase)
6502 if (tok->
str() !=
")")
6504 const Token *macro = tok->
link() ? tok->
link()->previous() :
nullptr;
6505 if (!macro || !macro->
isName())
6520 bool goback =
false;
6532 const bool isAnonymousNS = tok->
strAt(1) ==
"{";
6533 if (tok->
strAt(3 - isAnonymousNS) ==
"}") {
6542 if (tok->
str() ==
"{") {
6549 tok = tok->
tokAt(2 - isAnonymousNS);
6557 if (tok->
link() && tok->
str() ==
"(") {
6589 }
else if (tok->
str()==
"while") {
6592 tokPossibleDo =
nullptr;
6594 tokPossibleDo = tokPossibleDo->
link();
6595 if (!tokPossibleDo || tokPossibleDo->
strAt(-1) !=
"do")
6597 }
else if (tok->
str()==
"do") {
6604 tokEnd=tokEnd->
next();
6605 if (!tokEnd || tokEnd->
str()!=
"while")
6613 if (tokEnd->
strAt(1) ==
"else") {
6615 if (!tokEndNextNext || tokEndNextNext->
str() ==
"}")
6617 if (tokEndNextNext->
str() ==
"if")
6634 Token *tokAfterCondition=tokCondition;
6635 if (commandWithCondition) {
6636 if (tokCondition->
str()==
"(")
6637 tokAfterCondition=tokCondition->
link();
6641 if (!tokAfterCondition || tokAfterCondition->
strAt(1) ==
"]")
6644 tokAfterCondition=tokAfterCondition->
next();
6645 if (!tokAfterCondition ||
Token::Match(tokAfterCondition,
")|}|,")) {
6651 Token * tokStatement = tokAfterCondition;
6654 tokStatement = tokStatement->
tokAt(2);
6655 else if (tokStatement->
str() ==
"case") {
6659 if (tokStatement->
str() !=
":")
6661 tokStatement = tokStatement->
next();
6667 Token * tokBracesEnd=
nullptr;
6668 if (tokStatement->
str() ==
"{") {
6670 if (tokStatement != tokAfterCondition) {
6674 tokBracesEnd = tokStatement->
link();
6687 tokBracesEnd = tokCloseBrace;
6692 if (tokEnd->
str()!=
"}") {
6697 tokEnd = tokEnd->
link();
6703 tokEnd=tokEnd->
next();
6705 if (!tokEnd || tokEnd->
str() !=
";") {
6721 tokBracesEnd=tokCloseBrace;
6724 return tokBracesEnd;
6736 !(tok->
strAt(-1) ==
":" || tok->
strAt(-1) ==
"," || tok->
strAt(-1) ==
"::")) {
6740 std::map<std::string, Token *> argumentNames;
6741 bool bailOut =
false;
6742 Token * tokparam =
nullptr;
6745 const std::string& funcName(tok->
str());
6750 while (
nullptr != (tok1 = tok1->
tokAt(2))) {
6757 if (argumentNames.find(tok1->
str()) != argumentNames.end())
6759 else if (tok1->
str() != funcName)
6760 argumentNames[tok1->
str()] = tok1;
6762 if (tok1->
next()->
str() ==
")") {
6764 tok1 = tok1->
tokAt(-2);
6773 tok1 = tok1->
tokAt(-2);
6778 if (tok1->
next()->
str() ==
")") {
6779 tok1 = tok1->
tokAt(2);
6781 if (!tok1 || !tok1->
isName())
6795 tok1 = tok->
link()->next();
6798 for (
const Token* tok2 = tok1; tok2; tok2 = tok2->
next()) {
6801 if (tok2->
str() ==
"{") {
6813 std::map<std::string, Token *> argumentNames2;
6815 while (tok1 && tok1->
str() !=
"{") {
6820 if (tok1->
str() ==
";") {
6825 while (tok2->
str() ==
"]")
6826 tok2 = tok2->
link()->previous();
6834 if (argumentNames2.find(tok2->
str()) != argumentNames2.end()) {
6838 argumentNames2[tok2->
str()] = tok2;
6840 if (argumentNames.find(tok2->
str()) == argumentNames.end()) {
6846 tok1 = tok1->
next();
6849 if (bailOut || !tok1) {
6856 if (argumentNames.size() != argumentNames2.size()) {
6859 for (
const std::pair<const std::string, Token *>& argumentName : argumentNames) {
6860 if (argumentNames2.find(argumentName.first) == argumentNames2.end()) {
6865 argumentNames2[argumentName.first] = tok1->
next();
6871 while (tok->
str() !=
")") {
6874 Token *declEnd = declStart;
6877 while (declEnd->
next()->
str() !=
";" && declEnd->
next()->
str() !=
"{")
6878 declEnd = declEnd->
next();
6887 tok = declEnd->
next();
6890 if (tok->
str() ==
",")
6932 if (
Token::Match(tok,
"( %type% %type%| *| *| ( * ) (") ||
6933 Token::Match(tok,
"static_cast < %type% %type%| *| *| ( * ) (")) {
6936 if (tok1->
isCpp() && tok1->
str() ==
"static_cast")
6937 tok1 = tok1->
next();
6939 tok1 = tok1->
next();
6942 tok1 = tok1->
next();
6944 while (tok1->
next()->
str() ==
"*")
6945 tok1 = tok1->
next();
6962 if (
Token::Match(tok,
"delete|else|return|throw|typedef"))
6970 tok2 = tok2->
next();
6971 if (!tok2 || tok2->
str() !=
"(")
6974 tok2 = tok2->
tokAt(2);
6977 tok2 = tok2->
tokAt(2);
6978 if (tok2->
str() ==
"*")
6979 tok2 = tok2->
next();
6981 tok2 = tok2->
next();
6988 while (tok && tok->
str() !=
"(")
6992 if (!tok || !tok->
link() || !tok->
link()->next()) {
6995 Token *endTok = tok->
link()->next()->link();
6997 endTok = endTok->
linkAt(2);
6998 if (!
Token::Match(endTok,
") const|volatile| const|volatile| ;|,|)|=|[|{"))
7009 tok->
link()->deleteThis();
7019 if (tok3->
str() ==
"<" && tok3->
link())
7020 tok3 = tok3->
link();
7022 tok3 = tok3->
link();
7023 else if (tok3->
str() ==
"(") {
7024 tok3 = tok3->
link();
7026 tok3 = tok3->
next();
7053 bool finishedwithkr =
true;
7054 bool scopeDecl =
false;
7055 for (
Token *tok = tokBegin; tok != tokEnd; tok = tok->
next()) {
7068 !
Token::Match(tok,
"else|try|do|const|constexpr|override|volatile|noexcept"))) {
7076 lambdaStart = lambdaStart->
link();
7097 if (only_k_r_fpar && finishedwithkr) {
7106 }
else if (tok->
str() ==
"(") {
7108 for (
Token * tok2 = tok; tok2 && tok2 != tok->
link(); tok2 = tok2->
next()) {
7112 Token * lambdaBody = tok2;
7113 while (lambdaBody && lambdaBody != tok2->
link() && lambdaBody->
str() !=
"{")
7114 lambdaBody = lambdaBody->
next();
7115 if (lambdaBody && lambdaBody != tok2->
link() && lambdaBody->
link())
7133 if (
Token::Match(type0,
"else|return|public:|protected:|private:"))
7135 if (isCPP11 && type0->
str() ==
"using")
7140 bool isconst =
false;
7141 bool isstatic =
false;
7142 Token *tok2 = type0;
7146 tok2 = tok2->
next();
7153 tok2 = tok2->
next();
7164 tok2 = tok2->
next();
7171 if (tok2->
strAt(1) ==
"*")
7177 tok2 = tok2->
next();
7182 if (
Token::Match(tok2,
"%type% *|&| %name% , %type% *|&| %name%"))
7186 tok2 = tok2->
next();
7193 tok2 = tok2->
next();
7203 tok2 = tok2->
tokAt(2);
7206 int indentlevel = 0;
7209 for (
Token *tok3 = tok2; tok3; tok3 = tok3->
next()) {
7212 if (!parens && tok3->
str() ==
"<") {
7214 }
else if (!parens && tok3->
str() ==
">") {
7215 if (indentlevel == 0) {
7216 tok2 = tok3->
next();
7220 }
else if (!parens && tok3->
str() ==
">>") {
7221 if (indentlevel <= 1) {
7222 tok2 = tok3->
next();
7226 }
else if (tok3->
str() ==
"(") {
7228 }
else if (tok3->
str() ==
")") {
7234 }
else if (tok3->
str() ==
";") {
7241 tok2 = tok2->
next();
7252 Token *varName = tok2;
7254 varName = varName->
next();
7260 bool isPointerOrRef =
false;
7262 isPointerOrRef =
true;
7263 varName = varName->
next();
7267 if (varName->
str() !=
"const" && varName->
str() !=
"volatile") {
7270 varName = varName->
next();
7276 Token *endDecl = varName->
link()->linkAt(1);
7277 varName = varName->
link()->previous();
7279 endDecl = endDecl->
next();
7287 if (varName->
str() !=
"operator") {
7288 tok2 = varName->
next();
7290 if (tok2->
str() ==
"=" && (isstatic || (isconst && !isPointerOrRef))) {
7292 while (tok2 && tok2->
str() !=
"," && tok2->
str() !=
";") {
7294 tok2 = tok2->
link();
7295 const Token *tok3 = tok2;
7301 tok2 = tok2->
next();
7303 if (tok2 && tok2->
str() ==
";")
7312 tok2 = varName->
next();
7315 tok2 = tok2->
link()->next();
7318 if (tok2 && tok2->
str() ==
"=") {
7319 while (tok2 && tok2->
str() !=
"," && tok2->
str() !=
";") {
7321 tok2 = tok2->
link();
7322 tok2 = tok2->
next();
7324 if (tok2 && tok2->
str() ==
";")
7331 tok2 = varName->
next();
7332 tok2 = tok2->
link();
7334 tok2 = tok2->
next();
7335 if (tok2 && tok2->
str() !=
",")
7342 while (
Token::Match(commaTok,
"const|noexcept|override|final")) {
7343 commaTok = commaTok->
next();
7345 commaTok = commaTok->
link()->next();
7358 finishedwithkr =
false;
7362 if (tok2->
str() ==
",") {
7374 tok2 = tok2->
link();
7379 else if (std::strchr(
";,", tok2->
str()[0])) {
7383 varTok = varTok->
next();
7391 if (tok2->
str() ==
",") {
7399 tok2 = tok2->
next();
7402 finishedwithkr = (only_k_r_fpar && tok2 && tok2->
strAt(1) ==
"{");
7410 const std::string qualifiers[] = {
"extern",
"static",
"const"};
7415 bool continue2 =
false;
7416 for (
int i = 0; i <
sizeof(qualifiers)/
sizeof(qualifiers[0]); i++) {
7419 if (!tok->
next() || tok->
next()->
str() != qualifiers[i])
7423 Token* leftTok = tok;
7424 bool behindOther =
false;
7425 for (; leftTok; leftTok = leftTok->
previous()) {
7426 for (
int j = 0; j <= i; j++) {
7427 if (leftTok->
str() == qualifiers[j]) {
7442 (
isCPP() &&
Token::Match(leftTok,
"private:|protected:|public:|operator|template"))) {
7451 if (leftTok && !behindOther && !
Token::Match(leftTok,
";|{|}|(|,|private:|protected:|public:")) {
7462 }
else if (leftTok->
next()) {
7464 tok = leftTok->
next();
7478 if (
Token::Match(tok,
"%name% = %name% = %num%|%name% ;")) {
7482 tok2->
str() ==
"=" &&
7484 tok2 = tok2->
tokAt(-2);
7487 if (!tok2 || tok2->
str() !=
";") {
7493 const std::string& value(valueTok->
str());
7494 tok2 = tok2->
next();
7496 while (tok2 != stopAt) {
7499 tok2 = tok2->
tokAt(4);
7507 std::make_pair(
"and",
"&&")
7508 , std::make_pair(
"and_eq",
"&=")
7509 , std::make_pair(
"bitand",
"&")
7510 , std::make_pair(
"bitor",
"|")
7511 , std::make_pair(
"not_eq",
"!=")
7512 , std::make_pair(
"or",
"||")
7513 , std::make_pair(
"or_eq",
"|=")
7514 , std::make_pair(
"xor",
"^")
7515 , std::make_pair(
"xor_eq",
"^=")
7533 int executableScopeLevel = 0;
7535 std::vector<Token *> alt;
7536 bool replaceAll =
false;
7539 if (tok->
str() ==
")") {
7541 ++executableScopeLevel;
7542 tok =
const_cast<Token *
>(end);
7547 if (tok->
str() ==
"{") {
7548 if (executableScopeLevel > 0)
7549 ++executableScopeLevel;
7553 if (tok->
str() ==
"}") {
7554 if (executableScopeLevel > 0)
7555 --executableScopeLevel;
7562 const std::unordered_map<std::string, std::string>::const_iterator cOpIt =
cAlternativeTokens.find(tok->
str());
7570 if (!
Token::Match(tok->
previous(),
"%name%|%num%|%char%|)|]|> %name% %name%|%num%|%char%|%op%|("))
7574 if (executableScopeLevel == 0 &&
Token::Match(tok,
"%name% (")) {
7575 const Token *start = tok;
7593 (executableScopeLevel == 0U && tok->
strAt(-1) ==
"("))
7603 for (
Token *tok: alt) {
7604 const std::unordered_map<std::string, std::string>::const_iterator cOpIt =
cAlternativeTokens.find(tok->
str());
7606 tok->
str(cOpIt->second);
7607 else if (tok->
str() ==
"not")
7613 return !alt.empty();
7627 if (tok->
str() ==
"return")
7630 if (
Token::Match(tok,
"class|struct|union| %type% *| %name% ( &| %any% ) ;")) {
7632 }
else if (
Token::Match(tok,
"%type% *| %name% ( %type% (")) {
7635 tok2 = tok2->
next();
7638 }
else if (
Token::Match(tok,
"class|struct|union| %type% *| %name% ( &| %any% ) ,") && tok->
str() !=
"new") {
7640 while (tok1->
str() !=
",")
7641 tok1 = tok1->
next();
7644 const int numTokens = (
Token::Match(tok,
"class|struct|union")) ? 2U : 1U;
7655 if (tok->
strAt(2) !=
"*")
7664 if (tok->
str() ==
"*")
7668 if (tok->
str() ==
"sizeof")
7681 tok = tok->
tokAt(2);
7685 tok = tok->
tokAt(2);
7688 tok->
link()->deleteThis();
7699 if (tok->
str() !=
"else")
7708 if (tok->
strAt(1) !=
"if")
7711 for (
Token *tok2 = tok; tok2; tok2 = tok2->
next()) {
7713 tok2 = tok2->
link();
7716 if (tok2->
next() && tok2->
next()->
str() !=
"else") {
7742 semicolon = semicolon->
link();
7743 semicolon = semicolon->
next();
7745 if (semicolon->
str() !=
";")
7748 if (tok->
str() ==
"for") {
7754 bool rangeFor =
false;
7756 if (tok2->
str() ==
"(")
7757 tok2 = tok2->
link();
7758 else if (!rangeFor && tok2->
str() ==
"?")
7760 else if (tok2->
str() ==
":")
7762 tok2 = tok2->
next();
7764 if (!rangeFor || tok2->
str() !=
")")
7774 endscope = endscope->
linkAt(2);
7793 if (tok->
str() !=
"(")
7812 bool innerComma =
false;
7813 for (
const Token *inner = tok->
link()->previous(); inner != tok; inner = inner->
previous()) {
7814 if (inner->str() ==
")")
7815 inner = inner->link();
7816 if (inner->str() ==
",") {
7826 if (tok->
strAt(-2) !=
"operator" &&
7830 tok->
link()->deleteThis();
7840 tok->
link()->tokAt(-2)->deleteNext();
7846 tok->
link()->deleteThis();
7869 tok->
link()->deleteThis();
7877 tok->
link()->deleteThis();
7886 tok->
link()->deleteThis();
7902 tok2 = tok2->
tokAt(2);
7904 if (tok2 != tok->
link())
7918 tok->
link()->deleteThis();
7925 tok->
link()->deleteThis();
7931 if (
Token::Match(tok,
"( %bool%|%num% ) %cop%|;|,|)") &&
7932 tok->
strAt(-2) !=
"operator" &&
7936 tok->
link()->deleteThis();
7944 while (
Token::Match(tok2,
"%type%|static|const|extern") && tok2->
str() !=
"operator") {
7960 static const std::unordered_map<std::string, std::string> intrinsics = {
7961 {
"__has_nothrow_assign",
"has_nothrow_assign" },
7962 {
"__has_nothrow_constructor",
"has_nothrow_constructor" },
7963 {
"__has_nothrow_copy",
"has_nothrow_copy" },
7964 {
"__has_trivial_assign",
"has_trivial_assign" },
7965 {
"__has_trivial_constructor",
"has_trivial_constructor" },
7966 {
"__has_trivial_copy",
"has_trivial_copy" },
7967 {
"__has_trivial_destructor",
"has_trivial_destructor" },
7968 {
"__has_virtual_destructor",
"has_virtual_destructor" },
7969 {
"__is_abstract",
"is_abstract" },
7970 {
"__is_aggregate",
"is_aggregate" },
7971 {
"__is_assignable",
"is_assignable" },
7972 {
"__is_base_of",
"is_base_of" },
7973 {
"__is_class",
"is_class" },
7974 {
"__is_constructible",
"is_constructible" },
7975 {
"__is_convertible_to",
"is_convertible_to" },
7976 {
"__is_destructible",
"is_destructible" },
7977 {
"__is_empty",
"is_empty" },
7978 {
"__is_enum",
"is_enum" },
7979 {
"__is_final",
"is_final" },
7980 {
"__is_nothrow_assignable",
"is_nothrow_assignable" },
7981 {
"__is_nothrow_constructible",
"is_nothrow_constructible" },
7982 {
"__is_nothrow_destructible",
"is_nothrow_destructible" },
7983 {
"__is_pod",
"is_pod" },
7984 {
"__is_polymorphic",
"is_polymorphic" },
7985 {
"__is_trivially_assignable",
"is_trivially_assignable" },
7986 {
"__is_trivially_constructible",
"is_trivially_constructible" },
7987 {
"__is_union",
"is_union" },
7992 auto p = intrinsics.find(tok->
str());
7993 if (p == intrinsics.end())
7997 tok->
str(p->second);
8016 std::string unknownFunc;
8022 *unknown = !unknownFunc.empty();
8034 "checkLibraryNoReturn",
8035 "--check-library: Function " + unknownFunc +
"() should have <noreturn> configuration");
8076 tok->
strAt(1) +
" " +
8077 tok->
strAt(2) +
" " +
8078 tok->
strAt(3) +
"' is not handled. You can use -I or --include to add handling of this code.");
8085 "macroWithSemicolon",
8086 "Ensure that '" + macroName +
"' is defined either using -I, --include or -D.");
8097 std::string s = tok ? (
" " + tok->
str()) :
"";
8098 for (
int i = 0; i < s.size(); ++i) {
8099 if ((
unsigned char)s[i] >= 0x80)
8105 "nonStandardCharLiteral",
8106 "Non-standard character literal" + s +
". " + msg);
8150 for (
const Token *tok2 = tok->
tokAt(2); tok2 && tok2->
str() !=
")"; tok2 = tok2->
next()) {
8151 if (tok2->
str() ==
";") {
8156 tok2 = tok2->
link();
8167 if (
Token::Match(tok,
"const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
8173 tok2 = tok2->
next();
8181 if (
Token::Match(tok,
"template < class|typename %name% [,>]"))
8192 std::stack<const Token *> linkTokens;
8193 const Token *lastTok =
nullptr;
8197 if (tok->
link() ==
nullptr)
8200 linkTokens.push(tok);
8204 if (tok->
link() ==
nullptr)
8207 if (linkTokens.empty())
8210 if (tok->
link() != linkTokens.top())
8213 if (tok != tok->
link()->link())
8219 else if (tok->
link() !=
nullptr)
8223 if (!linkTokens.empty())
8233 std::stack<const Token *> ternaryOp;
8234 for (
const Token *tok = begin; tok != end && tok->
str() !=
";"; tok = tok->
next()) {
8235 if (tok->
str() ==
"?")
8236 ternaryOp.push(tok);
8237 else if (!ternaryOp.empty() && tok->
str() ==
":")
8246 return ternaryOp.empty() ? nullptr : ternaryOp.top();
8259 template<
typename T>
8265 return tok->next()->link();
8317 for (
const Token *inner = tok->
tokAt(2); inner != endTok; inner = inner->
next()) {
8319 inner = inner->
link();
8320 else if (inner->str() ==
";")
8330 for (
const Token *inner = tok->
tokAt(2); inner != endTok; inner = inner->
next()) {
8332 inner = inner->
link();
8333 else if (
Token::Match(inner->previous(),
"[,(] . %name% =|{"))
8339 std::set<std::string> possible;
8342 if (tok->
str() ==
"{") {
8344 while (prev && prev->
isName())
8346 if (prev && prev->
str() ==
")")
8350 }
else if (tok->
str() ==
"}")
8360 for (
const Token *tok2 = bodyStart; tok2 && tok2 != bodyEnd; tok2 = tok2->
next()) {
8366 if (possible.count(tok->
str()) == 0)
8367 possible.insert(tok->
str());
8410 if (tok2->
next()->
str() ==
"(") {
8423 static const std::unordered_set<std::string> nonConsecutiveKeywords{
"break",
8440 else if (tok->
str() ==
"[") {
8441 for (
const Token* inner = tok->
next(); inner != tok->
link(); inner = inner->next()) {
8443 inner = inner->link();
8464 else if (
Token::Match(tok,
"%name% throw|return") && std::isupper(tok->
str()[0]))
8468 else if (
Token::Match(tok,
"!!) %num%|%str%|%char% %assign%|++|--")) {
8473 if (tok->
link()->previous() && tok->
link()->previous()->isUpperCaseName())
8483 while (prev && prev->
str() !=
"(") {
8484 if (prev->
str() ==
")")
8485 prev = prev->
link();
8496 if (tok->
str() !=
"for") {
8503 if (tok->
isKeyword() && nonConsecutiveKeywords.count(tok->
str()) != 0) {
8504 if (
Token::Match(tok,
"%name% %name%") && nonConsecutiveKeywords.count(tok->
next()->
str()) == 1)
8506 const Token* prev = tok;
8507 while (prev && prev->
isName())
8523 tok2 = tok2->
next();
8527 tok2 = tok2->
next();
8529 syntaxError(tok2,
"Unexpected token '" + (tok2 ? tok2->
str() :
"") +
"'");
8537 static const std::unordered_set<std::string> nonGlobalKeywords{
"break",
8548 if (tok->
str() ==
"{")
8551 syntaxError(tok,
"keyword '" + tok->
str() +
"' is not allowed in global scope");
8561 const Token *switchToken = tok;
8566 for (; tok; tok = tok->
next()) {
8567 if (tok->
str() ==
"{") {
8572 if (tok->
str() ==
"}" && tok->
strAt(-1) ==
":")
8579 }
else if (tok->
str() ==
"(") {
8581 }
else if (tok->
str() ==
"case") {
8590 int semicolons = 0, colons = 0;
8591 const Token*
const startTok = tok;
8592 tok = tok->
next()->
link()->previous();
8594 for (; tok != startTok; tok = tok->
previous()) {
8595 if (tok->
str() ==
";") {
8597 }
else if (tok->
str() ==
":") {
8599 }
else if (tok->
str() ==
")") {
8608 if (semicolons == 0 && colons == 0)
8613 const Token *templateEndToken =
nullptr;
8615 if (!templateEndToken) {
8619 if (templateEndToken == tok)
8620 templateEndToken =
nullptr;
8630 bool match1 =
Token::Match(tok,
"%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|++|--|::|sizeof");
8631 bool match2 =
Token::Match(tok->
next(),
"{|if|else|while|do|for|return|switch|break");
8633 match1 = match1 ||
Token::Match(tok,
"throw|decltype|typeof");
8639 if (match1 && match2)
8642 if (
Token::Match(tok,
"%or%|%oror%|~|^|!|%comp%|+|-|/|%")) {
8647 code = tok->
str() +
"()";
8648 if (!code.empty()) {
8655 if (
Token::Match(tok,
"%assign% typename|class %assign%"))
8661 if (
Token::Match(tok,
"[;([{] %comp%|%oror%|%or%|%|/"))
8669 if (
Token::Match(tok->
previous(),
"(|[|{|<|%assign%|%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|::|sizeof"))
8673 if (
Token::Match(tok->
next(),
")|]|>|%assign%|%or%|%oror%|==|!=|/|>=|<=|&&"))
8710 for (
const Token* inner = tok->
next(); inner != end; inner = inner->
next()) {
8711 if (inner->str() ==
"{")
8712 inner = inner->link();
8713 else if (inner->str() ==
";") {
8737 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"))
8754 const Token *
const tok1 = tok;
8775 for (
const Token *tok = start; tok != end; tok = tok->
next()) {
8778 if (!allowSemicolon && tok->
str() ==
";")
8780 if (tok->
str() ==
"{")
8788 std::string str = source;
8790 for (std::string::size_type i = 0; i + 1U < str.size(); ++i) {
8796 if (str[i+1] ==
'x') {
8798 while (sz < 4 && std::isxdigit((
unsigned char)str[i+sz]))
8801 std::istringstream istr(str.substr(i+2, sz-2));
8802 istr >> std::hex >> c;
8808 std::istringstream istr(str.substr(i+1, sz-1));
8809 istr >> std::oct >> c;
8810 str = str.replace(i, sz, std::string(1U, (
char)c));
8816 else if (i+sz < str.size())
8817 str.replace(i, sz, std::string(1U, (
char)c));
8819 str.replace(i, str.size() - i - 1U,
"a");
8839 syntaxError(tryStartToken,
"Invalid function-try-catch block code. Did not find '{' for try body.");
8842 Token *
const tryEndToken = tryStartToken->
link();
8843 Token * endToken = tryEndToken;
8848 if (endToken->
str() !=
"{") {
8852 endToken = endToken->
link();
8854 if (!endToken || endToken == tryEndToken)
8863 static bool isAnonymousEnum(
const Token* tok)
8870 if (end->
str() ==
":") {
8880 const bool cpp =
isCPP();
8892 tok->
insertToken(
"Anonymous" + std::to_string(count++));
8898 if (tok1 &&
Token::Match(tok1->
link(),
"} const| *|&| const| %type% ,|;|[|(|{")) {
8899 tok->
insertToken(
"Anonymous" + std::to_string(count++));
8903 else if (isAnonymousEnum(tok)) {
8906 start->
next()->
link()->deleteThis();
8909 tok->
insertToken(
"Anonymous" + std::to_string(count++));
8914 std::stack<const Token*> scopeStart;
8915 const Token* functionEnd =
nullptr;
8920 if (tok->
str() ==
"{") {
8921 scopeStart.push(tok);
8923 functionEnd = tok->
link();
8927 else if (tok->
str() ==
"}") {
8928 if (!scopeStart.empty())
8930 if (tok == functionEnd)
8931 functionEnd =
nullptr;
8935 else if (
Token::Match(tok,
"class|struct|union|enum %type% :|{")) {
8943 next = next->
next();
8944 if (!next || next->
str() ==
";")
8951 if (
Token::Match(after->
next(),
"const|static|volatile| *|&| const| (| %type% )| ,|;|[|=|(|{")) {
8953 after = after->
next();
8954 while (!
Token::Match(start,
"struct|class|union|enum")) {
8956 after = after->
next();
8963 if (start->
str() !=
"class") {
8965 after = after->
next();
8968 after = after->
tokAt(2);
8971 after->
link()->deleteThis();
8978 after = after->
next();
8979 const bool isEnum = start->
str() ==
"enum";
8980 if (!isEnum && cpp) {
8982 after = after->
next();
9003 bool isClassStructUnionScope =
false;
9004 if (!scopeStart.empty()) {
9007 isClassStructUnionScope =
true;
9031 while (
Token::Match(tok,
"__cdecl|__stdcall|__fastcall|__thiscall|__clrcall|__syscall|__pascal|__fortran|__far|__near") || (windows &&
Token::Match(tok,
"WINAPI|APIENTRY|CALLBACK"))) {
9037 static bool isAttribute(
const Token* tok,
bool gcc) {
9038 return gcc ?
Token::Match(tok,
"__attribute__|__attribute (") :
Token::Match(tok,
"__declspec|_declspec (");
9041 static Token* getTokenAfterAttributes(
Token* tok,
bool gccattr) {
9043 while (isAttribute(after, gccattr))
9051 Token*
const after = getTokenAfterAttributes(tok, gccattr);
9056 Token *ftok = after;
9058 if (ftok->
str() ==
"<") {
9063 ftok = ftok->
next();
9066 ftok = ftok->
tokAt(2);
9075 return prev->
link()->previous();
9077 return prev->
link()->tokAt(-2);
9080 return prev->
link()->tokAt(-2);
9090 while (isAttribute(tok,
false)) {
9094 if (tok->
strAt(2) ==
"noreturn")
9096 else if (tok->
strAt(2) ==
"nothrow")
9101 }
else if (tok->
strAt(2) ==
"property")
9102 tok->
next()->
link()->insertToken(
"__property");
9119 while (isAttribute(tok,
true)) {
9122 for (
Token *attr = tok->
tokAt(2); attr->
str() !=
")"; attr = attr->next()) {
9124 attr = attr->linkAt(1);
9126 if (
Token::Match(attr,
"[(,] constructor|__constructor__ [,()]")) {
9132 else if (
Token::Match(attr,
"[(,] destructor|__destructor__ [,()]")) {
9138 else if (
Token::Match(attr,
"[(,] unused|__unused__|used|__used__ [,)]")) {
9139 Token *vartok =
nullptr;
9140 Token *after = getTokenAfterAttributes(tok,
true);
9146 prev = prev->
link()->previous();
9156 const std::string &attribute(attr->next()->str());
9157 if (attribute.find(
"unused") != std::string::npos)
9164 else if (
Token::Match(attr,
"[(,] pure|__pure__|const|__const__|noreturn|__noreturn__|nothrow|__nothrow__|warn_unused_result [,)]")) {
9168 const std::string &attribute(attr->next()->str());
9169 if (attribute.find(
"pure") != std::string::npos)
9171 else if (attribute.find(
"const") != std::string::npos)
9173 else if (attribute.find(
"noreturn") != std::string::npos)
9175 else if (attribute.find(
"nothrow") != std::string::npos)
9177 else if (attribute.find(
"warn_unused_result") != std::string::npos)
9197 if (tok->
str() !=
"(")
9204 if (attr.compare(attr.size()-2, 2,
"__") != 0)
9209 vartok = vartok->
next();
9211 vartok = vartok->
linkAt(1);
9224 if (tok->
tokAt(-2)) {
9225 tok = tok->
tokAt(-2);
9251 head = head->
next();
9260 head = head->
next();
9269 }
else if (
Token::Match(tok->
previous(),
") [ [ expects|ensures|assert default|audit|axiom| : %name% <|<=|>|>= %num% ] ]")) {
9271 if (vartok->
str() ==
":")
9272 vartok = vartok->
next();
9274 while (argtok && argtok->
str() !=
"(") {
9275 if (argtok->
str() == vartok->
str())
9277 if (argtok->
str() ==
")")
9278 argtok = argtok->
link();
9281 if (argtok && argtok->
str() == vartok->
str()) {
9282 if (vartok->
next()->
str() ==
">=")
9285 else if (vartok->
next()->
str() ==
">")
9288 else if (vartok->
next()->
str() ==
"<=")
9291 else if (vartok->
next()->
str() ==
"<")
9318 static const std::unordered_set<std::string> keywords = {
9345 if (keywords.find(tok->
str()) != keywords.end()) {
9348 const bool isinline = (tok->
str().find(
"inline") != std::string::npos);
9349 const bool isrestrict = (tok->
str().find(
"restrict") != std::string::npos);
9350 if (isinline || isrestrict) {
9353 temp->isInline(
true);
9355 temp->isRestrict(
true);
9363 if (tok->
str() ==
"auto")
9373 auto getTypeTokens = [tok]() {
9374 std::vector<Token*> ret;
9375 for (
Token *temp = tok;
Token::Match(temp,
"%name%"); temp = temp->previous()) {
9376 if (!temp->isKeyword())
9377 ret.emplace_back(temp);
9380 if (!temp->isKeyword())
9381 ret.emplace_back(temp);
9386 if (tok->
str() ==
"restrict") {
9387 for (
Token* temp: getTypeTokens())
9388 temp->isRestrict(
true);
9393 while (tok->
str() ==
"_Atomic") {
9394 for (
Token* temp: getTypeTokens())
9395 temp->isAtomic(
true);
9402 if (cpp20 && tok->
str() ==
"consteval") {
9404 tok->
str(
"constexpr");
9405 }
else if (cpp20 && tok->
str() ==
"constinit") {
9415 finalTok = finalTok->
next();
9420 finalTok = finalTok->
next();
9430 else if (
Token::Match(tok,
") const|override|final| noexcept :|{|;|,|const|override|final")) {
9434 while (tokNoExcept->
str() !=
"noexcept")
9435 tokNoExcept = tokNoExcept->
next();
9440 Token * braceStart = tokNoExcept->
next();
9441 tok = tok->
tokAt(3);
9447 else if (tok->
str() ==
"thread_local") {
9461 for (
Token* tok = start; tok != end; tok = tok->
next()) {
9472 static const std::unordered_map<std::string, TokenDebug> m = {{
"debug_valueflow",
TokenDebug::ValueFlow},
9477 auto it = m.find(tok->
str());
9478 if (it != m.end()) {
9480 tok = setTokenDebug(tok, it->second);
9489 const std::string &varname = tok->
next()->
str();
9492 int indentlevel = 0;
9494 while (
nullptr != (tok2 = tok2->
next())) {
9498 if (indentlevel <= 2)
9506 tok2 = tok2->
tokAt(-3);
9522 std::string instruction;
9530 else if (
Token::Match(tok,
"asm|__asm|__asm__ volatile|__volatile|__volatile__| (")) {
9533 if (partok->
str() !=
"(")
9534 partok = partok->
next();
9541 const Token *firstSemiColon =
nullptr;
9543 while (
Token::Match(endasm,
"%num%|%name%|,|:|;") || (endasm && endasm->
linenr() == comment)) {
9546 if (endasm->
str() ==
";") {
9547 comment = endasm->
linenr();
9548 if (!firstSemiColon)
9549 firstSemiColon = endasm;
9551 endasm = endasm->
next();
9558 }
else if (firstSemiColon) {
9561 }
else if (!endasm) {
9579 if (tok->
strAt(1) !=
";" && tok->
strAt(1) !=
"{")
9589 tok = tok->
tokAt(2);
9592 const int endposition = tok->
next()->
linenr();
9593 tok = tok->
tokAt(-3);
9594 for (
int i = 0; i < 4; ++i) {
9596 tok->
linenr(endposition);
9609 if (tok->
str() !=
"^")
9613 Token * start = tok;
9616 start = start->
link();
9623 last = last->
next();
9624 while (last && !
Token::Match(last,
"%cop%|,|;|{|}|)")) {
9626 last = last->
link();
9627 last = last->
next();
9630 if (start && last) {
9631 std::string asmcode;
9632 while (start->
next() != last) {
9633 asmcode += start->
next()->
str();
9636 if (last->
str() ==
"}")
9644 tok = start->
tokAt(4);
9652 std::set<std::string> var;
9655 if (
Token::Match(tok,
"%name%|] @ %num%|%name%|%str%|(")) {
9659 else if (end->
str() ==
"(") {
9661 while ((end = end->
next()) !=
nullptr) {
9662 if (end->
str() ==
"(")
9664 else if (end->
str() ==
")") {
9669 end = end ? end->
next() :
nullptr;
9670 }
else if (var.find(end->
str()) != var.end())
9676 end = end->
tokAt(2);
9680 var.insert(tok->
str());
9688 if (
Token::Match(tok,
"@ builtin|eeprom|far|inline|interrupt|near|noprd|nostack|nosvf|packed|stack|svlreg|tiny|vector")) {
9698 bool goback =
false;
9704 Token *last =
nullptr;
9709 if (!
Token::Match(tok,
";|{|}|public:|protected:|private:"))
9712 bool isEnum =
false;
9713 if (tok->
str() ==
"}") {
9714 const Token *type = tok->
link()->previous();
9715 while (type && type->
isName()) {
9716 if (type->
str() ==
"enum") {
9725 !
Token::Match(tok->
next(),
"case|public|protected|private|class|struct") &&
9730 if (tok1 && tok1->
tokAt(2) &&
9732 !
Token::Match(tok1->
tokAt(2),
"public|protected|private| %type% ::|<|,|{|;"))) {
9739 last = tok1->
next();
9741 }
else if (isEnum &&
Token::Match(tok,
"} %name%| : %num% ;")) {
9742 if (tok->
next()->
str() ==
":") {
9749 tok->
next()->
str() !=
"default") {
9750 const int offset = (tok->
next()->
str() ==
"const") ? 1 : 0;
9757 if (last && last->
str() ==
",") {
9758 Token * tok1 = last;
9763 tok1 = tok1->
next();
9771 static bool isStdContainerOrIterator(
const Token* tok,
const Settings& settings)
9777 static bool isStdSmartPointer(
const Token* tok,
const Settings& settings)
9789 std::set<std::string> userFunctions;
9792 bool insert =
false;
9793 if (
Token::Match(tok,
"enum class|struct| %name%| :|{")) {
9802 userFunctions.insert(tok->
str());
9804 const Token *start = tok;
9808 userFunctions.insert(tok->
str());
9817 isStdContainerOrIterator(tok,
mSettings))
9844 if (tok->
strAt(1) !=
"(")
9847 if (
Token::Match(tok,
"CopyMemory|RtlCopyMemory|RtlCopyBytes")) {
9849 }
else if (
Token::Match(tok,
"MoveMemory|RtlMoveMemory")) {
9850 tok->
str(
"memmove");
9851 }
else if (
Token::Match(tok,
"FillMemory|RtlFillMemory|RtlFillBytes")) {
9864 }
else if (
Token::Match(tok,
"ZeroMemory|RtlZeroMemory|RtlZeroBytes|RtlSecureZeroMemory")) {
9875 tok1 = tok1->
next();
9892 triplet(
const char* m,
const char* u) : mbcs(m), unicode(u) {}
9893 std::string mbcs, unicode;
9896 const std::map<std::string, triplet> apis = {
9897 std::make_pair(
"_topen", triplet(
"open",
"_wopen")),
9898 std::make_pair(
"_tsopen_s", triplet(
"_sopen_s",
"_wsopen_s")),
9899 std::make_pair(
"_tfopen", triplet(
"fopen",
"_wfopen")),
9900 std::make_pair(
"_tfopen_s", triplet(
"fopen_s",
"_wfopen_s")),
9901 std::make_pair(
"_tfreopen", triplet(
"freopen",
"_wfreopen")),
9902 std::make_pair(
"_tfreopen_s", triplet(
"freopen_s",
"_wfreopen_s")),
9903 std::make_pair(
"_tcscat", triplet(
"strcat",
"wcscat")),
9904 std::make_pair(
"_tcschr", triplet(
"strchr",
"wcschr")),
9905 std::make_pair(
"_tcscmp", triplet(
"strcmp",
"wcscmp")),
9906 std::make_pair(
"_tcsdup", triplet(
"strdup",
"wcsdup")),
9907 std::make_pair(
"_tcscpy", triplet(
"strcpy",
"wcscpy")),
9908 std::make_pair(
"_tcslen", triplet(
"strlen",
"wcslen")),
9909 std::make_pair(
"_tcsncat", triplet(
"strncat",
"wcsncat")),
9910 std::make_pair(
"_tcsncpy", triplet(
"strncpy",
"wcsncpy")),
9911 std::make_pair(
"_tcsnlen", triplet(
"strnlen",
"wcsnlen")),
9912 std::make_pair(
"_tcsrchr", triplet(
"strrchr",
"wcsrchr")),
9913 std::make_pair(
"_tcsstr", triplet(
"strstr",
"wcsstr")),
9914 std::make_pair(
"_tcstok", triplet(
"strtok",
"wcstok")),
9915 std::make_pair(
"_ftprintf", triplet(
"fprintf",
"fwprintf")),
9916 std::make_pair(
"_tprintf", triplet(
"printf",
"wprintf")),
9917 std::make_pair(
"_stprintf", triplet(
"sprintf",
"swprintf")),
9918 std::make_pair(
"_sntprintf", triplet(
"_snprintf",
"_snwprintf")),
9919 std::make_pair(
"_ftscanf", triplet(
"fscanf",
"fwscanf")),
9920 std::make_pair(
"_tscanf", triplet(
"scanf",
"wscanf")),
9921 std::make_pair(
"_stscanf", triplet(
"sscanf",
"swscanf")),
9922 std::make_pair(
"_ftprintf_s", triplet(
"fprintf_s",
"fwprintf_s")),
9923 std::make_pair(
"_tprintf_s", triplet(
"printf_s",
"wprintf_s")),
9924 std::make_pair(
"_stprintf_s", triplet(
"sprintf_s",
"swprintf_s")),
9925 std::make_pair(
"_sntprintf_s", triplet(
"_snprintf_s",
"_snwprintf_s")),
9926 std::make_pair(
"_ftscanf_s", triplet(
"fscanf_s",
"fwscanf_s")),
9927 std::make_pair(
"_tscanf_s", triplet(
"scanf_s",
"wscanf_s")),
9928 std::make_pair(
"_stscanf_s", triplet(
"sscanf_s",
"swscanf_s"))
9940 if (tok->
strAt(1) !=
"(")
9943 const std::map<std::string, triplet>::const_iterator
match = apis.find(tok->
str());
9944 if (
match!=apis.end()) {
9945 tok->
str(ansi ?
match->second.mbcs :
match->second.unicode);
9947 }
else if (
Token::Match(tok,
"_T|_TEXT|TEXT ( %char%|%str% )")) {
9953 if (tok->
str()[0] !=
'L')
9954 tok->
str(
"L" + tok->
str());
9989 while (tok && tok->
str() !=
"{" && tok->
str() !=
";")
9993 if (tok->
str() ==
";")
9997 for (
Token *tok2 = tok->
next(); tok2 != end; tok2 = tok2->
next()) {
9998 if (tok2->
str() ==
"__property" &&
10003 if (tok2->
str() ==
"{") {
10028 if (tok && tok->
str() ==
")") {
10036 }
else if (tok->
str() ==
"noexcept") {
10038 if (tok && tok->
str() ==
"(") {
10039 tok = tok->
link()->next();
10041 }
else if (tok->
str() ==
"throw" && tok->
next() && tok->
next()->
str() ==
"(") {
10042 tok = tok->
next()->
link()->next();
10047 if (tok && tok->
str() ==
"(") {
10048 tok = tok->
link()->next();
10069 if (
Token::Match(tok,
"using|:: operator %op%|%name% ;")) {
10075 if (tok->
str() !=
"operator")
10086 while (!
done && par) {
10099 if (par->
str() ==
"," && !op.empty())
10108 par = par->
tokAt(2);
10115 while (par->
str() !=
")") {
10127 }
else if (
Token::Match(par,
"\"\" %name% )| (|;|<")) {
10129 op += par->
strAt(1);
10130 par = par->
tokAt(2);
10131 if (par->
str() ==
")") {
10132 par->
link()->deleteThis();
10135 tok = par->
tokAt(-3);
10138 }
else if (par->
str() ==
"::") {
10142 }
else if (par->
str() ==
";" || par->
str() ==
")") {
10144 }
else if (par->
str() !=
"(") {
10150 if (par && !op.empty()) {
10156 tok->
str(
"operator" + op);
10161 if (!op.empty() && !returnsRef)
10167 const std::string name = tok->
strAt(2);
10186 "simplifyOperatorName: found unsimplified operator name");
10196 std::set<std::string> classNames;
10197 std::set<nonneg int> classVars;
10212 for (
const Token *tok2 = tok->
next(); tok2; tok2 = tok2->
next()) {
10213 if (tok2->
str() ==
"}")
10217 if (tok2->
str() ==
"{") {
10221 tok2 = tok2->
link();
10223 classNames.insert(tok->
strAt(1));
10230 if (
Token::Match(tok,
"%type% &| %var%") && classNames.find(tok->
str()) != classNames.end()) {
10234 classVars.insert(tok->
varId());
10238 if (
Token::Match(tok,
"%var% (") && classVars.find(tok->
varId()) != classVars.end()) {
10244 start = start->
linkAt(-1);
10248 start = start->
tokAt(-2);
10254 after = after->
linkAt(3);
10273 std::vector<Space> classInfo;
10275 if (
Token::Match(tok,
"class|struct|namespace %type% :|{") &&
10278 info.isNamespace = tok->
str() ==
"namespace";
10280 info.className = tok->
str();
10282 while (tok && tok->
str() !=
"{")
10286 info.bodyEnd = tok->
link();
10287 classInfo.push_back(std::move(info));
10288 }
else if (!classInfo.empty()) {
10289 if (tok == classInfo.back().bodyEnd)
10290 classInfo.pop_back();
10291 else if (tok->
str() == classInfo.back().className &&
10292 !classInfo.back().isNamespace && tok->
previous()->
str() !=
":" &&
10296 if (tok->
strAt(2) ==
"operator") {
10298 if (tok1->
str() ==
"(")
10299 tok1 = tok1->
next();
10301 while (tok1 && tok1->
str() !=
"(") {
10302 if (tok1->
str() ==
";")
10304 tok1 = tok1->
next();
10306 if (!tok1 || tok1->
str() !=
"(")
10308 }
else if (tok->
strAt(2) ==
"~")
10309 tok1 = tok1->
next();
10315 const bool isConstructorOrDestructor =
10317 if (!isConstructorOrDestructor) {
10319 if (!isPrependedByType) {
10323 if (!isPrependedByType) {
10325 isPrependedByType =
Token::Match(tok3,
"%type% * *|&");
10327 if (!isPrependedByType) {
10343 std::vector<std::pair<std::string, const Token *>> unknowns;
10345 for (
int i = 1; i <=
mVarId; ++i) {
10354 const Token * nameTok;
10359 name = nameTok->
str();
10374 name += tok->
str();
10380 else if (tok->
str() ==
"<")
10382 else if (tok->
str() ==
">")
10392 unknowns.emplace_back(std::move(name), nameTok);
10395 if (!unknowns.empty()) {
10399 for (
auto it = unknowns.cbegin(); it != unknowns.cend(); ++it) {
10401 if (it->first.find(
"std::") != 0) {
10402 if (it->first != last) {
10422 if (tok->
str() ==
"?") {
10423 bool parenthesesNeeded =
false;
10426 for (; tok2; tok2 = tok2->
next()) {
10428 tok2 = tok2->
link();
10429 else if (tok2->
str() ==
":") {
10433 }
else if (tok2->
str() ==
";" || (tok2->
link() && tok2->
str() !=
"{" && tok2->
str() !=
"}"))
10435 else if (tok2->
str() ==
",")
10436 parenthesesNeeded =
true;
10437 else if (tok2->
str() ==
"<")
10438 parenthesesNeeded =
true;
10439 else if (tok2->
str() ==
"?") {
10441 parenthesesNeeded =
true;
10444 if (parenthesesNeeded && tok2 && tok2->
str() ==
":") {
10455 const std::list<const Token*> callstack(1, tok);
10459 void Tokenizer::reportError(
const std::list<const Token*>& callstack,
Severity severity,
const std::string&
id,
const std::string& msg,
bool inconclusive)
const
10475 while (prev && prev->
isName())
10486 const Token *tokLastEnd =
nullptr;
10487 for (
const Token *tok = tokSQLStart->
tokAt(2); tok !=
nullptr; tok = tok->
next()) {
10488 if (tokLastEnd ==
nullptr && tok->
str() ==
";")
10490 else if (tok->
str() ==
"__CPPCHECK_EMBEDDED_SQL_EXEC__") {
10492 return tok->
next();
10494 }
else if (
Token::Match(tok,
"{|}|==|&&|!|^|<<|>>|++|+=|-=|/=|*=|>>=|<<=|~"))
10512 tok2 = tok2->
tokAt(2);
10514 if (!tok2 || tok2->
str() !=
"{")
10517 std::stack<Token *> links;
10518 tok2 = tok->
tokAt(2);
10520 while (tok2->
str() ==
"::") {
10524 tok2 = tok2->
tokAt(3);
10529 if (!links.empty() && tok2->
str() ==
"{") {
10530 tok2 = tok2->
link();
10531 while (!links.empty()) {
10533 tok2 = tok2->
next();
10550 while (end && end->
str() !=
";") {
10565 static bool sameTokens(
const Token *first,
const Token *last,
const Token *other)
10567 while (other && first->
str() == other->
str()) {
10570 first = first->
next();
10571 other = other->
next();
10577 static bool alreadyHasNamespace(
const Token *first,
const Token *last,
const Token *end)
10579 while (end && last->
str() == end->
str()) {
10611 if (tok->
str() ==
"{")
10613 else if (tok->
str() ==
"}")
10620 const std::string name(tok->
next()->
str());
10622 Token * tokNameEnd = tokNameStart;
10624 while (tokNameEnd && tokNameEnd->
next() && tokNameEnd->
next()->
str() !=
";") {
10625 if (tokNameEnd->
str() ==
"(") {
10631 tokNameEnd = tokNameEnd->
next();
10637 int endScope = scope;
10642 Token * tok2 = tokNext;
10644 while (tok2 && endScope >= scope) {
10649 else if (tok2->
str() == name) {
10652 if (sameTokens(tokNameStart, tokNameEnd, tok2->
tokAt(2))) {
10654 tok2 = deleteAlias(tok2->
previous());
10659 if (endScope == scope) {
10661 tok2 = deleteAlias(tok2->
previous());
10667 tok2 = deleteAlias(tok2->
previous());
10672 if (tok2->
strAt(1) ==
"::" && !alreadyHasNamespace(tokNameStart, tokNameEnd, tok2)) {
10675 tok2->
str(tokNameStart->
str());
10676 Token * tok3 = tokNameStart;
10677 while (tok3 != tokNameEnd) {
10679 tok2 = tok2->
next();
10680 tok3 = tok3->
next();
10684 tok2 = tok2->
next();
10693 }
else if (tokNext) {
10712 return std::any_of(directives.cbegin(), directives.cend(), [&](
const Directive& d) {
10713 return startsWith(d.str,
"#if") &&
10714 d.linenr >= start->linenr() &&
10715 d.linenr <= end->linenr() &&
10716 start->fileIndex() < list.getFiles().size() &&
10717 d.file == list.getFiles()[start->fileIndex()];
10725 return std::any_of(directives.cbegin(), directives.cend(), [&](
const Directive& d) {
10726 return d.linenr < bodyStart->linenr() && d.str ==
"#pragma pack(1)" && d.file == list.getFiles().front();
static bool match(const Token *tok, const std::string &rhs)
This is an interface, which the class responsible of error logging should implement.
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
static std::string toxml(const std::string &str)
Convert XML-sensitive characters into XML entities.
virtual void reportProgress(const std::string &filename, const char stage[], const std::size_t value)
Report progress to client.
File name and line number.
Wrapper for error messages, provided by reportErr()
const Container * detectContainerOrIterator(const Token *typeStart, bool *isIterator=nullptr, bool withoutStd=false) const
const SmartPointer * detectSmartPointer(const Token *tok, bool withoutStd=false) const
bool hasAnyTypeCheck(const std::string &typeName) const
bool isnoreturn(const Token *ftok) const
bool isScopeNoReturn(const Token *end, std::string *unknownFunc) const
const PodType * podtype(const std::string &name) const
bool markupFile(const std::string &path) const
bool isNotLibraryFunction(const Token *ftok) const
bool matchArguments(const Token *ftok, const std::string &functionName) const
bool isFunctionConst(const std::string &functionName, bool pure) const
static std::string toString(T value)=delete
static biguint toBigUNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
static bool isOctalDigit(char c)
Return true if given character is 0,1,2,3,4,5,6 or 7.
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
static bool isFloat(const std::string &str)
static bool isInt(const std::string &str)
static double toDoubleNumber(const std::string &str)
for conversion of numeric literals
unsigned long long biguint
static bool isPositive(const std::string &str)
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...
bool checkLibrary
Check for incomplete info in library files?
bool checkHeaders
Check code in the headers, this is on by default but can be turned off to save CPU.
std::vector< std::string > basePaths
Paths used as base for conversion to relative paths.
bool xml
write XML results (–xml)
bool checkConfiguration
Is the 'configuration checking' wanted?
static bool terminated()
termination requested?
std::size_t typedefMaxTime
The maximum time in seconds for the typedef simplification.
std::string buildDir
–cppcheck-build-dir.
std::set< std::string > summaryReturn
bool debugnormal
Is –debug-normal given?
bool daca
Are we running from DACA script?
bool verbose
Is –verbose given?
SHOWTIME_MODES showtime
show timing information (–showtime=file|summary|top5)
SimpleEnableGroup< Severity > severity
std::size_t templateMaxTime
The maximum time in seconds for the template instantiation.
bool debugSimplified
Is –debug-simplified given?
bool checkUnusedTemplates
Check unused/uninstantiated templates.
bool debugwarnings
Is –debug-warnings given?
Standards standards
Struct contains standards settings.
bool isEnabled(T flag) const
const Variable * getVariableFromVarId(nonneg int varId) const
const std::vector< const Variable * > & variableList() const
void setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens=nullptr)
Set valuetype in provided tokenlist.
void printXml(std::ostream &out) const
void setArrayDimensionsUsingValueFlow()
Set array dimensions when valueflow analysis is completed.
void printOut(const char *title=nullptr) const
Simplify templates from the preprocessed and partially simplified code.
void simplifyTemplates(const std::time_t maxtime)
Simplify templates.
static Token * findTemplateDeclarationEnd(Token *tok)
Find last token of a template declaration.
void checkComplicatedSyntaxErrorsInTemplates()
static unsigned int templateParameters(const Token *tok)
is the token pointing at a template parameters block < int , 3 > => yes
static bool simplifyNumericCalculations(Token *tok, bool isTemplate=true)
Simplify constant calculations such as "1+2" => "3".
const std::string & dump() const
static Token * copyTokens(Token *dest, const Token *first, const Token *last, bool one_line=true)
Copy tokens.
void createAst() const
Create abstract syntax tree.
const Token * back() const
get last token of list
void simplifyPlatformTypes()
Convert platform dependent types to standard types.
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.
const std::vector< std::string > & getFiles() const
Get filenames (the sourcefile + the files it include).
const Token * front() const
get first token of list
void validateAst(bool print) const
Check abstract syntax tree.
The token list that the TokenList generates is a linked-list of this class.
bool isRemovedVoidParameter() const
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
bool isSimplifiedScope() const
void deleteThis()
Remove the contents for this token from the token list.
nonneg int exprId() const
void setMacroName(std::string name)
const std::string & originalName() const
void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value)
void printOut(const char *title=nullptr) const
For debugging purposes, prints token and all tokens followed by it.
bool isAttributeUsed() const
bool addValue(const ValueFlow::Value &value)
Add token value.
bool hasKnownIntValue() const
static void replace(Token *replaceThis, Token *start, Token *end)
Replace token replaceThis with tokens between start and end, including start and end.
MathLib::bigint getKnownIntValue() const
bool isSimplifiedTypedef() const
bool isExpandedMacro() const
void concatStr(std::string const &b)
Concatenate two (quoted) strings.
bool isTemplateArg() const
Is current token a template argument?
void setTokenDebug(TokenDebug td)
bool isArithmeticalOp() const
std::string stringifyList(const stringifyOptions &options, const std::vector< std::string > *fileNames=nullptr, const Token *end=nullptr) const
bool isUpperCaseName() const
static void createMutualLinks(Token *begin, Token *end)
Links two elements against each other.
bool isAttributeDestructor() const
nonneg int progressValue() const
Get progressValue (0 - 100)
bool isControlFlowKeyword() const
void setBits(const unsigned char b)
static nonneg int getStrLength(const Token *tok)
bool isImplicitInt() const
const ValueType * valueType() const
const std::string & strAt(int index) const
bool isAttributeUnused() const
static void assignProgressValues(Token *tok)
Calculate progress values for all tokens.
void astOperand1(Token *tok)
void function(const Function *f)
Associate this token with given function.
static void move(Token *srcStart, Token *srcEnd, Token *newLocation)
Move srcStart and srcEnd tokens and all tokens between them into new a location.
const Token * findClosingBracket() const
Returns the closing bracket of opening '<'.
bool isSplittedVarDeclComma() const
bool isAttributeNodiscard() const
bool isAttributeExport() const
bool isOperatorKeyword() const
void printValueFlow(bool xml, std::ostream &out) const
bool isAttributeConstructor() const
void setRemovedVoidParameter(bool b)
static nonneg int getStrArraySize(const Token *tok)
void scopeInfo(std::shared_ptr< ScopeInfo2 > newScopeInfo)
static const Token * findsimplematch(const Token *const startTok, const char(&pattern)[count])
const Token * tokAt(int index) const
Token * insertTokenBefore(const std::string &tokenStr, const std::string &originalNameStr=emptyString, const std::string ¯oNameStr=emptyString)
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 scope(const Scope *s)
Associate this token with given scope.
void link(Token *linkToToken)
Create link to given token.
const Token * linkAt(int index) const
void printAst(bool verbose, bool xml, const std::vector< std::string > &fileNames, std::ostream &out) const
void type(const ::Type *t)
Associate this token with given type.
bool isAssignmentOp() const
bool isSplittedVarDeclEq() const
static void eraseTokens(Token *begin, const Token *end)
Delete tokens between begin and end.
nonneg int linenr() const
bool isStandardType() const
const Token * nextArgumentBeforeCreateLinks2() const
void variable(const Variable *v)
Associate this token with given variable.
bool isAttributeMaybeUnused() const
bool isComparisonOp() const
const std::list< ValueFlow::Value > & values() const
bool isAttributeNoreturn() const
bool isAttributeConst() const
const Token * nextArgument() const
void swapWithNext()
Swap the contents of this token with the next token.
const Token * findOpeningBracket() 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
bool isAttributePacked() const
bool isAttributeNothrow() const
std::string getMacroName() const
void deletePrevious(nonneg int count=1)
Unlink and delete the previous 'count' tokens.
nonneg int column() const
bool isAttributePure() const
void astParent(Token *tok)
The main purpose is to tokenize the source code.
bool isScopeNoReturn(const Token *endScopeToken, bool *unknown=nullptr) const
Check if inner scope ends with a call to a noreturn function.
nonneg int sizeOfType(const Token *type) const
Calculates sizeof value for given type.
void simplifyLabelsCaseDefault()
Simplify labels and 'case|default' syntaxes.
void simplifyRoundCurlyParentheses()
void simplifyOverloadedOperators()
simplify overloaded operators: 'obj(123)' => 'obj .
void simplifyMicrosoftStringFunctions()
Convert Microsoft string functions _tcscpy -> strcpy.
std::string mConfiguration
E.g.
void simplifyIfSwitchForInit()
Simplify C++17/C++20 if/switch/for initialization expression.
void simplifyBitfields()
Simplify bitfields - the field width is removed as we don't use it.
NORETURN void unknownMacroError(const Token *tok1) const
Warn about unknown macro(s), configuration is recommended.
void splitTemplateRightAngleBrackets(bool check)
Split up template right angle brackets.
Token * deleteInvalidTypedef(Token *typeDef)
void printDebugOutput(int simplification) const
print –debug output if debug flags match the simplification: 0=unknown/both simplifications 1=1st sim...
void elseif()
Simplify "if else".
void simplifyRedundantConsecutiveBraces()
void removeMacrosInGlobalScope()
Remove macros in global scope.
void simplifyHeadersAndUnusedTemplates()
If –check-headers=no has been given; then remove unneeded code in headers.
void simplifyTemplates()
Simplify templates.
void simplifyUsingError(const Token *usingStart, const Token *usingEnd)
bool isPacked(const Token *bodyStart) const
const Token * tokens() const
void simplifyAttribute()
Remove __attribute__ ((?))
static const Token * findSQLBlockEnd(const Token *tokSQLStart)
Find end of SQL (or PL/SQL) block.
void simplifyNamespaceAliases()
Convert namespace aliases.
void simplifyInitVar()
Simplify variable initialization '; int *p(0);' => '; int *p = 0;'.
static bool isGarbageExpr(const Token *start, const Token *end, bool allowSemicolon)
Detect garbage expression.
void removeUnnecessaryQualification()
Remove unnecessary member qualification.
void simplifyVarDecl(const bool only_k_r_fpar)
Simplify variable declarations (split up)
static bool isOneNumber(const std::string &s)
Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not?
void simplifyTypedef()
typedef A mytype; mytype c;
void createSymbolDatabase()
void prepareTernaryOpForAST()
Prepare ternary operators with parentheses so that the AST can be created.
bool simplifyTokens1(const std::string &configuration)
static std::string simplifyString(const std::string &source)
Modify strings in the token list by replacing hex and oct values.
bool simplifyTokenList1(const char FileName[])
Basic simplification of tokenlist.
void simplifyFunctionTryCatch()
Simplify function level try blocks: Convert "void f() try {} catch (int) {}" to "void f() { try {} ca...
void simplifyDoublePlusAndDoubleMinus()
void removeExtraTemplateKeywords()
Remove extra "template" keywords that are not used by Cppcheck.
void simplifyTypedefLHS()
Move typedef token to the left og the expression.
std::list< Directive > mDirectives
void simplifyCaseRange()
simplify case ranges (gcc extension)
ErrorLogger & mErrorLogger
errorlogger
bool simplifyRedundantParentheses()
Remove redundant parentheses:
void simplifyTypedefCpp()
void addSemicolonAfterUnknownMacro()
void simplifyCppcheckAttribute()
Remove __cppcheck__ ((?))
Token * getAttributeFuncTok(Token *tok, bool gccattr) const
Get function token for a attribute.
Tokenizer(const Settings &settings, ErrorLogger &errorLogger)
void simplifyEmptyNamespaces()
Simplify useless C++ empty namespaces, like: 'namespace name% { }'.
void findGarbageCode() const
Detect garbage code and call syntaxError() if found.
Token * simplifyAddBracesPair(Token *tok, bool commandWithCondition)
Add pair of braces to an single if-block, else-block, for-block, etc.
void simplifyMicrosoftMemoryFunctions()
Convert Microsoft memory functions CopyMemory(dst, src, len) -> memcpy(dst, src, len) FillMemory(dst,...
void setVarId()
Set variable id.
void setDirectives(std::list< Directive > directives)
void simplifyAssignmentBlock()
Simplify assignment where rhs is a block : "x=({123;});" => "{x=123;}".
void findComplicatedSyntaxErrorsInTemplates()
std::map< std::string, int > mTypeSize
sizeof information for known types
friend class SymbolDatabase
TokenList list
Token list: stores all tokens.
void simplifyNamespaceStd()
Add std:: in front of std classes, when using namespace std; was given.
static Token * initVar(Token *tok)
Token * simplifyAddBracesToCommand(Token *tok)
Add braces to an if-block, for-block, etc.
nonneg int mVarId
variable count
static bool isMemberFunction(const Token *openParen)
void simplifyKeyword()
Remove keywords "volatile", "inline", "register", and "restrict".
void macroWithSemicolonError(const Token *tok, const std::string ¯oName) const
nonneg int mUnnamedCount
unnamed count "Unnamed0", "Unnamed1", "Unnamed2", ...
bool isC() const
Is the code C.
void simplifyUsingToTypedef()
bool simplifyAddBraces()
Add braces to an if-block, for-block, etc.
void unhandled_macro_class_x_y(const Token *tok) const
Report that there is an unhandled "class x y {" code.
void reportUnknownMacros() const
Detect unknown macros and throw unknownMacro.
void arraySize()
Insert array size where it isn't given.
void createLinks2()
Setup links between < and >.
static void setVarIdClassFunction(const std::string &classname, Token *const startToken, const Token *const endToken, const std::map< std::string, nonneg int > &varlist, std::map< nonneg int, std::map< std::string, nonneg int >> &structMembers, nonneg int &varId_)
const Settings & mSettings
settings
void simplifyParameterVoid()
void sizeofAddParentheses()
Add parentheses for sizeof: sizeof x => sizeof(x)
void dump(std::ostream &out) const
void validateC() const
Is there C++ code in C file?
static bool operatorEnd(const Token *tok)
void simplifyStaticConst()
Simplify the location of "static" and "const" qualifiers in a variable declaration or definition.
void simplifyDeclspec()
Remove __declspec()
void createLinks()
Setup links for tokens so that one can call Token::link().
NORETURN void cppcheckError(const Token *tok) const
Send error message to error logger about internal bug.
void markCppCasts()
Set isCast() for C++ casts.
NORETURN void unmatchedToken(const Token *tok) const
Syntax error.
void simplifyPointerToStandardType()
Simplify pointer to standard type (C only)
void simplifySpaceshipOperator()
Simplify c++20 spaceship operator.
void combineStringAndCharLiterals()
void printUnknownTypes() const
Output list of unknown types.
void simplifyBorland()
Remove Borland code.
TemplateSimplifier *const mTemplateSimplifier
void removeRedundantSemicolons()
Reduces "; ;" to ";", except in "( ; ; )".
void simplifyCallingConvention()
Remove calling convention.
void arraySizeAfterValueFlow()
void simplifyFunctionPointers()
Simplify function pointers.
void setPodTypes()
Set pod types.
void unsupportedTypedef(const Token *tok) const
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg, bool inconclusive=false) const
report error message
void simplifyAsm()
Remove __asm.
const Token * processFunc(const Token *tok2, bool inOperator) const
static const Token * isFunctionHead(const Token *tok, const std::string &endsWith)
is token pointing at function head?
bool simplifyCAlternativeTokens()
Simplify the 'C Alternative Tokens' Examples: "if(s and t)" => "if(s && t)" "while((r bitand s) and n...
void simplifyAt()
Simplify @… (compiler extension)
void concatenateNegativeNumberAndAnyPositive()
void validate() const
assert that tokens are ok - used during debugging for example to catch problems in simplifyTokenList1...
bool isCPP() const
Is the code CPP.
bool hasIfdef(const Token *start, const Token *end) const
NORETURN void syntaxErrorC(const Token *tok, const std::string &what) const
Syntax error.
void simplifyStructDecl()
Struct simplification "struct S { } s;" => "struct S { }; S s;".
SymbolDatabase * mSymbolDatabase
Symbol database that all checks etc can use.
bool duplicateTypedef(Token *&tokPtr, const Token *name, const Token *typeDef) const
void simplifyTypeIntrinsics()
static const Token * startOfExecutableScope(const Token *tok)
Helper function to check for start of function execution scope.
void simplifyAsm2()
asm heuristics, Put ^{} statements in asm()
void simplifyOperatorName()
Collapse operator name tokens into single token operator = => operator=.
std::vector< TypedefInfo > mTypedefInfo
void removeMacroInClassDef()
Remove undefined macro in class definition: class DLLEXPORT Fred { }; class Fred FINAL : Base { };.
void simplifyCoroutines()
Simplify coroutines - just put parentheses around arguments for co_* keywords so they can be handled ...
NORETURN void syntaxError(const Token *tok, const std::string &code=emptyString) const
Syntax error.
void checkForEnumsWithTypedef()
TimerResults * mTimerResults
TimerResults.
void simplifyNestedNamespace()
Convert C++17 style nested namespace to older style.
void simplifyArrayAccessSyntax()
void unhandledCharLiteral(const Token *tok, const std::string &msg) const
void simplifyCPPAttribute()
Remove [[attribute]] (C++11, C23) from TokenList.
void simplifyVariableMultipleAssign()
Simplify multiple assignments.
void checkConfiguration() const
Check configuration (unknown macros etc)
void simplifyFunctionParameters()
Simplify functions like "void f(x) int x; {" into "void f(int x) {".
Information about a class type.
const Library::Container * container
If the type is a container defined in a cfg file, this is the used.
Information about a member variable.
const Type * type() const
Get Type pointer of known type.
const Token * typeEndToken() const
Get type end token.
const Token * typeStartToken() const
Get type start token.
static const std::string emptyString
static void replace(std::string &source, const std::unordered_map< std::string, std::string > &substitutionMap)
Severity
enum class for severity.
Token * findLambdaEndScope(Token *tok)
@ portability
Portability warning.
@ information
Checking information.
CPPCHECKLIB std::string create(const Tokenizer &tokenizer, const std::string &cfg)
void setValues(TokenList &tokenlist, SymbolDatabase &symboldatabase, ErrorLogger &errorLogger, const Settings &settings, TimerResultsIntf *timerResults)
Perform valueflow analysis.
Array dimension information.
MathLib::bigint num
(assumed) dimension length when size is a number, 0 if not known
A preprocessor directive Each preprocessor directive (#include, #define, #undef, #if,...
Simple container to be thrown when internal error is detected.
enum Standards::cppstd_t cpp
static void indent(std::string &str, const nonneg int indent1, const nonneg int indent2)
static std::string getExpression(const Token *tok)
static Token * splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount)
static void setVarIdStructMembers(Token *&tok1, std::map< nonneg int, std::map< std::string, nonneg int >> &structMembers, nonneg int &varId)
static Token * skipTernaryOp(Token *tok)
static Token * matchMemberFunctionName(const Member &func, const std::list< ScopeInfo2 > &scopeInfo)
static const std::unordered_set< std::string > notstart_cpp
static bool isCPPAttribute(const Token *tok)
static const std::unordered_map< std::string, std::string > cAlternativeTokens
static bool isClassStructUnionEnumStart(const Token *tok)
is tok the start brace { of a class, struct, union, or enum
static bool setVarIdParseDeclaration(Token *&tok, const VariableMap &variableMap, bool executableScope)
static unsigned int tokDistance(const Token *tok1, const Token *tok2)
static Token * matchMemberName(const std::list< std::string > &scope, const Token *nsToken, Token *memberToken, const std::list< ScopeInfo2 > &scopeInfo)
static T * skipCPPOrAlignAttribute(T *tok)
static const Token * findUnmatchedTernaryOp(const Token *const begin, const Token *const end, int depth=0)
static Token * matchMemberVarName(const Member &var, const std::list< ScopeInfo2 > &scopeInfo)
static T * skipInitializerList(T *tok)
static bool isEnumStart(const Token *tok)
Return whether tok is the "{" that starts an enumerator list.
static const std::unordered_set< std::string > notstart_c
static bool isEnumScope(const Token *tok)
static std::string getScopeName(const std::list< ScopeInfo2 > &scopeInfo)
static bool isNonMacro(const Token *tok)
static bool scopesMatch(const std::string &scope1, const std::string &scope2, const ScopeInfo3 *globalScope)
static void linkBrackets(const Tokenizer &tokenizer, std::stack< const Token * > &type, std::stack< Token * > &links, Token *const token, const char open, const char close)
static bool setVarIdClassDeclaration(Token *const startToken, VariableMap &variableMap, const nonneg int scopeStartVarId, std::map< nonneg int, std::map< std::string, nonneg int >> &structMembers)
static bool isAlignAttribute(const Token *tok)
static Token * skipCaseLabel(Token *tok)
static void skipEnumBody(T *&tok)
static bool isNumberOneOf(const std::string &s, MathLib::bigint intConstant, const char *floatConstant)
Helper function to check whether number is equal to integer constant X or floating point pattern X....
static bool isStringLiteral(const std::string &str)
static std::string id_string(const void *p)
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
bool endsWith(const std::string &str, char c)
static const char * bool_to_string(bool b)