55 #include <unordered_map>
56 #include <unordered_set>
60 #include <simplecpp.h>
67 struct VarIdScopeInfo {
68 VarIdScopeInfo() =
default;
69 VarIdScopeInfo(
bool isExecutable,
bool isStructInit,
bool isEnum,
nonneg int startVarid)
70 : isExecutable(isExecutable), isStructInit(isStructInit), isEnum(isEnum), startVarid(startVarid) {}
72 const bool isExecutable{};
73 const bool isStructInit{};
75 const nonneg int startVarid{};
82 if (!tok || tok->
str() !=
"{")
92 defStart = defStart->next();
93 if (defStart && defStart->str() ==
"{")
94 tok = defStart->link()->next();
101 if (tok->
str() ==
"(")
103 if (tok->
str() !=
")")
109 while (tok && tok->
str() ==
"[" && tok->
link()) {
110 if (
endsWith.find(tok->
str()) != std::string::npos)
112 tok = tok->
link()->next();
114 return (tok &&
endsWith.find(tok->
str()) != std::string::npos) ? tok :
nullptr;
116 if (tok->
isCpp() && tok->
str() ==
")") {
118 while (
Token::Match(tok,
"const|noexcept|override|final|volatile|mutable|&|&& !!(") ||
121 if (tok && tok->
str() ==
")")
123 while (tok && tok->
str() ==
"[")
124 tok = tok->
link()->next();
141 return (tok &&
endsWith.find(tok->
str()) != std::string::npos) ? tok :
nullptr;
154 while (tok2 && !
Token::Match(tok2,
"class|struct|union|enum|{|}|;"))
164 mErrorLogger(errorLogger),
181 const std::map<std::string, int>::const_iterator it =
mTypeSize.find(type);
187 return podtype->
size;
194 if (!type || type->
str().empty())
200 const std::map<std::string, int>::const_iterator it =
mTypeSize.find(type->
str());
206 return podtype->
size;
209 if (type->
str() ==
"double")
211 if (type->
str() ==
"long")
223 Token * tok = tokPtr;
227 if (end->
str() ==
"[") {
230 end = end->
link()->next();
231 }
else if (end->
str() ==
",") {
241 end = (end)?end->
next():
nullptr;
245 }
else if (end->
str() ==
"(") {
261 tokPtr = end->
link();
275 }
else if (end->
str() ==
">") {
280 while (end && end->
str() !=
"{")
283 tokPtr = end->
link();
293 (!
Token::Match(tok->
previous(),
"return|new|const|friend|public|private|protected|throw|extern") &&
304 if (tok->
strAt(-2) ==
"typedef" &&
306 typeDef->
strAt(3) !=
"{") {
320 return tok->
next()->
str() !=
";";
322 return tok->
next()->
str() !=
";";
343 std::ostringstream str;
344 const Token *tok1 = tok;
347 if (level == 0 && tok->
str() ==
";")
349 if (tok->
str() ==
"{")
351 else if (tok->
str() ==
"}") {
366 "Failed to parse \'" + str.str() +
"\'. The checking continues anyway.");
371 Token *tok =
nullptr;
374 while (typeDef->
next()) {
375 if (typeDef->
next()->
str() ==
";") {
379 if (typeDef->
next()->
str() ==
"{")
381 else if (typeDef->
next()->
str() ==
"}")
399 std::string className;
400 const Token* bodyEnd{};
401 const Token* bodyEnd2{};
403 std::set<std::string> recordTypes;
410 std::set<std::string> qualifiers;
413 qualifiers.insert(tok->
next()->
str());
429 if (tok1->
str() ==
":") {
431 while (tok1 && tok1->
str() !=
"{")
446 name =
"Unnamed" + std::to_string((*unnamedCount)++);
463 for (
const std::string &qualifier : qualifiers) {
491 tok2 = tok2->
tokAt(5);
501 if (tok2->
next()->
str() ==
"(")
512 tok2 = tok2->
tokAt(2);
517 if (tok2->
str() ==
"(" &&
518 tok2->
link()->next() &&
519 tok2->
link()->next()->str() ==
"(") {
522 if (tok2->
next()->
str() ==
"(")
532 if (tok2->
next()->
str() ==
"(")
553 if ((
Token::Match(tok,
"[;{}] using %name% :: %name% ::|;") && !tok->tokAt(2)->isKeyword()) ||
554 (
Token::Match(tok,
"[;{}] using :: %name% :: %name% ::|;") && !tok->tokAt(3)->isKeyword())) {
557 endtok = endtok->
next();
559 endtok = endtok->
tokAt(2);
560 if (endtok && endtok->
str() ==
";") {
575 if (tok->str() ==
"typedef") {
576 bool doSimplify = !
Token::Match(tok->previous(),
";|{|}|:|public:|private:|protected:");
579 bool haveStart =
false;
600 start = start->
next();
611 class TypedefSimplifier {
613 Token* mTypedefToken;
614 Token* mEndToken{
nullptr};
615 std::pair<Token*, Token*> mRangeType;
616 std::pair<Token*, Token*> mRangeTypeQualifiers;
617 std::pair<Token*, Token*> mRangeAfterVar;
618 Token* mNameToken{
nullptr};
620 bool mReplaceFailed =
false;
624 explicit TypedefSimplifier(
Token* typedefToken) : mTypedefToken(typedefToken) {
627 start = start->
next();
630 if (
Token::Match(start,
"const| enum|struct|union|class %name%| {")) {
634 Token* nameToken = rangeBefore.second->
link()->next();
636 nameToken = nameToken->
next();
637 const std::pair<Token*, Token*> rangeQualifiers(rangeBefore.second->link()->next(), nameToken);
640 if (
Token::Match(rangeBefore.second->previous(),
"enum|struct|union|class {"))
641 rangeBefore.second->previous()->insertToken(nameToken->
str());
642 mRangeType = rangeBefore;
643 mRangeTypeQualifiers = rangeQualifiers;
649 mNameToken = nameToken;
650 mEndToken = nameToken->
next();
655 for (
Token* type = start;
Token::Match(type,
"%name%|*|&|&&"); type = type->next()) {
656 if (type != start &&
Token::Match(type,
"%name% ;") && !type->isStandardType()) {
657 mRangeType.first = start;
658 mRangeType.second = type;
660 mEndToken = mNameToken->
next();
669 mRangeType.first = start;
670 mRangeType.second = type;
672 mEndToken = end->
next();
673 mRangeAfterVar.first = mNameToken->
next();
674 mRangeAfterVar.second = mEndToken;
680 mRangeType.first = start;
681 mRangeType.second = mNameToken;
682 mRangeAfterVar.first = mNameToken->
next();
683 mRangeAfterVar.second = mEndToken;
689 mRangeType.first = start;
690 mRangeType.second = type;
691 mRangeAfterVar.first = mNameToken->
next();
692 mRangeAfterVar.second = mEndToken;
698 printTypedef(typedefToken);
702 const Token* getTypedefToken()
const {
703 return mTypedefToken;
706 bool isUsed()
const {
710 bool isInvalidConstFunctionType(
const std::map<std::string, TypedefSimplifier>& m)
const {
711 if (!
Token::Match(mTypedefToken,
"typedef const %name% %name% ;"))
713 const auto it = m.find(mTypedefToken->
strAt(2));
723 bool replaceFailed()
const {
724 return mReplaceFailed;
727 bool isStructEtc()
const {
728 return mRangeType.second && mRangeType.second->str() ==
"{";
731 std::string name()
const {
732 return mNameToken ? mNameToken->str() :
"";
736 if (tok == mNameToken)
743 bool pointerType =
false;
744 for (
const Token* type = mRangeType.first; type != mRangeType.second; type = type->
next()) {
745 if (type->str() ==
"*" || type->str() ==
"&") {
750 for (
const Token* type = mRangeTypeQualifiers.first; type != mRangeTypeQualifiers.second; type = type->
next()) {
751 if (type->str() ==
"*" || type->str() ==
"&") {
759 Token* tok2 = insertTokens(tok, mRangeType);
760 insertTokens(tok2, mRangeTypeQualifiers);
766 const bool isFunctionPointer =
Token::Match(mNameToken,
"%name% )");
767 if (isFunctionPointer && isCast(tok->
previous())) {
769 insertTokens(tok, std::pair<Token*, Token*>(mRangeType.first, mNameToken->linkAt(1)));
777 tok->
str(mRangeType.second->previous()->str());
782 if (
Token::Match(mRangeType.first,
"const| struct|class %name% %name% ;")) {
784 tok->
str(mRangeType.second->previous()->str());
786 mReplaceFailed =
true;
793 bool pointerType =
false;
794 for (
const Token* type = mRangeType.first; type != mRangeType.second; type = type->
next()) {
795 if (type->str() ==
"*") {
812 for (
const Token* type = mRangeType.first; type != mRangeType.second; type = type->
next()) {
813 if (type->str() == kw) {
821 mReplaceFailed =
true;
827 auto rangeType = mRangeType;
829 while (
Token::Match(rangeType.first,
"const|class|struct|union"))
830 rangeType.first = rangeType.first->next();
833 Token*
const tok2 = insertTokens(tok, rangeType);
834 Token*
const tok3 = insertTokens(tok2, mRangeTypeQualifiers);
840 after = after->
next();
843 after = after->
link()->next();
851 bool useAfterVarRange =
true;
854 useAfterVarRange =
false;
862 if (prev->
isName() && prev != tok3)
873 if (isFunctionPointer) {
875 after = after->
link()->linkAt(1)->next();
876 else if (after->
str() ==
"(") {
877 useAfterVarRange =
false;
881 else if (after->
str() ==
"[") {
882 while (after && after->
str() ==
"[")
883 after = after->
link()->next();
888 after = after->
link()->next();
892 throw InternalError(tok,
"Failed to simplify typedef. Is the code valid?");
894 Token*
const tok4 = useAfterVarRange ? insertTokens(after->
previous(), mRangeAfterVar)->
next() : tok3->
next();
906 std::stack<Token*> brackets;
907 for (; tok != tok4; tok = tok->
next()) {
917 void removeDeclaration() {
928 static int canReplaceStatic(
const Token* tok) {
929 if (!
Token::Match(tok,
"%name% %name%|*|&|&&|;|(|)|,|::")) {
944 if (prev->
str() ==
")")
952 bool isGeneric =
false;
953 for (; tok; tok = tok->
previous()) {
968 bool canReplace(
const Token* tok) {
969 if (mNameToken == tok)
974 const int res = canReplaceStatic(tok);
975 if (res == 0 || res == 1)
984 tok->
str() != mRangeType.second->previous()->str())
990 for (
const Token* after = tok->
next(); after; after = after->
next()) {
993 if (after->
str() ==
"<" && after->
link())
1004 if (
Token::Match(before,
"struct|union|class|enum") || before->isStandardType())
1006 if (before->str() ==
"::")
1008 if (before->isName())
1015 Token* endToken()
const {
1020 static bool isCast(
const Token* tok) {
1028 static Token* insertTokens(
Token* to, std::pair<Token*,Token*> range) {
1029 for (
const Token* from = range.first; from != range.second; from = from->
next()) {
1039 static void printTypedef(
const Token *tok) {
1041 while (tok && (
indent > 0 || tok->
str() !=
";")) {
1042 if (tok->
str() ==
"{")
1044 else if (tok->
str() ==
"}")
1046 std::cout <<
" " << tok->
str();
1058 std::map<std::string, int> numberOfTypedefs;
1060 if (tok->
str() ==
"typedef") {
1061 TypedefSimplifier ts(tok);
1063 numberOfTypedefs[ts.name()]++;
1068 int indentlevel = 0;
1069 std::map<std::string, TypedefSimplifier> typedefs;
1072 if (tok->
str()[0] ==
'{')
1074 else if (tok->
str()[0] ==
'}')
1079 if (indentlevel == 0 && tok->
str() ==
"typedef") {
1080 TypedefSimplifier ts(tok);
1081 if (!ts.fail() && numberOfTypedefs[ts.name()] == 1 &&
1082 (numberOfTypedefs.find(ts.getTypedefToken()->strAt(1)) == numberOfTypedefs.end() || ts.getTypedefToken()->strAt(2) ==
"(")) {
1085 "It is unspecified behavior to const qualify a function type.");
1086 typedefs.emplace(ts.name(), ts);
1087 if (!ts.isStructEtc())
1088 tok = ts.endToken();
1093 auto it = typedefs.find(tok->
str());
1094 if (it != typedefs.end() && it->second.canReplace(tok)) {
1095 std::set<std::string> r;
1096 while (it != typedefs.end() && r.insert(tok->
str()).second) {
1098 it = typedefs.find(tok->
str());
1100 }
else if (tok->
str() ==
"enum") {
1105 if (tok->
str() ==
"{")
1110 if (!typedefs.empty())
1113 for (
auto &t: typedefs) {
1114 if (!t.second.replaceFailed()) {
1115 const Token*
const typedefToken = t.second.getTypedefToken();
1117 typedefInfo.
name = t.second.name();
1121 typedefInfo.
used = t.second.isUsed();
1124 t.second.removeDeclaration();
1149 bool isNamespace =
false;
1150 std::string className, fullClassName;
1151 bool hasClass =
false;
1152 bool goback =
false;
1155 std::vector<Space> spaceInfo(1);
1169 if (maxTime > 0 && std::time(
nullptr) > maxTime) {
1175 "Typedef simplification instantiation maximum time exceeded",
1189 if (tok->
str() !=
"typedef") {
1193 }
else if (
Token::Match(tok,
"class|struct|namespace %any%") &&
1195 isNamespace = (tok->
str() ==
"namespace");
1197 className = tok->
next()->
str();
1199 fullClassName = className;
1201 tok1 = tok1->
tokAt(2);
1202 fullClassName +=
" :: " + tok1->
str();
1204 }
else if (hasClass && tok->
str() ==
";") {
1206 }
else if (hasClass && tok->
str() ==
"{") {
1208 spaceInfo.back().recordTypes.insert(fullClassName);
1211 info.isNamespace = isNamespace;
1212 info.className = className;
1213 info.bodyEnd = tok->
link();
1214 info.bodyEnd2 = tok->
link();
1215 spaceInfo.push_back(std::move(info));
1218 }
else if (spaceInfo.size() > 1 && tok->
str() ==
"}" && spaceInfo.back().bodyEnd == tok) {
1219 spaceInfo.pop_back();
1228 tokClass = tokClass->
next();
1229 if (
Token::Match(tokClass,
"struct|enum|union|class %type%| {|:")) {
1248 Token *typeStart =
nullptr;
1249 Token *typeEnd =
nullptr;
1250 Token *argStart =
nullptr;
1251 Token *argEnd =
nullptr;
1252 Token *arrayStart =
nullptr;
1253 Token *arrayEnd =
nullptr;
1254 Token *specStart =
nullptr;
1255 Token *specEnd =
nullptr;
1256 Token *typeDef = tok;
1257 Token *argFuncRetStart =
nullptr;
1258 Token *argFuncRetEnd =
nullptr;
1259 Token *funcStart =
nullptr;
1260 Token *funcEnd =
nullptr;
1262 bool function =
false;
1263 bool functionPtr =
false;
1264 bool functionRetFuncPtr =
false;
1265 bool functionPtrRetFuncPtr =
false;
1266 bool ptrToArray =
false;
1267 bool refToArray =
false;
1268 bool ptrMember =
false;
1269 bool typeOf =
false;
1270 Token *namespaceStart =
nullptr;
1271 Token *namespaceEnd =
nullptr;
1277 if (tokOffset->
str() ==
"::") {
1278 typeStart = tokOffset;
1279 tokOffset = tokOffset->
next();
1282 tokOffset = tokOffset->
tokAt(2);
1284 typeEnd = tokOffset;
1287 tokOffset = tokOffset->
next();
1289 typeStart = tokOffset;
1292 tokOffset = tokOffset->
tokAt(2);
1295 typeEnd = tokOffset;
1298 tokOffset = tokOffset->
next();
1300 typeStart = tokOffset;
1302 while (
Token::Match(tokOffset,
"const|struct|enum %type%") ||
1304 tokOffset = tokOffset->
next();
1306 typeEnd = tokOffset;
1308 tokOffset = tokOffset->
next();
1313 typeEnd = tokOffset;
1314 tokOffset = tokOffset->
next();
1319 if (tokOffset && tokOffset->
str() ==
"::") {
1320 typeEnd = tokOffset;
1321 tokOffset = tokOffset->
next();
1326 typeEnd = tokOffset;
1327 tokOffset = tokOffset->
next();
1329 typeEnd = tokOffset;
1330 tokOffset = tokOffset->
next();
1343 if (!
isC() && tokOffset->
str() ==
"<") {
1347 typeEnd = typeEnd->
tokAt(2);
1355 typeEnd = typeEnd->
next();
1358 tokOffset = tok->
next();
1361 std::list<std::string> pointers;
1364 pointers.push_back(tokOffset->
str());
1365 tokOffset = tokOffset->
next();
1374 typeName = tokOffset;
1375 tokOffset = tokOffset->
next();
1378 while (tokOffset && tokOffset->
str() ==
"[") {
1380 arrayStart = tokOffset;
1381 arrayEnd = tokOffset->
link();
1382 tokOffset = arrayEnd->
next();
1390 else if (tokOffset && tokOffset->
str() ==
"(") {
1391 Token *tokOffset2 =
nullptr;
1393 tokOffset2 = tokOffset->
next();
1394 if (tokOffset2->
str() ==
"typename")
1395 tokOffset2 = tokOffset2->
next();
1397 tokOffset2 = tokOffset2->
tokAt(2);
1401 if (typeName->
str() ==
"void") {
1413 typeEnd = typeEnd->
next();
1415 funcStart = funcEnd = tokOffset2;
1416 tokOffset = tokOffset2->
tokAt(3);
1417 typeName = tokOffset->
tokAt(-2);
1418 argStart = tokOffset;
1419 argEnd = tokOffset->
link();
1420 tok = argEnd->
next();
1426 if (tokOffset->
link()->next()->str() ==
"const") {
1427 specStart = tokOffset->
link()->next();
1428 specEnd = specStart;
1430 argStart = tokOffset;
1431 argEnd = tokOffset->
link();
1432 tok = argEnd->
next();
1456 argStart = tokOffset;
1457 argEnd = tokOffset->
link();
1458 typeName = tokOffset->
link()->next();
1459 tok = typeName->
next();
1466 else if (tokOffset->
str() ==
"(" && (
1475 if (tokOffset->
next()->
str() ==
"(")
1476 tokOffset = tokOffset->
next();
1478 pointers.emplace_back(
"*");
1479 tokOffset = tokOffset->
tokAt(2);
1482 if (tokOffset->
link()->strAt(-2) ==
"*")
1486 funcStart = tokOffset->
next();
1487 tokOffset = tokOffset->
link();
1488 funcEnd = tokOffset->
tokAt(-2);
1490 argStart = tokOffset->
next();
1491 argEnd = tokOffset->
next()->
link();
1495 tok = argEnd->
next();
1501 specEnd = spec->
next();
1504 tok = specEnd->
next();
1509 if (tok->
str() ==
")")
1515 if (tokOffset->
link()->next()) {
1516 tok = tokOffset->
link()->next();
1517 tokOffset = tokOffset->
tokAt(2);
1519 argStart = tokOffset;
1520 argEnd = tokOffset->
link();
1528 else if (
Token::Match(tokOffset,
"( * ( * %type% ) (") &&
1531 functionPtrRetFuncPtr =
true;
1533 tokOffset = tokOffset->
tokAt(6);
1534 typeName = tokOffset->
tokAt(-2);
1535 argStart = tokOffset;
1536 argEnd = tokOffset->
link();
1540 argFuncRetStart = argEnd->
tokAt(2);
1541 argFuncRetEnd = argFuncRetStart->
link();
1545 tok = argFuncRetEnd->
next();
1552 functionRetFuncPtr =
true;
1554 tokOffset = tokOffset->
tokAt(3);
1556 argStart = tokOffset;
1557 argEnd = tokOffset->
link();
1559 argFuncRetStart = argEnd->
tokAt(2);
1560 if (!argFuncRetStart)
1563 argFuncRetEnd = argFuncRetStart->
link();
1567 tok = argFuncRetEnd->
next();
1568 }
else if (
Token::Match(tokOffset,
"( * ( %type% ) (")) {
1569 functionRetFuncPtr =
true;
1571 tokOffset = tokOffset->
tokAt(5);
1572 typeName = tokOffset->
tokAt(-2);
1573 argStart = tokOffset;
1574 argEnd = tokOffset->
link();
1578 argFuncRetStart = argEnd->
tokAt(2);
1579 if (!argFuncRetStart)
1582 argFuncRetEnd = argFuncRetStart->
link();
1586 tok = argFuncRetEnd->
next();
1590 else if (
Token::Match(tokOffset,
"( *|& %type% ) [")) {
1591 ptrToArray = (tokOffset->
next()->
str() ==
"*");
1592 refToArray = !ptrToArray;
1593 tokOffset = tokOffset->
tokAt(2);
1594 typeName = tokOffset;
1595 arrayStart = tokOffset->
tokAt(2);
1596 arrayEnd = arrayStart->
link();
1600 tok = arrayEnd->
next();
1604 else if (
Token::Match(tokOffset,
"( %type% :: * %type% ) ;")) {
1605 tokOffset = tokOffset->
tokAt(2);
1606 namespaceStart = tokOffset->
previous();
1607 namespaceEnd = tokOffset;
1609 tokOffset = tokOffset->
tokAt(2);
1610 typeName = tokOffset;
1611 tok = tokOffset->
tokAt(2);
1628 typedefInfo.
name = typeName->
str();
1632 typedefInfo.
used =
false;
1636 std::string pattern = typeName->
str();
1638 bool simplifyType =
false;
1639 bool inMemberFunc =
false;
1640 int memberScope = 0;
1641 bool globalScope =
false;
1642 int classLevel = spaceInfo.size();
1643 bool inTypeDef =
false;
1644 bool inEnum =
false;
1645 std::string removed;
1646 std::string classPath;
1647 for (
size_t i = 1; i < spaceInfo.size(); ++i) {
1648 if (!classPath.empty())
1649 classPath +=
" :: ";
1650 classPath += spaceInfo[i].className;
1653 for (
Token *tok2 = tok; tok2; tok2 = tok2->
next()) {
1668 Token* varDecl = tok2;
1670 varDecl = varDecl->
next();
1679 tok2 = tok2->
link();
1680 tok2 = tok2->
next();
1691 if (tok2->
str() ==
"}") {
1695 if (memberScope == 0)
1696 inMemberFunc =
false;
1700 if (classLevel > 1 && tok2 == spaceInfo[classLevel - 1].bodyEnd2) {
1704 for (
int i = classLevel; i < spaceInfo.size(); ++i)
1705 pattern += (spaceInfo[i].className +
" :: ");
1707 pattern += typeName->
str();
1709 if (scope == 0 && !(classLevel > 1 && tok2 == spaceInfo[classLevel - 1].bodyEnd))
1711 scope = std::max(scope - 1, 0);
1732 if (spaceInfo.size() > 1 && classLevel < spaceInfo.size() &&
1733 func->
strAt(offset) == spaceInfo[classLevel].className) {
1735 inMemberFunc =
true;
1741 else if (tok2->
str() ==
"{") {
1743 if (tok2->
isCpp()) {
1744 if (tok2->
strAt(-2) ==
"namespace") {
1745 if (classLevel < spaceInfo.size() &&
1746 spaceInfo[classLevel].isNamespace &&
1747 spaceInfo[classLevel].className == tok2->
previous()->
str()) {
1748 spaceInfo[classLevel].bodyEnd2 = tok2->
link();
1751 for (
int i = classLevel; i < spaceInfo.size(); ++i)
1752 pattern += spaceInfo[i].className +
" :: ";
1754 pattern += typeName->
str();
1772 else if (tok2->
isCpp() &&
1773 tok2->
str() ==
"operator" &&
1777 tok2->
strAt(2) ==
"(" &&
1782 if (spaceInfo.size() > 1 && classLevel < spaceInfo.size() &&
1783 tok2->
strAt(-2) == spaceInfo[classLevel].className) {
1784 tok2 = tok2->
next();
1785 simplifyType =
true;
1797 (inMemberFunc && tok2->
str() == typeName->
str()))) {
1799 if (!(inMemberFunc && tok2->
str() == typeName->
str()) && pattern.find(
"::") != std::string::npos) {
1800 Token *start = tok2;
1802 int back = classLevel - 1;
1809 if (qualificationTok->
str() == spaceInfo[back].className) {
1810 start = qualificationTok;
1819 if (good && back == 1 && start->
strAt(-1) ==
"::")
1825 if (!removed.empty())
1826 removed.insert(0,
" ");
1827 removed.insert(0, tok2->
strAt(-2) +
" " + tok2->
strAt(-1));
1833 if (tok2->
strAt(-1) ==
"::") {
1834 removed.insert(0,
":: ");
1840 for (
int i = classLevel; i < spaceInfo.size(); ++i) {
1841 if (!removed.empty())
1843 removed += (tok2->
str() +
" " + tok2->
strAt(1));
1847 simplifyType =
true;
1850 if (tok2->
strAt(-1) ==
"::") {
1851 int relativeSpaceInfoSize = spaceInfo.size();
1853 while (relativeSpaceInfoSize > 1 &&
1854 tokBeforeType && tokBeforeType->
str() ==
"::" &&
1855 tokBeforeType->
strAt(-1) == spaceInfo[relativeSpaceInfoSize-1].className) {
1856 tokBeforeType = tokBeforeType->
tokAt(-2);
1857 --relativeSpaceInfoSize;
1859 if (tokBeforeType && tokBeforeType->
str() !=
"::") {
1861 simplifyType =
true;
1864 tok2 = tok2->
next();
1867 if (tok2->
str() !=
"}") {
1868 while (tok2->
next()) {
1869 if (tok2->
next()->
str() ==
"{")
1871 else if (tok2->
next()->
str() ==
"}")
1874 tok2 = tok2->
next();
1880 simplifyType = (TypedefSimplifier::canReplaceStatic(tok2) != 0);
1892 if (functionPtr && (tok2->
previous()->
str() ==
"operator" ||
1893 (tok2->
next() && tok2->
next()->
str() ==
"operator"))) {
1894 simplifyType =
false;
1895 tok2 = tok2->
next();
1906 bool inCast =
false;
1907 bool inTemplate =
false;
1908 bool inOperator =
false;
1909 bool inSizeof =
false;
1911 const bool sameStartEnd = (typeStart == typeEnd);
1914 const bool isDerived =
Token::Match(tok2->
previous(),
"public|protected|private|: %type% {|,");
1932 if (tok2->
strAt(-1) ==
"operator" ||
1936 if (typeStart->
str() ==
"typename" && tok2->
strAt(-1)==
"typename") {
1938 typeStart = typeStart->
next();
1942 bool structRemoved =
false;
1943 if ((isDerived || inTemplate) &&
Token::Match(typeStart,
"class|struct")) {
1944 if (typeStart->
str() ==
"struct")
1945 structRemoved =
true;
1946 typeStart = typeStart->
next();
1949 typeStart = typeStart->
next();
1952 typeEnd = typeStart;
1955 const bool isPointerTypeCall = !inOperator &&
Token::Match(tok2,
"%name% ( )") && !pointers.empty();
1958 Token* replStart = tok2;
1959 for (
Token* tok3 = typeStart; tok3 && (tok3->
str() !=
";"); tok3 = tok3->
next())
1961 if (isPointerTypeCall) {
1964 tok2 = tok2->
next();
1969 tok2->
str(typeStart->
str());
1972 if (
Token::Match(typeStart,
"class|struct|union") || structRemoved) {
1978 tok2 = tok2->
next();
1981 for (
int i = classLevel; i < spaceInfo.size(); ++i) {
1983 tok2 = tok2->
next();
1985 tok2 = tok2->
next();
1990 Token *start = tok2;
1991 std::string removed1 = removed;
1992 std::string::size_type idx = removed1.rfind(
" ::");
1994 if (idx != std::string::npos)
1995 removed1.resize(idx);
1996 if (removed1 == classPath && !removed1.empty()) {
1997 for (std::vector<Space>::const_reverse_iterator it = spaceInfo.crbegin(); it != spaceInfo.crend(); ++it) {
1998 if (it->recordTypes.find(start->
str()) != it->recordTypes.end()) {
1999 std::string::size_type spaceIdx = 0;
2000 std::string::size_type startIdx = 0;
2001 while ((spaceIdx = removed1.find(
' ', startIdx)) != std::string::npos) {
2003 startIdx = spaceIdx + 1;
2009 idx = removed1.rfind(
" ::");
2010 if (idx == std::string::npos)
2013 removed1.resize(idx);
2021 if (!pointers.empty()) {
2022 for (
const std::string &p : pointers) {
2025 tok2 = tok2->
next();
2031 tok2 = tok2->
next();
2035 if (funcStart && funcEnd) {
2037 tok2 = tok2->
next();
2038 Token *paren = tok2;
2051 tok2 = tok2->
next();
2057 Token *spec = specStart;
2059 tok2 = tok2->
next();
2060 while (spec != specEnd) {
2061 spec = spec->
next();
2063 tok2 = tok2->
next();
2068 else if (functionPtr ||
function) {
2071 bool needParen =
true;
2072 if (!inTemplate &&
function && tok2->
next() && tok2->
next()->
str() !=
"*")
2076 tok2 = tok2->
next();
2079 if (namespaceStart) {
2080 const Token *tok4 = namespaceStart;
2082 while (tok4 != namespaceEnd) {
2084 tok2 = tok2->
next();
2085 tok4 = tok4->
next();
2088 tok2 = tok2->
next();
2092 tok2 = tok2->
next();
2103 tok2 = tok2->
next();
2114 tok2 = tok2->
next();
2118 Token *spec = specStart;
2120 tok2 = tok2->
next();
2121 while (spec != specEnd) {
2122 spec = spec->
next();
2124 tok2 = tok2->
next();
2127 }
else if (functionRetFuncPtr || functionPtrRetFuncPtr) {
2129 tok2 = tok2->
next();
2132 tok2 = tok2->
next();
2134 Token * tok4 =
nullptr;
2135 if (functionPtrRetFuncPtr) {
2137 tok2 = tok2->
next();
2140 tok2 = tok2->
next();
2145 if (!tok2 || !tok2->
next())
2148 if (tok2->
next()->
str() !=
")")
2149 tok2 = tok2->
next();
2152 if (tok4 && functionPtrRetFuncPtr) {
2154 tok2 = tok2->
next();
2161 tok2 = tok2->
next();
2165 }
else if (ptrToArray || refToArray) {
2167 tok2 = tok2->
next();
2174 tok2 = tok2->
next();
2176 bool hasName =
false;
2181 if (tok2->
next()->
str() !=
"(")
2182 tok2 = tok2->
next();
2185 if (tok2 && tok2->
next() && tok2->
next()->
str() ==
"(")
2189 if (tok2 && tok2->
next() && tok2->
next()->
str() ==
"[")
2197 tok2 = tok2->
next();
2198 }
else if (ptrMember) {
2201 tok2 = tok2->
next();
2206 const bool castOperator = inOperator &&
Token::Match(tok2,
"%type% (");
2207 Token *openParenthesis =
nullptr;
2209 if (!castOperator) {
2211 tok2 = tok2->
next();
2213 openParenthesis = tok2;
2216 const Token *tok4 = namespaceStart;
2218 while (tok4 != namespaceEnd) {
2220 tok2 = tok2->
next();
2221 tok4 = tok4->
next();
2224 tok2 = tok2->
next();
2227 tok2 = tok2->
next();
2229 if (openParenthesis) {
2232 tok2 = tok2->
next();
2235 tok2 = tok2->
next();
2240 }
else if (typeOf) {
2249 if (arrayStart && arrayEnd) {
2254 if (!inCast && !inSizeof && !inTemplate)
2255 tok2 = tok2->
next();
2257 if (tok2->
str() ==
"const")
2258 tok2 = tok2->
next();
2268 tok2 = tok3->
tokAt(3);
2270 tok2 = tok2->
tokAt(2);
2272 tok2 = tok2->
tokAt(2);
2274 tok2 = tok2->
tokAt(3);
2278 while (tok2->
strAt(1) ==
"::")
2279 tok2 = tok2->
tokAt(2);
2282 if (tok2->
str() ==
"(")
2283 tok2 = tok2->
link();
2285 if (tok2->
strAt(1) ==
"(")
2290 tok2 = tok2->
next();
2292 tok2 = tok2->
tokAt(3);
2296 tok2 = tok2->
next();
2304 while (tok2->
next()->
str() ==
"[")
2311 if (tok2->
str() ==
"=") {
2312 if (tok2->
next()->
str() ==
"{")
2313 tok2 = tok2->
next()->
link()->next();
2314 else if (tok2->
next()->
str().at(0) ==
'\"')
2315 tok2 = tok2->
tokAt(2);
2320 simplifyType =
false;
2329 if (tok->
str() ==
";")
2331 else if (tok->
str() ==
",") {
2332 arrayStart =
nullptr;
2334 tokOffset = tok->
next();
2338 pointers.push_back(tokOffset->
str());
2339 tokOffset = tokOffset->
next();
2343 typeName = tokOffset;
2344 tokOffset = tokOffset->
next();
2346 if (tokOffset && tokOffset->
str() ==
"[") {
2347 arrayStart = tokOffset;
2351 tokOffset = tokOffset->
next();
2353 if (!tokOffset->
next())
2355 if (tokOffset->
next()->
str() ==
";")
2357 if (tokOffset->
str() ==
"]")
2359 tokOffset = tokOffset->
next();
2362 arrayEnd = tokOffset;
2363 tokOffset = tokOffset->
next();
2411 ScopeInfo3() : parent(nullptr), type(
Global), bodyStart(nullptr), bodyEnd(nullptr) {}
2412 ScopeInfo3(ScopeInfo3 *parent_,
Type type_, std::string name_,
const Token *bodyStart_,
const Token *bodyEnd_)
2413 : parent(parent_), type(type_), name(std::move(name_)), bodyStart(bodyStart_), bodyEnd(bodyEnd_) {
2417 ScopeInfo3 *scope = parent;
2418 while (scope && scope->parent) {
2419 if (scope->name.empty())
2421 fullName = scope->name +
" :: " + fullName;
2422 scope = scope->parent;
2426 std::list<ScopeInfo3> children;
2428 std::string fullName;
2430 const Token * bodyStart;
2431 const Token * bodyEnd;
2432 std::set<std::string> usingNamespaces;
2433 std::set<std::string> recordTypes;
2434 std::set<std::string> baseTypes;
2436 ScopeInfo3 *addChild(
Type scopeType,
const std::string &scopeName,
const Token *bodyStartToken,
const Token *bodyEndToken) {
2437 children.emplace_back(
this, scopeType, scopeName, bodyStartToken, bodyEndToken);
2438 return &children.back();
2441 bool hasChild(
const std::string &childName)
const {
2442 return std::any_of(children.cbegin(), children.cend(), [&](
const ScopeInfo3& child) {
2443 return child.name == childName;
2447 const ScopeInfo3 * findInChildren(
const std::string & scope)
const {
2448 for (
const auto & child : children) {
2449 if (child.type == Record && (child.name == scope || child.fullName == scope))
2452 const ScopeInfo3 * temp = child.findInChildren(scope);
2459 const ScopeInfo3 * findScope(
const std::string & scope)
const {
2460 const ScopeInfo3 * tempScope =
this;
2463 auto it = std::find_if(tempScope->children.cbegin(), tempScope->children.cend(), [&](
const ScopeInfo3& child) {
2464 return &child != this && child.type == Record && (child.name == scope || child.fullName == scope);
2466 if (it != tempScope->children.end())
2469 if (tempScope->parent) {
2470 for (
const auto &sibling : tempScope->parent->children) {
2471 if (sibling.name == tempScope->name && &sibling !=
this) {
2472 const ScopeInfo3 * temp = sibling.findInChildren(scope);
2478 tempScope = tempScope->parent;
2483 bool findTypeInBase(
const std::string &scope)
const {
2487 if (baseTypes.find(scope) != baseTypes.end())
2490 for (
const std::string & base : baseTypes) {
2491 const ScopeInfo3 * baseScope = findScope(base);
2493 if (baseScope ==
this)
2495 if (baseScope && baseScope->fullName == scope)
2497 if (baseScope && baseScope->findTypeInBase(scope))
2503 ScopeInfo3 * findScope(
const ScopeInfo3 * scope) {
2504 if (scope->bodyStart == bodyStart)
2506 for (
auto & child : children) {
2507 ScopeInfo3 * temp = child.findScope(scope);
2515 void setScopeInfo(
Token *tok, ScopeInfo3 *&scopeInfo,
bool debug=
false)
2519 if (tok->
str() ==
"{" && scopeInfo->parent && tok == scopeInfo->bodyStart)
2521 if (tok->
str() ==
"}") {
2522 if (scopeInfo->parent && tok == scopeInfo->bodyEnd)
2523 scopeInfo = scopeInfo->parent;
2526 ScopeInfo3 *parent = scopeInfo->parent;
2527 while (parent && parent->bodyEnd != tok)
2528 parent = parent->parent;
2532 throw std::runtime_error(
"Internal error: unmatched }");
2537 if (!
Token::Match(tok,
"namespace|class|struct|union %name% {|:|::|<")) {
2539 if (
Token::Match(tok,
"using namespace %name% ;|::")) {
2541 std::string nameSpace;
2542 while (tok1 && tok1->
str() !=
";") {
2543 if (!nameSpace.empty())
2545 nameSpace += tok1->
str();
2546 tok1 = tok1->
next();
2548 scopeInfo->usingNamespaces.insert(std::move(nameSpace));
2551 else if (tok->
str() ==
"{") {
2562 if (tok1->
strAt(-1) !=
")")
2567 tok1 = tok1->
tokAt(-2);
2568 if (tok1->
strAt(-1) !=
")" && tok1->
strAt(-1) !=
"}")
2573 if (tok1->
strAt(-1) ==
">")
2577 tok1 = tok1->
tokAt(-2);
2578 if (tok1->
str() ==
"~")
2580 std::string scope = tok1->
strAt(-1);
2582 scope = tok1->
strAt(-3) +
" :: " + scope;
2583 tok1 = tok1->
tokAt(-2);
2585 scopeInfo = scopeInfo->addChild(ScopeInfo3::MemberFunction, scope, tok, tok->
link());
2591 scopeInfo = scopeInfo->addChild(ScopeInfo3::Other,
emptyString, tok, tok->
link());
2596 const bool record =
Token::Match(tok,
"class|struct|union %name%");
2598 std::string classname = tok->
str();
2600 tok = tok->
tokAt(2);
2601 classname +=
" :: " + tok->
str();
2606 scopeInfo->recordTypes.insert(classname);
2610 if (tok && tok->
str() ==
"<") {
2617 std::set<std::string> baseTypes;
2618 if (tok && tok->
str() ==
":") {
2621 while (
Token::Match(tok,
"public|protected|private|virtual"))
2630 if (tok && tok->
str() ==
"<") {
2633 endTok = endTok->
next();
2634 while (tok != endTok) {
2641 baseTypes.insert(std::move(base));
2645 if (tok && tok->
str() ==
"{") {
2646 scopeInfo = scopeInfo->addChild(record ? ScopeInfo3::Record : ScopeInfo3::Namespace, classname, tok, tok->
link());
2647 scopeInfo->baseTypes = std::move(baseTypes);
2655 for (; tok && (level > 0 || tok->
str() !=
";"); tok = tok->
next()) {
2656 if (tok->
str() ==
"{")
2658 else if (level > 0 && tok->
str() ==
"}")
2666 const Token *nameToken,
2667 const std::string &scope,
2669 const std::string &scope1,
2670 const ScopeInfo3 *currentScope,
2671 const ScopeInfo3 *memberClassScope)
2675 if (tok1 && tok1->
str() != nameToken->
str())
2679 if (tok1 == nameToken) {
2680 tok = findSemicolon(tok1);
2685 if (tok1->
strAt(-1) ==
"using") {
2688 if (currentScope->bodyEnd)
2689 tok =
const_cast<Token*
>(currentScope->bodyEnd->previous());
2699 std::string qualification;
2700 const Token* tok2 = tok1;
2701 std::string::size_type index = scope.size();
2702 std::string::size_type new_index = std::string::npos;
2706 if (
match && !scope1.empty()) {
2707 new_index = scope1.rfind(
' ', index - 1);
2708 if (new_index != std::string::npos)
2709 last = scope1.substr(new_index, index - new_index);
2710 else if (!qualification.empty())
2719 if (!qualification.empty())
2720 qualification =
" :: " + qualification;
2721 qualification = tok2->
strAt(-2) + qualification;
2723 tok2 = tok2->
tokAt(-2);
2726 std::string fullScope1 = scope1;
2727 if (!scope1.empty() && !qualification.empty())
2728 fullScope1 +=
" :: ";
2729 fullScope1 += qualification;
2731 if (scope == fullScope1)
2734 const ScopeInfo3 *scopeInfo = memberClassScope ? memberClassScope : currentScope;
2737 if (qualification.empty() && scopeInfo->findTypeInBase(scope))
2741 const ScopeInfo3 * tempScope = scopeInfo;
2744 const std::set<std::string>& usingNS = tempScope->usingNamespaces;
2745 if (!usingNS.empty()) {
2746 if (qualification.empty()) {
2747 if (usingNS.find(scope) != usingNS.end())
2750 const std::string suffix =
" :: " + qualification;
2751 if (std::any_of(usingNS.cbegin(), usingNS.cend(), [&](
const std::string& ns) {
2752 return scope == ns + suffix;
2757 tempScope = tempScope->parent;
2760 std::string newScope1 = scope1;
2763 index = newScope1.size();
2764 while (!newScope1.empty()) {
2765 const std::string::size_type separator = newScope1.rfind(
" :: ", index - 1);
2766 if (separator != std::string::npos)
2767 newScope1.resize(separator);
2771 std::string newFullScope1 = newScope1;
2772 if (!newScope1.empty() && !qualification.empty())
2773 newFullScope1 +=
" :: ";
2774 newFullScope1 += qualification;
2776 if (scope == newFullScope1)
2783 std::string memberFunctionScope(
const Token *tok)
2785 std::string qualification;
2788 if (!qualification.empty())
2789 qualification =
" :: " + qualification;
2790 qualification = qualTok->
str() + qualification;
2791 qualTok = qualTok->
tokAt(-2);
2793 return qualification;
2796 const Token * memberFunctionEnd(
const Token *tok)
2798 if (tok->
str() !=
"(")
2804 if (end->
str() ==
";")
2819 static bool scopesMatch(
const std::string &scope1,
const std::string &scope2,
const ScopeInfo3 *globalScope)
2821 if (scope1.empty() || scope2.empty())
2825 if (scope1 == scope2)
2829 if (scope1 == (
":: " + scope2)) {
2830 std::string::size_type end = scope2.find_first_of(
' ');
2831 if (end == std::string::npos)
2832 end = scope2.size();
2833 if (globalScope->hasChild(scope2.substr(0, end)))
2835 }
else if (scope2 == (
":: " + scope1)) {
2836 std::string::size_type end = scope1.find_first_of(
' ');
2837 if (end == std::string::npos)
2838 end = scope1.size();
2839 if (globalScope->hasChild(scope1.substr(0, end)))
2847 unsigned int dist = 0;
2848 const Token* tok = tok1;
2849 while (tok != tok2) {
2870 if (end->
str() ==
"<")
2880 if (end->
str() ==
",") {
2887 const unsigned int maxReplacementTokens = 1000;
2889 bool substitute =
false;
2890 ScopeInfo3 scopeInfo;
2891 ScopeInfo3 *currentScope = &scopeInfo;
2893 Using(
Token *start,
Token *end) : startTok(start), endTok(end) {}
2897 std::list<Using> usingList;
2907 Token *bodyStart = tok;
2909 if (bodyStart->
str() ==
"<")
2911 bodyStart = bodyStart ? bodyStart->
next() :
nullptr;
2914 tok = bodyStart->
link();
2918 if (
Token::Match(tok,
"{|}|namespace|class|struct|union") ||
2922 }
catch (
const std::runtime_error &) {
2924 "simplifyUsing: unmatched body end");
2934 currentScope->recordTypes.insert(end->
strAt(2));
2943 if (!(tok->
strAt(-1) !=
">" &&
2949 const std::string& name = tok->
strAt(1);
2951 std::string scope = currentScope->fullName;
2952 Token *usingStart = tok;
2954 if (tok->
strAt(2) ==
"=") {
2957 start = tok->
tokAt(3);
2961 Token *usingEnd = findSemicolon(start);
2968 if (
Token::Match(start,
"class|struct|union|enum %name%| {|:")) {
2970 const bool hasName =
Token::Match(structEnd,
"%name%");
2974 structEnd = structEnd->
next();
2977 if (structEnd->
str() ==
":") {
2978 structEnd = structEnd->
next();
2979 while (structEnd && structEnd->
str() !=
"{")
2980 structEnd = structEnd->
next();
2986 structEnd = structEnd->
link();
2993 std::string newName;
2994 if (structEnd->
strAt(2) ==
";")
3005 usingStart = structEnd->
tokAt(2);
3006 nameToken = usingStart->
next();
3007 if (usingStart->
strAt(2) ==
"=")
3008 start = usingStart->
tokAt(3);
3011 usingEnd = findSemicolon(start);
3021 else if (start->
str() ==
"typename") {
3023 Token *temp = start;
3025 temp = temp->
tokAt(2);
3036 ScopeInfo3 scopeInfo1;
3037 ScopeInfo3 *currentScope1 = &scopeInfo1;
3039 Token *endToken =
nullptr;
3040 bool inMemberFunc =
false;
3041 const ScopeInfo3 * memberFuncScope =
nullptr;
3042 const Token * memberFuncEnd =
nullptr;
3046 if (currentScope->type == ScopeInfo3::Other ||
3047 currentScope->type == ScopeInfo3::MemberFunction) {
3048 scopeInfo1 = scopeInfo;
3049 currentScope1 = scopeInfo1.findScope(currentScope);
3052 startToken = usingEnd->
next();
3053 endToken =
const_cast<Token*
>(currentScope->bodyEnd->next());
3054 if (currentScope->type == ScopeInfo3::MemberFunction) {
3055 const ScopeInfo3 * temp = currentScope->findScope(currentScope->fullName);
3057 inMemberFunc =
true;
3058 memberFuncScope = temp;
3059 memberFuncEnd = endToken;
3064 std::string scope1 = currentScope1->fullName;
3066 Token *enumOpenBrace =
nullptr;
3067 for (
Token* tok1 = startToken; !skip && tok1 && tok1 != endToken; tok1 = tok1->
next()) {
3069 if (tok1 && tok1 == enumOpenBrace) {
3070 tok1 = tok1->
link();
3071 enumOpenBrace =
nullptr;
3075 if ((
Token::Match(tok1,
"{|}|namespace|class|struct|union") && tok1->
strAt(-1) !=
"using") ||
3079 }
catch (
const std::runtime_error &) {
3081 "simplifyUsing: unmatched body end");
3083 scope1 = currentScope1->fullName;
3084 if (inMemberFunc && memberFuncEnd && tok1 == memberFuncEnd) {
3085 inMemberFunc =
false;
3086 memberFuncScope =
nullptr;
3087 memberFuncEnd =
nullptr;
3096 tok1 = declEndToken;
3101 if (tok1->
str() ==
"enum") {
3103 tok1 = tok1->
next();
3104 Token *defStart = tok1;
3106 defStart = defStart->
next();
3108 enumOpenBrace = defStart;
3114 if (!scope1.empty())
3116 scope1 += memberFunctionScope(tok1);
3117 const ScopeInfo3 * temp = currentScope1->findScope(scope1);
3119 const Token *end = memberFunctionEnd(tok1);
3121 inMemberFunc =
true;
3122 memberFuncScope = temp;
3123 memberFuncEnd = end;
3128 if (inMemberFunc && memberFuncScope) {
3129 if (!usingMatch(nameToken, scope, tok1, scope1, currentScope1, memberFuncScope))
3131 }
else if (!usingMatch(nameToken, scope, tok1, scope1, currentScope1,
nullptr))
3134 const auto nReplace =
tokDistance(start, usingEnd);
3135 if (nReplace > maxReplacementTokens) {
3141 std::string fullScope = scope;
3142 std::string removed;
3144 removed = (tok1->
strAt(-2) +
" :: ") + removed;
3145 if (fullScope == tok1->
strAt(-2)) {
3150 const std::string::size_type idx = fullScope.rfind(
"::");
3152 if (idx == std::string::npos)
3155 if (tok1->
strAt(-2) == fullScope.substr(idx + 3)) {
3158 fullScope.resize(idx - 1);
3164 if (tok1->
strAt(-1) ==
"::") {
3165 removed.insert(0,
":: ");
3169 Token * arrayStart =
nullptr;
3172 Token *type = start;
3173 if (type->
str() ==
"::") {
3174 type = type->
next();
3176 type = type->
tokAt(2);
3178 type = type->
next();
3181 type = type->
tokAt(2);
3184 type = type->
next();
3186 while (
Token::Match(type,
"const|class|struct|union|enum %type%") ||
3188 type = type->
next();
3190 type = type->
next();
3194 type = type->
next();
3199 if (type && type->
str() ==
"::") {
3200 type = type->
next();
3205 type = type->
next();
3207 type = type->
next();
3220 if (type->
str() ==
"<") {
3224 type = type->
tokAt(2);
3231 type = type->
next();
3233 type = type->
next();
3237 std::list<std::string> pointers;
3239 pointers.push_back(type->
str());
3240 type = type->
next();
3244 if (type && type->
str() ==
"[") {
3252 type = type->
next();
3257 else if (type->
next()->
str() ==
";")
3259 else if (type->
str() ==
"]")
3262 type = type->
next();
3265 type = type->
next();
3266 }
while (type && type->
str() ==
"[");
3270 if (!tok1 || !tok1->
next())
3275 if (type && type == usingEnd) {
3286 std::string removed1 = std::move(removed);
3287 std::string::size_type idx = removed1.rfind(
" ::");
3288 if (idx != std::string::npos)
3289 removed1.resize(idx);
3291 ScopeInfo3 * tempScope = currentScope;
3292 while (tempScope->parent) {
3293 if (tempScope->recordTypes.find(start->
str()) != tempScope->recordTypes.end()) {
3294 std::string::size_type spaceIdx = 0;
3295 std::string::size_type startIdx = 0;
3296 while ((spaceIdx = removed1.find(
' ', startIdx)) != std::string::npos) {
3298 startIdx = spaceIdx + 1;
3304 idx = removed1.rfind(
" ::");
3305 if (idx == std::string::npos)
3308 removed1.resize(idx);
3309 tempScope = tempScope->parent;
3314 if (
Token::Match(tok1,
"%name% ( )") && !pointers.empty()) {
3319 after = tok2->
next();
3335 usingList.emplace_back(usingStart, usingEnd);
3339 for (std::list<Using>::reverse_iterator it = usingList.rbegin(); it != usingList.rend(); ++it) {
3340 Token *usingStart = it->startTok;
3341 Token *usingEnd = it->endTok;
3343 if (usingEnd->
next())
3350 if (usingEnd->
next()) {
3368 for (
const Token *tok = usingStart; tok && tok != usingEnd; tok = tok->
next()) {
3374 std::list<const Token *> callstack(1, usingStart);
3376 "Failed to parse \'" + str +
"\'. The checking continues anyway.",
Certainty::normal));
3425 const char* disableValueflowEnv = std::getenv(
"DISABLE_VALUEFLOW");
3426 const bool doValueFlow = !disableValueflowEnv || (std::strcmp(disableValueflowEnv,
"1") != 0);
3444 simplecpp::characterLiteralToLL(tok->
str());
3445 }
catch (
const std::exception &e) {
3473 tok = tok->
tokAt(2);
3502 const bool cpp =
isCPP();
3506 const char c1 = tok->
str()[0];
3508 if (tok->
str().length() == 1 && tok->
next()->
str().length() == 1) {
3509 const char c2 = tok->
next()->
str()[0];
3512 if (c2 ==
'=' && (std::strchr(
"+-*/%|^=!<>", c1)) && !
Token::Match(tok->
previous(),
"%type% *")) {
3515 const Token* opening =
3520 tok->
str(tok->
str() + c2);
3524 }
else if (tok->
next()->
str() ==
"=") {
3525 if (tok->
str() ==
">>") {
3528 }
else if (tok->
str() ==
"<<") {
3532 }
else if (cpp && (c1 ==
'p' || c1 ==
'_') &&
3533 Token::Match(tok,
"private|protected|public|__published : !!:")) {
3534 bool simplify =
false;
3537 if (prev->
str() ==
")") {
3539 }
else if (prev->
str() ==
"(") {
3544 if (par != 0U || prev->
str() ==
"(")
3557 tok->
str(tok->
str() +
":");
3560 }
else if (tok->
str() ==
"->") {
3624 const bool isExtC = tok->
next()->
str().size() == 3;
3625 if (tok->
strAt(2) ==
"{") {
3626 tok2 = tok2->
next();
3627 while ((tok2 = tok2->
next()) && tok2 != tok->
linkAt(2))
3654 if (
Token::Match(tok,
"( { %bool%|%char%|%num%|%str%|%name% ; } )")) {
3685 tok = tok->
tokAt(3);
3694 const std::string number(tok->
str());
3696 tok->
str(indexTok->
str());
3698 indexTok->
str(number);
3732 while (tok->
next()) {
3733 if (tok->
str() ==
"+") {
3734 if (tok->
next()->
str()[0] ==
'-') {
3736 if (tok->
str().size() == 1) {
3741 tok->
str(tok->
str().substr(1));
3747 }
else if (tok->
str() ==
"-") {
3748 if (tok->
next()->
str()[0] ==
'-') {
3750 if (tok->
str().size() == 1) {
3755 tok->
str(tok->
str().substr(1));
3772 auto getStrTok = [](
Token* tok,
bool addLength,
Token*& endStmt) ->
Token* {
3774 endStmt = tok->
tokAt(5);
3775 return tok->
tokAt(4);
3778 tok = tok->
tokAt(4);
3785 endStmt = tok->
tokAt(parCount + 1);
3795 bool addlength =
false;
3804 if (
const Token* strTok = getStrTok(tok, addlength, endStmt)) {
3814 for (
Token *tok2 = tok->
tokAt(4); tok2 && tok2 != end; tok2 = tok2->
next()) {
3816 if (tok2->
str() ==
"[" && tok2->
link()->strAt(1) ==
"=") {
3824 tok2 = tok2->
link();
3825 }
else if (tok2->
str() ==
",") {
3838 tok = end->
next() ? end->
next() : end;
3847 if (!var || !var->isArray())
3849 if (!
Token::Match(var->nameToken(),
"%name% [ ] = { ["))
3852 const Token*
const startToken = var->nameToken()->
tokAt(4);
3853 const Token*
const endToken = startToken->
link();
3854 for (
const Token* tok = startToken; tok != endToken; tok = tok->
next()) {
3861 if (maxIndex >= 0) {
3863 Token* tok =
const_cast<Token*
>(var->nameToken()->next());
3875 d.
num = maxIndex + 1;
3876 std::vector<Dimension> dimensions{d};
3877 const_cast<Variable*
>(var)->setDimensions(dimensions);
3885 while (
nullptr != (tok = tok->
next())) {
3886 if (tok->
str() ==
"?") {
3888 }
else if (tok->
str() ==
":") {
3890 if (colonLevel == 0) {
3910 assert(tok->
str() ==
"case");
3911 while (
nullptr != (tok = tok->
next())) {
3914 else if (tok->
str() ==
"?") {
3928 if (tok->
str() !=
")")
3938 return (tok && tok->
str() ==
"{") ? tok :
nullptr;
3946 const bool cpp =
isCPP();
3947 bool executablescope =
false;
3948 int indentLevel = 0;
3954 executablescope =
true;
3957 if (!executablescope)
3960 if (tok->
str() ==
"{") {
3965 }
else if (tok->
str() ==
"}") {
3967 if (indentLevel == 0) {
3968 executablescope =
false;
3978 if (tok->
str() !=
":" || tok->
strAt(-1) ==
"case" || !tok->
next())
3986 tok = tok->
tokAt(2);
3997 if (
Token::Match(tok,
"case %num%|%char% ... %num%|%char% :")) {
4000 end = std::min(start + 50, end);
4002 tok = tok->
tokAt(2);
4020 std::string nextScopeNameAddition;
4021 std::shared_ptr<ScopeInfo2> primaryScope = std::make_shared<ScopeInfo2>(
"",
nullptr);
4029 if (
Token::Match(tok,
"using namespace %name% ::|<|;")) {
4030 std::string usingNamespaceName;
4031 for (
const Token* namespaceNameToken = tok->
tokAt(2);
4032 namespaceNameToken && namespaceNameToken->
str() !=
";";
4033 namespaceNameToken = namespaceNameToken->next()) {
4034 usingNamespaceName += namespaceNameToken->str();
4035 usingNamespaceName +=
" ";
4037 if (!usingNamespaceName.empty())
4038 usingNamespaceName.pop_back();
4039 tok->
scopeInfo()->usingNamespaces.insert(std::move(usingNamespaceName));
4040 }
else if (
Token::Match(tok,
"namespace|class|struct|union %name% {|::|:|<")) {
4041 for (
Token* nameTok = tok->
next(); nameTok && !
Token::Match(nameTok,
"{|:"); nameTok = nameTok->next()) {
4043 nextScopeNameAddition =
"";
4046 nextScopeNameAddition.append(nameTok->str());
4047 nextScopeNameAddition.append(
" ");
4049 if (!nextScopeNameAddition.empty())
4050 nextScopeNameAddition.pop_back();
4065 if (tok1->
strAt(-1) !=
")")
4068 tok1 = tok1->
tokAt(-2);
4069 if (tok1->
strAt(-1) !=
")")
4073 if (tok1->
strAt(-1) ==
">")
4076 tok1 = tok1->
tokAt(-2);
4077 std::string scope = tok1->
strAt(-1);
4079 scope = tok1->
strAt(-3) +
" :: " + scope;
4080 tok1 = tok1->
tokAt(-2);
4083 if (!nextScopeNameAddition.empty() && !scope.empty())
4084 nextScopeNameAddition +=
" :: ";
4085 nextScopeNameAddition += scope;
4091 std::shared_ptr<ScopeInfo2> newScopeInfo = std::make_shared<ScopeInfo2>(tok->
scopeInfo()->name, tok->
link(), tok->
scopeInfo()->usingNamespaces);
4093 if (!newScopeInfo->name.empty() && !nextScopeNameAddition.empty())
4094 newScopeInfo->name.append(
" :: ");
4095 newScopeInfo->name.append(nextScopeNameAddition);
4096 nextScopeNameAddition =
"";
4100 tok->
scopeInfo(std::move(newScopeInfo));
4122 std::unordered_map<std::string, nonneg int> mVariableId;
4123 std::unordered_map<std::string, nonneg int> mVariableId_global;
4124 std::stack<std::vector<std::pair<std::string, nonneg int>>> mScopeInfo;
4125 mutable nonneg int mVarId{};
4127 VariableMap() =
default;
4130 void addVariable(
const std::string& varname,
bool globalNamespace);
4131 bool hasVariable(
const std::string& varname)
const {
4132 return mVariableId.find(varname) != mVariableId.end();
4135 const std::unordered_map<std::string, nonneg int>& map(
bool global)
const {
4136 return global ? mVariableId_global : mVariableId;
4145 void VariableMap::enterScope()
4147 mScopeInfo.emplace();
4150 bool VariableMap::leaveScope()
4152 if (mScopeInfo.empty())
4155 for (
const std::pair<std::string, nonneg int>& outerVariable : mScopeInfo.top()) {
4156 if (outerVariable.second != 0)
4157 mVariableId[outerVariable.first] = outerVariable.second;
4159 mVariableId.erase(outerVariable.first);
4165 void VariableMap::addVariable(
const std::string& varname,
bool globalNamespace)
4167 if (mScopeInfo.empty()) {
4168 mVariableId[varname] = ++mVarId;
4169 if (globalNamespace)
4170 mVariableId_global[varname] = mVariableId[varname];
4173 std::unordered_map<std::string, nonneg int>::iterator it = mVariableId.find(varname);
4174 if (it == mVariableId.end()) {
4175 mScopeInfo.top().emplace_back(varname, 0);
4176 mVariableId[varname] = ++mVarId;
4177 if (globalNamespace)
4178 mVariableId_global[varname] = mVariableId[varname];
4181 mScopeInfo.top().emplace_back(varname, it->second);
4182 it->second = ++mVarId;
4187 const Token*
const tok1 = tok;
4192 nonneg int typeCount = 0;
4193 nonneg int singleNameCount = 0;
4194 bool hasstruct =
false;
4195 bool bracket =
false;
4213 singleNameCount = 0;
4216 }
else if (!hasstruct && variableMap.map(
false).count(tok2->
str()) && tok2->
previous()->
str() !=
"::") {
4218 tok2 = tok2->
next();
4219 if (!tok2 || tok2->
str() !=
"::")
4228 const Token *start = tok;
4232 if (closingBracket ==
nullptr) {
4235 tok2 = closingBracket;
4236 if (tok2->
str() !=
">")
4238 singleNameCount = 1;
4252 tok3 = tok3->
link();
4253 if (tok3->
str() ==
",")
4261 }
else if (tok2->
str() ==
"::") {
4262 singleNameCount = 0;
4263 }
else if (tok2->
str() !=
"*" && tok2->
str() !=
"...") {
4266 tok2 = tok2->
next();
4270 bool isLambdaArg =
false;
4273 if (tok3 && tok3->
str() ==
",") {
4276 tok3 = tok3->
link();
4287 if (!
Token::Match(fdecl,
"[;{}] %name%") || count <= 1)
4302 if (executableScope && ref && !isLambdaArg) {
4305 else if (tok2->
str() !=
")" || tok2->
link()->strAt(-1) !=
"catch")
4312 if (typeCount >= 2 && executableScope &&
Token::Match(tok2,
")| [")) {
4313 const Token *tok3 = tok2->
str() ==
")" ? tok2->
next() : tok2;
4314 while (tok3 && tok3->
str() ==
"[") {
4315 tok3 = tok3->
link()->next();
4323 return (typeCount >= 2 && tok2 &&
Token::Match(tok2->
tokAt(-2),
"!!:: %type%"));
4328 std::map<
nonneg int, std::map<std::string, nonneg int>>& structMembers,
4335 if (struct_varid == 0)
4338 std::map<std::string, nonneg int>& members = structMembers[struct_varid];
4340 tok = tok->
tokAt(3);
4341 while (tok->
str() !=
"}") {
4346 const std::map<std::string, nonneg int>::iterator it = members.find(tok->
str());
4347 if (it == members.end()) {
4348 members[tok->
str()] = ++varId;
4351 tok->
varId(it->second);
4364 tok = tok->
tokAt(3);
4368 tok = tok->
tokAt(2);
4369 if (struct_varid == 0)
4372 if (tok->
str() ==
".")
4379 std::map<std::string, nonneg int>& members = structMembers[struct_varid];
4380 const std::map<std::string, nonneg int>::iterator it = members.find(tok->
str());
4381 if (it == members.end()) {
4382 members[tok->
str()] = ++varId;
4385 tok->
varId(it->second);
4393 VariableMap& variableMap,
4394 const nonneg int scopeStartVarId,
4395 std::map<
nonneg int, std::map<std::string, nonneg int>>& structMembers)
4398 const Token*
const endToken = startToken->
link();
4401 std::string className;
4403 if (!tok->
isName() && tok->
str() !=
":")
4405 if (
Token::Match(tok,
"class|struct|enum %type% [:{]")) {
4406 className = tok->
next()->
str();
4412 int indentlevel = 0;
4413 bool initList =
false;
4414 bool inEnum =
false;
4415 const Token *initListArgLastToken =
nullptr;
4416 for (
Token *tok = startToken->
next(); tok != endToken; tok = tok->
next()) {
4420 if (tok == initListArgLastToken)
4421 initListArgLastToken =
nullptr;
4422 else if (!initListArgLastToken &&
4425 initListArgLastToken = tok->
link();
4427 if (tok->
str() ==
"{") {
4429 if (initList && !initListArgLastToken)
4432 }
else if (tok->
str() ==
"}") {
4435 }
else if (initList && indentlevel == 0 &&
Token::Match(tok->
previous(),
"[,:] %name% [({]")) {
4436 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(
false).find(tok->
str());
4437 if (it != variableMap.map(
false).end()) {
4438 tok->
varId(it->second);
4440 }
else if (tok->
isName() && tok->
varId() <= scopeStartVarId) {
4441 if (indentlevel > 0 || initList) {
4446 if (tok->
next()->
str() ==
"::") {
4447 if (tok->
str() == className)
4448 tok = tok->
tokAt(2);
4454 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(
false).find(tok->
str());
4455 if (it != variableMap.map(
false).end()) {
4456 tok->
varId(it->second);
4461 }
else if (indentlevel == 0 && tok->
str() ==
":" && !initListArgLastToken)
4472 Token *
const startToken,
4473 const Token *
const endToken,
4474 const std::map<std::string, nonneg int> &varlist,
4475 std::map<
nonneg int, std::map<std::string, nonneg int>>& structMembers,
4478 const auto pos = classname.rfind(
' ');
4479 const std::string lastScope = classname.substr(pos == std::string::npos ? 0 : pos + 1);
4480 for (
Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->
next()) {
4492 const std::map<std::string, nonneg int>::const_iterator it = varlist.find(tok2->
str());
4493 if (it != varlist.end()) {
4494 tok2->
varId(it->second);
4519 #define NOTSTART_C "NOT", "case", "default", "goto", "not", "return", "sizeof", "typedef"
4522 "delete",
"friend",
"new",
"throw",
"using",
"virtual",
"explicit",
"const_cast",
"dynamic_cast",
"reinterpret_cast",
"static_cast",
"template"
4530 VariableMap variableMap;
4531 std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
4533 std::stack<VarIdScopeInfo> scopeStack;
4535 scopeStack.emplace();
4536 std::stack<const Token *> functionDeclEndStack;
4537 const Token *functionDeclEndToken =
nullptr;
4538 bool initlist =
false;
4539 bool inlineFunction =
false;
4546 tok = closingBracket;
4550 if (tok == functionDeclEndToken) {
4551 functionDeclEndStack.pop();
4552 functionDeclEndToken = functionDeclEndStack.empty() ? nullptr : functionDeclEndStack.top();
4553 if (tok->
str() ==
":")
4555 else if (tok->
str() ==
";") {
4556 if (!variableMap.leaveScope())
4558 }
else if (tok->
str() ==
"{") {
4559 scopeStack.emplace(
true, scopeStack.top().isStructInit || tok->
strAt(-1) ==
"=",
false, variableMap.getVarId());
4563 if (ifToken && ifToken->
str() ==
")")
4564 ifToken = ifToken->
link();
4569 if (ifToken && ifToken->
str() ==
"if") {
4571 variableMap.enterScope();
4574 }
else if (!initlist && tok->
str()==
"(") {
4575 const Token * newFunctionDeclEnd =
nullptr;
4576 if (!scopeStack.top().isExecutable)
4579 const Token* tokenLinkNext = tok->
link()->next();
4581 tokenLinkNext = tokenLinkNext->
next();
4583 tokenLinkNext = tokenLinkNext->
next();
4585 tokenLinkNext = tokenLinkNext->
link()->next();
4588 if (tokenLinkNext && tokenLinkNext->
str() ==
"{")
4589 newFunctionDeclEnd = tokenLinkNext;
4591 if (newFunctionDeclEnd && newFunctionDeclEnd != functionDeclEndToken) {
4592 functionDeclEndStack.push(newFunctionDeclEnd);
4593 functionDeclEndToken = newFunctionDeclEnd;
4594 variableMap.enterScope();
4597 inlineFunction =
false;
4599 const Token *
const startToken = (tok->
str() ==
"{") ? tok : tok->
link();
4605 if (tok->
str() ==
"{") {
4612 (initlist && tok->
strAt(-1) ==
"}")) {
4613 isExecutable =
true;
4615 isExecutable = ((scopeStack.top().isExecutable || initlist || tok->
strAt(-1) ==
"else") &&
4617 if (!(scopeStack.top().isStructInit || tok->
strAt(-1) ==
"="))
4618 variableMap.enterScope();
4621 scopeStack.emplace(isExecutable, scopeStack.top().isStructInit || tok->
strAt(-1) ==
"=",
isEnumStart(tok), variableMap.getVarId());
4623 bool isNamespace =
false;
4625 if (tok1->
str() ==
"namespace") {
4631 if (!initlist && !
isC() && !scopeStack.top().isExecutable && tok->
link() && !isNamespace) {
4634 scopeStack.top().startVarid,
4640 if (!scopeStack.top().isStructInit) {
4641 variableMap.leaveScope();
4645 if (ifToken && ifToken->
str() ==
")")
4646 ifToken = ifToken->
link()->previous();
4649 if (startToken->
strAt(-1) ==
"else" || (ifToken && ifToken->
str() ==
"if" && tok->
strAt(1) !=
"else")) {
4651 variableMap.leaveScope();
4656 if (scopeStack.empty()) {
4657 scopeStack.emplace();
4663 if ((!scopeStack.top().isStructInit &&
4666 (tok->
str() ==
"(" && !scopeStack.top().isExecutable &&
isFunctionHead(tok,
";:")) ||
4667 (tok->
str() ==
"," && (!scopeStack.top().isExecutable || inlineFunction || !tok->
previous()->
varId())) ||
4684 tok2 = tok2->
next();
4690 if (notstart.find(tok2->
str()) != notstart.end())
4702 while (tok2 && tok2->
str() !=
"]") {
4704 variableMap.addVariable(tok2->
str(),
false);
4705 tok2 = tok2->
next();
4713 }
catch (
const Token * errTok) {
4717 if (tok->
str() ==
"(" &&
isFunctionHead(tok,
"{") && scopeStack.top().isExecutable)
4718 inlineFunction =
true;
4723 for (
Token *declTok = declTypeTok->
linkAt(1); declTok != declTypeTok; declTok = declTok->
previous()) {
4724 if (declTok->isName() && !
Token::Match(declTok->previous(),
"::|.") && variableMap.hasVariable(declTok->str()))
4725 declTok->varId(variableMap.map(
false).find(declTok->str())->second);
4737 if (prev2->
isCpp() &&
4743 if (!scopeStack.top().isExecutable) {
4748 if (tok3->
str() ==
"=") {
4753 if (tok3->
str() ==
",") {
4762 (tok3->
isName() && (variableMap.hasVariable(tok3->
str()) ||
4765 tok3->
str() ==
"(" ||
4766 notstart.find(tok3->
str()) != notstart.end()) {
4775 if (tok2->
link() != tok2->
next() &&
4784 variableMap.addVariable(prev2->
str(), scopeStack.size() <= 1);
4787 for (
const Token *tok3 = prev2->
next(); tok3 && tok3->
str() !=
";"; tok3 = tok3->
next()) {
4789 tok3 = tok3->
link();
4791 variableMap.addVariable(tok3->
next()->
str(),
false);
4799 if (tok && tok->
str() ==
"<") {
4801 while (tok != end) {
4804 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(
false).find(tok->
str());
4805 if (it != variableMap.map(
false).end())
4806 tok->
varId(it->second);
4822 bool globalNamespace =
false;
4827 globalNamespace =
true;
4836 if (scopeStack.top().isExecutable &&
Token::Match(tok,
"%name% [,)[]")) {
4843 if (start->
str() ==
"(") {
4852 if (start->
varId() > 0)
4860 const bool isNotstartKeyword = start->
next() && notstart.find(start->
next()->
str()) != notstart.end();
4872 const std::unordered_map<std::string, nonneg int>::const_iterator it = variableMap.map(globalNamespace).find(tok->
str());
4873 if (it != variableMap.map(globalNamespace).end()) {
4874 tok->
varId(it->second);
4884 }
while (tok && (tok->
isName() || tok->
str() ==
","));
4891 mVarId = variableMap.getVarId();
4896 Member(std::list<std::string> s, std::list<const Token *> ns,
Token *t) : usingnamespaces(std::move(ns)), scope(std::move(s)), tok(t) {}
4897 std::list<const Token *> usingnamespaces;
4898 std::list<std::string> scope;
4907 ret += (ret.empty() ?
"" :
" :: ") + (si.name);
4913 std::list<ScopeInfo2>::const_iterator scopeIt = scopeInfo.cbegin();
4916 for (std::list<std::string>::const_iterator it = scope.cbegin(); it != scope.cend(); ++it) {
4917 if (scopeIt == scopeInfo.cend() || scopeIt->name != *it)
4925 if (scopeIt != scopeInfo.end() && nsToken->
str() == scopeIt->name) {
4926 nsToken = nsToken->
tokAt(2);
4934 if (scopeIt == scopeInfo.end() || nsToken->
str() != scopeIt->name)
4940 while (scopeIt != scopeInfo.end()) {
4943 if (memberToken->
str() != scopeIt->name)
4945 if (memberToken->
next()->
str() ==
"<") {
4950 memberToken = memberToken->
tokAt(2);
4954 return Token::Match(memberToken,
"~| %name%") ? memberToken :
nullptr;
4959 if (scopeInfo.empty())
4968 for (
const Token *ns : member.usingnamespaces) {
4990 return Token::Match(tok,
"~| %name% (") ? tok :
nullptr;
4993 template<
typename T>
4996 T*
const start = tok;
4998 tok = tok->
tokAt(tok->strAt(1) ==
"::" ? 1 : 2);
5000 tok = tok->
tokAt(2);
5003 const bool isTemplate = tok->
str() ==
"<";
5004 tok = tok->link()->next();
5005 if (isTemplate && tok && tok->link())
5006 tok = tok->link()->next();
5013 std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
5016 std::list<Member> allMemberFunctions;
5017 std::list<Member> allMemberVars;
5019 std::map<const Token *, std::string> endOfScope;
5020 std::list<std::string> scope;
5021 std::list<const Token *> usingnamespaces;
5024 if (
Token::Match(tok,
"using namespace %name% ::|;")) {
5027 endtok = endtok->
tokAt(2);
5029 usingnamespaces.push_back(tok->
tokAt(2));
5034 scope.push_back(tok->
strAt(1));
5039 if (tok->
str() ==
"}") {
5040 const std::map<const Token *, std::string>::iterator it = endOfScope.find(tok);
5041 if (it != endOfScope.end())
5042 scope.remove(it->second);
5045 Token*
const tok1 = tok;
5060 if (tok->
str() ==
"~")
5072 allMemberFunctions.emplace_back(scope, usingnamespaces, tok1);
5074 allMemberVars.emplace_back(scope, usingnamespaces, tok1);
5078 std::list<ScopeInfo2> scopeInfo;
5081 std::map<std::string, std::map<std::string, nonneg int>> varsByClass;
5083 while (tok->
str() ==
"}" && !scopeInfo.empty() && tok == scopeInfo.back().bodyEnd)
5084 scopeInfo.pop_back();
5086 if (!
Token::Match(tok,
"namespace|class|struct %name% {|:|::|<"))
5090 const std::string scopeName2(scopeName.empty() ? std::string() : (scopeName +
" :: "));
5092 std::list<const Token*> classnameTokens{ tok->
next() };
5094 while (
Token::Match(tokStart,
":: %name%") || tokStart->
str() ==
"<") {
5095 if (tokStart->
str() ==
"<") {
5100 tokStart = closeTok->
next();
5102 classnameTokens.push_back(tokStart->
next());
5103 tokStart = tokStart->
tokAt(2);
5107 std::string classname;
5108 for (
const Token *it : classnameTokens)
5109 classname += (classname.empty() ?
"" :
" :: ") + it->
str();
5111 std::map<std::string, nonneg int> &thisClassVars = varsByClass[scopeName2 + classname];
5116 tokStart = tokStart->
next();
5120 std::string baseClassName = tokStart->
str();
5121 const Token* baseStart = tokStart;
5123 baseClassName.insert(0, baseStart->
strAt(-2) +
" :: ");
5124 baseStart = baseStart->
tokAt(-2);
5126 std::string scopeName3(scopeName2);
5127 while (!scopeName3.empty()) {
5128 const std::string name = scopeName3 + baseClassName;
5129 if (varsByClass.find(name) != varsByClass.end()) {
5130 baseClassName = name;
5134 if (scopeName3.size() <= 8)
5136 scopeName3.erase(scopeName3.size() - 4);
5137 const std::string::size_type pos = scopeName3.rfind(
" :: ");
5138 if (pos == std::string::npos)
5140 scopeName3.erase(pos + 4);
5142 const std::map<std::string, nonneg int>& baseClassVars = varsByClass[baseClassName];
5143 thisClassVars.insert(baseClassVars.cbegin(), baseClassVars.cend());
5145 tokStart = tokStart->
next();
5151 std::transform(classnameTokens.cbegin(), classnameTokens.cend(), std::back_inserter(scopeInfo), [&](
const Token* tok) {
5152 return ScopeInfo2(tok->str(), tokStart->link());
5155 for (
Token *tok2 = tokStart->
next(); tok2 && tok2 != tokStart->
link(); tok2 = tok2->
next()) {
5158 if (tok2->
str() ==
"(") {
5162 tok2 = funcstart->
link();
5167 if (tok2->
strAt(-1) ==
")")
5169 tok2 = tok2->
link();
5171 tok2 = tok2->
link();
5177 tok2 = tok2->
link();
5183 else if (tok2->
varId() > 0)
5184 thisClassVars[tok2->
str()] = tok2->
varId();
5188 if (thisClassVars.empty())
5192 for (
const Member &var : allMemberVars) {
5196 if (tok2->
varId() == 0)
5197 tok2->
varId(thisClassVars[tok2->
str()]);
5200 if (
isC() || tok->
str() ==
"namespace")
5204 for (
const Member &func : allMemberFunctions) {
5209 if (tok2->
str() ==
"~")
5229 tok3 = tok3->
tokAt(2);
5231 tok3 = tok3->
next();
5233 tok3 = tok3->
tokAt(2);
5238 const std::map<std::string, nonneg int>::const_iterator varpos = thisClassVars.find(tok3->
str());
5239 if (varpos != thisClassVars.end())
5240 tok3->
varId(varpos->second);
5243 if (tok3->
strAt(1) ==
"<") {
5257 static void linkBrackets(
const Tokenizer & tokenizer, std::stack<const Token*>& type, std::stack<Token*>& links,
Token *
const token,
const char open,
const char close)
5259 if (token->
str()[0] == open) {
5262 }
else if (token->
str()[0] == close) {
5263 if (links.empty()) {
5267 if (type.top()->str()[0] != open) {
5279 std::stack<const Token*> type;
5280 std::stack<Token*> links1;
5281 std::stack<Token*> links2;
5282 std::stack<Token*> links3;
5284 if (token->link()) {
5285 token->link(
nullptr);
5295 if (!links1.empty()) {
5300 if (!links2.empty()) {
5305 if (!links3.empty()) {
5316 bool isStruct =
false;
5318 std::stack<Token*> type;
5319 std::stack<Token*> templateTokens;
5326 if (token->link()) {
5329 else if (!type.empty() &&
Token::Match(token,
"}|]|)")) {
5330 while (type.top()->str() ==
"<") {
5331 if (!templateTokens.empty() && templateTokens.top()->next() == type.top())
5332 templateTokens.pop();
5337 }
else if (templateTokens.empty() && !isStruct &&
Token::Match(token,
"%oror%|&&|;")) {
5342 if (token->tokType() ==
Token::eLogicalOp && !type.empty() && type.top()->str() ==
"<") {
5344 bool foundComparison =
false;
5345 while (
Token::Match(prev,
"%name%|%num%|%str%|%cop%|)|]") && prev != type.top()) {
5346 if (prev->
str() ==
")" || prev->
str() ==
"]")
5347 prev = prev->
link();
5351 foundComparison =
true;
5354 if (prev == type.top() && foundComparison)
5357 foundComparison =
false;
5358 while (
Token::Match(next,
"%name%|%num%|%str%|%cop%|(|[") && next->
str() !=
">") {
5359 if (next->
str() ==
"(" || next->
str() ==
"[")
5360 next = next->
link();
5364 foundComparison =
true;
5365 next = next->
next();
5367 if (next && next->
str() ==
">" && foundComparison)
5371 while (!type.empty() && type.top()->str() ==
"<") {
5376 if (
Token::Match(end,
"> %var% ;") && (type.top()->tokAt(-2) ==
nullptr ||
Token::Match(type.top()->tokAt(-2),
";|}|{")))
5380 }
else if (token->str() ==
"<" &&
5381 ((token->previous() && (token->previous()->isTemplate() ||
5382 (token->previous()->isName() && !token->previous()->varId()) ||
5383 (token->strAt(-1) ==
"]" && (!
Token::Match(token->linkAt(-1)->previous(),
"%name%|)") || token->linkAt(-1)->previous()->isKeyword())) ||
5384 (token->strAt(-1) ==
")" && token->linkAt(-1)->strAt(-1) ==
"operator"))) ||
5387 if (token->previous()->str() ==
"template")
5388 templateTokens.push(token);
5389 }
else if (token->str() ==
">" || token->str() ==
">>") {
5390 if (type.empty() || type.top()->str() !=
"<")
5392 Token *
const top1 = type.top();
5394 Token *
const top2 = type.empty() ? nullptr : type.top();
5396 if (!top2 || top2->
str() !=
"<") {
5397 if (token->str() ==
">>")
5399 if (!
Token::Match(token->next(),
"%name%|%cop%|%assign%|::|,|(|)|{|}|;|[|]|:|.|=|?|...") &&
5404 if (token->str() ==
">>" && top1 && top2) {
5411 if (templateTokens.size() == 2 && (top1 == templateTokens.top() || top2 == templateTokens.top())) {
5412 templateTokens.pop();
5413 templateTokens.pop();
5417 if (
Token::Match(token,
"> %name%") && !token->next()->isKeyword() &&
5419 (templateTokens.empty() || top1 != templateTokens.top()))
5422 if (!templateTokens.empty() && top1 == templateTokens.top())
5423 templateTokens.pop();
5434 if (
Token::Match(tok,
"const_cast|dynamic_cast|reinterpret_cast|static_cast")) {
5452 endToken = endToken->
next();
5453 while (
Token::Match(endToken->
next(),
"%name%|%num%|%str%|[|(|.|::|++|--|!|~") || (
Token::Match(endToken,
"%type% * %op%|?|:|const|;|,"))) {
5455 endToken = endToken->
linkAt(1);
5457 endToken = endToken->
next();
5475 if (
Token::Match(tok,
"if|for|while|BOOST_FOREACH %name% (")) {
5480 }
else if (tok->
strAt(1) ==
"constexpr") {
5620 Token *lt =
nullptr;
5626 else if (lt &&
Token::Match(tok,
">|>> %name%|::|(")) {
5627 const Token *
const end = tok;
5628 for (tok = lt; tok != end; tok = tok->
next()) {
5743 if (tok->
str() ==
"(") {
5744 const Token *tok1 = tok;
5748 }
else if (tok->
str() ==
"@") {
5890 std::cout <<
"<debug>" << std::endl;
5906 std::cout <<
"</debug>" << std::endl;
5917 const Token * typetok = var->typeStartToken();
5918 while (typetok && typetok != var->typeEndToken())
5919 typetok = typetok->
next();
5921 if (typetok != var->typeEndToken()) {
5925 "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()));
5939 std::set<const Library::Container*> containers;
5941 outs +=
" <directivelist>";
5944 outs +=
" <directive ";
5948 outs +=
"linenr=\"";
5949 outs += std::to_string(dir.linenr);
5958 outs +=
" </directivelist>";
5962 outs +=
" <tokenlist>";
5965 outs +=
" <token id=\"";
5967 outs +=
"\" file=\"";
5969 outs +=
"\" linenr=\"";
5970 outs += std::to_string(tok->
linenr());
5971 outs +=
"\" column=\"";
5972 outs += std::to_string(tok->
column());
5979 outs +=
" scope=\"";
5983 outs +=
" type=\"name\"";
5985 outs +=
" isUnsigned=\"true\"";
5987 outs +=
" isSigned=\"true\"";
5989 outs +=
" type=\"number\"";
5991 outs +=
" isInt=\"true\"";
5993 outs +=
" isFloat=\"true\"";
5995 outs +=
" type=\"string\" strlen=\"";
6000 outs +=
" type=\"char\"";
6002 outs +=
" type=\"boolean\"";
6003 else if (tok->
isOp()) {
6004 outs +=
" type=\"op\"";
6006 outs +=
" isArithmeticalOp=\"true\"";
6008 outs +=
" isAssignmentOp=\"true\"";
6010 outs +=
" isComparisonOp=\"true\"";
6012 outs +=
" isLogicalOp=\"true\"";
6015 outs +=
" isCast=\"true\"";
6017 outs +=
" externLang=\"C\"";
6021 outs +=
" isTemplateArg=\"true\"";
6023 outs +=
" isRemovedVoidParameter=\"true\"";
6025 outs +=
" isSplittedVarDeclComma=\"true\"";
6027 outs +=
" isSplittedVarDeclEq=\"true\"";
6029 outs +=
" isImplicitInt=\"true\"";
6031 outs +=
" isComplex=\"true\"";
6033 outs +=
" isRestrict=\"true\"";
6035 outs +=
" isAtomic=\"true\"";
6037 outs +=
" isAttributeExport=\"true\"";
6039 outs +=
" isAttributeMaybeUnused=\"true\"";
6041 outs +=
" isAttributeUnused=\"true\"";
6047 if (tok->
varId() > 0) {
6048 outs +=
" varId=\"";
6049 outs += std::to_string(tok->
varId());
6053 outs +=
" exprId=\"";
6054 outs += std::to_string(tok->
exprId());
6058 outs +=
" variable=\"";
6063 outs +=
" function=\"";
6067 if (!tok->
values().empty()) {
6068 outs +=
" values=\"";
6073 outs +=
" type-scope=\"";
6078 outs +=
" astParent=\"";
6083 outs +=
" astOperand1=\"";
6088 outs +=
" astOperand2=\"";
6093 outs +=
" originalName=\"";
6107 outs +=
" noreturn=\"true\"";
6113 outs +=
" </tokenlist>";
6122 containers.erase(
nullptr);
6123 if (!containers.empty()) {
6124 outs +=
" <containers>";
6127 outs +=
" <container id=\"";
6129 outs +=
"\" array-like-index-op=\"";
6132 outs +=
"std-string-like=\"";
6137 outs +=
" </containers>";
6145 outs +=
" <typedef-info>";
6151 outs += typedefInfo.name;
6159 outs += std::to_string(typedefInfo.lineNumber);
6162 outs +=
" column=\"";
6163 outs += std::to_string(typedefInfo.column);
6167 outs += std::to_string(typedefInfo.used?1:0);
6173 outs +=
" </typedef-info>";
6205 std::set<std::string> keep;
6209 if (
Token::Match(closingBracket,
"> class|struct %name% {"))
6210 tok = closingBracket->
linkAt(3);
6216 if (!checkHeaders && tok->
fileIndex() != 0)
6220 keep.insert(tok->
str());
6225 keep.insert(tok->
str());
6229 const std::set<std::string> functionStart{
"static",
"const",
"unsigned",
"signed",
"void",
"bool",
"char",
"short",
"int",
"long",
"float",
"*"};
6232 const bool isIncluded = (tok->
fileIndex() != 0);
6238 while (prev && prev->
isName())
6250 if (isIncluded && removeUnusedIncludedFunctions) {
6253 while (start && functionStart.find(start->
str()) != functionStart.end())
6254 start = start->
next();
6263 if (isIncluded && removeUnusedIncludedClasses) {
6264 if (
Token::Match(tok,
"class|struct %name% [:{]") && keep.find(tok->
strAt(1)) == keep.end()) {
6267 if (endToken->
str() ==
":") {
6268 endToken = endToken->
next();
6270 endToken = endToken->
next();
6279 if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) {
6282 if (
Token::Match(closingBracket,
"> class|struct %name% [;:{]") && keep.find(closingBracket->
strAt(2)) == keep.end()) {
6283 const Token *endToken = closingBracket->
tokAt(3);
6284 if (endToken->
str() ==
":") {
6285 endToken = endToken->
next();
6287 endToken = endToken->
next();
6289 if (endToken && endToken->
str() ==
"{")
6290 endToken = endToken->
link()->next();
6291 if (endToken && endToken->
str() ==
";") {
6310 if (
Token::Match(tok,
"%name%|>|) .|:: template %name%")) {
6315 templateName = templateName->
next();
6321 if (templateName->
str() ==
"(" && templateName->
link())
6322 templateName->
link()->isTemplate(
true);
6333 line = prev->
str() +
" " + line;
6334 line +=
"!!!" + tok->
str() +
"!!!";
6336 line +=
" " + next->str();
6342 std::vector<std::pair<std::string, int>> vars;
6346 if (tok->
str() ==
"{")
6348 else if (tok->
str() ==
"}") {
6349 vars.erase(std::remove_if(vars.begin(), vars.end(), [scopeLevel](
const std::pair<std::string, int>& v) {
6350 return v.second == scopeLevel;
6355 vars.emplace_back(tok->
strAt(2), scopeLevel);
6359 return v.first == tok->previous()->str();
6367 if (endTok && endTok->
str() ==
">>") {
6370 }
else if (endTok && endTok->
str() ==
">>=") {
6375 }
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) {
6376 return v.first == tok->next()->str();
6395 if (tok->
str() ==
"(") {
6408 if (tok2 && tok2->
str() ==
"(")
6409 tok2 = tok2->
link()->next();
6416 !
Token::Match(tok2,
"requires|namespace|class|struct|union|private:|protected:|public:"))
6423 if (
Token::Match(tok2,
"namespace|class|struct|union")) {
6425 const Token *tok3 = tok2;
6427 tok3 = tok3->
next();
6428 if (tok3 && tok3->
str() ==
"{") {
6447 const Token *tok3 = tok2;
6449 tok3 = tok3->
tokAt(2);
6459 if (tok->
str() ==
"{") {
6461 while (prev && prev->
isName())
6463 if (prev && prev->
str() ==
")")
6490 if (!
Token::Match(tok,
"class|struct %name% %name% final| {|:"))
6495 if (nextIsUppercase && !afterNextIsUppercase)
6497 else if (!nextIsUppercase && afterNextIsUppercase)
6509 if (tok->
str() !=
")")
6511 const Token *macro = tok->
link() ? tok->
link()->previous() :
nullptr;
6512 if (!macro || !macro->
isName())
6527 bool goback =
false;
6539 const bool isAnonymousNS = tok->
strAt(1) ==
"{";
6540 if (tok->
strAt(3 - isAnonymousNS) ==
"}") {
6549 if (tok->
str() ==
"{") {
6556 tok = tok->
tokAt(2 - isAnonymousNS);
6564 if (tok->
link() && tok->
str() ==
"(") {
6596 }
else if (tok->
str()==
"while") {
6599 tokPossibleDo =
nullptr;
6601 tokPossibleDo = tokPossibleDo->
link();
6602 if (!tokPossibleDo || tokPossibleDo->
strAt(-1) !=
"do")
6604 }
else if (tok->
str()==
"do") {
6611 tokEnd=tokEnd->
next();
6612 if (!tokEnd || tokEnd->
str()!=
"while")
6620 if (tokEnd->
strAt(1) ==
"else") {
6622 if (!tokEndNextNext || tokEndNextNext->
str() ==
"}")
6624 if (tokEndNextNext->
str() ==
"if")
6641 Token *tokAfterCondition=tokCondition;
6642 if (commandWithCondition) {
6643 if (tokCondition->
str()==
"(")
6644 tokAfterCondition=tokCondition->
link();
6648 if (!tokAfterCondition || tokAfterCondition->
strAt(1) ==
"]")
6651 tokAfterCondition=tokAfterCondition->
next();
6652 if (!tokAfterCondition ||
Token::Match(tokAfterCondition,
")|}|,")) {
6658 Token * tokStatement = tokAfterCondition;
6661 tokStatement = tokStatement->
tokAt(2);
6662 else if (tokStatement->
str() ==
"case") {
6666 if (tokStatement->
str() !=
":")
6668 tokStatement = tokStatement->
next();
6674 Token * tokBracesEnd=
nullptr;
6675 if (tokStatement->
str() ==
"{") {
6677 if (tokStatement != tokAfterCondition) {
6681 tokBracesEnd = tokStatement->
link();
6694 tokBracesEnd = tokCloseBrace;
6699 if (tokEnd->
str()!=
"}") {
6704 tokEnd = tokEnd->
link();
6710 tokEnd=tokEnd->
next();
6712 if (!tokEnd || tokEnd->
str() !=
";") {
6728 tokBracesEnd=tokCloseBrace;
6731 return tokBracesEnd;
6743 !(tok->
strAt(-1) ==
":" || tok->
strAt(-1) ==
"," || tok->
strAt(-1) ==
"::")) {
6747 std::map<std::string, Token *> argumentNames;
6748 bool bailOut =
false;
6749 Token * tokparam =
nullptr;
6752 const std::string& funcName(tok->
str());
6757 while (
nullptr != (tok1 = tok1->
tokAt(2))) {
6764 if (argumentNames.find(tok1->
str()) != argumentNames.end())
6766 else if (tok1->
str() != funcName)
6767 argumentNames[tok1->
str()] = tok1;
6769 if (tok1->
next()->
str() ==
")") {
6771 tok1 = tok1->
tokAt(-2);
6780 tok1 = tok1->
tokAt(-2);
6785 if (tok1->
next()->
str() ==
")") {
6786 tok1 = tok1->
tokAt(2);
6788 if (!tok1 || !tok1->
isName())
6802 tok1 = tok->
link()->next();
6805 for (
const Token* tok2 = tok1; tok2; tok2 = tok2->
next()) {
6808 if (tok2->
str() ==
"{") {
6820 std::map<std::string, Token *> argumentNames2;
6822 while (tok1 && tok1->
str() !=
"{") {
6827 if (tok1->
str() ==
";") {
6832 while (tok2->
str() ==
"]")
6833 tok2 = tok2->
link()->previous();
6841 if (argumentNames2.find(tok2->
str()) != argumentNames2.end()) {
6845 argumentNames2[tok2->
str()] = tok2;
6847 if (argumentNames.find(tok2->
str()) == argumentNames.end()) {
6853 tok1 = tok1->
next();
6856 if (bailOut || !tok1) {
6863 if (argumentNames.size() != argumentNames2.size()) {
6866 for (
const std::pair<const std::string, Token *>& argumentName : argumentNames) {
6867 if (argumentNames2.find(argumentName.first) == argumentNames2.end()) {
6872 argumentNames2[argumentName.first] = tok1->
next();
6878 while (tok->
str() !=
")") {
6881 Token *declEnd = declStart;
6884 while (declEnd->
next()->
str() !=
";" && declEnd->
next()->
str() !=
"{")
6885 declEnd = declEnd->
next();
6894 tok = declEnd->
next();
6897 if (tok->
str() ==
",")
6939 if (
Token::Match(tok,
"( %type% %type%| *| *| ( * ) (") ||
6940 Token::Match(tok,
"static_cast < %type% %type%| *| *| ( * ) (")) {
6943 if (tok1->
isCpp() && tok1->
str() ==
"static_cast")
6944 tok1 = tok1->
next();
6946 tok1 = tok1->
next();
6949 tok1 = tok1->
next();
6951 while (tok1->
next()->
str() ==
"*")
6952 tok1 = tok1->
next();
6969 if (
Token::Match(tok,
"delete|else|return|throw|typedef"))
6977 tok2 = tok2->
next();
6978 if (!tok2 || tok2->
str() !=
"(")
6981 tok2 = tok2->
tokAt(2);
6984 tok2 = tok2->
tokAt(2);
6985 if (tok2->
str() ==
"*")
6986 tok2 = tok2->
next();
6988 tok2 = tok2->
next();
6995 while (tok && tok->
str() !=
"(")
6999 if (!tok || !tok->
link() || !tok->
link()->next()) {
7002 Token *endTok = tok->
link()->next()->link();
7004 endTok = endTok->
linkAt(2);
7005 if (!
Token::Match(endTok,
") const|volatile| const|volatile| ;|,|)|=|[|{"))
7016 tok->
link()->deleteThis();
7026 if (tok3->
str() ==
"<" && tok3->
link())
7027 tok3 = tok3->
link();
7029 tok3 = tok3->
link();
7030 else if (tok3->
str() ==
"(") {
7031 tok3 = tok3->
link();
7033 tok3 = tok3->
next();
7060 bool finishedwithkr =
true;
7061 bool scopeDecl =
false;
7062 for (
Token *tok = tokBegin; tok != tokEnd; tok = tok->
next()) {
7075 !
Token::Match(tok,
"else|try|do|const|constexpr|override|volatile|noexcept"))) {
7083 lambdaStart = lambdaStart->
link();
7104 if (only_k_r_fpar && finishedwithkr) {
7113 }
else if (tok->
str() ==
"(") {
7115 for (
Token * tok2 = tok; tok2 && tok2 != tok->
link(); tok2 = tok2->
next()) {
7119 Token * lambdaBody = tok2;
7120 while (lambdaBody && lambdaBody != tok2->
link() && lambdaBody->
str() !=
"{")
7121 lambdaBody = lambdaBody->
next();
7122 if (lambdaBody && lambdaBody != tok2->
link() && lambdaBody->
link())
7140 if (
Token::Match(type0,
"else|return|public:|protected:|private:"))
7142 if (isCPP11 && type0->
str() ==
"using")
7147 bool isconst =
false;
7148 bool isstatic =
false;
7149 Token *tok2 = type0;
7153 tok2 = tok2->
next();
7160 tok2 = tok2->
next();
7171 tok2 = tok2->
next();
7178 if (tok2->
strAt(1) ==
"*")
7184 tok2 = tok2->
next();
7189 if (
Token::Match(tok2,
"%type% *|&| %name% , %type% *|&| %name%"))
7193 tok2 = tok2->
next();
7200 tok2 = tok2->
next();
7210 tok2 = tok2->
tokAt(2);
7213 int indentlevel = 0;
7216 for (
Token *tok3 = tok2; tok3; tok3 = tok3->
next()) {
7219 if (!parens && tok3->
str() ==
"<") {
7221 }
else if (!parens && tok3->
str() ==
">") {
7222 if (indentlevel == 0) {
7223 tok2 = tok3->
next();
7227 }
else if (!parens && tok3->
str() ==
">>") {
7228 if (indentlevel <= 1) {
7229 tok2 = tok3->
next();
7233 }
else if (tok3->
str() ==
"(") {
7235 }
else if (tok3->
str() ==
")") {
7241 }
else if (tok3->
str() ==
";") {
7248 tok2 = tok2->
next();
7259 Token *varName = tok2;
7261 varName = varName->
next();
7267 bool isPointerOrRef =
false;
7269 isPointerOrRef =
true;
7270 varName = varName->
next();
7274 if (varName->
str() !=
"const" && varName->
str() !=
"volatile") {
7277 varName = varName->
next();
7283 Token *endDecl = varName->
link()->linkAt(1);
7284 varName = varName->
link()->previous();
7286 endDecl = endDecl->
next();
7294 if (varName->
str() !=
"operator") {
7295 tok2 = varName->
next();
7297 if (tok2->
str() ==
"=" && (isstatic || (isconst && !isPointerOrRef))) {
7299 while (tok2 && tok2->
str() !=
"," && tok2->
str() !=
";") {
7301 tok2 = tok2->
link();
7302 const Token *tok3 = tok2;
7308 tok2 = tok2->
next();
7310 if (tok2 && tok2->
str() ==
";")
7319 tok2 = varName->
next();
7322 tok2 = tok2->
link()->next();
7325 if (tok2 && tok2->
str() ==
"=") {
7326 while (tok2 && tok2->
str() !=
"," && tok2->
str() !=
";") {
7328 tok2 = tok2->
link();
7329 tok2 = tok2->
next();
7331 if (tok2 && tok2->
str() ==
";")
7338 tok2 = varName->
next();
7339 tok2 = tok2->
link();
7341 tok2 = tok2->
next();
7342 if (tok2 && tok2->
str() !=
",")
7349 while (
Token::Match(commaTok,
"const|noexcept|override|final")) {
7350 commaTok = commaTok->
next();
7352 commaTok = commaTok->
link()->next();
7365 finishedwithkr =
false;
7369 if (tok2->
str() ==
",") {
7381 tok2 = tok2->
link();
7386 else if (std::strchr(
";,", tok2->
str()[0])) {
7390 varTok = varTok->
next();
7398 if (tok2->
str() ==
",") {
7406 tok2 = tok2->
next();
7409 finishedwithkr = (only_k_r_fpar && tok2 && tok2->
strAt(1) ==
"{");
7417 const std::string qualifiers[] = {
"extern",
"static",
"const"};
7422 bool continue2 =
false;
7423 for (
int i = 0; i <
sizeof(qualifiers)/
sizeof(qualifiers[0]); i++) {
7426 if (!tok->
next() || tok->
next()->
str() != qualifiers[i])
7430 Token* leftTok = tok;
7431 bool behindOther =
false;
7432 for (; leftTok; leftTok = leftTok->
previous()) {
7433 for (
int j = 0; j <= i; j++) {
7434 if (leftTok->
str() == qualifiers[j]) {
7449 (
isCPP() &&
Token::Match(leftTok,
"private:|protected:|public:|operator|template"))) {
7458 if (leftTok && !behindOther && !
Token::Match(leftTok,
";|{|}|(|,|private:|protected:|public:")) {
7469 }
else if (leftTok->
next()) {
7471 tok = leftTok->
next();
7485 if (
Token::Match(tok,
"%name% = %name% = %num%|%name% ;")) {
7489 tok2->
str() ==
"=" &&
7491 tok2 = tok2->
tokAt(-2);
7494 if (!tok2 || tok2->
str() !=
";") {
7500 const std::string& value(valueTok->
str());
7501 tok2 = tok2->
next();
7503 while (tok2 != stopAt) {
7506 tok2 = tok2->
tokAt(4);
7514 std::make_pair(
"and",
"&&")
7515 , std::make_pair(
"and_eq",
"&=")
7516 , std::make_pair(
"bitand",
"&")
7517 , std::make_pair(
"bitor",
"|")
7518 , std::make_pair(
"not_eq",
"!=")
7519 , std::make_pair(
"or",
"||")
7520 , std::make_pair(
"or_eq",
"|=")
7521 , std::make_pair(
"xor",
"^")
7522 , std::make_pair(
"xor_eq",
"^=")
7540 int executableScopeLevel = 0;
7542 std::vector<Token *> alt;
7543 bool replaceAll =
false;
7546 if (tok->
str() ==
")") {
7548 ++executableScopeLevel;
7549 tok =
const_cast<Token *
>(end);
7554 if (tok->
str() ==
"{") {
7555 if (executableScopeLevel > 0)
7556 ++executableScopeLevel;
7560 if (tok->
str() ==
"}") {
7561 if (executableScopeLevel > 0)
7562 --executableScopeLevel;
7569 const std::unordered_map<std::string, std::string>::const_iterator cOpIt =
cAlternativeTokens.find(tok->
str());
7577 if (!
Token::Match(tok->
previous(),
"%name%|%num%|%char%|)|]|> %name% %name%|%num%|%char%|%op%|("))
7581 if (executableScopeLevel == 0 &&
Token::Match(tok,
"%name% (")) {
7582 const Token *start = tok;
7600 (executableScopeLevel == 0U && tok->
strAt(-1) ==
"("))
7610 for (
Token *tok: alt) {
7611 const std::unordered_map<std::string, std::string>::const_iterator cOpIt =
cAlternativeTokens.find(tok->
str());
7613 tok->
str(cOpIt->second);
7614 else if (tok->
str() ==
"not")
7620 return !alt.empty();
7634 if (tok->
str() ==
"return")
7637 if (
Token::Match(tok,
"class|struct|union| %type% *| %name% ( &| %any% ) ;")) {
7639 }
else if (
Token::Match(tok,
"%type% *| %name% ( %type% (")) {
7642 tok2 = tok2->
next();
7645 }
else if (
Token::Match(tok,
"class|struct|union| %type% *| %name% ( &| %any% ) ,") && tok->
str() !=
"new") {
7647 while (tok1->
str() !=
",")
7648 tok1 = tok1->
next();
7651 const int numTokens = (
Token::Match(tok,
"class|struct|union")) ? 2U : 1U;
7662 if (tok->
strAt(2) !=
"*")
7671 if (tok->
str() ==
"*")
7675 if (tok->
str() ==
"sizeof")
7688 tok = tok->
tokAt(2);
7692 tok = tok->
tokAt(2);
7695 tok->
link()->deleteThis();
7706 if (tok->
str() !=
"else")
7715 if (tok->
strAt(1) !=
"if")
7718 for (
Token *tok2 = tok; tok2; tok2 = tok2->
next()) {
7720 tok2 = tok2->
link();
7723 if (tok2->
next() && tok2->
next()->
str() !=
"else") {
7749 semicolon = semicolon->
link();
7750 semicolon = semicolon->
next();
7752 if (semicolon->
str() !=
";")
7755 if (tok->
str() ==
"for") {
7761 bool rangeFor =
false;
7763 if (tok2->
str() ==
"(")
7764 tok2 = tok2->
link();
7765 else if (!rangeFor && tok2->
str() ==
"?")
7767 else if (tok2->
str() ==
":")
7769 tok2 = tok2->
next();
7771 if (!rangeFor || tok2->
str() !=
")")
7781 endscope = endscope->
linkAt(2);
7800 if (tok->
str() !=
"(")
7819 bool innerComma =
false;
7820 for (
const Token *inner = tok->
link()->previous(); inner != tok; inner = inner->
previous()) {
7821 if (inner->str() ==
")")
7822 inner = inner->link();
7823 if (inner->str() ==
",") {
7833 if (tok->
strAt(-2) !=
"operator" &&
7837 tok->
link()->deleteThis();
7847 tok->
link()->tokAt(-2)->deleteNext();
7853 tok->
link()->deleteThis();
7876 tok->
link()->deleteThis();
7884 tok->
link()->deleteThis();
7893 tok->
link()->deleteThis();
7909 tok2 = tok2->
tokAt(2);
7911 if (tok2 != tok->
link())
7925 tok->
link()->deleteThis();
7932 tok->
link()->deleteThis();
7938 if (
Token::Match(tok,
"( %bool%|%num% ) %cop%|;|,|)") &&
7939 tok->
strAt(-2) !=
"operator" &&
7943 tok->
link()->deleteThis();
7951 while (
Token::Match(tok2,
"%type%|static|const|extern") && tok2->
str() !=
"operator") {
7967 static const std::unordered_map<std::string, std::string> intrinsics = {
7968 {
"__has_nothrow_assign",
"has_nothrow_assign" },
7969 {
"__has_nothrow_constructor",
"has_nothrow_constructor" },
7970 {
"__has_nothrow_copy",
"has_nothrow_copy" },
7971 {
"__has_trivial_assign",
"has_trivial_assign" },
7972 {
"__has_trivial_constructor",
"has_trivial_constructor" },
7973 {
"__has_trivial_copy",
"has_trivial_copy" },
7974 {
"__has_trivial_destructor",
"has_trivial_destructor" },
7975 {
"__has_virtual_destructor",
"has_virtual_destructor" },
7976 {
"__is_abstract",
"is_abstract" },
7977 {
"__is_aggregate",
"is_aggregate" },
7978 {
"__is_assignable",
"is_assignable" },
7979 {
"__is_base_of",
"is_base_of" },
7980 {
"__is_class",
"is_class" },
7981 {
"__is_constructible",
"is_constructible" },
7982 {
"__is_convertible_to",
"is_convertible_to" },
7983 {
"__is_destructible",
"is_destructible" },
7984 {
"__is_empty",
"is_empty" },
7985 {
"__is_enum",
"is_enum" },
7986 {
"__is_final",
"is_final" },
7987 {
"__is_nothrow_assignable",
"is_nothrow_assignable" },
7988 {
"__is_nothrow_constructible",
"is_nothrow_constructible" },
7989 {
"__is_nothrow_destructible",
"is_nothrow_destructible" },
7990 {
"__is_pod",
"is_pod" },
7991 {
"__is_polymorphic",
"is_polymorphic" },
7992 {
"__is_trivially_assignable",
"is_trivially_assignable" },
7993 {
"__is_trivially_constructible",
"is_trivially_constructible" },
7994 {
"__is_union",
"is_union" },
7999 auto p = intrinsics.find(tok->
str());
8000 if (p == intrinsics.end())
8004 tok->
str(p->second);
8023 std::string unknownFunc;
8029 *unknown = !unknownFunc.empty();
8041 "checkLibraryNoReturn",
8042 "--check-library: Function " + unknownFunc +
"() should have <noreturn> configuration");
8083 tok->
strAt(1) +
" " +
8084 tok->
strAt(2) +
" " +
8085 tok->
strAt(3) +
"' is not handled. You can use -I or --include to add handling of this code.");
8092 "macroWithSemicolon",
8093 "Ensure that '" + macroName +
"' is defined either using -I, --include or -D.");
8104 std::string s = tok ? (
" " + tok->
str()) :
"";
8105 for (
int i = 0; i < s.size(); ++i) {
8106 if ((
unsigned char)s[i] >= 0x80)
8112 "nonStandardCharLiteral",
8113 "Non-standard character literal" + s +
". " + msg);
8157 for (
const Token *tok2 = tok->
tokAt(2); tok2 && tok2->
str() !=
")"; tok2 = tok2->
next()) {
8158 if (tok2->
str() ==
";") {
8163 tok2 = tok2->
link();
8174 if (
Token::Match(tok,
"const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
8180 tok2 = tok2->
next();
8188 if (
Token::Match(tok,
"template < class|typename %name% [,>]"))
8199 std::stack<const Token *> linkTokens;
8200 const Token *lastTok =
nullptr;
8204 if (tok->
link() ==
nullptr)
8207 linkTokens.push(tok);
8211 if (tok->
link() ==
nullptr)
8214 if (linkTokens.empty())
8217 if (tok->
link() != linkTokens.top())
8220 if (tok != tok->
link()->link())
8226 else if (tok->
link() !=
nullptr)
8230 if (!linkTokens.empty())
8240 std::stack<const Token *> ternaryOp;
8241 for (
const Token *tok = begin; tok != end && tok->
str() !=
";"; tok = tok->
next()) {
8242 if (tok->
str() ==
"?")
8243 ternaryOp.push(tok);
8244 else if (!ternaryOp.empty() && tok->
str() ==
":")
8253 return ternaryOp.empty() ? nullptr : ternaryOp.top();
8266 template<
typename T>
8272 return tok->next()->link();
8324 for (
const Token *inner = tok->
tokAt(2); inner != endTok; inner = inner->
next()) {
8326 inner = inner->
link();
8327 else if (inner->str() ==
";")
8337 for (
const Token *inner = tok->
tokAt(2); inner != endTok; inner = inner->
next()) {
8339 inner = inner->
link();
8340 else if (
Token::Match(inner->previous(),
"[,(] . %name% =|{"))
8346 std::set<std::string> possible;
8349 if (tok->
str() ==
"{") {
8351 while (prev && prev->
isName())
8353 if (prev && prev->
str() ==
")")
8357 }
else if (tok->
str() ==
"}")
8367 for (
const Token *tok2 = bodyStart; tok2 && tok2 != bodyEnd; tok2 = tok2->
next()) {
8373 if (possible.count(tok->
str()) == 0)
8374 possible.insert(tok->
str());
8417 if (tok2->
next()->
str() ==
"(") {
8430 static const std::unordered_set<std::string> nonConsecutiveKeywords{
"break",
8447 else if (tok->
str() ==
"[") {
8448 for (
const Token* inner = tok->
next(); inner != tok->
link(); inner = inner->next()) {
8450 inner = inner->link();
8471 else if (
Token::Match(tok,
"%name% throw|return") && std::isupper(tok->
str()[0]))
8475 else if (
Token::Match(tok,
"!!) %num%|%str%|%char% %assign%|++|--")) {
8480 if (tok->
link()->previous() && tok->
link()->previous()->isUpperCaseName())
8490 while (prev && prev->
str() !=
"(") {
8491 if (prev->
str() ==
")")
8492 prev = prev->
link();
8503 if (tok->
str() !=
"for") {
8510 if (tok->
isKeyword() && nonConsecutiveKeywords.count(tok->
str()) != 0) {
8511 if (
Token::Match(tok,
"%name% %name%") && nonConsecutiveKeywords.count(tok->
next()->
str()) == 1)
8513 const Token* prev = tok;
8514 while (prev && prev->
isName())
8530 tok2 = tok2->
next();
8534 tok2 = tok2->
next();
8536 syntaxError(tok2,
"Unexpected token '" + (tok2 ? tok2->
str() :
"") +
"'");
8544 static const std::unordered_set<std::string> nonGlobalKeywords{
"break",
8555 if (tok->
str() ==
"{")
8558 syntaxError(tok,
"keyword '" + tok->
str() +
"' is not allowed in global scope");
8568 const Token *switchToken = tok;
8573 for (; tok; tok = tok->
next()) {
8574 if (tok->
str() ==
"{") {
8579 if (tok->
str() ==
"}" && tok->
strAt(-1) ==
":")
8586 }
else if (tok->
str() ==
"(") {
8588 }
else if (tok->
str() ==
"case") {
8597 int semicolons = 0, colons = 0;
8598 const Token*
const startTok = tok;
8599 tok = tok->
next()->
link()->previous();
8601 for (; tok != startTok; tok = tok->
previous()) {
8602 if (tok->
str() ==
";") {
8604 }
else if (tok->
str() ==
":") {
8606 }
else if (tok->
str() ==
")") {
8615 if (semicolons == 0 && colons == 0)
8620 const Token *templateEndToken =
nullptr;
8622 if (!templateEndToken) {
8626 if (templateEndToken == tok)
8627 templateEndToken =
nullptr;
8637 bool match1 =
Token::Match(tok,
"%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|++|--|::|sizeof");
8638 bool match2 =
Token::Match(tok->
next(),
"{|if|else|while|do|for|return|switch|break");
8640 match1 = match1 ||
Token::Match(tok,
"throw|decltype|typeof");
8646 if (match1 && match2)
8649 if (
Token::Match(tok,
"%or%|%oror%|~|^|!|%comp%|+|-|/|%")) {
8654 code = tok->
str() +
"()";
8655 if (!code.empty()) {
8662 if (
Token::Match(tok,
"%assign% typename|class %assign%"))
8668 if (
Token::Match(tok,
"[;([{] %comp%|%oror%|%or%|%|/"))
8676 if (
Token::Match(tok->
previous(),
"(|[|{|<|%assign%|%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|::|sizeof"))
8680 if (
Token::Match(tok->
next(),
")|]|>|%assign%|%or%|%oror%|==|!=|/|>=|<=|&&"))
8719 for (
const Token* inner = tok->
next(); inner != end; inner = inner->
next()) {
8720 if (inner->str() ==
"{")
8721 inner = inner->link();
8733 if (tok->
str() ==
"typedef") {
8734 for (
const Token* tok2 = tok->
next(); tok2 && tok2->
str() !=
";"; tok2 = tok2->
next()) {
8735 if (tok2->
str() ==
"{") {
8736 tok2 = tok2->
link();
8763 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"))
8782 const Token *
const tok1 = tok;
8803 for (
const Token *tok = start; tok != end; tok = tok->
next()) {
8806 if (!allowSemicolon && tok->
str() ==
";")
8808 if (tok->
str() ==
"{")
8816 std::string str = source;
8818 for (std::string::size_type i = 0; i + 1U < str.size(); ++i) {
8824 if (str[i+1] ==
'x') {
8826 while (sz < 4 && std::isxdigit((
unsigned char)str[i+sz]))
8829 std::istringstream istr(str.substr(i+2, sz-2));
8830 istr >> std::hex >> c;
8836 std::istringstream istr(str.substr(i+1, sz-1));
8837 istr >> std::oct >> c;
8838 str = str.replace(i, sz, std::string(1U, (
char)c));
8844 else if (i+sz < str.size())
8845 str.replace(i, sz, std::string(1U, (
char)c));
8847 str.replace(i, str.size() - i - 1U,
"a");
8867 syntaxError(tryStartToken,
"Invalid function-try-catch block code. Did not find '{' for try body.");
8870 Token *
const tryEndToken = tryStartToken->
link();
8871 Token * endToken = tryEndToken;
8876 if (endToken->
str() !=
"{") {
8880 endToken = endToken->
link();
8882 if (!endToken || endToken == tryEndToken)
8891 static bool isAnonymousEnum(
const Token* tok)
8898 if (end->
str() ==
":") {
8908 const bool cpp =
isCPP();
8920 tok->
insertToken(
"Anonymous" + std::to_string(count++));
8926 if (tok1 &&
Token::Match(tok1->
link(),
"} const| *|&| const| %type% ,|;|[|(|{")) {
8927 tok->
insertToken(
"Anonymous" + std::to_string(count++));
8931 else if (isAnonymousEnum(tok)) {
8934 start->
next()->
link()->deleteThis();
8937 tok->
insertToken(
"Anonymous" + std::to_string(count++));
8942 std::stack<const Token*> scopeStart;
8943 const Token* functionEnd =
nullptr;
8948 if (tok->
str() ==
"{") {
8949 scopeStart.push(tok);
8951 functionEnd = tok->
link();
8955 else if (tok->
str() ==
"}") {
8956 if (!scopeStart.empty())
8958 if (tok == functionEnd)
8959 functionEnd =
nullptr;
8963 else if (
Token::Match(tok,
"class|struct|union|enum %type% :|{")) {
8971 next = next->
next();
8972 if (!next || next->
str() ==
";")
8979 if (
Token::Match(after->
next(),
"const|static|volatile| *|&| const| (| %type% )| ,|;|[|=|(|{")) {
8981 after = after->
next();
8982 while (!
Token::Match(start,
"struct|class|union|enum")) {
8984 after = after->
next();
8991 if (start->
str() !=
"class") {
8993 after = after->
next();
8996 after = after->
tokAt(2);
8999 after->
link()->deleteThis();
9006 after = after->
next();
9007 const bool isEnum = start->
str() ==
"enum";
9008 if (!isEnum && cpp) {
9010 after = after->
next();
9031 bool isClassStructUnionScope =
false;
9032 if (!scopeStart.empty()) {
9035 isClassStructUnionScope =
true;
9059 while (
Token::Match(tok,
"__cdecl|__stdcall|__fastcall|__thiscall|__clrcall|__syscall|__pascal|__fortran|__far|__near") || (windows &&
Token::Match(tok,
"WINAPI|APIENTRY|CALLBACK"))) {
9065 static bool isAttribute(
const Token* tok,
bool gcc) {
9066 return gcc ?
Token::Match(tok,
"__attribute__|__attribute (") :
Token::Match(tok,
"__declspec|_declspec (");
9069 static Token* getTokenAfterAttributes(
Token* tok,
bool gccattr) {
9071 while (isAttribute(after, gccattr))
9079 Token*
const after = getTokenAfterAttributes(tok, gccattr);
9084 Token *ftok = after;
9086 if (ftok->
str() ==
"<") {
9091 ftok = ftok->
next();
9094 ftok = ftok->
tokAt(2);
9103 return prev->
link()->previous();
9105 return prev->
link()->tokAt(-2);
9108 return prev->
link()->tokAt(-2);
9118 while (isAttribute(tok,
false)) {
9122 if (tok->
strAt(2) ==
"noreturn")
9124 else if (tok->
strAt(2) ==
"nothrow")
9129 }
else if (tok->
strAt(2) ==
"property")
9130 tok->
next()->
link()->insertToken(
"__property");
9147 while (isAttribute(tok,
true)) {
9150 for (
Token *attr = tok->
tokAt(2); attr->
str() !=
")"; attr = attr->next()) {
9152 attr = attr->linkAt(1);
9154 if (
Token::Match(attr,
"[(,] constructor|__constructor__ [,()]")) {
9160 else if (
Token::Match(attr,
"[(,] destructor|__destructor__ [,()]")) {
9166 else if (
Token::Match(attr,
"[(,] unused|__unused__|used|__used__ [,)]")) {
9167 Token *vartok =
nullptr;
9168 Token *after = getTokenAfterAttributes(tok,
true);
9174 prev = prev->
link()->previous();
9184 const std::string &attribute(attr->next()->str());
9185 if (attribute.find(
"unused") != std::string::npos)
9192 else if (
Token::Match(attr,
"[(,] pure|__pure__|const|__const__|noreturn|__noreturn__|nothrow|__nothrow__|warn_unused_result [,)]")) {
9196 const std::string &attribute(attr->next()->str());
9197 if (attribute.find(
"pure") != std::string::npos)
9199 else if (attribute.find(
"const") != std::string::npos)
9201 else if (attribute.find(
"noreturn") != std::string::npos)
9203 else if (attribute.find(
"nothrow") != std::string::npos)
9205 else if (attribute.find(
"warn_unused_result") != std::string::npos)
9225 if (tok->
str() !=
"(")
9232 if (attr.compare(attr.size()-2, 2,
"__") != 0)
9237 vartok = vartok->
next();
9239 vartok = vartok->
linkAt(1);
9252 if (tok->
tokAt(-2)) {
9253 tok = tok->
tokAt(-2);
9279 head = head->
next();
9288 head = head->
next();
9297 }
else if (
Token::Match(tok->
previous(),
") [ [ expects|ensures|assert default|audit|axiom| : %name% <|<=|>|>= %num% ] ]")) {
9299 if (vartok->
str() ==
":")
9300 vartok = vartok->
next();
9302 while (argtok && argtok->
str() !=
"(") {
9303 if (argtok->
str() == vartok->
str())
9305 if (argtok->
str() ==
")")
9306 argtok = argtok->
link();
9309 if (argtok && argtok->
str() == vartok->
str()) {
9310 if (vartok->
next()->
str() ==
">=")
9313 else if (vartok->
next()->
str() ==
">")
9316 else if (vartok->
next()->
str() ==
"<=")
9319 else if (vartok->
next()->
str() ==
"<")
9346 static const std::unordered_set<std::string> keywords = {
9373 if (keywords.find(tok->
str()) != keywords.end()) {
9376 const bool isinline = (tok->
str().find(
"inline") != std::string::npos);
9377 const bool isrestrict = (tok->
str().find(
"restrict") != std::string::npos);
9378 if (isinline || isrestrict) {
9381 temp->isInline(
true);
9383 temp->isRestrict(
true);
9391 if (tok->
str() ==
"auto")
9401 auto getTypeTokens = [tok]() {
9402 std::vector<Token*> ret;
9403 for (
Token *temp = tok;
Token::Match(temp,
"%name%"); temp = temp->previous()) {
9404 if (!temp->isKeyword())
9405 ret.emplace_back(temp);
9408 if (!temp->isKeyword())
9409 ret.emplace_back(temp);
9414 if (tok->
str() ==
"restrict") {
9415 for (
Token* temp: getTypeTokens())
9416 temp->isRestrict(
true);
9421 while (tok->
str() ==
"_Atomic") {
9422 for (
Token* temp: getTypeTokens())
9423 temp->isAtomic(
true);
9430 if (cpp20 && tok->
str() ==
"consteval") {
9432 tok->
str(
"constexpr");
9433 }
else if (cpp20 && tok->
str() ==
"constinit") {
9443 finalTok = finalTok->
next();
9448 finalTok = finalTok->
next();
9458 else if (
Token::Match(tok,
") const|override|final| noexcept :|{|;|,|const|override|final")) {
9462 while (tokNoExcept->
str() !=
"noexcept")
9463 tokNoExcept = tokNoExcept->
next();
9468 Token * braceStart = tokNoExcept->
next();
9469 tok = tok->
tokAt(3);
9475 else if (tok->
str() ==
"thread_local") {
9489 for (
Token* tok = start; tok != end; tok = tok->
next()) {
9500 static const std::unordered_map<std::string, TokenDebug> m = {{
"debug_valueflow",
TokenDebug::ValueFlow},
9505 auto it = m.find(tok->
str());
9506 if (it != m.end()) {
9508 tok = setTokenDebug(tok, it->second);
9517 const std::string &varname = tok->
next()->
str();
9520 int indentlevel = 0;
9522 while (
nullptr != (tok2 = tok2->
next())) {
9526 if (indentlevel <= 2)
9534 tok2 = tok2->
tokAt(-3);
9550 std::string instruction;
9558 else if (
Token::Match(tok,
"asm|__asm|__asm__ volatile|__volatile|__volatile__| (")) {
9561 if (partok->
str() !=
"(")
9562 partok = partok->
next();
9569 const Token *firstSemiColon =
nullptr;
9571 while (
Token::Match(endasm,
"%num%|%name%|,|:|;") || (endasm && endasm->
linenr() == comment)) {
9574 if (endasm->
str() ==
";") {
9575 comment = endasm->
linenr();
9576 if (!firstSemiColon)
9577 firstSemiColon = endasm;
9579 endasm = endasm->
next();
9586 }
else if (firstSemiColon) {
9589 }
else if (!endasm) {
9607 if (tok->
strAt(1) !=
";" && tok->
strAt(1) !=
"{")
9617 tok = tok->
tokAt(2);
9620 const int endposition = tok->
next()->
linenr();
9621 tok = tok->
tokAt(-3);
9622 for (
int i = 0; i < 4; ++i) {
9624 tok->
linenr(endposition);
9637 if (tok->
str() !=
"^")
9641 Token * start = tok;
9644 start = start->
link();
9651 last = last->
next();
9652 while (last && !
Token::Match(last,
"%cop%|,|;|{|}|)")) {
9654 last = last->
link();
9655 last = last->
next();
9658 if (start && last) {
9659 std::string asmcode;
9660 while (start->
next() != last) {
9661 asmcode += start->
next()->
str();
9664 if (last->
str() ==
"}")
9672 tok = start->
tokAt(4);
9680 std::set<std::string> var;
9683 if (
Token::Match(tok,
"%name%|] @ %num%|%name%|%str%|(")) {
9687 else if (end->
str() ==
"(") {
9689 while ((end = end->
next()) !=
nullptr) {
9690 if (end->
str() ==
"(")
9692 else if (end->
str() ==
")") {
9697 end = end ? end->
next() :
nullptr;
9698 }
else if (var.find(end->
str()) != var.end())
9704 end = end->
tokAt(2);
9708 var.insert(tok->
str());
9716 if (
Token::Match(tok,
"@ builtin|eeprom|far|inline|interrupt|near|noprd|nostack|nosvf|packed|stack|svlreg|tiny|vector")) {
9726 bool goback =
false;
9732 Token *last =
nullptr;
9737 if (!
Token::Match(tok,
";|{|}|public:|protected:|private:"))
9740 bool isEnum =
false;
9741 if (tok->
str() ==
"}") {
9742 const Token *type = tok->
link()->previous();
9743 while (type && type->
isName()) {
9744 if (type->
str() ==
"enum") {
9753 !
Token::Match(tok->
next(),
"case|public|protected|private|class|struct") &&
9758 if (tok1 && tok1->
tokAt(2) &&
9760 !
Token::Match(tok1->
tokAt(2),
"public|protected|private| %type% ::|<|,|{|;"))) {
9767 last = tok1->
next();
9769 }
else if (isEnum &&
Token::Match(tok,
"} %name%| : %num% ;")) {
9770 if (tok->
next()->
str() ==
":") {
9777 tok->
next()->
str() !=
"default") {
9778 const int offset = (tok->
next()->
str() ==
"const") ? 1 : 0;
9785 if (last && last->
str() ==
",") {
9786 Token * tok1 = last;
9791 tok1 = tok1->
next();
9799 static bool isStdContainerOrIterator(
const Token* tok,
const Settings& settings)
9805 static bool isStdSmartPointer(
const Token* tok,
const Settings& settings)
9817 std::set<std::string> userFunctions;
9820 bool insert =
false;
9821 if (
Token::Match(tok,
"enum class|struct| %name%| :|{")) {
9830 userFunctions.insert(tok->
str());
9832 const Token *start = tok;
9836 userFunctions.insert(tok->
str());
9845 isStdContainerOrIterator(tok,
mSettings))
9872 if (tok->
strAt(1) !=
"(")
9875 if (
Token::Match(tok,
"CopyMemory|RtlCopyMemory|RtlCopyBytes")) {
9877 }
else if (
Token::Match(tok,
"MoveMemory|RtlMoveMemory")) {
9878 tok->
str(
"memmove");
9879 }
else if (
Token::Match(tok,
"FillMemory|RtlFillMemory|RtlFillBytes")) {
9892 }
else if (
Token::Match(tok,
"ZeroMemory|RtlZeroMemory|RtlZeroBytes|RtlSecureZeroMemory")) {
9903 tok1 = tok1->
next();
9920 triplet(
const char* m,
const char* u) : mbcs(m), unicode(u) {}
9921 std::string mbcs, unicode;
9924 const std::map<std::string, triplet> apis = {
9925 std::make_pair(
"_topen", triplet(
"open",
"_wopen")),
9926 std::make_pair(
"_tsopen_s", triplet(
"_sopen_s",
"_wsopen_s")),
9927 std::make_pair(
"_tfopen", triplet(
"fopen",
"_wfopen")),
9928 std::make_pair(
"_tfopen_s", triplet(
"fopen_s",
"_wfopen_s")),
9929 std::make_pair(
"_tfreopen", triplet(
"freopen",
"_wfreopen")),
9930 std::make_pair(
"_tfreopen_s", triplet(
"freopen_s",
"_wfreopen_s")),
9931 std::make_pair(
"_tcscat", triplet(
"strcat",
"wcscat")),
9932 std::make_pair(
"_tcschr", triplet(
"strchr",
"wcschr")),
9933 std::make_pair(
"_tcscmp", triplet(
"strcmp",
"wcscmp")),
9934 std::make_pair(
"_tcsdup", triplet(
"strdup",
"wcsdup")),
9935 std::make_pair(
"_tcscpy", triplet(
"strcpy",
"wcscpy")),
9936 std::make_pair(
"_tcslen", triplet(
"strlen",
"wcslen")),
9937 std::make_pair(
"_tcsncat", triplet(
"strncat",
"wcsncat")),
9938 std::make_pair(
"_tcsncpy", triplet(
"strncpy",
"wcsncpy")),
9939 std::make_pair(
"_tcsnlen", triplet(
"strnlen",
"wcsnlen")),
9940 std::make_pair(
"_tcsrchr", triplet(
"strrchr",
"wcsrchr")),
9941 std::make_pair(
"_tcsstr", triplet(
"strstr",
"wcsstr")),
9942 std::make_pair(
"_tcstok", triplet(
"strtok",
"wcstok")),
9943 std::make_pair(
"_ftprintf", triplet(
"fprintf",
"fwprintf")),
9944 std::make_pair(
"_tprintf", triplet(
"printf",
"wprintf")),
9945 std::make_pair(
"_stprintf", triplet(
"sprintf",
"swprintf")),
9946 std::make_pair(
"_sntprintf", triplet(
"_snprintf",
"_snwprintf")),
9947 std::make_pair(
"_ftscanf", triplet(
"fscanf",
"fwscanf")),
9948 std::make_pair(
"_tscanf", triplet(
"scanf",
"wscanf")),
9949 std::make_pair(
"_stscanf", triplet(
"sscanf",
"swscanf")),
9950 std::make_pair(
"_ftprintf_s", triplet(
"fprintf_s",
"fwprintf_s")),
9951 std::make_pair(
"_tprintf_s", triplet(
"printf_s",
"wprintf_s")),
9952 std::make_pair(
"_stprintf_s", triplet(
"sprintf_s",
"swprintf_s")),
9953 std::make_pair(
"_sntprintf_s", triplet(
"_snprintf_s",
"_snwprintf_s")),
9954 std::make_pair(
"_ftscanf_s", triplet(
"fscanf_s",
"fwscanf_s")),
9955 std::make_pair(
"_tscanf_s", triplet(
"scanf_s",
"wscanf_s")),
9956 std::make_pair(
"_stscanf_s", triplet(
"sscanf_s",
"swscanf_s"))
9968 if (tok->
strAt(1) !=
"(")
9971 const std::map<std::string, triplet>::const_iterator
match = apis.find(tok->
str());
9972 if (
match!=apis.end()) {
9973 tok->
str(ansi ?
match->second.mbcs :
match->second.unicode);
9975 }
else if (
Token::Match(tok,
"_T|_TEXT|TEXT ( %char%|%str% )")) {
9981 if (tok->
str()[0] !=
'L')
9982 tok->
str(
"L" + tok->
str());
10017 while (tok && tok->
str() !=
"{" && tok->
str() !=
";")
10021 if (tok->
str() ==
";")
10024 const Token* end = tok->
link()->next();
10025 for (
Token *tok2 = tok->
next(); tok2 != end; tok2 = tok2->
next()) {
10026 if (tok2->
str() ==
"__property" &&
10031 if (tok2->
str() ==
"{") {
10056 if (tok && tok->
str() ==
")") {
10064 }
else if (tok->
str() ==
"noexcept") {
10066 if (tok && tok->
str() ==
"(") {
10067 tok = tok->
link()->next();
10069 }
else if (tok->
str() ==
"throw" && tok->
next() && tok->
next()->
str() ==
"(") {
10070 tok = tok->
next()->
link()->next();
10075 if (tok && tok->
str() ==
"(") {
10076 tok = tok->
link()->next();
10097 if (
Token::Match(tok,
"using|:: operator %op%|%name% ;")) {
10103 if (tok->
str() !=
"operator")
10114 while (!
done && par) {
10127 if (par->
str() ==
"," && !op.empty())
10136 par = par->
tokAt(2);
10143 while (par->
str() !=
")") {
10155 }
else if (
Token::Match(par,
"\"\" %name% )| (|;|<")) {
10157 op += par->
strAt(1);
10158 par = par->
tokAt(2);
10159 if (par->
str() ==
")") {
10160 par->
link()->deleteThis();
10163 tok = par->
tokAt(-3);
10166 }
else if (par->
str() ==
"::") {
10170 }
else if (par->
str() ==
";" || par->
str() ==
")") {
10172 }
else if (par->
str() !=
"(") {
10178 if (par && !op.empty()) {
10184 tok->
str(
"operator" + op);
10189 if (!op.empty() && !returnsRef)
10195 const std::string name = tok->
strAt(2);
10214 "simplifyOperatorName: found unsimplified operator name");
10224 std::set<std::string> classNames;
10225 std::set<nonneg int> classVars;
10240 for (
const Token *tok2 = tok->
next(); tok2; tok2 = tok2->
next()) {
10241 if (tok2->
str() ==
"}")
10245 if (tok2->
str() ==
"{") {
10249 tok2 = tok2->
link();
10251 classNames.insert(tok->
strAt(1));
10258 if (
Token::Match(tok,
"%type% &| %var%") && classNames.find(tok->
str()) != classNames.end()) {
10262 classVars.insert(tok->
varId());
10266 if (
Token::Match(tok,
"%var% (") && classVars.find(tok->
varId()) != classVars.end()) {
10272 start = start->
linkAt(-1);
10276 start = start->
tokAt(-2);
10282 after = after->
linkAt(3);
10301 std::vector<Space> classInfo;
10303 if (
Token::Match(tok,
"class|struct|namespace %type% :|{") &&
10306 info.isNamespace = tok->
str() ==
"namespace";
10308 info.className = tok->
str();
10310 while (tok && tok->
str() !=
"{")
10314 info.bodyEnd = tok->
link();
10315 classInfo.push_back(std::move(info));
10316 }
else if (!classInfo.empty()) {
10317 if (tok == classInfo.back().bodyEnd)
10318 classInfo.pop_back();
10319 else if (tok->
str() == classInfo.back().className &&
10320 !classInfo.back().isNamespace && tok->
previous()->
str() !=
":" &&
10324 if (tok->
strAt(2) ==
"operator") {
10326 if (tok1->
str() ==
"(")
10327 tok1 = tok1->
next();
10329 while (tok1 && tok1->
str() !=
"(") {
10330 if (tok1->
str() ==
";")
10332 tok1 = tok1->
next();
10334 if (!tok1 || tok1->
str() !=
"(")
10336 }
else if (tok->
strAt(2) ==
"~")
10337 tok1 = tok1->
next();
10343 const bool isConstructorOrDestructor =
10345 if (!isConstructorOrDestructor) {
10347 if (!isPrependedByType) {
10351 if (!isPrependedByType) {
10353 isPrependedByType =
Token::Match(tok3,
"%type% * *|&");
10355 if (!isPrependedByType) {
10371 std::vector<std::pair<std::string, const Token *>> unknowns;
10373 for (
int i = 1; i <=
mVarId; ++i) {
10382 const Token * nameTok;
10387 name = nameTok->
str();
10402 name += tok->
str();
10408 else if (tok->
str() ==
"<")
10410 else if (tok->
str() ==
">")
10420 unknowns.emplace_back(std::move(name), nameTok);
10423 if (!unknowns.empty()) {
10427 for (
auto it = unknowns.cbegin(); it != unknowns.cend(); ++it) {
10429 if (it->first.find(
"std::") != 0) {
10430 if (it->first != last) {
10450 if (tok->
str() ==
"?") {
10451 bool parenthesesNeeded =
false;
10454 for (; tok2; tok2 = tok2->
next()) {
10456 tok2 = tok2->
link();
10457 else if (tok2->
str() ==
":") {
10461 }
else if (tok2->
str() ==
";" || (tok2->
link() && tok2->
str() !=
"{" && tok2->
str() !=
"}"))
10463 else if (tok2->
str() ==
",")
10464 parenthesesNeeded =
true;
10465 else if (tok2->
str() ==
"<")
10466 parenthesesNeeded =
true;
10467 else if (tok2->
str() ==
"?") {
10469 parenthesesNeeded =
true;
10472 if (parenthesesNeeded && tok2 && tok2->
str() ==
":") {
10483 const std::list<const Token*> callstack(1, tok);
10487 void Tokenizer::reportError(
const std::list<const Token*>& callstack,
Severity severity,
const std::string&
id,
const std::string& msg,
bool inconclusive)
const
10503 while (prev && prev->
isName())
10514 const Token *tokLastEnd =
nullptr;
10515 for (
const Token *tok = tokSQLStart->
tokAt(2); tok !=
nullptr; tok = tok->
next()) {
10516 if (tokLastEnd ==
nullptr && tok->
str() ==
";")
10518 else if (tok->
str() ==
"__CPPCHECK_EMBEDDED_SQL_EXEC__") {
10520 return tok->
next();
10522 }
else if (
Token::Match(tok,
"{|}|==|&&|!|^|<<|>>|++|+=|-=|/=|*=|>>=|<<=|~"))
10540 tok2 = tok2->
tokAt(2);
10542 if (!tok2 || tok2->
str() !=
"{")
10545 std::stack<Token *> links;
10546 tok2 = tok->
tokAt(2);
10548 while (tok2->
str() ==
"::") {
10552 tok2 = tok2->
tokAt(3);
10557 if (!links.empty() && tok2->
str() ==
"{") {
10558 tok2 = tok2->
link();
10559 while (!links.empty()) {
10561 tok2 = tok2->
next();
10578 while (end && end->
str() !=
";") {
10593 static bool sameTokens(
const Token *first,
const Token *last,
const Token *other)
10595 while (other && first->
str() == other->
str()) {
10598 first = first->
next();
10599 other = other->
next();
10605 static bool alreadyHasNamespace(
const Token *first,
const Token *last,
const Token *end)
10607 while (end && last->
str() == end->
str()) {
10639 if (tok->
str() ==
"{")
10641 else if (tok->
str() ==
"}")
10648 const std::string name(tok->
next()->
str());
10650 Token * tokNameEnd = tokNameStart;
10652 while (tokNameEnd && tokNameEnd->
next() && tokNameEnd->
next()->
str() !=
";") {
10653 if (tokNameEnd->
str() ==
"(") {
10659 tokNameEnd = tokNameEnd->
next();
10665 int endScope = scope;
10670 Token * tok2 = tokNext;
10672 while (tok2 && endScope >= scope) {
10677 else if (tok2->
str() == name) {
10680 if (sameTokens(tokNameStart, tokNameEnd, tok2->
tokAt(2))) {
10682 tok2 = deleteAlias(tok2->
previous());
10687 if (endScope == scope) {
10689 tok2 = deleteAlias(tok2->
previous());
10695 tok2 = deleteAlias(tok2->
previous());
10700 if (tok2->
strAt(1) ==
"::" && !alreadyHasNamespace(tokNameStart, tokNameEnd, tok2)) {
10703 tok2->
str(tokNameStart->
str());
10704 Token * tok3 = tokNameStart;
10705 while (tok3 != tokNameEnd) {
10707 tok2 = tok2->
next();
10708 tok3 = tok3->
next();
10712 tok2 = tok2->
next();
10721 }
else if (tokNext) {
10740 return std::any_of(directives.cbegin(), directives.cend(), [&](
const Directive& d) {
10741 return startsWith(d.str,
"#if") &&
10742 d.linenr >= start->linenr() &&
10743 d.linenr <= end->linenr() &&
10744 start->fileIndex() < list.getFiles().size() &&
10745 d.file == list.getFiles()[start->fileIndex()];
10753 return std::any_of(directives.cbegin(), directives.cend(), [&](
const Directive& d) {
10754 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)
bool isUnevaluated(const Token *tok)
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)