37 #include <type_traits>
45 while (
Token::Match(tok,
"%oror%|&&|requires %name%|(")) {
47 if (after->
str() ==
"(") {
48 tok = after->
link()->next();
56 after = after->
tokAt(2);
59 tok = after ? after->
next() :
nullptr;
69 explicit FindToken(
const Token *token) : mToken(token) {}
71 return tokenAndName.
token() == mToken;
74 const Token *
const mToken;
79 explicit FindName(std::string name) : mName(std::move(name)) {}
81 return tokenAndName.
name() == mName;
84 const std::string mName;
89 explicit FindFullName(std::string fullName) : mFullName(std::move(fullName)) {}
91 return tokenAndName.
fullName() == mFullName;
94 const std::string mFullName;
99 mToken(token), mScope(std::move(scope)), mName(mToken ? mToken->str() :
""),
100 mFullName(mScope.empty() ? mName : (mScope +
" :: " + mName)),
101 mNameToken(nullptr), mParamEnd(nullptr), mFlags(0)
106 if (end && end->
strAt(1) ==
"(") {
115 mToken(token), mScope(std::move(scope)), mName(nameToken->str()),
116 mFullName(mScope.empty() ? mName : (mScope +
" :: " + mName)),
117 mNameToken(nameToken), mParamEnd(paramEnd), mFlags(0)
127 if (temp->
str() ==
">")
130 temp = temp->
tokAt(-2);
157 if (tok1->
str() ==
"<") {
160 tok1 = closing->
next();
171 tok1 = tok1->
link()->next();
173 if (tok1->
str() ==
"<")
188 if (start->
strAt(-1) ==
"~")
190 const Token *end = start;
196 if (start->
strAt(-2) ==
">")
199 start = start->
tokAt(-2);
202 if (start && start != end) {
205 while (start && start->
next() != end) {
206 if (start->
str() ==
"<")
213 start = start->
next();
231 mToken(other.mToken), mScope(other.mScope), mName(other.mName), mFullName(other.mFullName),
232 mNameToken(other.mNameToken), mParamEnd(other.mParamEnd), mFlags(other.mFlags)
240 if (mToken && mToken->templateSimplifierPointers())
241 mToken->templateSimplifierPointers()->erase(
this);
245 std::string ret =
" <TokenAndName name=\"" +
ErrorLogger::toxml(mName) +
"\" file=\"" +
ErrorLogger::toxml(fileNames.at(mToken->fileIndex())) +
"\" line=\"" + std::to_string(mToken->linenr()) +
"\">\n";
246 for (
const Token* tok = mToken; tok && !
Token::Match(tok,
"[;{}]"); tok = tok->next())
248 return ret +
" </TokenAndName>\n";
254 return mParamEnd->
tokAt(4);
260 if (aliasStartToken())
267 const Token *end = aliasEndToken();
269 for (
const Token *tok1 = aliasStartToken(); tok1 != end; tok1 = tok1->
next()) {
299 tok = tok->next()->link();
301 tok = tok->linkAt(2);
303 tok = tok->next()->link();
326 std::set<std::string> usedtypes;
329 unsigned int level = 0;
334 if (tok2->str() ==
"(")
336 else if (tok2->str() ==
"<") {
337 bool inclevel =
false;
340 else if (level == 0 &&
Token::Match(tok2->previous(),
"%type%")) {
342 if (!(
Token::Match(tok2->next(),
"*| %type%|%num% ;") ||
346 }
else if (tok2->next() && tok2->next()->isStandardType() && !
Token::Match(tok2->tokAt(2),
"(|{"))
350 else if (
Token::Match(tok2->tokAt(-2),
"<|, %type% <") && usedtypes.find(tok2->previous()->str()) != usedtypes.end())
352 else if (
Token::Match(tok2,
"< %type%") && usedtypes.find(tok2->next()->str()) != usedtypes.end())
359 tok3 = tok3->
tokAt(2);
362 }
else if (tok2->strAt(-1) ==
">")
368 usedtypes.insert(tok2->previous()->str());
370 }
else if (tok2->str() ==
">") {
373 }
else if (tok2->str() ==
">>") {
388 unsigned int numberOfParameters = 1;
392 if (tok->
str() !=
"<")
397 if (!tok || tok->
str() ==
">")
400 unsigned int level = 0;
407 if (closing->
str() ==
">>")
408 return numberOfParameters;
409 tok = closing->
next();
413 return numberOfParameters;
414 if (tok->
str() ==
",") {
415 ++numberOfParameters;
443 if (tok->
str() ==
">") {
445 return numberOfParameters;
447 }
else if (tok->
str() ==
">>" || tok->
str() ==
">>=") {
449 return numberOfParameters;
451 }
else if (tok->
str() ==
",") {
453 ++numberOfParameters;
472 if (tok->
str() ==
">" && level == 0)
473 return numberOfParameters;
474 if ((tok->
str() ==
">>" || tok->
str() ==
">>=") && level == 1)
475 return numberOfParameters;
476 if (tok->
str() ==
",") {
478 ++numberOfParameters;
485 if (tok->
str() ==
"::")
489 if (tok && tok->
str() ==
"*")
514 tok = tok->
link()->next();
535 if (tok->
str() ==
">>" || tok->
str() ==
">>=") {
543 tok = tok->
link()->next();
549 if (tok->
str() !=
",")
552 ++numberOfParameters;
558 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
562 tok = tok->next()->findClosingBracket();
571 bool in_init =
false;
573 if (tok2->str() ==
"<")
574 tok2 = tok2->findClosingBracket();
577 else if (tok2->str() ==
":")
580 tok2 = tok2->linkAt(1);
581 if (tok2->strAt(1) ==
"{")
587 if (tok2 && tok2->str() ==
"{") {
589 if (tok && tok->strAt(1) ==
";")
591 }
else if (tok2 && tok2->str() ==
";")
611 if (!begin || begin == end)
614 while (begin->
next() && begin->
next() != end) {
630 for (
auto& fwd : *forwardDecls) {
631 for (
const Token* tok = beg; tok != end; tok = tok->
next())
632 if (fwd.second == tok) {
633 fwd.second =
nullptr;
645 if (end && end->
next()) {
657 bool codeWithTemplates =
false;
662 if (tok->strAt(-1) ==
"<" || tok->strAt(-1) ==
",")
665 if (tok->strAt(-1) ==
">")
668 const Token *tok1 = tok;
669 while (tok1 && tok1->
next()) {
673 tok1 = closing->
next();
677 if (tok->strAt(2)==
"typename" &&
680 codeWithTemplates =
true;
682 for (
const Token *tok2 = parmEnd; tok2; tok2 = tok2->
next()) {
683 if (tok2->str() ==
"(" && tok2->link())
685 else if (tok2->str() ==
")")
689 tok2 = tok2->linkAt(1);
693 TokenAndName decl(tok, tok->scopeInfo()->name, parmEnd->
tokAt(namepos), parmEnd);
709 return codeWithTemplates;
730 return nameToken->
next();
747 const Token* argToken = functionToken->
next();
749 if (argToken->
str() ==
")")
752 args.push_back(argToken);
755 args.push_back(argToken);
763 const Token* endToken = functionToken->
link();
772 return std::all_of(params.cbegin(), params.cend(), [](
const Token* param) {
773 return Token::Match(param->previous(),
"typename|class %name% ,|>");
779 std::multimap<std::string, const TokenAndName *> functionNameMap;
782 if (decl.isFunction())
783 functionNameMap.insert(std::make_pair(decl.name(), &decl));
787 if (decl.isFunction())
788 functionNameMap.insert(std::make_pair(decl.name(), &decl));
791 const Token *skip =
nullptr;
801 const bool isUsing = tok->
strAt(1) ==
"using";
802 if (isUsing &&
Token::Match(tok->tokAt(2),
"%name% <")) {
807 }
else if (tok->strAt(-1) ==
"<") {
813 skip = tok->
tokAt(pos);
823 }
else if (
Token::Match(tok,
"template using %name% <")) {
833 }
else if (
Token::Match(tok->previous(),
"(|{|}|;|=|>|<<|:|.|*|&|return|<|,|!|[ %name% ::|<|(") ||
835 Token::Match(tok->tokAt(-2),
"[,:] private|protected|public %name% ::|<")) {
836 std::string scopeName = tok->
scopeInfo()->name;
837 std::string qualification;
838 Token * qualificationTok = tok;
840 qualification += (qualification.empty() ?
"" :
" :: ") + tok->
str();
851 if (tok->strAt(1) ==
"(") {
852 std::vector<const Token *> instantiationArgs;
855 std::string fullName;
856 if (!qualification.empty())
857 fullName = qualification +
" :: " + tok->str();
858 else if (!scopeName.empty())
859 fullName = scopeName +
" :: " + tok->str();
861 fullName = tok->str();
864 auto range = functionNameMap.equal_range(tok->str());
865 for (
auto pos = range.first; pos != range.second; ++pos) {
867 if (pos->second->fullName() == fullName ||
868 (pos->second->scope() == fullName && tok->str() == pos->second->name())) {
869 std::vector<const Token *> templateParams;
876 std::vector<const Token *> declarationParams;
880 if (instantiationArgs.empty() || instantiationArgs.size() != declarationParams.size())
885 for (
size_t i = 0; i < declarationParams.size(); ++i) {
887 const bool isArgLiteral =
Token::Match(instantiationArgs[i],
"%num%|%str%|%char%|%bool% ,|)");
888 if (isArgLiteral &&
Token::Match(declarationParams[i],
"const| %type% &| %name%| ,|)")) {
892 if (templateParams[0]->str() == declarationParams[i]->str())
900 if (
match == declarationParams.size()) {
901 const Token *arg = instantiationArgs[argMatch];
905 tok->insertToken(
"bool");
909 tok->insertToken(
"wchar_t");
911 tok->insertToken(
"char");
914 tok->insertToken(
"*");
916 tok->insertToken(
"wchar_t");
918 tok->insertToken(
"char");
919 tok->insertToken(
"const");
925 const char suffix = arg->
str().back();
926 if (suffix ==
'f' || suffix ==
'F')
927 tok->insertToken(
"float");
928 else if (suffix ==
'l' || suffix ==
'L') {
929 tok->insertToken(
"double");
930 tok->next()->isLong(
true);
932 tok->insertToken(
"double");
933 }
else if (num.
isInt()) {
935 if (suffix.find(
"LL") != std::string::npos) {
936 tok->insertToken(
"long");
937 tok->next()->isLong(
true);
938 }
else if (suffix.find(
'L') != std::string::npos)
939 tok->insertToken(
"long");
941 tok->insertToken(
"int");
942 if (suffix.find(
'U') != std::string::npos)
943 tok->next()->isUnsigned(
true);
950 tok->insertToken(
"<");
958 Token::Match(tok,
"const_cast|dynamic_cast|reinterpret_cast|static_cast"))
972 for (; tok2 && tok2 != tok; tok2 = tok2->
previous()) {
983 const std::string fullName = scopeName + (scopeName.empty()?
"":
" :: ") +
984 qualification + (qualification.empty()?
"":
" :: ") + tok->str();
993 for (
const auto & nameSpace : tok->scopeInfo()->usingNamespaces) {
994 std::string fullNameSpace = scopeName + (scopeName.empty()?
"":
" :: ") +
995 nameSpace + (qualification.empty()?
"":
" :: ") + qualification;
996 std::string newFullName = fullNameSpace +
" :: " + tok->str();
1000 std::string::size_type offset = 0;
1001 std::string::size_type pos = 0;
1002 while ((pos = nameSpace.find(
' ', offset)) != std::string::npos) {
1016 if (scopeName.empty()) {
1017 if (!qualification.empty())
1023 const std::string::size_type pos = scopeName.rfind(
" :: ");
1024 scopeName = (pos == std::string::npos) ? std::string() : scopeName.substr(0,pos);
1054 std::list<Default> eq;
1056 std::set<std::size_t> defaultedArgPos;
1059 std::size_t templatepar = 1;
1062 std::size_t templateParmDepth = 0;
1065 std::map<std::string, unsigned int> typeParameterNames;
1081 if (tok->str() ==
"<" &&
1082 (tok->strAt(1) ==
">" || (tok->previous()->isName() &&
1083 typeParameterNames.find(tok->strAt(-1)) == typeParameterNames.end())))
1084 ++templateParmDepth;
1087 if (tok->str() ==
">") {
1088 if (templateParmDepth<2) {
1090 eq.back().end = tok;
1093 --templateParmDepth;
1097 if (
Token::Match(tok,
"typename|class|%type% %name% ,|>"))
1098 typeParameterNames[tok->strAt(1)] = templatepar - 1;
1101 if (tok->str() ==
"," && (1 == templateParmDepth)) {
1103 eq.back().end = tok;
1109 if (defaultedArgPos.insert(templatepar).second) {
1110 eq.emplace_back(Default{tok,
nullptr});
1123 if (declaration.
fullName() != instantiation.fullName())
1127 std::vector<std::vector<const Token *>> instantiationArgs;
1128 std::size_t index = 0;
1132 if (end != instantiation.token()->
tokAt(2))
1133 instantiationArgs.resize(1);
1134 for (
const Token *tok1 = instantiation.token()->
tokAt(2); tok1 && tok1 != end; tok1 = tok1->
next()) {
1138 instantiationArgs[index].push_back(tok1);
1139 tok1 = tok1->next();
1140 }
while (tok1 && tok1 != endLink);
1141 instantiationArgs[index].push_back(tok1);
1142 }
else if (tok1->str() ==
"<" &&
1143 (tok1->strAt(1) ==
">" || (tok1->previous()->isName() &&
1144 typeParameterNames.find(tok1->strAt(-1)) == typeParameterNames.end()))) {
1147 instantiationArgs[index].push_back(tok1);
1148 tok1 = tok1->
next();
1149 }
while (tok1 && tok1 != endLink);
1150 instantiationArgs[index].push_back(tok1);
1151 }
else if (tok1->str() ==
",") {
1153 instantiationArgs.resize(index + 1);
1155 instantiationArgs[index].push_back(tok1);
1159 Token *tok = instantiation.token()->
next();
1162 tok = instantiationEnd;
1164 if (tok && tok->
str() ==
">") {
1166 std::list<Default>::const_iterator it = eq.cbegin();
1167 for (std::size_t i = (templatepar - eq.size()); it != eq.cend() && i < usedpar; ++i)
1170 while (it != eq.cend()) {
1174 const std::list<const Token*> locationList(1, it->eq);
1178 "TemplateSimplifier couldn't find end of template parameter.",
1185 if ((usedpar + count) && usedpar <= (instantiationArgs.size() + count)) {
1189 std::stack<Token *> links;
1190 for (
const Token* from = it->eq->
next(); from && from != it->end; from = from->
next()) {
1191 auto entry = typeParameterNames.find(from->str());
1192 if (entry != typeParameterNames.end() && entry->second < instantiationArgs.size()) {
1193 for (
const Token *tok1 : instantiationArgs[entry->second]) {
1194 tok->
insertToken(tok1->str(), tok1->originalName());
1199 else if (!links.empty() &&
Token::Match(tok,
")|]|}")) {
1205 tok->
insertToken(from->str(), from->originalName());
1210 else if (!links.empty() &&
Token::Match(tok,
")|]|}")) {
1225 for (
const auto & entry : eq) {
1226 Token *
const eqtok = entry.eq;
1228 int indentlevel = 0;
1229 for (tok2 = eqtok->
next(); tok2; tok2 = tok2->
next()) {
1235 tok2 = tok2->
link();
1243 }
else if (indentlevel > 0 && tok2->
str() ==
">")
1245 else if (indentlevel == 0 &&
Token::Match(tok2,
",|>"))
1247 if (indentlevel < 0)
1258 FindName(declaration.
name()));
1276 if (!aliasDeclaration.
isAlias()) {
1282 std::vector<const Token *> aliasParameters;
1284 std::map<std::string, unsigned int> aliasParameterNames;
1285 for (
unsigned int argnr = 0; argnr < aliasParameters.size(); ++argnr)
1286 aliasParameterNames[aliasParameters[argnr]->str()] = argnr;
1303 std::vector<std::pair<Token *, Token *>> args;
1306 Token *
const start = tok2;
1309 tok2 = tok2->
link();
1310 else if (tok2->
str() ==
"<") {
1315 tok2 = tok2->
next();
1318 args.emplace_back(start, tok2);
1319 if (tok2 && tok2->
str() ==
",") {
1320 tok2 = tok2->
next();
1325 if (!tok2 || tok2->
str() !=
">" ||
1326 (!aliasDeclaration.
isVariadic() && (args.size() != aliasParameters.size())) ||
1327 (aliasDeclaration.
isVariadic() && (args.size() < aliasParameters.size()))) {
1339 for (
Token *tok1 = dst->
next(); tok1 != end; tok1 = tok1->
next()) {
1340 if (!tok1->isName())
1342 if (aliasParameterNames.find(tok1->str()) != aliasParameterNames.end()) {
1343 const unsigned int argnr = aliasParameterNames[tok1->str()];
1344 const Token *
const fromStart = args[argnr].first;
1345 const Token *
const fromEnd = args[argnr].second->
previous();
1347 const bool tempOK(temp && temp != tok1->
next());
1351 }
else if (tok1->str() ==
"typename")
1356 for (
Token *tok1 = dst->
next(); tok1 != end; tok1 = tok1->
next()) {
1357 if (!tok1->isName())
1359 if (aliasParameterNames.find(tok2->
str()) == aliasParameterNames.end()) {
1399 assert(instance->
strAt(1) ==
"<");
1419 while (tok && tok->
next()) {
1425 while (tok->
next() && tok != end) {
1434 while (tok->
next() && tok->
next() != closing) {
1451 while (tok && tok->
next()) {
1457 while (tok->
next() && tok != end) {
1466 while (tok->
next() && tok->
next() != closing) {
1482 if (
Token::Match(tok,
"> friend| class|struct|union %type% :|<|;|{|::")) {
1483 namepos = tok->
strAt(1) ==
"friend" ? 3 : 2;
1484 tok = tok->
tokAt(namepos);
1487 if (tok->
strAt(1) ==
"::") {
1488 tok = tok->
tokAt(2);
1492 if (!end || !end->
tokAt(2)) {
1497 end = end->
tokAt(2);
1501 }
while (tok && tok != end);
1511 if (!tok || tok->
str() !=
">")
1537 const Token * tokStart = tok;
1540 tokStart = tokStart->
tokAt(-2);
1544 const bool insert = tokStart != tok;
1546 std::string::size_type start = 0;
1547 std::string::size_type end = 0;
1548 bool inTemplate =
false;
1550 while ((end = templateDeclaration.
scope().find(
' ', start)) != std::string::npos) {
1551 std::string token = templateDeclaration.
scope().substr(start, end - start);
1553 if (token == tokStart->
str() && tok->
strAt(-1) !=
"::")
1578 std::string token = templateDeclaration.
scope().substr(start, end - start);
1579 if (token != tokStart->
str() || tok->
strAt(-1) !=
"::") {
1598 const std::string& scope = templateDeclaration.
scope();
1601 std::string::size_type pos = 0;
1604 while ((pos = scope.find(
"::", pos)) != std::string::npos) {
1621 const std::vector<const Token *> &typeParametersInDeclaration,
1622 const std::string &newName,
1625 bool inTemplateDefinition =
false;
1626 const Token *startOfTemplateDeclaration =
nullptr;
1627 const Token *endOfTemplateDefinition =
nullptr;
1628 const Token *
const templateDeclarationNameToken = templateDeclaration.
nameToken();
1629 const Token *
const templateDeclarationToken = templateDeclaration.
paramEnd();
1630 const bool isClass = templateDeclaration.
isClass();
1631 const bool isFunction = templateDeclaration.
isFunction();
1633 const bool isVariable = templateDeclaration.
isVariable();
1635 std::vector<newInstantiation> newInstantiations;
1638 if (copy && isClass) {
1642 }
else if ((isFunction && (copy || isSpecialization)) ||
1643 (isVariable && !isSpecialization) ||
1647 bool isStatic =
false;
1649 const Token * start;
1657 start = temp1->
next();
1663 FindToken(it->second));
1673 const Token * temp = templateDeclarationNameToken;
1675 scope.insert(0, temp->
strAt(-2) +
" :: ");
1676 temp = temp->
tokAt(-2);
1679 start = templateDeclarationToken->
next();
1680 end = templateDeclarationNameToken->
next();
1681 if (end->
str() ==
"<")
1683 if (end->
str() ==
"(")
1684 end = end->
link()->next();
1685 else if (isVariable && end->
str() ==
"=") {
1687 while (temp && temp->
str() !=
";") {
1689 temp = temp->
link();
1690 temp = temp->
next();
1695 unsigned int typeindentlevel = 0;
1696 while (end && !(typeindentlevel == 0 &&
Token::Match(end,
";|{|:"))) {
1712 std::map<const Token *, Token *> links;
1713 bool inAssignment =
false;
1714 while (start && start != end) {
1715 if (isVariable && start->
str() ==
"=")
1716 inAssignment =
true;
1717 unsigned int itype = 0;
1718 while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != start->
str())
1722 (!isVariable || !
Token::Match(typeParametersInDeclaration[itype]->previous(),
"<|, %type% >|,"))) {
1723 typeindentlevel = 0;
1724 std::stack<Token *> brackets1;
1725 bool pointerType =
false;
1727 const bool isVariadicTemplateArg = templateDeclaration.
isVariadic() && itype + 1 == typeParametersInDeclaration.size();
1728 if (isVariadicTemplateArg &&
Token::Match(start,
"%name% ... %name%"))
1729 start = start->
tokAt(2);
1730 const std::string endStr(isVariadicTemplateArg ?
">" :
",>");
1732 typetok && (typeindentlevel > 0 || endStr.find(typetok->str()[0]) == std::string::npos);
1733 typetok = typetok->next()) {
1734 if (typeindentlevel == 0 && typetok->str() ==
"*")
1740 else if (typeindentlevel > 0 && typetok->str() ==
">")
1742 else if (typetok->str() ==
"(")
1744 else if (typetok->str() ==
")")
1746 dst->
insertToken(typetok->str(), typetok->originalName(), typetok->getMacroName(),
true);
1751 previous->
isSigned(typetok->isSigned());
1753 previous->
isLong(typetok->isLong());
1755 brackets1.push(previous);
1756 }
else if (previous->
str() ==
"}") {
1757 assert(brackets1.empty() ==
false);
1758 assert(brackets1.top()->str() ==
"{");
1761 }
else if (previous->
str() ==
")") {
1762 assert(brackets1.empty() ==
false);
1763 assert(brackets1.top()->str() ==
"(");
1766 }
else if (previous->
str() ==
"]") {
1767 assert(brackets1.empty() ==
false);
1768 assert(brackets1.top()->str() ==
"[");
1780 if (isSpecialization && !copy && !scope.empty() &&
Token::Match(start, (scope + templateDeclarationNameToken->
str()).c_str())) {
1782 while (start->
strAt(1) != templateDeclarationNameToken->
str())
1783 start = start->
next();
1784 }
else if (start->
str() == templateDeclarationNameToken->
str() &&
1785 !(templateDeclaration.
isFunction() && templateDeclaration.
scope().empty() &&
1787 if (start->
strAt(1) !=
"<" ||
Token::Match(start, newName.c_str()) || !inAssignment) {
1791 if (start->
strAt(1) ==
"<")
1797 newInstantiations.emplace_back(dst->
previous(), templateDeclaration.
scope());
1801 if (start->
strAt(1) ==
"<") {
1806 const Token * type = start;
1807 while (type && type != closing->
next()) {
1810 name += type->
str();
1811 type = type->
next();
1815 return Token::simpleMatch(inst.token(), name.c_str(), name.size());
1825 if (start != closing) {
1846 if (start->
link()) {
1850 std::map<const Token *, Token *>::iterator link = links.find(start);
1852 if (link != links.end()) {
1860 start = start->
next();
1866 if (isVariable || isFunction)
1870 if (copy && (isClass || isFunction)) {
1872 Token * start = templateInstantiation.
token();
1876 if (start->
strAt(-1) ==
"extern")
1883 if (inTemplateDefinition) {
1884 if (!endOfTemplateDefinition) {
1888 while (temp && temp->
str() !=
";") {
1890 temp = temp->
link();
1891 temp = temp->
next();
1893 endOfTemplateDefinition = temp;
1895 }
else if (tok3->str() ==
"{")
1896 endOfTemplateDefinition = tok3->
link();
1898 if (tok3 == endOfTemplateDefinition) {
1899 inTemplateDefinition =
false;
1900 startOfTemplateDeclaration =
nullptr;
1904 if (tok3->str()==
"template") {
1905 if (tok3->next() && tok3->next()->str()==
"<") {
1906 std::vector<const Token *> localTypeParametersInDeclaration;
1908 inTemplateDefinition = localTypeParametersInDeclaration.size() == typeParametersInDeclaration.size();
1910 inTemplateDefinition =
false;
1912 startOfTemplateDeclaration = tok3;
1915 tok3 = tok3->
link();
1918 if (tok3 == templateDeclarationToken) {
1919 tok3 = tok3->next();
1920 if (tok3->str() ==
"static")
1921 tok3 = tok3->next();
1925 else if (inTemplateDefinition &&
1927 templateInstantiation.
name() == tok3->str() &&
1930 bool istemplate =
false;
1931 Token * tok5 =
nullptr;
1932 for (
Token *prev = tok3; prev && !
Token::Match(prev,
"[;{}]"); prev = prev->previous()) {
1933 if (prev->str() ==
"template") {
1943 while (tok4 && tok4->
str() !=
"(")
1944 tok4 = tok4->
next();
1950 tok5 = tok5->
next();
1952 std::stack<Token *> brackets2;
1953 while (tok5 && tok5 != tok3) {
1957 if (!templateDeclaration.
scope().empty() && tok5->
strAt(-1) !=
"::")
1969 unsigned int itype = 0;
1970 while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != tok5->
str())
1975 std::stack<Token *> brackets1;
1978 typetok = typetok->next()) {
1983 brackets1.push(back);
1984 }
else if (back->
str() ==
"}") {
1985 assert(brackets1.empty() ==
false);
1986 assert(brackets1.top()->str() ==
"{");
1989 }
else if (back->
str() ==
")") {
1990 assert(brackets1.empty() ==
false);
1991 assert(brackets1.top()->str() ==
"(");
1994 }
else if (back->
str() ==
"]") {
1995 assert(brackets1.empty() ==
false);
1996 assert(brackets1.top()->str() ==
"[");
2002 back->
isSigned(typetok->isSigned());
2003 back->
isLong(typetok->isLong());
2014 brackets2.push(back);
2015 }
else if (back->
str() ==
"}") {
2016 assert(brackets2.empty() ==
false);
2017 assert(brackets2.top()->str() ==
"{");
2020 }
else if (back->
str() ==
")") {
2021 assert(brackets2.empty() ==
false);
2022 assert(brackets2.top()->str() ==
"(");
2025 }
else if (back->
str() ==
"]") {
2026 assert(brackets2.empty() ==
false);
2027 assert(brackets2.top()->str() ==
"[");
2034 tok5 = tok5->
next();
2037 if (!templateDeclaration.
scope().empty() && tok3->strAt(-1) !=
"::")
2042 while (tok3 && tok3->str() !=
"::")
2043 tok3 = tok3->next();
2047 FindToken(startOfTemplateDeclaration));
2056 std::stack<Token *> brackets;
2059 const std::string lastName = (templateInstantiation.
name().find(
' ') != std::string::npos) ? templateInstantiation.
name().substr(templateInstantiation.
name().rfind(
' ')+1) : templateInstantiation.
name();
2061 std::stack<const Token *> templates;
2062 for (; tok3; tok3 = tok3->next()) {
2063 if (tok3->isName() && !
Token::Match(tok3,
"class|typename|struct") && !tok3->isStandardType()) {
2065 unsigned int itype = 0;
2066 while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != tok3->str())
2071 unsigned int typeindentlevel = 0;
2072 std::stack<Token *> brackets1;
2074 bool pointerType =
false;
2075 const bool isVariadicTemplateArg = templateDeclaration.
isVariadic() && itype + 1 == typeParametersInDeclaration.size();
2078 if (isVariadicTemplateArg &&
Token::Match(tok3,
"%name% ... %name%"))
2079 tok3 = tok3->tokAt(2);
2080 const std::string endStr(isVariadicTemplateArg ?
">" :
",>");
2082 typetok && (typeindentlevel > 0 || endStr.find(typetok->str()[0]) == std::string::npos);
2083 typetok = typetok->next()) {
2084 if (typeindentlevel == 0 && typetok->str() ==
"*")
2090 brackets1.push(typetok->next());
2092 }
else if (typeindentlevel > 0 && typetok->str() ==
">" && brackets1.top()->str() ==
"<") {
2095 }
else if (
Token::Match(typetok,
"const_cast|dynamic_cast|reinterpret_cast|static_cast <")) {
2096 brackets1.push(typetok->next());
2098 }
else if (typetok->str() ==
"(")
2100 else if (typetok->str() ==
")")
2109 brackets1.push(back);
2110 else if (back->
str() ==
"}") {
2111 assert(brackets1.empty() ==
false);
2112 assert(brackets1.top()->str() ==
"{");
2116 }
else if (back->
str() ==
")") {
2117 assert(brackets1.empty() ==
false);
2118 assert(brackets1.top()->str() ==
"(");
2122 }
else if (back->
str() ==
"]") {
2123 assert(brackets1.empty() ==
false);
2124 assert(brackets1.top()->str() ==
"[");
2141 if (tok3->str() == lastName) {
2144 if (closingBracket) {
2146 if (tok3 == templateDeclarationNameToken ||
2150 tok3 = closingBracket;
2157 if (!templateDeclaration.
scope().empty() &&
2166 if (
Token::Match(tok3->tokAt(-3),
"> friend class|struct|union")) {
2171 if (!templateDeclaration.
scope().empty() &&
2172 (isClass ? tok3->strAt(1) !=
"(" :
true)) {
2190 templates.push(tok2);
2191 }
else if (!templates.empty() && templates.top() == tok3)
2195 !
Token::Match(tok3,
"template|static_cast|const_cast|reinterpret_cast|dynamic_cast") &&
2196 Token::Match(tok3->next()->findClosingBracket(),
">|>>")) {
2201 while (num < typeParametersInDeclaration.size() && par != closingBracket) {
2202 const std::string pattern(
"[<,] " + typeParametersInDeclaration[num]->str() +
" [,>]");
2206 par = par->
tokAt(2);
2208 if (num < typeParametersInDeclaration.size() || par != closingBracket)
2213 if (!templates.empty())
2217 const Token *prev = tok3;
2220 scope = prev->
strAt(-2);
2222 scope = prev->
strAt(-2) +
" :: " + scope;
2226 if (prev->
strAt(-1) !=
"::") {
2228 std::string token_scope = tok3->scopeInfo()->name;
2229 const std::string::size_type end = token_scope.find_last_of(
" :: ");
2230 if (end != std::string::npos) {
2231 token_scope.resize(end);
2233 scope = std::move(token_scope);
2235 scope = token_scope +
" :: " + scope;
2240 newInstantiations.emplace_back(
mTokenList.
back(), std::move(scope));
2241 else if (!inTemplateDefinition)
2242 newInstantiations.emplace_back(tok3, std::move(scope));
2247 if (tok3->str() ==
"{") {
2249 }
else if (tok3->str() ==
"(") {
2251 }
else if (tok3->str() ==
"[") {
2253 }
else if (tok3->str() ==
"}") {
2254 assert(brackets.empty() ==
false);
2255 assert(brackets.top()->str() ==
"{");
2258 if (brackets.empty() && !
Token::Match(tok3,
"} >|,|{")) {
2259 inTemplateDefinition =
false;
2260 if (isClass && tok3->strAt(1) ==
";") {
2261 const Token* tokSemicolon = tok3->
next();
2266 }
else if (tok3->str() ==
")") {
2267 assert(brackets.empty() ==
false);
2268 assert(brackets.top()->str() ==
"(");
2271 }
else if (tok3->str() ==
"]") {
2272 assert(brackets.empty() ==
false);
2273 assert(brackets.top()->str() ==
"[");
2280 assert(brackets.empty());
2284 for (
const auto & inst : newInstantiations) {
2287 simplifyTemplateArgs(inst.token->tokAt(2), inst.token->next()->findClosingBracket(), &newInstantiations);
2289 if (templateDeclaration.
name() != inst.token->str() ||
2290 (inst.token->tokAt(2)->isNumber() || inst.token->tokAt(2)->isStandardType()))
2340 const std::string &num2 = op->
next()->
str();
2375 switch (op->
str()[0]) {
2377 tok->
str((v1 << v2).str());
2380 tok->
str((v1 >> v2).str());
2383 tok->
str((v1 & v2).str());
2386 tok->
str((v1 | v2).str());
2389 tok->
str((v1 ^ v2).str());
2398 const bool result = (op->
str() ==
"||") ? (
op1 ||
op2) : (
op1 &&
op2);
2399 tok->
str(result ?
"1" :
"0");
2425 unsigned int colonLevel = 1;
2426 while (
nullptr != (tok = tok->
next())) {
2427 if (tok->
str() ==
"?") {
2429 }
else if (tok->
str() ==
":") {
2431 if (colonLevel == 0) {
2436 if (tok->
link() && tok->
str() ==
"(")
2449 for (
auto& inst : *newInst) {
2450 for (
const Token* tok = beg; tok != end; tok = tok->
next())
2451 if (inst.token == tok) {
2452 inst.token =
nullptr;
2467 for (
Token *tok = first->
next(); tok && tok != end; tok = tok->
next()) {
2468 if (tok->str() ==
"sizeof") {
2474 tok->str(std::to_string(1));
2498 tok->str(std::to_string(size));
2502 }
else if (tok->strAt(1) ==
"(") {
2503 tok = tok->linkAt(1);
2508 if ((
Token::Match(tok->previous(),
"(|&&|%oror%|,") || tok == start) &&
2509 (
Token::Match(tok->tokAt(3),
")|&&|%oror%|?") || tok->tokAt(3) == end)) {
2511 const std::string &cmp(tok->next()->str());
2518 else if (cmp ==
"!=")
2520 else if (cmp ==
"<=")
2522 else if (cmp ==
">=")
2524 else if (cmp ==
"<")
2532 tok = tok->previous();
2540 for (
Token *tok = first->
next(); tok && tok != end; tok = tok->
next()) {
2541 if (tok->str() ==
"?" &&
2542 ((tok->previous()->isNumber() || tok->previous()->isBoolean()) ||
2544 const int offset = (tok->previous()->str() ==
")") ? 2 : 1;
2553 tok->insertToken(tok->strAt(-offset));
2556 tok = tok->tokAt(-2);
2559 tok = tok->tokAt(-2);
2562 tok->next()->deleteNext();
2579 unsigned int ternaryOplevel = 0;
2580 for (
const Token *endTok = colon; endTok; endTok = endTok->
next()) {
2582 endTok = endTok->link();
2583 else if (endTok->str() ==
"<" && (endTok->strAt(1) ==
">" ||
templateParameters(endTok)))
2584 endTok = endTok->findClosingBracket();
2585 else if (endTok->str() ==
"?")
2588 if (endTok->str() ==
":" && ternaryOplevel)
2590 else if (endTok->str() ==
">" && !end)
2604 for (
Token *tok = first->
next(); tok && tok != end; tok = tok->
next()) {
2606 (tok->previous() && !tok->previous()->isName())) {
2621 frontToken = frontToken->
previous();
2623 while (tok && offset <= 0) {
2624 if (tok == frontToken)
2630 return tok && offset > 0;
2638 while (tok && offset >= 0) {
2639 if (tok == backToken)
2645 return tok && offset < 0;
2653 const bool bounded = frontToken || backToken;
2657 for (
Token *tok = frontToken; tok && tok != backToken; tok = tok->
next()) {
2669 (tok->tokAt(2)->varId()>0 ||
2672 tok->str() !=
">" &&
2673 tok->str() !=
")" &&
2674 tok->str() !=
"]") {
2682 Token::Match(tok->previous(),
"(|&&|%oror% %char% %comp% %num% &&|%oror%|)")) {
2700 if (tok->isBoolean())
2704 const char suffix = tok->str().back();
2705 if (suffix ==
'f' || suffix ==
'F')
2707 else if (suffix ==
'l' || suffix ==
'L') {
2714 if (suffix.find(
"LL") != std::string::npos) {
2717 }
else if (suffix.find(
'L') != std::string::npos)
2721 tok->isUnsigned(suffix.find(
'U') != std::string::npos);
2731 tok->isSigned(
false);
2732 tok->isUnsigned(
false);
2739 if (tok && tok->isNumber()) {
2747 prev = prev->
tokAt(-2);
2756 unsigned int par = 0;
2757 const Token *tok2 = tok;
2758 const bool andAnd = (tok->next()->str() ==
"&&");
2759 for (; tok2; tok2 = tok2->
next()) {
2760 if (tok2->
str() ==
"(" || tok2->
str() ==
"[")
2762 else if (tok2->
str() ==
")" || tok2->
str() ==
"]") {
2776 if (tok->str() ==
"0" &&
validTokenStart(bounded, tok, frontToken, -1)) {
2780 tok = tok->previous();
2781 if (
Token::Match(tok->tokAt(-4),
"[;{}] %name% = %name% [+-|] 0 ;") &&
2782 tok->strAt(-3) == tok->previous()->str()) {
2783 tok = tok->tokAt(-4);
2786 tok = tok->previous();
2792 Token::Match(tok->previous(),
"return|case 0 [+|]"))) {
2793 tok = tok->previous();
2796 }
else if ((((
Token::Match(tok->previous(),
"[=[(,] 0 * %name%|%num% ,|]|)|;|=|%cop%") ||
2797 Token::Match(tok->previous(),
"return|case 0 *|&& %name%|%num% ,|:|;|=|%cop%")) &&
2800 Token::Match(tok->previous(),
"return|case 0 *|&& (")) &&
2803 if (tok->next()->str() ==
"(")
2808 (
Token::Match(tok->previous(),
"[=[(,] 0 && *|& %any% ,|]|)|;|=|%cop%") ||
2809 Token::Match(tok->previous(),
"return|case 0 && *|& %any% ,|:|;|=|%cop%"))) {
2812 if (tok->next()->str() ==
"(")
2819 if (tok->str() ==
"1" &&
validTokenStart(bounded, tok, frontToken, -1)) {
2821 (
Token::Match(tok->previous(),
"[=[(,] 1 %oror% %any% ,|]|)|;|=|%cop%") ||
2822 Token::Match(tok->previous(),
"return|case 1 %oror% %any% ,|:|;|=|%cop%"))) {
2824 if (tok->next()->str() ==
"(")
2829 (
Token::Match(tok->previous(),
"[=[(,] 1 %oror% *|& %any% ,|]|)|;|=|%cop%") ||
2830 Token::Match(tok->previous(),
"return|case 1 %oror% *|& %any% ,|:|;|=|%cop%"))) {
2833 if (tok->next()->str() ==
"(")
2844 tok = tok->previous();
2845 if (tok->str() ==
"*")
2846 tok = tok->previous();
2854 tok->strAt(-2) !=
">") {
2855 tok = tok->previous();
2865 tok = tok->previous();
2867 tok = tok->previous();
2880 const std::string &cmp(tok->next()->str());
2886 result = (
op1 ==
op2) ?
"1" :
"0";
2887 else if (cmp ==
"!=")
2888 result = (
op1 !=
op2) ?
"1" :
"0";
2889 else if (cmp ==
"<=")
2890 result = (
op1 <=
op2) ?
"1" :
"0";
2891 else if (cmp ==
">=")
2892 result = (
op1 >=
op2) ?
"1" :
"0";
2893 else if (cmp ==
"<")
2894 result = (
op1 <
op2) ?
"1" :
"0";
2896 result = (
op1 >
op2) ?
"1" :
"0";
2901 tok = tok->previous();
2911 std::vector<const Token *> & typeParametersInDeclaration)
2913 assert(tok->
strAt(-1) ==
"<");
2915 typeParametersInDeclaration.clear();
2917 bool inDefaultValue =
false;
2918 for (; tok && tok!= end; tok = tok->
next()) {
2922 tok = closing->
next();
2926 if (!inDefaultValue) {
2927 typeParametersInDeclaration.push_back(tok);
2928 if (tok->
strAt(1) ==
"=")
2929 inDefaultValue =
true;
2931 }
else if (inDefaultValue) {
2932 if (tok->
str() ==
",")
2933 inDefaultValue =
false;
2934 else if (tok->
str() ==
"<") {
2944 const Token *templateDeclarationNameToken,
2945 const Token *templateInstantiationNameToken,
2946 const std::list<const Token *> & specializations)
2949 for (std::list<const Token *>::const_iterator it = specializations.cbegin(); it != specializations.cend(); ++it) {
2952 const Token *startToken = (*it);
2954 startToken = startToken->
previous();
2961 const Token *instToken = templateInstantiationNameToken->
tokAt(2);
2966 while (declToken != endToken) {
2967 if (declToken->
str() != instToken->
str() ||
2978 declToken = declToken->
next();
2979 instToken = instToken->
next();
2982 if (declToken && instToken && declToken == endToken && instToken->
str() ==
">") {
2984 return templateDeclarationNameToken == *it;
2989 return Token::Match(templateDeclarationNameToken,
"%name% !!<") &&
2990 (templateDeclarationNameToken->
str().find(
'<') == std::string::npos);
2995 std::list<std::string> &typeStringsUsedInTemplateInstantiation)
2997 std::string typeForNewName;
2998 unsigned int indentlevel = 0;
3000 for (
Token *tok3 = tok2->
tokAt(2); tok3 != endToken && (indentlevel > 0 || tok3->str() !=
">"); tok3 = tok3->
next()) {
3002 if (tok3->str() ==
"[" && !
Token::Match(tok3->next(),
"%num%| ]")) {
3003 typeForNewName.clear();
3006 if (!tok3->next()) {
3007 typeForNewName.clear();
3012 else if (indentlevel > 0 &&
Token::Match(tok3,
"> ,|>|::"))
3014 else if (indentlevel == 0 &&
Token::Match(tok3->previous(),
"[<,]")) {
3021 const bool constconst = tok3->str() ==
"const" && tok3->strAt(1) ==
"const";
3023 if (tok3->isUnsigned())
3024 typeStringsUsedInTemplateInstantiation.emplace_back(
"unsigned");
3025 else if (tok3->isSigned())
3026 typeStringsUsedInTemplateInstantiation.emplace_back(
"signed");
3028 typeStringsUsedInTemplateInstantiation.emplace_back(
"long");
3029 typeStringsUsedInTemplateInstantiation.push_back(tok3->str());
3032 if (!constconst && !
Token::Match(tok3,
"class|struct|enum")) {
3033 if (!typeForNewName.empty())
3034 typeForNewName +=
' ';
3035 if (tok3->isUnsigned())
3036 typeForNewName +=
"unsigned ";
3037 else if (tok3->isSigned())
3038 typeForNewName +=
"signed ";
3039 if (tok3->isLong()) {
3040 typeForNewName +=
"long ";
3042 typeForNewName += tok3->str();
3046 return typeForNewName;
3051 const std::list<const Token *> &specializations,
3052 const std::time_t maxtime,
3053 std::set<std::string> &expandedtemplates)
3060 std::vector<const Token *> typeParametersInDeclaration;
3064 const bool isfunc = templateDeclaration.
isFunction();
3065 const bool isVar = templateDeclaration.
isVariable();
3069 unsigned int recursiveCount = 0;
3071 bool instantiated =
false;
3075 if (!instantiation.token())
3082 std::list<std::string> typeStringsUsedInTemplateInstantiation;
3083 const std::string typeForNewName = templateDeclaration.
name() +
"<" +
getNewName(instantiation.token(), typeStringsUsedInTemplateInstantiation) +
">";
3085 const std::list<const Token *> callstack(1, instantiation.token());
3089 "templateRecursion",
3090 "TemplateSimplifier: max template recursion ("
3092 +
") reached for template '"+typeForNewName+
"'. You might want to limit Cppcheck recursion.",
3106 if (!((instantiation.fullName() == templateDeclaration.
fullName()) ||
3107 (instantiation.name() == templateDeclaration.
name() &&
3108 instantiation.fullName() == templateDeclaration.
scope()))) {
3112 if (instantiation.name() != templateDeclaration.
name())
3116 if (!instantiation.scope().empty() && !templateDeclaration.
scope().empty())
3121 if (templateDeclaration.
nameToken()->
strAt(-1) ==
"~" && instantiation.token()->strAt(-1) !=
"~")
3125 if (!instantiation.isFunction() && templateDeclaration.
isFunction()) {
3131 if (templateDeclaration.
isFunction() && instantiation.isFunction()) {
3132 std::vector<const Token*> declFuncArgs;
3134 std::vector<const Token*> instFuncParams;
3137 if (declFuncArgs.size() != instFuncParams.size()) {
3142 for (; tok != end; tok = tok->
next()) {
3143 if (tok->
str() ==
"=")
3147 if (instFuncParams.size() < (declFuncArgs.size() - count) || instFuncParams.size() > declFuncArgs.size())
3153 if (templateDeclaration.
isFunction() && templateDeclaration.
scope().empty() &&
3154 (instantiation.token()->strAt(-1) ==
"." ||
3161 Token *
const tok2 = instantiation.token();
3165 if (maxtime > 0 && std::time(
nullptr) > maxtime) {
3171 "Template instantiation maximum time exceeded",
3181 const Token *startToken = tok2;
3183 if (startToken->
strAt(-2) ==
">") {
3190 startToken = startToken->
tokAt(-2);
3194 (!specialized && !
instantiateMatch(tok2, typeParametersInDeclaration.size(), templateDeclaration.
isVariadic(), isfunc ?
"(" : isVar ?
";|%op%|(" :
"*|&|::| %name%")))
3199 std::list<std::string> typeStringsUsedInTemplateInstantiation;
3200 std::string typeForNewName =
getNewName(tok2, typeStringsUsedInTemplateInstantiation);
3202 if ((typeForNewName.empty() && !templateDeclaration.
isVariadic()) ||
3203 (!typeParametersInDeclaration.empty() && !
instantiateMatch(tok2, typeParametersInDeclaration.size(), templateDeclaration.
isVariadic(),
nullptr))) {
3205 std::list<const Token *> callstack(1, tok2);
3207 "Failed to instantiate template \"" + instantiation.name() +
"\". The checking continues anyway.",
Certainty::normal));
3209 if (typeForNewName.empty())
3215 const std::string newName(templateDeclaration.
name() +
" < " + typeForNewName +
" >");
3216 const std::string newFullName(templateDeclaration.
scope() + (templateDeclaration.
scope().empty() ?
"" :
" :: ") + newName);
3218 if (expandedtemplates.insert(newFullName).second) {
3219 expandTemplate(templateDeclaration, instantiation, typeParametersInDeclaration, newName, !specialized && !isVar);
3220 instantiated =
true;
3230 if (!instantiated && specialized) {
3231 auto * tok2 =
const_cast<Token *
>(templateDeclaration.
nameToken());
3235 if (maxtime > 0 && std::time(
nullptr) > maxtime) {
3241 "Template instantiation maximum time exceeded",
3251 Token *startToken = tok2;
3253 if (startToken->
strAt(-2) ==
">") {
3260 startToken = startToken->
tokAt(-2);
3277 std::list<std::string> typeStringsUsedInTemplateInstantiation;
3278 std::string typeForNewName =
getNewName(tok2, typeStringsUsedInTemplateInstantiation);
3280 if (typeForNewName.empty()) {
3282 std::list<const Token *> callstack(1, tok2);
3284 "Failed to instantiate template \"" + templateDeclaration.
name() +
"\". The checking continues anyway.",
Certainty::normal));
3290 const std::string newName(templateDeclaration.
name() +
" < " + typeForNewName +
" >");
3291 const std::string newFullName(templateDeclaration.
scope() + (templateDeclaration.
scope().empty() ?
"" :
" :: ") + newName);
3293 if (expandedtemplates.insert(newFullName).second) {
3294 expandTemplate(templateDeclaration, templateDeclaration, typeParametersInDeclaration, newName, !specialized && !isVar);
3295 instantiated =
true;
3304 return instantiated;
3309 std::list<std::string>::const_iterator it = strings.cbegin();
3314 while (tok && tok != end && it != strings.cend()) {
3316 if (*it !=
"unsigned")
3320 if (it == strings.cend())
3323 if (*it !=
"signed")
3327 if (it == strings.cend())
3335 if (it == strings.cend())
3338 if (*it != tok->
str())
3343 return it == strings.cend() && tok && tok->
str() ==
">";
3348 const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
3349 const std::string &newName)
3351 std::list<std::pair<Token *, Token *>> removeTokens;
3354 Token::Match(nameTok,
"template|const_cast|dynamic_cast|reinterpret_cast|static_cast"))
3357 std::set<TemplateSimplifier::TokenAndName*>* pointers = nameTok->templateSimplifierPointers();
3360 if (pointers && !pointers->empty()) {
3362 if (instantiation.
fullName() != (*pointers->begin())->fullName()) {
3364 if (nameTok->str() != instantiation.
name())
3371 if (nameTok->str() != instantiation.
name())
3383 const Token *
const nameTok1 = nameTok;
3384 nameTok->
str(newName);
3388 for (
const Token *tok = nameTok1->
next(); tok != tok2; tok = tok->
next()) {
3389 if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) {
3390 std::list<TokenAndName>::iterator ti;
3392 if (ti->token() == tok) {
3403 removeTokens.emplace_back(nameTok, tok2->
next());
3407 while (!removeTokens.empty()) {
3408 eraseTokens(removeTokens.back().first, removeTokens.back().second);
3409 removeTokens.pop_back();
3427 std::vector<const Token*> specArgs;
3428 std::vector<const Token*> declArgs;
3432 if (specArgs.size() == declArgs.size()) {
3447 if (spec.isSpecialization()) {
3449 return specMatch(spec, decl);
3455 return specMatch(spec, decl);
3468 if (spec.isPartialSpecialization()) {
3470 return specMatch(spec, decl);
3476 return specMatch(spec, decl);
3489 std::vector<const Token *> params1;
3495 if (decl.isPartialSpecialization() || decl.isAlias() || decl.isFriend())
3498 std::vector<const Token *> params2;
3503 if (params1.size() == params2.size()) {
3505 if (forwardDecl.fullName() == decl.fullName()) {
3507 if ((decl.nameToken()->strAt(1) ==
"(" && forwardDecl.nameToken()->strAt(1) ==
"(") ||
3508 (decl.nameToken()->strAt(1) ==
"{" && forwardDecl.nameToken()->strAt(1) ==
";")) {
3512 for (
size_t k = 0; k < params1.size(); k++) {
3514 if (params1[k]->strAt(1) ==
"=" && params2[k]->strAt(1) !=
"=") {
3517 while (end && !(level == 0 &&
Token::Match(end,
",|>"))) {
3530 decl.paramEnd(decl.token()->next()->findClosingBracket());
3539 std::cout <<
indent <<
"token: ";
3540 if (tokenAndName.
token())
3543 std::cout <<
"nullptr";
3544 std::cout << std::endl;
3545 std::cout <<
indent <<
"scope: \"" << tokenAndName.
scope() <<
"\"" << std::endl;
3546 std::cout <<
indent <<
"name: \"" << tokenAndName.
name() <<
"\"" << std::endl;
3547 std::cout <<
indent <<
"fullName: \"" << tokenAndName.
fullName() <<
"\"" << std::endl;
3548 std::cout <<
indent <<
"nameToken: ";
3552 std::cout <<
"nullptr";
3553 std::cout << std::endl;
3554 std::cout <<
indent <<
"paramEnd: ";
3558 std::cout <<
"nullptr";
3559 std::cout << std::endl;
3560 std::cout <<
indent <<
"flags: ";
3562 std::cout <<
" isClass";
3564 std::cout <<
" isFunction";
3566 std::cout <<
" isVariable";
3568 std::cout <<
" isAlias";
3570 std::cout <<
" isSpecialization";
3572 std::cout <<
" isPartialSpecialization";
3574 std::cout <<
" isForwardDeclaration";
3576 std::cout <<
" isVariadic";
3578 std::cout <<
" isFriend";
3579 std::cout << std::endl;
3584 std::cout <<
indent <<
"type: ";
3585 while (start && start != end) {
3587 std::cout <<
"unsigned";
3589 std::cout <<
"signed";
3591 std::cout <<
"long";
3592 std::cout << start->
str();
3593 start = start->
next();
3595 std::cout << end->
str() << std::endl;
3611 std::cout << std::endl;
3612 std::cout << text << std::endl;
3613 std::cout << std::endl;
3617 std::cout <<
"mTemplateDeclarations[" << count++ <<
"]:" << std::endl;
3623 std::cout <<
"mTemplateForwardDeclarations[" << count++ <<
"]:" << std::endl;
3627 unsigned int mapIndex = 0;
3629 unsigned int declIndex = 0;
3631 if (mapItem.first == decl.token()) {
3632 unsigned int forwardIndex = 0;
3634 if (mapItem.second == forwardDecl.token()) {
3635 std::cout <<
"mTemplateForwardDeclarationsMap[" << mapIndex <<
"]:" << std::endl;
3636 std::cout <<
" mTemplateDeclarations[" << declIndex
3637 <<
"] => mTemplateForwardDeclarations[" << forwardIndex <<
"]" << std::endl;
3650 unsigned int decl1Index = 0;
3652 if (decl1.isSpecialization() && mapItem.first == decl1.token()) {
3654 unsigned int decl2Index = 0;
3656 if (mapItem.second == decl2.token()) {
3657 std::cout <<
"mTemplateSpecializationMap[" << mapIndex <<
"]:" << std::endl;
3658 std::cout <<
" mTemplateDeclarations[" << decl1Index
3659 <<
"] => mTemplateDeclarations[" << decl2Index <<
"]" << std::endl;
3668 if (mapItem.second == decl2.token()) {
3669 std::cout <<
"mTemplateSpecializationMap[" << mapIndex <<
"]:" << std::endl;
3670 std::cout <<
" mTemplateDeclarations[" << decl1Index
3671 <<
"] => mTemplateForwardDeclarations[" << decl2Index <<
"]" << std::endl;
3685 unsigned int decl1Index = 0;
3687 if (mapItem.first == decl1.token()) {
3689 unsigned int decl2Index = 0;
3691 if (mapItem.second == decl2.token()) {
3692 std::cout <<
"mTemplatePartialSpecializationMap[" << mapIndex <<
"]:" << std::endl;
3693 std::cout <<
" mTemplateDeclarations[" << decl1Index
3694 <<
"] => mTemplateDeclarations[" << decl2Index <<
"]" << std::endl;
3703 if (mapItem.second == decl2.token()) {
3704 std::cout <<
"mTemplatePartialSpecializationMap[" << mapIndex <<
"]:" << std::endl;
3705 std::cout <<
" mTemplateDeclarations[" << decl1Index
3706 <<
"] => mTemplateForwardDeclarations[" << decl2Index <<
"]" << std::endl;
3721 std::cout <<
"mTemplateInstantiations[" << count++ <<
"]:" << std::endl;
3731 tok->str(
"sizeof...");
3742 tok = tok->next()->findClosingBracket();
3772 unsigned int passCount = 0;
3773 constexpr
unsigned int passCountMax = 10;
3774 for (; passCount < passCountMax; ++passCount) {
3777 bool usingChanged =
false;
3779 usingChanged =
true;
3798 if (passCount == 0) {
3805 mDump =
" <TemplateSimplifier>\n" +
mDump +
" </TemplateSimplifier>\n";
3813 std::string title(
"Template Simplifier pass " + std::to_string(passCount + 1));
3835 printOut(
"### Template Simplifier pass " + std::to_string(passCount + 1) +
" ###");
3838 std::unordered_map<std::string, int> nameOrdinal;
3841 nameOrdinal.emplace(decl.fullName(), ordinal++);
3844 auto score = [&](
const Token* arg) {
3846 for (
const Token* tok = arg; tok; tok = tok->
next()) {
3847 if (tok->str() ==
",")
3851 else if (tok->str() ==
"<") {
3867 std::vector<const Token*> xargs;
3869 std::vector<const Token*> yargs;
3871 if (xargs.size() != yargs.size())
3872 return xargs.size() < yargs.size();
3875 return std::lexicographical_compare(xargs.begin(),
3881 return score(xarg) < score(yarg);
3888 std::set<std::string> expandedtemplates;
3891 if (iter1->isAlias() || iter1->isFriend())
3895 std::list<const Token *> specializations;
3897 if (iter2->isAlias() || iter2->isFriend())
3900 if (iter1->fullName() == iter2->fullName())
3901 specializations.push_back(iter2->nameToken());
3917 return decl.token() == it->token();
3920 if (it->isSpecialization()) {
3922 Token * tok = it->token();
3960 Token * start = j.token();
3963 while (end && end->
str() !=
";")
3967 if (end && end->
next())
3974 if (passCount == passCountMax) {
3980 "TemplateSimplifier: pass count limit hit before simplifications were finished.",
3988 bool simplify =
false;
3990 if (tok->str() ==
"template")
3992 if (tok->str() ==
"{")
3994 if (!simplify || tok->str() !=
"(")
3996 const Token *op =
nullptr;
3997 const Token *args =
nullptr;
4000 args = tok->
link()->previous();
4003 args = tok->
link()->previous()->isName() ? nullptr : tok->next();
4004 }
else if (
Token::Match(tok->link()->tokAt(-3),
"%op% ... )")) {
4005 op = tok->
link()->tokAt(-2);
4007 }
else if (
Token::Match(tok->link()->tokAt(-3),
"... %op% %name% )")) {
4008 op = tok->
link()->tokAt(-2);
4009 args = tok->
next()->
isName() ? nullptr : tok->link()->previous();
4014 const std::string strop = op->
str();
4015 const std::string strargs = (args && args->
isName()) ? args->
str() :
"";
4018 tok->insertToken(
")");
4019 if (!strargs.empty()) {
4020 tok->insertToken(
"...");
4021 tok->insertToken(strargs);
4023 tok->insertToken(
"(");
4025 tok->insertToken(
"__cppcheck_fold_" + strop +
"__");
static bool match(const Token *tok, const std::string &rhs)
int numberOfArguments(const Token *ftok)
Determines the number of arguments - if token is a function call or macro.
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()
static std::string divide(const std::string &first, const std::string &second)
static std::string subtract(const std::string &first, const std::string &second)
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
static std::string calculate(const std::string &first, const std::string &second, char action)
static bool isFloat(const std::string &str)
static std::string add(const std::string &first, const std::string &second)
static bool isNullValue(const std::string &str)
Does the string represent the numerical value of 0? In case leading or trailing white space is provid...
static bool isNegative(const std::string &str)
static bool isInt(const std::string &str)
static std::string multiply(const std::string &first, const std::string &second)
static std::string getSuffix(const std::string &value)
bool debugtemplate
Is –debug-template given?
bool debugnormal
Is –debug-normal given?
int maxTemplateRecursion
max template recursion
SimpleEnableGroup< Severity > severity
bool debugwarnings
Is –debug-warnings given?
Standards standards
Struct contains standards settings.
bool isEnabled(T flag) const
Token and its full scopename.
std::string dump(const std::vector< std::string > &fileNames) const
void isFriend(bool state)
const Token * paramEnd() const
bool isForwardDeclaration() const
bool isSameFamily(const TemplateSimplifier::TokenAndName &decl) const
Is declaration the same family (class, function or variable).
void isFunction(bool state)
const std::string & scope() const
bool isAliasToken(const Token *tok) const
Is token an alias token? template < ...
void isPartialSpecialization(bool state)
void isSpecialization(bool state)
const std::string & name() const
bool isPartialSpecialization() const
void isVariable(bool state)
TokenAndName(Token *token, std::string scope)
Constructor used for instantiations.
const std::string & fullName() const
const Token * nameToken() const
void isForwardDeclaration(bool state)
const Token * aliasEndToken() const
Get alias end token.
bool isSpecialization() const
const Token * aliasStartToken() const
Get alias start token.
void isVariadic(bool state)
static bool alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok)
Simplify templates : check if namespace already present.
void simplifyTemplateAliases()
simplify template aliases
static bool matchSpecialization(const Token *templateDeclarationNameToken, const Token *templateInstantiationNameToken, const std::list< const Token * > &specializations)
void getTemplateInstantiations()
Get template instantiations.
void simplifyTemplateArgs(Token *start, const Token *end, std::vector< newInstantiation > *newInst=nullptr)
Simplify template instantiation arguments.
std::list< TokenAndName > mTemplateDeclarations
void addNamespace(const TokenAndName &templateDeclaration, const Token *tok)
Simplify templates : add namespace to template name.
std::list< TokenAndName > mInstantiatedTemplates
std::vector< TokenAndName > mTypesUsedInTemplateInstantiation
static void deleteToken(Token *tok)
Delete specified token without invalidating pointer to following token.
static void getTemplateParametersInDeclaration(const Token *tok, std::vector< const Token * > &typeParametersInDeclaration)
TemplateParametersInDeclaration.
static bool getTemplateNamePositionTemplateClass(const Token *tok, int &namepos)
Get class template name position.
bool getTemplateDeclarations()
Get template declarations.
static bool instantiateMatch(const Token *instance, const std::size_t numberOfArguments, bool variadic, const char patternAfter[])
Match template declaration/instantiation.
bool simplifyTemplateInstantiations(const TokenAndName &templateDeclaration, const std::list< const Token * > &specializations, const std::time_t maxtime, std::set< std::string > &expandedtemplates)
Simplify templates : expand all instantiations for a template.
std::vector< TokenAndName > mExplicitInstantiationsToDelete
std::list< TokenAndName > mTemplateForwardDeclarations
static NORETURN void syntaxError(const Token *tok)
Syntax error.
void printOut(const TokenAndName &tokenAndName, const std::string &indent=" ") const
ErrorLogger & mErrorLogger
void simplifyTemplates(const std::time_t maxtime)
Simplify templates.
static Token * findTemplateDeclarationEnd(Token *tok)
Find last token of a template declaration.
static void eraseTokens(Token *begin, const Token *end)
void getSpecializations()
Try to locate a matching declaration for each user defined specialization.
void checkComplicatedSyntaxErrorsInTemplates()
std::unordered_map< const Token *, int > mTemplateNamePos
static bool removeTemplate(Token *tok, std::map< Token *, Token * > *forwardDecls=nullptr)
Remove a specific "template < ..." template class/function.
const Settings & mSettings
std::string getNewName(Token *tok2, std::list< std::string > &typeStringsUsedInTemplateInstantiation)
Get the new token name.
bool simplifyCalculations(Token *frontToken=nullptr, const Token *backToken=nullptr, bool isTemplate=true)
Simplify constant calculations such as "1+2" => "3".
void useDefaultArgumentValues()
simplify template instantiations (use default argument values)
void replaceTemplateUsage(const TokenAndName &instantiation, const std::list< std::string > &typeStringsUsedInTemplateInstantiation, const std::string &newName)
Replace all matching template usages 'Foo < int >' => 'Foo<int>'.
static unsigned int templateParameters(const Token *tok)
is the token pointing at a template parameters block < int , 3 > => yes
void expandTemplate(const TokenAndName &templateDeclaration, const TokenAndName &templateInstantiation, const std::vector< const Token * > &typeParametersInDeclaration, const std::string &newName, bool copy)
Expand a template.
static bool simplifyNumericCalculations(Token *tok, bool isTemplate=true)
Simplify constant calculations such as "1+2" => "3".
static bool getTemplateNamePositionTemplateVariable(const Token *tok, int &namepos)
Get variable template name position.
std::list< TokenAndName > mTemplateInstantiations
TemplateSimplifier(Tokenizer &tokenizer)
void addInstantiation(Token *token, const std::string &scope)
Add template instantiation.
std::map< Token *, Token * > mTemplateForwardDeclarationsMap
std::list< TokenAndName > mMemberFunctionsToDelete
static bool getTemplateNamePositionTemplateFunction(const Token *tok, int &namepos)
Get function template name position.
std::map< Token *, Token * > mTemplatePartialSpecializationMap
void fixForwardDeclaredDefaultArgumentValues()
Fix forward declared default argument values by copying them when they are not present in the declara...
int getTemplateNamePosition(const Token *tok)
Match template declaration/instantiation.
std::map< Token *, Token * > mTemplateSpecializationMap
void getPartialSpecializations()
Try to locate a matching declaration for each user defined partial specialization.
static Token * copyTokens(Token *dest, const Token *first, const Token *last, bool one_line=true)
Copy tokens.
std::string fileLine(const Token *tok) const
Get file:line for a given token.
const Token * back() const
get last token of list
bool validateToken(const Token *tok) const
Verify that the given token is an element of the tokenlist.
const std::vector< std::string > & getFiles() const
Get filenames (the sourcefile + the files it include).
void addtoken(const std::string &str, const nonneg int lineno, const nonneg int column, const nonneg int fileno, bool split=false)
const Token * front() const
get first token of list
The token list that the TokenList generates is a linked-list of this class.
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
void deleteThis()
Remove the contents for this token from the token list.
const std::string & originalName() const
void printOut(const char *title=nullptr) const
For debugging purposes, prints token and all tokens followed by it.
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
bool isTemplateArg() const
Is current token a template argument?
void templateSimplifierPointer(TemplateSimplifier::TokenAndName *tokenAndName)
static void createMutualLinks(Token *begin, Token *end)
Links two elements against each other.
nonneg int progressValue() const
Get progressValue (0 - 100)
static nonneg int getStrLength(const Token *tok)
const std::string & strAt(int index) const
const Token * findClosingBracket() const
Returns the closing bracket of opening '<'.
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 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
bool isAssignmentOp() 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
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
std::string getMacroName() const
void deletePrevious(nonneg int count=1)
Unlink and delete the previous 'count' tokens.
nonneg int column() const
The main purpose is to tokenize the source code.
nonneg int sizeOfType(const Token *type) const
Calculates sizeof value for given type.
TokenList list
Token list: stores all tokens.
static const Token * isFunctionHead(const Token *tok, const std::string &endsWith)
is token pointing at function head?
static const Token * startOfExecutableScope(const Token *tok)
Helper function to check for start of function execution scope.
#define REQUIRES(msg,...)
static const std::string emptyString
@ information
Checking information.
static bool isFalse(const ValueFlow::Value &v)
Simple container to be thrown when internal error is detected.
enum Standards::cppstd_t cpp
newInstantiation(Token *t, std::string s)
static Token * skipTernaryOp(Token *tok, const Token *backToken)
static void getFunctionArguments(const Token *nameToken, std::vector< const Token * > &args)
static bool isConstMethod(const Token *nameToken)
static bool areAllParamsTypes(const std::vector< const Token * > ¶ms)
static bool matchTemplateParameters(const Token *nameTok, const std::list< std::string > &strings)
static bool isLowerThanShift(const Token *lower)
static void invalidateForwardDecls(const Token *beg, const Token *end, std::map< Token *, Token * > *forwardDecls)
static bool validTokenStart(bool bounded, const Token *tok, const Token *frontToken, int offset)
static void invalidateInst(const Token *beg, const Token *end, std::vector< newInstantiation > *newInst)
static bool isLowerThanLogicalAnd(const Token *lower)
static bool isLowerEqualThanMulDiv(const Token *lower)
static Token * skipRequires(Token *tok)
static const Token * getFunctionToken(const Token *nameToken)
static bool validTokenEnd(bool bounded, const Token *tok, const Token *backToken, int offset)
static bool isLowerThanPlusMinus(const Token *lower)
static bool isLowerThanXor(const Token *lower)
static T * findTemplateDeclarationEndImpl(T *tok)
static bool isLowerThanAnd(const Token *lower)
static bool specMatch(const TemplateSimplifier::TokenAndName &spec, const TemplateSimplifier::TokenAndName &decl)
static bool isLowerThanOr(const Token *lower)
static bool isLowerThanMulDiv(const Token *lower)
static void indent(std::string &str, const nonneg int indent1, const nonneg int indent2)
static const char * bool_to_string(bool b)