25 #include "simplecpp.h"
45 #include <type_traits>
46 #include <unordered_set>
51 template<
class T,
class U>
52 bool operator()(
const T &x,
const U &y)
const {
61 mTokensFrontBack(tokensFrontBack)
67 :
Token(const_cast<
Token*>(tok)->mTokensFrontBack)
108 if (
mStr ==
"true" ||
mStr ==
"false")
114 else if (std::isalpha((
unsigned char)
mStr[0]) ||
mStr[0] ==
'_' ||
mStr[0] ==
'$') {
121 }
else if (simplecpp::Token::isNumberLike(
mStr)) {
126 }
else if (
mStr ==
"=" ||
mStr ==
"<<=" ||
mStr ==
">>=" ||
127 (
mStr.size() == 2U &&
mStr[1] ==
'=' && std::strchr(
"+-*/%&^|",
mStr[0])))
129 else if (
mStr.size() == 1 &&
mStr.find_first_of(
",[]()?:") != std::string::npos)
131 else if (
mStr==
"<<" ||
mStr==
">>" || (
mStr.size()==1 &&
mStr.find_first_of(
"+-*/%") != std::string::npos))
133 else if (
mStr.size() == 1 &&
mStr.find_first_of(
"&|^~") != std::string::npos)
135 else if (
mStr.size() <= 2 &&
148 else if (
mStr ==
"<=>")
150 else if (
mStr.size() == 2 &&
154 else if (
mStr.size() == 1 && (
mStr.find_first_of(
"{}") != std::string::npos || (
mLink &&
mStr.find_first_of(
"<>") != std::string::npos)))
156 else if (
mStr ==
"...")
168 static const std::unordered_set<std::string>
stdTypes = {
"bool"
207 return std::none_of(
mStr.begin(),
mStr.end(), [](
char c) {
208 return std::islower(c);
218 mStr.insert(0, b.substr(0, b.find(
'"')));
227 std::string::size_type pos = 0U;
228 while ((pos = ret.find(
'\\', pos)) != std::string::npos) {
230 if (ret[pos] >=
'a') {
233 else if (ret[pos] ==
'r')
235 else if (ret[pos] ==
't')
239 return ret.substr(0,pos);
247 while (
mNext && count > 0) {
318 fromToken->
mImpl =
nullptr;
359 if (replaceThis->
next())
372 for (
Token *tok = start; tok != end->
next(); tok = tok->
next())
379 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
382 while (index > 0 && tok) {
386 while (index < 0 && tok) {
387 tok = tok->previous();
403 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
406 T *tok = thisTok->tokAt(index);
408 throw InternalError(thisTok,
"Internal error. Token::linkAt called with index outside the tokens range.");
430 #if defined(__GNUC__)
433 inline __attribute__((always_inline))
439 switch (haystack[0]) {
441 if (haystack[3] ==
'%') {
443 if (tok->
varId() != 0)
447 throw InternalError(tok,
"Internal error. Token::Match called with varid 0. Please report this to Cppcheck developers");
452 if (tok->
varId() == varid)
467 if (haystack[3] ==
'%') {
480 if (haystack[4] ==
'%') {
494 if (haystack[0] ==
'h') {
500 else if (haystack[1] ==
'p') {
531 if (haystack[1] ==
'%') {
533 if (haystack[0] ==
'p') {
559 if (*haystack ==
'|')
568 #if defined(__GNUC__)
570 inline __attribute__((always_inline))
574 const char *needle = tok->
str().c_str();
575 const char *needlePointer = needle;
577 if (needlePointer == needle && haystack[0] ==
'%' && haystack[1] !=
'|' && haystack[1] !=
'\0' && haystack[1] !=
' ') {
581 }
else if (*haystack ==
'|') {
582 if (*needlePointer == 0) {
587 needlePointer = needle;
589 }
else if (*needlePointer == *haystack) {
590 if (*needlePointer ==
'\0')
594 }
else if (*haystack ==
' ' || *haystack ==
'\0') {
595 if (needlePointer == needle)
602 needlePointer = needle;
607 if (*haystack ==
' ' || *haystack ==
'\0') {
610 if (*haystack ==
'|') {
619 if (*needlePointer ==
'\0')
635 const char *current = pattern;
636 const char *end = pattern + pattern_len;
638 const char *
next =
static_cast<const char*
>(std::memchr(pattern,
' ', pattern_len));
643 const std::size_t length =
next - current;
645 if (!tok || length != tok->
mStr.length() || std::strncmp(current, tok->
mStr.c_str(), length) != 0)
650 next = std::strchr(++current,
' ');
664 return (*
str ==
' ' && *word == 0);
678 if (*
str ==
' ' || *
str == 0)
693 const char *p = pattern;
705 if (p[0] ==
'!' && p[1] ==
'!' && p[2] !=
'\0') {
706 while (*p && *p !=
' ')
716 if (tok->
str().length() != 1)
719 const char *temp = p+1;
720 bool chrFound =
false;
722 while (*temp && *temp !=
' ') {
727 else if (*temp == tok->
str()[0]) {
735 if (count > 1 && tok->
str()[0] ==
']')
745 else if (p[0] ==
'!' && p[1] ==
'!' && p[2] !=
'\0') {
756 while (*p && *p !=
' ')
767 if (!(p = strchr(p,
' ')))
779 assert(tok !=
nullptr);
785 std::string::const_iterator it =
str.cbegin();
786 const std::string::const_iterator end =
str.cend();
809 assert(tok !=
nullptr);
813 int sizeofstring = 1;
814 for (
int i = 0; i < (int)
str.size(); i++) {
825 nonneg int sizeofType = 1;
848 newLocation->
next(srcStart);
851 for (
Token *tok = srcStart; tok != srcEnd->
next(); tok = tok->
next())
855 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
858 for (T* tok = thisTok; tok; tok = tok->next()) {
859 if (tok->str() ==
",")
881 for (
const Token* tok =
this; tok; tok = tok->
next()) {
882 if (tok->str() ==
",")
886 else if (tok->str() ==
"<") {
898 for (
const Token* tok =
this; tok; tok = tok->
next()) {
899 if (tok->str() ==
",")
914 return tok->
strAt(-1) ==
"operator";
930 const Token *closing =
nullptr;
931 const bool templateParameter(
strAt(-1) ==
"template");
932 std::set<std::string> templateParameters;
936 if (prev->str() ==
"=")
944 unsigned int depth = 0;
945 for (closing =
this; closing !=
nullptr; closing = closing->
next()) {
947 closing = closing->
link();
953 else if (closing->
str() ==
"<" && closing->
previous() &&
955 (templateParameter ? templateParameters.find(closing->
strAt(-1)) == templateParameters.end() :
true))
957 else if (closing->
str() ==
">") {
960 }
else if (closing->
str() ==
">>" || closing->
str() ==
">>=") {
961 if (!isDecl && depth == 1)
968 else if (templateParameter && depth == 1 && closing->
str() ==
"," &&
970 templateParameters.insert(closing->
strAt(-1));
987 const Token *opening =
nullptr;
989 unsigned int depth = 0;
990 for (opening =
this; opening !=
nullptr; opening = opening->
previous()) {
992 opening = opening->
link();
997 else if (opening->
str() ==
">")
999 else if (opening->
str() ==
"<") {
1016 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
1019 for (T* tok = startTok; tok; tok = tok->next()) {
1036 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
1039 for (T* tok = startTok; tok && tok != end; tok = tok->
next()) {
1055 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
1058 for (T* tok = startTok; tok; tok = tok->next()) {
1074 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
1077 for (T* tok = startTok; tok && tok != end; tok = tok->
next()) {
1105 Token*
Token::insertToken(
const std::string& tokenStr,
const std::string& originalNameStr,
const std::string& macroNameStr,
bool prepend)
1112 newToken->
str(tokenStr);
1116 if (newToken !=
this) {
1129 newToken->
next(
this);
1137 this->
next(newToken);
1143 if (newToken->
str() ==
"{") {
1144 std::string nextScopeNameAddition;
1146 Token *tok1 = newToken;
1155 if (tok1->
strAt(-1) !=
")")
1158 tok1 = tok1->
tokAt(-2);
1159 if (tok1->
strAt(-1) !=
")")
1162 if (tok1->
strAt(-1) ==
">")
1165 tok1 = tok1->
tokAt(-2);
1170 tok1 = tok1->
tokAt(-2);
1172 nextScopeNameAddition +=
scope;
1179 while (nameTok && !
Token::Match(nameTok,
"namespace|class|struct|union %name% {|::|:|<")) {
1183 for (nameTok = nameTok->
next(); nameTok && !
Token::Match(nameTok,
"{|:|<"); nameTok = nameTok->
next()) {
1184 nextScopeNameAddition.append(nameTok->
str());
1185 nextScopeNameAddition.append(
" ");
1187 if (!nextScopeNameAddition.empty())
1188 nextScopeNameAddition.pop_back();
1195 if (!newScopeInfo->name.empty() && !nextScopeNameAddition.empty()) newScopeInfo->name.append(
" :: ");
1196 newScopeInfo->name.append(nextScopeNameAddition);
1197 nextScopeNameAddition =
"";
1199 newToken->
scopeInfo(std::move(newScopeInfo));
1200 }
else if (newToken->
str() ==
"}") {
1206 matchingTok = matchingTok->
previous();
1208 if (matchingTok && matchingTok->
previous()) {
1212 if (prepend && newToken->
previous()) {
1217 if (newToken->
str() ==
";") {
1218 const Token* statementStart;
1220 if (
Token::Match(statementStart,
"using namespace %name% ::|;")) {
1221 const Token * tok1 = statementStart->
tokAt(2);
1222 std::string nameSpace;
1223 while (tok1 && tok1->
str() !=
";") {
1224 if (!nameSpace.empty())
1226 nameSpace += tok1->
str();
1227 tok1 = tok1->
next();
1240 if (!begin || begin == end)
1243 while (begin->
next() && begin->
next() != end) {
1250 assert(begin !=
nullptr);
1251 assert(end !=
nullptr);
1252 assert(begin != end);
1259 if (title && title[0])
1260 std::cout <<
"\n### " << title <<
" ###\n";
1266 if (title && title[0])
1267 std::cout <<
"\n### " << title <<
" ###\n";
1274 const Token *end =
this;
1297 if (
isName() &&
mStr.find(
' ') != std::string::npos) {
1298 for (
const char i :
mStr) {
1302 }
else if (
mStr[0] !=
'\"' ||
mStr.find(
'\0') == std::string::npos)
1305 for (
const char i :
mStr) {
1314 ret += (options.
idtype ?
"var" :
"");
1318 ret += (options.
idtype ?
"expr" :
"");
1331 options.
varid = varid;
1333 options.
macro = macro;
1347 std::map<int, unsigned int> lineNumbers;
1348 for (
const Token *tok =
this; tok != end; tok = tok->
next()) {
1349 assert(tok &&
"end precedes token");
1352 bool fileChange =
false;
1353 if (tok->mImpl->mFileIndex !=
fileIndex) {
1355 lineNumbers[
fileIndex] = tok->mImpl->mFileIndex;
1359 if (options.
files) {
1360 ret +=
"\n\n##file ";
1361 if (fileNames && fileNames->size() > tok->mImpl->mFileIndex)
1362 ret += fileNames->at(tok->mImpl->mFileIndex);
1372 if (options.
linebreaks && (lineNumber != tok->linenr() || fileChange)) {
1373 if (lineNumber+4 < tok->linenr() &&
fileIndex == tok->mImpl->mFileIndex) {
1375 ret += std::to_string(lineNumber+1);
1377 ret += std::to_string(tok->linenr()-1);
1379 ret += std::to_string(tok->linenr());
1382 ret += std::to_string(tok->linenr());
1384 }
else if (lineNumber > tok->linenr()) {
1385 lineNumber = tok->linenr();
1388 ret += std::to_string(lineNumber);
1393 while (lineNumber < tok->
linenr()) {
1397 ret += std::to_string(lineNumber);
1399 if (lineNumber == tok->linenr())
1404 lineNumber = tok->linenr();
1407 ret += tok->stringify(options);
1408 if (tok->next() != end && (!options.
linebreaks || (tok->next()->linenr() == tok->linenr() && tok->next()->fileIndex() == tok->fileIndex())))
1415 std::string
Token::stringifyList(
bool varid,
bool attributes,
bool linenumbers,
bool linebreaks,
bool files,
const std::vector<std::string>* fileNames,
const Token* end)
const
1418 options.
varid = varid;
1420 options.
macro = attributes;
1423 options.
files = files;
1429 return stringifyList(
false, attributes,
false,
false,
false,
nullptr, end);
1434 return stringifyList(varid,
false,
true,
true,
true,
nullptr,
nullptr);
1439 const Token* tok2 = tok;
1442 throw InternalError(
this,
"Internal error. AST cyclic dependency.");
1484 for (
const Token *tok = start; tok && tok != end; tok = tok->
next()) {
1485 if (tok->str() ==
"(")
1487 else if (tok->str() ==
")") {
1489 start = tok->
link();
1501 for (
const Token *tok = end; tok && tok != start; tok = tok->
previous()) {
1502 if (tok->str() ==
")")
1504 else if (tok->str() ==
"(") {
1516 const Token *
const top =
this;
1519 const Token *start = top;
1524 const Token *end = top;
1527 if (end->
str() ==
"[") {
1549 throw InternalError(start,
"Cannot find start of expression");
1553 return std::pair<const Token *, const Token *>(start,end);
1570 std::stack<const Token *> operands;
1571 operands.push(
this);
1572 while (!operands.empty()) {
1573 const Token *op = operands.top();
1600 for (
int distance = 1; distance < 10 && tokbefore; distance++) {
1616 for (
const Token *tok = start; tok && tok != end; tok = tok->
next()) {
1617 if (tok->isUnsigned())
1619 if (tok->isLong() && !tok->isLiteral())
1622 for (
const unsigned char c: tok->str()) {
1629 else if (c >=
' ' && c <= 126)
1633 sprintf(str,
"\\x%02x", c);
1637 }
else if (tok->originalName().empty() || tok->isUnsigned() || tok->isLong()) {
1640 ret += tok->originalName();
1655 const std::string strindent(
indent,
' ');
1657 out << strindent <<
"<token str=\"" << tok->
str() <<
'\"';
1659 out <<
" varId=\"" << tok->
varId() <<
'\"';
1661 out <<
" variable=\"" << tok->
variable() <<
'\"';
1663 out <<
" function=\"" << tok->
function() <<
'\"';
1664 if (!tok->
values().empty())
1665 out <<
" values=\"" << &tok->
values() <<
'\"';
1668 out <<
"/>" << std::endl;
1672 out << '>
' << std::endl;
1673 if (tok->astOperand1())
1674 astStringXml(tok->astOperand1(), indent+2U, out);
1675 if (tok->astOperand2())
1676 astStringXml(tok->astOperand2(), indent+2U, out);
1677 out << strindent << "</token>" << std::endl;
1681 void Token::printAst(bool verbose, bool xml, const std::vector<std::string> &fileNames, std::ostream &out) const
1684 out << "\n\n##AST" << std::endl;
1686 std::set<const Token *> printed;
1687 for (const Token *tok = this; tok; tok = tok->next()) {
1688 if (!tok->mImpl->mAstParent && tok->mImpl->mAstOperand1) {
1689 if (printed.find(tok) != printed.end())
1691 printed.insert(tok);
1694 out << "<ast scope=\"" << tok->scope() << "\" fileIndex=\"" << tok->fileIndex() << "\" linenr=\"" << tok->linenr()
1695 << "\" column=\"" << tok->column() << "\">" << std::endl;
1696 astStringXml(tok, 2U, out);
1697 out << "</ast>" << std::endl;
1699 out << "[" << fileNames[tok->fileIndex()] << ":" << tok->linenr() << "]" << std::endl << tok->astStringVerbose() << std::endl;
1701 out << tok->astString(" ") << std::endl;
1702 if (tok->str() == "(")
1708 static void indent(std::string &str, const nonneg int indent1, const nonneg int indent2)
1710 for (int i = 0; i < indent1; ++i)
1712 for (int i = indent1; i < indent2; i += 2)
1716 void Token::astStringVerboseRecursive(std::string& ret, const nonneg int indent1, const nonneg int indent2) const
1718 if (isExpandedMacro())
1721 if (mImpl->mValueType)
1722 ret += " \'" + mImpl->mValueType->str() + '\
'';
1724 std::ostringstream ostr;
1725 ostr << std::hex <<
function();
1726 ret +=
" f:" + ostr.str();
1730 if (mImpl->mAstOperand1) {
1731 int i1 = indent1, i2 = indent2 + 2;
1732 if (indent1 == indent2 && !mImpl->mAstOperand2)
1734 indent(ret, indent1, indent2);
1735 ret += mImpl->mAstOperand2 ?
"|-" :
"`-";
1736 mImpl->mAstOperand1->astStringVerboseRecursive(ret, i1, i2);
1738 if (mImpl->mAstOperand2) {
1739 int i1 = indent1, i2 = indent2 + 2;
1740 if (indent1 == indent2)
1742 indent(ret, indent1, indent2);
1744 mImpl->mAstOperand2->astStringVerboseRecursive(ret, i1, i2);
1772 outs +=
" <valueflow>\n";
1774 outs +=
"\n\n##Value flow\n";
1775 for (
const Token *tok =
this; tok; tok = tok->
next()) {
1783 outs +=
" <values id=\"";
1795 if (line != tok->
linenr()) {
1797 outs += std::to_string(tok->
linenr());
1806 return value.valueKind == valueKind;
1812 switch (valueKind) {
1818 outs +=
"inconclusive ";
1821 outs +=
"possible ";
1831 switch (value.valueType) {
1834 outs +=
"intvalue=\"";
1839 outs +=
"intvalue=\"";
1840 outs += std::to_string(value.intvalue);
1845 outs +=
"tokvalue=\"";
1850 outs +=
"floatvalue=\"";
1851 outs += std::to_string(value.floatValue);
1855 outs +=
"movedvalue=\"";
1860 outs +=
"uninit=\"1\"";
1863 outs +=
"buffer-size=\"";
1864 outs += std::to_string(value.intvalue);
1868 outs +=
"container-size=\"";
1869 outs += std::to_string(value.intvalue);
1873 outs +=
"iterator-start=\"";
1874 outs += std::to_string(value.intvalue);
1878 outs +=
"iterator-end=\"";
1879 outs += std::to_string(value.intvalue);
1883 outs +=
"lifetime=\"";
1886 outs +=
" lifetime-scope=\"";
1889 outs +=
" lifetime-kind=\"";
1894 outs +=
"symbolic=\"";
1897 outs +=
" symbolic-delta=\"";
1898 outs += std::to_string(value.intvalue);
1902 outs +=
" bound=\"";
1905 if (value.condition) {
1906 outs +=
" condition-line=\"";
1907 outs += std::to_string(value.condition->linenr());
1910 if (value.isKnown())
1911 outs +=
" known=\"true\"";
1912 else if (value.isPossible())
1913 outs +=
" possible=\"true\"";
1914 else if (value.isImpossible())
1915 outs +=
" impossible=\"true\"";
1916 else if (value.isInconclusive())
1917 outs +=
" inconclusive=\"true\"";
1920 outs += std::to_string(value.path);
1927 if (&value != &
values->front())
1929 outs += value.toString();
1933 outs +=
" </values>\n";
1934 else if (
values->size() > 1U)
1940 outs +=
" </valueflow>\n";
1950 return !v.isImpossible() && v.isIntValue() && v.intvalue <= val;
1959 return !v.isImpossible() && v.isIntValue() && v.intvalue >= val;
1968 for (std::list<ValueFlow::Value>::const_iterator it =
mImpl->
mValues->begin(); it !=
mImpl->
mValues->end(); ++it) {
1969 if (it->isImpossible())
1992 const Token *ret =
nullptr;
1993 int minsize = INT_MAX;
1994 for (std::list<ValueFlow::Value>::const_iterator it =
mImpl->
mValues->begin(); it !=
mImpl->
mValues->end(); ++it) {
1995 if (it->isTokValue() && it->tokvalue && it->tokvalue->tokType() ==
Token::eString) {
1996 const int size =
getStrSize(it->tokvalue, settings);
1997 if (!ret || size < minsize) {
2012 const Token *ret =
nullptr;
2014 for (std::list<ValueFlow::Value>::const_iterator it =
mImpl->
mValues->begin(); it !=
mImpl->
mValues->end(); ++it) {
2015 if (it->isTokValue() && it->tokvalue && it->tokvalue->tokType() ==
Token::eString) {
2017 if (!ret || length > maxlength) {
2035 static bool removePointValue(std::list<ValueFlow::Value>& values, std::list<ValueFlow::Value>::iterator& x)
2041 x = values.erase(x);
2047 bool result =
false;
2048 for (
auto itx = values.begin(); itx != values.end(); ++itx) {
2049 if (itx->isNonValue())
2054 for (; ity != values.end(); ++ity) {
2055 if (ity->isNonValue())
2059 if (itx->valueType != ity->valueType)
2061 if (itx->isImpossible() == ity->isImpossible())
2065 if (!itx->equalValue(*ity)) {
2066 auto compare = [](
const std::list<ValueFlow::Value>::const_iterator& x,
const std::list<ValueFlow::Value>::const_iterator& y) {
2067 return x->compareValue(*y, less{});
2069 auto itMax = std::max(itx, ity, compare);
2070 auto itMin = std::min(itx, ity, compare);
2073 values.erase(itMin);
2077 values.erase(itMax);
2082 const bool removex = !itx->isImpossible() || ity->isKnown();
2083 const bool removey = !ity->isImpossible() || itx->isKnown();
2084 if (itx->bound == ity->bound) {
2092 result = removex || removey;
2107 template<
class Iterator>
2111 return std::next(x);
2117 (*it)->bound = x->bound;
2118 std::for_each(std::move(start), std::move(it), [&](
ValueIterator y) {
2121 return values.erase(x);
2126 for (
auto x = values.begin(); x != values.end();) {
2127 if (x->isNonValue()) {
2135 std::vector<ValueIterator> adjValues;
2136 for (
auto y = values.begin(); y != values.end(); y++) {
2139 if (y->isNonValue())
2141 if (x->valueType != y->valueType)
2143 if (x->valueKind != y->valueKind)
2147 if (x->bound != y->bound) {
2162 adjValues.push_back(y);
2164 if (adjValues.empty()) {
2170 assert(xx != values.end() && yy != values.end());
2171 return xx->compareValue(*yy, less{});
2196 if (!x.equalValue(y))
2198 if (x.bound != y.
bound)
2211 for (
int i = 0; i < 4; i++) {
2240 return x.isKnown() && sameValueType(x, value) && !x.equalValue(value);
2256 std::list<ValueFlow::Value>::iterator it;
2266 if (!it->equalValue(value))
2309 int total_count = 0;
2310 for (
Token *tok2 = tok; tok2; tok2 = tok2->
next())
2313 for (
Token *tok2 = tok; tok2; tok2 = tok2->
next())
2314 tok2->mImpl->mProgressValue = count++ *100 / total_count;
2321 for (
Token *tok =
this; tok; tok = tok->
next())
2347 if (typeTok !=
nullptr)
2349 const Token* lhsVarTok{};
2388 vars.cbegin(), vars.cend(), [&](
const Variable* var) {
2389 return var->type() == vars.front()->type();
2391 return vars.front()->type();
2402 return {tok, tok->
next()};
2417 std::pair<const Token*, const Token*> result;
2421 tok2 = tok2->
tokAt(2);
2431 const Token* varTok = tok2;
2433 varTok = varTok->
next();
2435 varTok = varTok->
tokAt(2);
2436 std::pair<const Token*, const Token*> r =
typeDecl(varTok);
2445 declEnd = declEnd->
link()->next();
2446 return { tok2->
next(), declEnd };
2448 const Token *typeBeg{}, *typeEnd{};
2453 else if (tok2->
str() ==
"{") {
2458 result = { typeBeg->
next(), typeEnd };
2479 return {
function->
retDef,
function->returnDefEnd() };
2484 return {
function->retDef,
function->returnDefEnd()};
2491 const ::Type * t =
typeOf(tok);
2492 if (!t || !t->classDef)
2494 return {t->classDef->next(), t->classDef->tokAt(2)};
2500 std::string ret = vt->
str();
2505 if (!r.first || !r.second)
2507 return r.first->stringifyList(r.second,
false);
2524 return value.isKnown() && value.isIntValue();
2537 return value.isKnown() && value.valueType == t;
2547 return value.isKnown() && value.isSymbolicValue() && value.tokvalue &&
2548 value.tokvalue->exprId() == tok->exprId();
2557 return value.isKnown() && value.valueType == t;
2567 return value.isIntValue() && !value.isImpossible() && value.intvalue == val;
2572 template<
class Compare>
2580 if (!value.isIntValue())
2582 if (value.isImpossible())
2584 if (path > -0 && value.path != 0 && value.path != path)
2586 if ((!ret || compare(value.intvalue, ret->
intvalue)) && ((value.condition !=
nullptr) == condition))
2611 return value.isMovedValue() && !value.isImpossible() &&
2612 value.moveKind != ValueFlow::Value::MoveKind::NonMovedVariable;
2623 return value.isContainerSizeValue() && !value.isImpossible() && value.intvalue == val;
2636 templateSimplifierPointer->token(
nullptr);
2651 while (attr && attr->
type != type)
2654 attr->
value = value;
2658 attr->
value = value;
2667 while (attr && attr->
type != type)
2670 value = attr->
value;
2671 return attr !=
nullptr;
2676 while (
Token::Match(tok,
"%name%|.|::|*|&|&&|<|(|template|decltype|sizeof")) {
2701 while (
Token::Match(tok,
"mutable|constexpr|consteval|noexcept|.")) {
bool astIsContainer(const Token *tok)
bool astIsRangeBasedForDecl(const Token *tok)
Is given token a range-declaration in a range-based for loop.
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
const Token * getTokenArgumentFunction(const Token *tok, int &argn)
Return the token to the function and the argument number.
bool astIsSmartPointer(const Token *tok)
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
const Token * nextAfterAstRightmostLeaf(const Token *tok)
bool astIsIterator(const Token *tok)
const Token * previousBeforeAstLeftmostLeaf(const Token *tok)
std::vector< const Variable * > getArgumentVars(const Token *tok, int argnr)
const Token * getLHSVariableToken(const Token *tok)
bool succeeds(const Token *tok1, const Token *tok2)
If tok1 comes after tok2.
const Token * retDef
function return type token
const ::Type * retType
function return type
bool isFloatArgValid(const Token *ftok, int argnr, double argvalue) const
bool isIntArgValid(const Token *ftok, int argnr, const MathLib::bigint argvalue) const
static bool isFloat(const std::string &str)
static bool isInt(const std::string &str)
unsigned long long biguint
Function * function
function info for this function
This is just a container for general settings so that we don't need to pass individual values to func...
SimpleEnableGroup< Certainty > certainty
SimpleEnableGroup< Severity > severity
bool isEnabled(T flag) const
bool isKeyword(const std::string &str) const
const std::vector< std::string > & getFiles() const
Get filenames (the sourcefile + the files it include).
The token list that the TokenList generates is a linked-list of this class.
Token(const Token &)=delete
void update_property_info()
Updates internal property cache like _isName or _isBoolean.
const ValueFlow::Value * getMovedValue() const
bool hasKnownValue() const
const ValueFlow::Value * getValue(const MathLib::bigint val) const
const ValueFlow::Value * getContainerSizeValue(const MathLib::bigint val) 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.
static bool firstWordEquals(const char *str, const char *word)
Works almost like strcmp() except returns only true or false and if str has empty space ' ' character...
void deleteThis()
Remove the contents for this token from the token list.
nonneg int exprId() const
void takeData(Token *fromToken)
used by deleteThis() to take data from token to delete
void setMacroName(std::string name)
void printLines(int lines=5) const
print out tokens - used for debugging
const std::string & originalName() const
void printOut(const char *title=nullptr) const
For debugging purposes, prints token and all tokens followed by it.
const ValueFlow::Value * getMinValue(bool condition, MathLib::bigint path=0) const
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
std::string stringify(const stringifyOptions &options) const
bool addValue(const ValueFlow::Value &value)
Add token value.
std::string astStringZ3() const
static int multiCompare(const Token *tok, const char *haystack, nonneg int varid)
Needle is build from multiple alternatives.
bool hasKnownIntValue() const
const ValueFlow::Value * getMaxValue(bool condition, MathLib::bigint path=0) const
static void replace(Token *replaceThis, Token *start, Token *end)
Replace token replaceThis with tokens between start and end, including start and end.
bool isExpandedMacro() const
void concatStr(std::string const &b)
Concatenate two (quoted) strings.
static std::pair< const Token *, const Token * > typeDecl(const Token *tok, bool pointedToType=false)
const Token * nextTemplateArgument() const
void templateSimplifierPointer(TemplateSimplifier::TokenAndName *tokenAndName)
std::string stringifyList(const stringifyOptions &options, const std::vector< std::string > *fileNames=nullptr, const Token *end=nullptr) const
static nonneg int getStrSize(const Token *tok, const Settings &settings)
const Token * getValueTokenMaxStrLength() const
std::shared_ptr< ScopeInfo2 > scopeInfo() const
const Token * getValueTokenMinStrSize(const Settings &settings, MathLib::bigint *path=nullptr) const
bool isUpperCaseName() const
static void createMutualLinks(Token *begin, Token *end)
Links two elements against each other.
const Scope * scope() const
void setValueType(ValueType *vt)
static nonneg int getStrLength(const Token *tok)
const ValueFlow::Value * getKnownValue(ValueFlow::Value::ValueType t) const
ConstTokenRange until(const Token *t) const
static const ::Type * typeOf(const Token *tok, const Token **typeTok=nullptr)
const ValueType * valueType() const
const std::string & strAt(int index) const
static void assignProgressValues(Token *tok)
Calculate progress values for all tokens.
bool hasKnownSymbolicValue(const Token *tok) const
void astOperand1(Token *tok)
TokensFrontBack & mTokensFrontBack
bool isCalculation() const
Is current token a calculation? Only true for operands.
const Function * function() const
void function(const Function *f)
Associate this token with given function.
std::pair< const Token *, const Token * > findExpressionStartEndTokens() const
static void move(Token *srcStart, Token *srcEnd, Token *newLocation)
Move srcStart and srcEnd tokens and all tokens between them into new a location.
std::string expressionString() const
const std::string & str() const
const Token * findClosingBracket() const
Returns the closing bracket of opening '<'.
void astStringVerboseRecursive(std::string &ret, const nonneg int indent1=0, const nonneg int indent2=0) const
Internal helper function to avoid excessive string allocations.
void setFlag(uint64_t flag_, bool state_)
Set specified flag state.
void printValueFlow(bool xml, std::ostream &out) const
std::string astStringVerbose() const
const ValueFlow::Value * getValueGE(const MathLib::bigint val, const Settings &settings) const
static const char * chrInFirstWord(const char *str, char c)
Works almost like strchr() except if str has empty space ' ' character, that character is handled as ...
const ::Type * type() const
void update_property_isStandardType()
Update internal property cache about isStandardType()
bool isUnaryPreOp() const
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
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
std::string strValue() const
This can be called only for tokens that are strings, else the assert() is called.
void type(const ::Type *t)
Associate this token with given type.
static std::string typeStr(const Token *tok)
bool isAssignmentOp() const
const ValueFlow::Value * getValueLE(const MathLib::bigint val, const Settings &settings) const
static void eraseTokens(Token *begin, const Token *end)
Delete tokens between begin and end.
nonneg int linenr() const
bool isStandardType() const
const ValueFlow::Value * getInvalidValue(const Token *ftok, nonneg int argnr, const Settings &settings) const
const Token * nextArgumentBeforeCreateLinks2() const
void variable(const Variable *v)
Associate this token with given variable.
bool isComparisonOp() const
const std::list< ValueFlow::Value > & values() const
void update_property_char_string_literal()
Update internal property cache about string and char literals.
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
void deletePrevious(nonneg int count=1)
Unlink and delete the previous 'count' tokens.
void astParent(Token *tok)
bool isSymbolicValue() const
Bound bound
The value bound
std::string toString() const
enum ValueFlow::Value::ValueType valueType
ValueKind
How known is this value.
@ Inconclusive
Inconclusive.
@ Impossible
Listed values are impossible.
@ Known
Only listed values are possible.
@ Possible
This value is possible, other unlisted values may also be possible.
bool isLifetimeValue() const
static bool sameToken(const Token *tok1, const Token *tok2)
bool isImpossible() const
const Token * condition
Condition that this value depends on.
const Token * tokvalue
token value - the token that has the value.
long long intvalue
int value (or sometimes bool value?)
nonneg int varId
For calculated values - varId that calculated value depends on.
enum ValueFlow::Value::ValueKind valueKind
bool isInconclusive() const
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
const Token * smartPointerTypeToken
Smart pointer type token.
const Token * containerTypeToken
The container type token.
enum ValueType::Sign sign
Information about a member variable.
const Token * declEndToken() const
Get end token of variable declaration E.g.
const Token * typeEndToken() const
Get type end token.
const Token * nameToken() const
Get name token.
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
const Token * typeStartToken() const
Get type start token.
const ValueType * valueType() const
#define REQUIRES(msg,...)
static const std::string emptyString
Token * findTypeEnd(Token *tok)
Token * findLambdaEndScope(Token *tok)
const Value * findValue(const std::list< Value > &values, const Settings &settings, const std::function< bool(const Value &)> &pred)
size_t getSizeOf(const ValueType &vt, const Settings &settings, int maxRecursion=0)
Simple container to be thrown when internal error is detected.
enum TokenImpl::CppcheckAttributes::Type type
CppcheckAttributes * next
std::list< ValueFlow::Value > * mValues
const Function * mFunction
std::string * mOriginalName
static const std::list< ValueFlow::Value > mEmptyValueList
nonneg int mProgressValue
A value from 0-100 that provides a rough idea about where in the token list this token is located.
std::set< TemplateSimplifier::TokenAndName * > * mTemplateSimplifierPointers
CppcheckAttributes * mCppcheckAttributes
std::shared_ptr< ScopeInfo2 > mScopeInfo
void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value)
nonneg int mIndex
Token index.
bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint &value) const
static stringifyOptions forDebugExprId()
static stringifyOptions forPrintOut()
This struct stores pointers to the front and back tokens of the list this token is in.
static const Token * goToRightParenthesis(const Token *start, const Token *end)
static const std::unordered_set< std::string > controlFlowKeywords
std::list< ValueFlow::Value >::iterator ValueIterator
static int multiCompareImpl(const Token *tok, const char *haystack, nonneg int varid)
static void removeOverlaps(std::list< ValueFlow::Value > &values)
static T * findmatchImpl(T *const startTok, const char pattern[], const nonneg int varId)
static const Token * goToLeftParenthesis(const Token *start, const Token *end)
static bool sameValueType(const ValueFlow::Value &x, const ValueFlow::Value &y)
static const std::unordered_set< std::string > stdTypes
static std::string stringFromTokenRange(const Token *start, const Token *end)
static bool isOperator(const Token *tok)
static bool removeContradiction(std::list< ValueFlow::Value > &values)
static void mergeAdjacent(std::list< ValueFlow::Value > &values)
static bool isAdjacent(const ValueFlow::Value &x, const ValueFlow::Value &y)
static void indent(std::string &str, const nonneg int indent1, const nonneg int indent2)
static int multiComparePercent(const Token *tok, const char *&haystack, nonneg int varid)
static T * findsimplematchImpl(T *const startTok, const char pattern[], size_t pattern_len)
static T * linkAtImpl(T *thisTok, int index)
static const ValueFlow::Value * getCompareValue(const std::list< ValueFlow::Value > &values, bool condition, MathLib::bigint path, Compare compare)
static void removeContradictions(std::list< ValueFlow::Value > &values)
static T * nextArgumentImpl(T *thisTok)
static bool removePointValue(std::list< ValueFlow::Value > &values, std::list< ValueFlow::Value >::iterator &x)
static ValueIterator removeAdjacentValues(std::list< ValueFlow::Value > &values, ValueIterator x, Iterator start, Iterator last)
static T * tokAtImpl(T *tok, int index)
static void astStringXml(const Token *tok, nonneg int indent, std::ostream &out)
static bool isStringLiteral(const std::string &str)
static std::string id_string(const void *p)
static bool isPrefixStringCharLiteral(const std::string &str, char q, const std::string &p)
static std::string getStringLiteral(const std::string &str)
static bool isCharLiteral(const std::string &str)