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)