42 #include <initializer_list>
46 #include <type_traits>
47 #include <unordered_map>
53 const std::function<
bool(
const Token*)>& pred)
59 for (
const Token* tok = start; tok != end; tok = tok->
next()) {
60 if (tok->exprId() != exprid)
71 if (!tok || depth >= 100)
73 if (tok->
str() ==
",") {
99 const Token* tok = ftok;
105 if (!startTok && tok->
next() != tok->
link())
112 std::vector<const Token*> result;
119 std::vector<Token*> result;
127 if (!tok || depth < 0)
129 if (tok->
str() == op)
147 if (tok->
varId() == varid)
156 if (tok->
exprId() == exprid)
168 return valueType->
type == ValueType::Type::CHAR && valueType->
pointer == 0U && valueType->
sign ==
sign;
212 return vt->
type >= ValueType::Type::FLOAT && vt->
pointer == 0U;
282 return parent->
next();
318 return function->containerYield;
330 std::pair<const Token*, const Token*> decl =
Token::typeDecl(expr, pointedToType);
331 if (decl.first && decl.second) {
333 for (
const Token *type = decl.first;
Token::Match(type,
"%name%|::") && type != decl.second; type = type->next()) {
344 if (tok->
str() == rhs)
356 const Token *ret =
nullptr;
360 std::string s = tok->
str();
363 else if (s[0] ==
'<')
371 }
else if (comp ==
"!=" && rhs ==
"0") {
372 if (tok->
str() ==
"!") {
378 }
else if (comp ==
"==" && rhs ==
"0") {
379 if (tok->
str() ==
"!") {
385 while (ret && ret->
str() ==
".")
389 else if (ret && ret->
varId() == 0U)
406 return Token::Match(varDeclEndToken,
"; %var%") && varDeclEndToken->
next() == tok;
411 return Token::Match(tok,
"std :: string|wstring|u16string|u32string !!::") ||
455 const Token* ftok =
nullptr;
468 return !returnType.empty() && returnType.back() !=
'&';
496 for (
const Token * tok2 = startTok; tok2 != stopTok; tok2 = tok2->
next()) {
503 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
508 T* leftmostLeaf = tok;
509 while (leftmostLeaf->astOperand1())
510 leftmostLeaf = leftmostLeaf->astOperand1();
511 return leftmostLeaf->previous();
523 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
526 T * rightmostLeaf = tok;
527 if (!rightmostLeaf || !rightmostLeaf->astOperand1())
534 if (rightmostLeaf->astOperand2() &&
precedes(rightmostLeaf, rightmostLeaf->astOperand2()))
535 rightmostLeaf = rightmostLeaf->astOperand2();
536 else if (rightmostLeaf->astOperand1() &&
precedes(rightmostLeaf, rightmostLeaf->astOperand1()))
537 rightmostLeaf = rightmostLeaf->astOperand1();
540 }
while (rightmostLeaf->astOperand1() || rightmostLeaf->astOperand2());
541 while (
Token::Match(rightmostLeaf->next(),
"]|)") && !
hasToken(rightmostLeaf->next()->link(), rightmostLeaf->next(), tok))
542 rightmostLeaf = rightmostLeaf->next();
543 if (
Token::Match(rightmostLeaf,
"{|(|[") && rightmostLeaf->link())
544 rightmostLeaf = rightmostLeaf->link();
545 return rightmostLeaf->next();
624 std::vector<const Token*> result;
628 result.insert(result.end(), sub.cbegin(), sub.cend());
630 result.push_back(tok2);
645 if (members.size() < 2)
648 auto it = std::find_if(members.crbegin(), members.crend(), [&](
const Token* tok2) {
649 const Variable* var = tok2->variable();
651 return var->isLocal() || var->isArgument();
652 if (Token::simpleMatch(tok2,
"["))
654 return isTemporary(tok2, &library);
656 if (it == members.rend())
659 if (std::any_of(it.base() - 1, members.cend() - 1, [&](
const Token* tok2) {
660 const Token* obj = getParentLifetimeObject(tok2);
661 const Variable* var = obj->variable();
663 if (var && var->isArray())
665 if (astIsPointer(obj) || astIsContainerView(obj) || astIsIterator(obj))
667 if (!astIsUniqueSmartPointer(obj)) {
668 if (astIsSmartPointer(obj))
670 const Token* dotTok = obj->next();
671 if (!Token::simpleMatch(dotTok,
".")) {
672 const Token* endTok = nextAfterAstRightmostLeaf(obj);
674 dotTok = obj->next();
675 else if (Token::simpleMatch(endTok,
"."))
677 else if (Token::simpleMatch(endTok->next(),
"."))
678 dotTok = endTok->next();
681 if (Token::simpleMatch(dotTok,
".") && dotTok->originalName() ==
"->")
684 return var && var->isReference();
720 *parent = tok->
astParent()->astOperand1();
721 if (tok->
astParent()->astOperand1()->valueType())
722 return {*tok->
astParent()->astOperand1()->valueType()};
725 const Token* ftok =
nullptr;
729 const Token* typeTok =
nullptr;
730 if (ftok && argn >= 0) {
732 std::vector<ValueType> result;
733 const Token* nameTok =
nullptr;
737 if (!var->valueType())
739 nameTok = var->nameToken();
740 result.push_back(*var->valueType());
742 if (result.size() == 1 && nameTok && parent) {
750 const Scope* scope = t->classScope;
755 assert(argn < scope->varlist.size());
756 auto it = std::next(scope->
varlist.cbegin(), argn);
758 return {*it->valueType()};
765 const Token* contTok = tok->
astParent()->tokAt(-2)->astOperand1();
770 return {std::move(vtParent)};
811 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
819 T* endTok = tok->linkAt(1);
821 return endTok->tokAt(2)->astOperand2();
824 tok->next()->astOperand2()->astOperand2())
825 return tok->next()->astOperand2()->astOperand2()->astOperand1();
827 return tok->next()->astOperand2()->astOperand1();
828 return tok->next()->astOperand2();
831 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
836 T* startBlock = endBlock->link();
842 return getCondTok(startBlock->previous()->link());
848 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
855 if (tok->str() !=
"(")
861 return tok->astOperand2()->astOperand1();
864 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
871 if (tok->str() !=
"(")
877 return tok->astOperand2()->astOperand2()->astOperand2();
916 if (scope->
isLoopScope() || scope->
type == Scope::ScopeType::eSwitch) {
928 bool &knownInitValue,
942 if (minInitValue.empty()) {
945 minInitValue.push_back(v->
intvalue);
947 if (minInitValue.empty())
950 knownInitValue = initExpr->
astOperand2()->hasKnownIntValue();
951 initValue = minInitValue.front();
957 if (Token::Match(condExpr,
"%oror%|&&") || tok->astOperand2()->getKnownIntValue() < condExpr->astOperand2()->getKnownIntValue())
967 if (condExpr->
str() ==
"<")
968 lastValue = condExpr->
astOperand2()->getKnownIntValue() - 1;
970 lastValue = condExpr->
astOperand2()->getKnownIntValue();
980 if (!varDeclEndToken)
1019 if (tok->
varId() == varid)
1023 if (!val.isLocalLifetimeValue())
1025 if (val.tokvalue->varId() == varid) {
1026 if (val.isInconclusive()) {
1041 const Token* r =
nullptr;
1047 if (childTok->
exprId() == 0)
1049 if (ref.token != tok && expr->
exprId() == childTok->
exprId()) {
1055 if (val.isImpossible())
1057 if (val.isLocalLifetimeValue() || (pointer && val.isSymbolicValue() && val.intvalue == 0)) {
1058 if (findAstNode(val.tokvalue,
1059 [&](const Token* aliasTok) {
1060 return aliasTok != childTok && aliasTok->exprId() == childTok->exprId();
1062 if (val.isInconclusive() && inconclusive != nullptr) {
1075 if (!r && value && inconclusive)
1084 for (
const Token *tok = startTok; tok != endTok; tok = tok->
next()) {
1109 if (expr->
str() ==
"this")
1124 if (classScope && classScope->
function)
1142 bool result =
false;
1146 return ChildrenToVisit::done;
1210 startToken = varTok;
1211 if (varTok->
exprId() == 0) {
1214 }
else if (!
precedes(startToken, endToken)) {
1231 if (std::find(errors->cbegin(), errors->cend(), item) != errors->cend())
1233 errors->push_back(std::move(item));
1242 struct ReferenceTokenLess {
1251 refs_result.push_back({tok, std::move(errors)});
1258 refs_result.push_back({tok, std::move(errors)});
1263 if (!varDeclEndToken) {
1265 refs_result.push_back({tok, std::move(errors)});
1269 errors.emplace_back(varDeclEndToken,
"Passed to reference.");
1271 refs_result.push_back({tok, std::move(errors)});
1277 errors.emplace_back(varDeclEndToken,
"Assigned to reference.");
1279 if (vartok == tok || (!temporary &&
isTemporary(vartok,
nullptr,
true) &&
1282 refs_result.push_back({tok, std::move(errors)});
1290 std::set<ReferenceToken, ReferenceTokenLess> result;
1294 result.insert(refs.cbegin(), refs.cend());
1296 result.insert(refs.cbegin(), refs.cend());
1300 refs_result.push_back({tok, std::move(errors)});
1304 if (!result.empty()) {
1306 refs_result.insert(refs_result.end(), result.cbegin(), result.cend());
1314 refs_result.push_back({tok, std::move(errors)});
1317 std::set<ReferenceToken, ReferenceTokenLess> result;
1319 for (
const Token* returnTok : returns) {
1320 if (returnTok == tok)
1324 const Variable* argvar = rt.token->variable();
1327 refs_result.push_back({tok, std::move(errors)});
1334 refs_result.push_back({tok, std::move(errors)});
1338 if (n >= args.size()) {
1340 refs_result.push_back({tok, std::move(errors)});
1343 const Token* argTok = args[n];
1345 er.emplace_back(returnTok,
"Return reference.");
1349 result.insert(refs.cbegin(), refs.cend());
1352 refs_result.push_back({tok, std::move(errors)});
1358 if (!result.empty()) {
1360 refs_result.insert(refs_result.end(), result.cbegin(), result.cend());
1365 refs_result.push_back({tok, std::move(errors)});
1374 if (refs.size() == 1) {
1376 *errors = std::move(refs.front().errors);
1377 return refs.front().token;
1397 const auto v1 = std::find_if(tok1->
values().cbegin(), tok1->
values().cend(), isKnownFn);
1398 if (v1 == tok1->
values().end()) {
1401 if (v1->isNonValue() || v1->isContainerSizeValue() || v1->isSymbolicValue())
1403 const auto v2 = std::find_if(tok2->
values().cbegin(), tok2->
values().cend(), isKnownFn);
1404 if (v2 == tok2->
values().end()) {
1407 if (v1->valueType != v2->valueType) {
1411 return compare(*v1, *v2, sameLifetime);
1438 if (tok1 ==
nullptr || tok2 ==
nullptr)
1441 auto adjustForCast = [](
const Token* tok) {
1442 if (tok->astOperand2() &&
Token::Match(tok->previous(),
"%type% (|{") && tok->previous()->isStandardType())
1443 return tok->astOperand2();
1447 tok1 = adjustForCast(tok1);
1450 tok2 = adjustForCast(tok2);
1475 parent->
astParent()->astParent()->astOperand1()->str() ==
"for";
1486 parent->
astParent()->astParent()->astOperand1()->str() ==
"for";
1530 return std::any_of(vtParents.cbegin(), vtParents.cend(), [&](
const ValueType& vt) {
1531 return vt.pointer == 0 && vt.type == ValueType::BOOL;
1560 if (tok1 ==
nullptr || tok2 ==
nullptr)
1563 if (tok1->
isCpp()) {
1576 const bool tok_str_eq = tok1->
str() == tok2->
str();
1580 const Token *followTok1 = tok1, *followTok2 = tok2;
1584 followTok2 = followTok2->astOperand2();
1589 if (followVar && !tok_str_eq && (followTok1->
varId() || followTok2->varId() || followTok1->
enumerator() || followTok2->enumerator())) {
1593 return isSameExpression(macro, varTok1, followTok2, settings,
true, followVar, errors);
1598 return isSameExpression(macro, followTok1, varTok2, settings,
true, followVar, errors);
1603 return isSameExpression(macro, varTok1, varTok2, settings,
true, followVar, errors);
1610 if (refTok1 != tok1 || refTok2 != tok2) {
1611 if (refTok1 && !refTok1->
varId() && refTok2 && !refTok2->
varId()) {
1612 const Token *start = refTok1, *end = refTok2;
1614 std::swap(start, end);
1618 return isSameExpression(macro, refTok1, refTok2, settings, pure, followVar, errors);
1627 const Token* condTok =
nullptr;
1628 const Token* exprTok =
nullptr;
1637 const Token* varTok1 =
nullptr;
1638 const Token* varTok2 = exprTok;
1641 value = &condTok->
astOperand1()->values().front();
1643 }
else if (condTok->
astOperand2()->hasKnownIntValue()) {
1644 value = &condTok->
astOperand2()->values().front();
1650 bool compare =
false;
1663 return isSameExpression(macro, varTok1, varTok2, settings, pure, followVar, errors);
1686 const Token * ftok = tok1;
1691 if (!tok1->
function()->isConst() && !tok1->
function()->isAttributeConst() &&
1692 !tok1->
function()->isAttributePure())
1703 tok1->
str() !=
"dynamic_cast")
1711 while (t1 && t2 && t1 != end1 && t2 != end2) {
1717 if (t1 != end1 || t2 != end2)
1723 if (tok1->
str() ==
"{")
1732 t1->
str() == t2->
str() &&
1738 if (!t1 || !t2 || t1->
str() !=
")" || t2->
str() !=
")")
1741 bool noncommutativeEquals =
1743 noncommutativeEquals = noncommutativeEquals &&
1746 if (noncommutativeEquals)
1758 bool commutativeEquals = commutative &&
1760 commutativeEquals = commutativeEquals &&
1764 return commutativeEquals;
1769 if (cond ==
nullptr)
1774 if (cond->
str() ==
"==" || cond->
str() ==
">=")
1776 if (cond->
str() ==
"<=")
1778 if (cond->
str() ==
"<")
1780 if (cond->
str() ==
">")
1787 if (!cond1 || !cond2)
1790 if (
isSameExpression(
true, cond1, cond2, settings, pure, followVar, errors))
1793 if (!isNot && cond1->
str() ==
"&&" && cond2->
str() ==
"&&") {
1794 for (
const Token* tok1: {
1797 for (
const Token* tok2: {
1800 if (
isSameExpression(
true, tok1, tok2, settings, pure, followVar, errors)) {
1808 if (cond1->
str() != cond2->
str() && (cond1->
str() ==
"||" || cond2->
str() ==
"||")) {
1809 const Token* orCond =
nullptr;
1810 const Token* otherCond =
nullptr;
1811 if (cond1->
str() ==
"||") {
1815 if (cond2->
str() ==
"||") {
1823 if (cond1->
str() ==
"!") {
1824 if (cond2->
str() ==
"!=") {
1835 if (cond2->
str() ==
"!")
1836 return isOppositeCond(isNot, cond2, cond1, settings, pure, followVar, errors);
1839 if (cond1->
str() ==
"==" && cond2->
str() ==
"==") {
1850 cond2->
astOperand1()->astOperand1()->astOperand1(),
1862 cond1->
astOperand1()->astOperand1()->astOperand1(),
1875 const std::string &comp1 = cond1->
str();
1881 comp2 = cond2->
str();
1884 comp2 = cond2->
str();
1885 if (comp2[0] ==
'>')
1887 else if (comp2[0] ==
'<')
1891 if (!isNot && comp2.empty()) {
1892 const Token *expr1 =
nullptr, *value1 =
nullptr, *expr2 =
nullptr, *value2 =
nullptr;
1897 }
else if (cond1->
astOperand1()->hasKnownIntValue()) {
1902 else if (
op1[0] ==
'<')
1908 }
else if (cond2->
astOperand1()->hasKnownIntValue()) {
1913 else if (
op2[0] ==
'<')
1916 if (!expr1 || !value1 || !expr2 || !value2) {
1919 if (!
isSameExpression(
true, expr1, expr2, settings, pure, followVar, errors))
1925 if (
op1 ==
"<" ||
op1 ==
"<=")
1927 if (
op1 ==
">=" ||
op1 ==
">")
1934 return ((comp1 ==
"==" && comp2 ==
"!=") ||
1935 (comp1 ==
"!=" && comp2 ==
"==") ||
1936 (comp1 ==
"<" && comp2 ==
">=") ||
1937 (comp1 ==
"<=" && comp2 ==
">") ||
1938 (comp1 ==
">" && comp2 ==
"<=") ||
1939 (comp1 ==
">=" && comp2 ==
"<") ||
1940 (!isNot && ((comp1 ==
"<" && comp2 ==
">") ||
1941 (comp1 ==
">" && comp2 ==
"<") ||
1942 (comp1 ==
"==" && (comp2 ==
"!=" || comp2 ==
">" || comp2 ==
"<")) ||
1943 ((comp1 ==
"!=" || comp1 ==
">" || comp1 ==
"<") && comp2 ==
"==")
1951 if (
isOppositeCond(
true, tok1, tok2, settings, pure, followVar, errors))
1963 if (var.isReference() || var.isPointer())
1964 return !var.isConst();
1976 if (f->isAttributePure() || f->isAttributeConst())
1989 std::vector<const Function*> fs = f->getOverloadedFunctions();
1990 if (std::any_of(fs.cbegin(), fs.cend(), [&](
const Function* g) {
1993 if (f->argumentList.size() != g->argumentList.size())
1995 if (functionModifiesArguments(g))
1997 if (g->isConst() && Function::returnsConst(g))
2005 if (f->argumentList.empty())
2006 return f->isConstexpr();
2029 bool constMember = !memberFunction;
2039 return constMember && std::all_of(args.cbegin(), args.cend(), [](
const Token* tok) {
2040 const Variable* var = tok->variable();
2042 return var->isConst();
2066 if (tok->
str() ==
"{")
2080 if (tok && tok->
varId()) {
2098 if (f.type != Function::eFunction)
2101 const std::string freturnType = f.retType ? f.retType->name() : f.retDef->stringifyList(f.returnDefEnd());
2102 return f.argumentList.size() != fun->argumentList.size() || returnType != freturnType || f.name() == fun->name();
2110 const Type * varType = var->
type();
2114 auto pred = [=](
const Variable& v) {
2116 return v.
type() && v.
type()->name() == varType->
name() && v.name() != var->
name();
2119 v.isClass() == var->
isClass() &&
2120 v.isArray() == var->
isArray() &&
2122 v.name() != var->
name();
2124 if (std::any_of(scope->
varlist.cbegin(), scope->
varlist.cend(), pred))
2152 return Token::Match(tok,
"return|goto|throw|continue|break");
2161 if (function->isEscapeFunction())
2163 if (function->isAttributeNoreturn())
2165 }
else if (library) {
2182 if (function->isEscapeFunction())
2184 if (function->isAttributeNoreturn())
2192 *unknownFunc = ftok;
2204 if (!endToken || endToken->
str() !=
"}")
2215 return isReturnScope(prev, library, unknownFunc, functionScope) &&
2221 return isReturnScope(prev, library, unknownFunc, functionScope);
2223 if (
isEscaped(prev->
link()->astTop(), functionScope, library))
2226 return isReturnScope(prev, library, unknownFunc, functionScope);
2245 return prev && prev->
isName();
2255 while (scope && scope != var->
scope()) {
2256 if (scope->
type == type)
2267 if (tok->
varId() == varid)
2279 if (tok->
str() ==
"{")
2280 return tok->
scope()->bodyStart == tok;
2281 if (tok->
str() ==
"}")
2282 return tok->
scope()->bodyEnd == tok;
2286 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
2291 T* parent = tok->astParent();
2292 if (parent && (parent->isUnaryOp(
"&") || parent->isIncDecOp()))
2293 parent = parent->astParent();
2294 while (parent && parent->isCast())
2295 parent = parent->astParent();
2296 if (
Token::Match(parent,
"[+-]") && parent->valueType() && parent->valueType()->pointer)
2297 parent = parent->astParent();
2304 parent = parent->astParent();
2306 parent = parent->astParent();
2307 if (!parent || parent->str() !=
"(")
2314 while (argtok && argtok->astParent() && (!
Token::Match(argtok->astParent(),
",|(|{") || argtok->astParent()->isCast())) {
2315 argtok = argtok->astParent();
2320 argtok = argtok->astOperand1();
2323 tok = tok->astParent();
2332 if (tok->astOperand2())
2333 tok = tok->astOperand1();
2334 while (tok && (tok->isUnaryOp(
"*") || tok->str() ==
"["))
2335 tok = tok->astOperand1();
2337 return tok->tokAt(2);
2339 tok = tok->astOperand2();
2342 if (!tok->astOperand2() && tok->astOperand1()) {
2343 tok = tok->astOperand1();
2346 tok = tok->astOperand2();
2348 tok = tok->astOperand1();
2350 if (tok && tok->link() && tok->str() ==
">")
2351 tok = tok->link()->previous();
2370 std::vector<const Variable*> result;
2388 if (tokIsBrace && typeScope->
numConstructors == 0 && argnr < typeScope->varlist.size()) {
2389 auto it = std::next(typeScope->
varlist.cbegin(), argnr);
2393 const bool constructor = tokIsBrace || (tok->
variable() && tok->
variable()->nameToken() == tok);
2395 if (
function.argCount() < argCount)
2397 if (constructor && !
function.isConstructor())
2401 const Variable* argvar =
function.getArgumentVar(argnr);
2403 result.push_back(argvar);
2418 const Token* typeTok =
nullptr;
2446 const Token *
const tok1 = tok;
2454 if (deref && indirect > 0)
2473 parenTok = parenTok->
link()->next();
2474 const bool possiblyPassedByReference = (parenTok->
next() == tok1 ||
Token::Match(tok1->
previous(),
", %name% [,)}]"));
2485 if (indirect == 0 &&
isArray(tok1))
2489 if (indirect > 0 && requireInit && requireNonNull)
2496 if (indirect == 0 && requireNonNull)
2499 if (possiblyPassedByReference) {
2509 if (tok == var->nameToken() && (!var->isReference() || var->isConst()) && (!var->isClass() || (var->valueType() && var->valueType()->container)))
2514 bool conclusive =
false;
2520 if (arg->isPointer() && !(arg->valueType() && arg->valueType()->isConst(indirect)))
2522 if (indirect > 1 && addressOf && arg->isPointer() && (!arg->valueType() || !arg->valueType()->isConst(indirect-1)))
2524 if (arg->isArray() || (!arg->isPointer() && (!arg->valueType() || arg->valueType()->type ==
ValueType::UNKNOWN_TYPE)))
2527 if (!arg->isConst() && arg->isReference())
2530 if (addressOf && tok1->
astParent()->isUnaryOp(
"&")) {
2532 while (castToken->
astParent()->isCast())
2554 const Token *tok2 = tok;
2562 if (derefs > indirect)
2584 auto skipRedundantPtrOp = [](
const Token* tok,
const Token* parent) {
2586 while (parent && gparent && ((parent->isUnaryOp(
"*") && gparent->
isUnaryOp(
"&")) || (parent->isUnaryOp(
"&") && gparent->
isUnaryOp(
"*")))) {
2594 tok2 = skipRedundantPtrOp(tok2, tok2->
astParent());
2597 if (((indirect == 0 || tok2 != tok) || (indirect == 1 && tok2->
str() ==
".")) && tok2 == tok2->
astParent()->astOperand1())
2616 if (vt && vt->
isConst(indirect))
2628 tok2->
astParent()->astOperand1() == tok2) {
2690 const Token *ftok = tok2;
2697 const Token * ptok = tok2;
2700 int pindirect = indirect;
2718 const Token *typeStart = tok2->
astParent()->previous()->link()->previous();
2722 for (
const Token *vartok = typeStart->
tokAt(2); vartok != tok2; vartok = vartok->
next()) {
2723 if (vartok->varId()) {
2724 const Variable* refvar = vartok->variable();
2755 (parent->
astParent()->astOperand1() == parent)) {
2771 return findVariableChanged(start, end, indirect, exprid, globalvar, settings, depth) !=
nullptr;
2783 if (tok->exprId() != exprid)
2791 template<class F, class R=decltype(std::declval<F>()())>
2796 return [=]()
mutable -> R {
2806 REQUIRES(
"F must be a function that returns a Token class",
2807 std::is_convertible<decltype(std::declval<F>()()),
const Token*> )>
2825 bool aliased =
false;
2827 auto expr = getExprTok();
2853 }, tok, indirect, expr->
exprId(), globalvar, settings, depth);
2862 auto getExprTok =
memoize([&] {
2865 for (
Token *tok = start; tok != end; tok = tok->
next()) {
2887 start = start->
tokAt(2);
2899 const std::vector<const Variable*> &vars,
2902 std::set<int> varids;
2903 std::transform(vars.cbegin(), vars.cend(), std::inserter(varids, varids.begin()), [](
const Variable* var) {
2904 return var->declarationId();
2906 const bool globalvar = std::any_of(vars.cbegin(), vars.cend(), [](
const Variable* var) {
2907 return var->isGlobal();
2909 for (
const Token* tok = start; tok != end; tok = tok->
next()) {
2910 if (tok->varId() == 0 || varids.count(tok->varId()) == 0) {
2942 for (
const Token* tok = start; tok != end; tok = tok->
next()) {
2951 template<
class Find>
2963 const Token* result =
nullptr;
2970 bool global =
false;
2980 if (tok->
exprId() > 0 || global) {
2981 const Token* modifedTok = find(start, end, [&](
const Token* tok2) {
2984 indirect = vt->pointer;
2985 if (vt->type == ValueType::ITERATOR)
2988 for (
int i = 0; i <= indirect; ++i) {
2995 result = modifedTok;
3005 struct ExpressionChangedSimpleFind {
3007 const Token* operator()(
const Token* start,
const Token* end, F f)
const
3013 struct ExpressionChangedSkipDeadCode {
3015 const std::function<std::vector<MathLib::bigint>(
const Token* tok)>*
evaluate;
3016 ExpressionChangedSkipDeadCode(
const Library& library,
3017 const std::function<std::vector<MathLib::bigint>(
const Token* tok)>&
evaluate)
3021 const Token* operator()(
const Token* start,
const Token* end, F f)
const
3041 const std::function<std::vector<MathLib::bigint>(
const Token* tok)>&
evaluate,
3045 expr, start, end, settings, depth, ExpressionChangedSkipDeadCode{settings.
library,
evaluate});
3050 const Token* tok = ftok;
3058 if (!startTok && tok->
next() != tok->
link())
3070 const Token* openBracket = start->
next();
3072 openBracket = openBracket->
next();
3073 if (openBracket && openBracket->
str()==
"(" && openBracket->
next() && openBracket->
next()->
str()!=
")") {
3074 const Token* argument=openBracket->
next();
3090 return v.nameToken() == var->nameToken();
3094 return std::distance(f->
argumentList.cbegin(), arg_it);
3107 if (tok->
str() ==
"(")
3112 }
else if (
Token::Match(tok,
"begin|cbegin|rbegin|crbegin|end|cend|rend|crend (")) {
3124 if (args.size() != 2)
3129 const Token* tok1 =
nullptr;
3130 const Token* tok2 =
nullptr;
3142 return tok1 || tok2;
3147 if (!last || !last->
isCpp() || last->
str() !=
"}")
3157 template<
class T,
REQUIRES(
"T must be a Token class", std::is_convertible<T*, const Token*> )>
3160 auto maybeLambda = [](T* tok) ->
bool {
3163 tok = tok->link()->previous();
3165 if (tok->str() ==
">")
3167 if (tok->str() ==
"new")
3169 tok = tok->previous();
3175 if (!first || !first->isCpp() || first->str() !=
"[")
3177 if (!maybeLambda(first->previous()))
3181 const Token* roundOrCurly = first->
link()->next();
3182 if (roundOrCurly->
link() && roundOrCurly->
str() ==
"<")
3183 roundOrCurly = roundOrCurly->
link()->next();
3184 if (first->astOperand1() != roundOrCurly)
3188 if (tok->astOperand1() && tok->astOperand1()->str() ==
"(")
3189 tok = tok->astOperand1();
3190 if (tok->astOperand1() && tok->astOperand1()->str() ==
"{")
3191 return tok->astOperand1()->link();
3209 if (!stream->
isCpp())
3215 if (stream->
astParent()->astOperand1() != stream)
3235 const Token *parent = op;
3258 if (skipPredicate && skipPredicate(tok))
3268 return !args.empty() && std::all_of(args.cbegin(), args.cend(), [&](
const Token* t) {
3269 return isConstVarExpression(t, skipPredicate);
3286 if (
Token::Match(tok,
"%bool%|%num%|%str%|%char%|nullptr|NULL"))
3291 return tok->
variable()->isConst() && tok->
variable()->nameToken() && tok->
variable()->nameToken()->hasKnownValue();
3311 const int nCtor = ftok->
variable()->type()->classScope->numConstructors;
3317 return f.isConstructor();
3329 if (arg->isReference() || (arg->isPointer() && indirect == 1)) {
3333 if (bodytok->variable() == arg) {
3334 if (arg->isReference())
3344 if (!args.empty() && indirect == 0 && !addressOf)
3348 }
else if (ftok->
str() ==
"{") {
3352 if (indirect == 0 &&
astIsPointer(tok) && !addressOf && isnullbad)
3354 bool hasIndirect =
false;
3356 if (isuninitbad && (!addressOf || isnullbad))
3377 if (indirect > 0 && parent) {
3393 if (indirect == 0) {
3394 if (
Token::Match(parent,
"%cop%|%assign%|++|--") && parent->
str() !=
"=" &&
3403 if (op->
str() ==
"=") {
3447 std::vector<const Variable*> result;
3496 if (vartok && vartok->
variable() && vartok->
variable()->nameToken() == vartok)
3520 if (expr->
isCpp() &&
Token::Match(expr,
"static_cast|const_cast|dynamic_cast|reinterpret_cast <"))
3522 else if (!expr->
isCast())
3540 bool globalData =
false;
3543 [expr, &globalData, &var](
const Token *tok) {
3549 return ChildrenToVisit::none;
3554 return ChildrenToVisit::none;
3558 const Variable *lhsvar = tok->astOperand1()->variable();
3559 const ValueType *lhstype = tok->astOperand1()->valueType();
3560 if (lhsvar->isPointer()) {
3562 return ChildrenToVisit::none;
3564 if (lhsvar->isArgument() && lhsvar->isArray()) {
3566 return ChildrenToVisit::none;
3568 if (lhsvar->isArgument() && (!lhstype || (lhstype->type <= ValueType::Type::VOID && !lhstype->container))) {
3570 return ChildrenToVisit::none;
3575 return ChildrenToVisit::none;
3579 if (tok->variable()->isReference() && tok != tok->variable()->nameToken()) {
3581 return ChildrenToVisit::none;
3585 return ChildrenToVisit::none;
3589 return ChildrenToVisit::none;
3591 if (tok->
variable()->isArgument() && tok->
variable()->isPointer() && tok != expr) {
3593 return ChildrenToVisit::none;
3595 if (tok->
variable()->isPointerArray()) {
3597 return ChildrenToVisit::none;
3603 return ChildrenToVisit::none;
3609 return globalData || !var;
3614 return Token::Match(tok,
"alignof|_Alignof|_alignof|__alignof|__alignof__|decltype|offsetof|sizeof|typeid|typeof|__typeof__ (");
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
Is given syntax tree a variable comparison against value.
int numberOfArgumentsWithoutAst(const Token *start)
Get number of arguments without using AST.
static bool compareKnownValue(const Token *const tok1, const Token *const tok2, const std::function< bool(const ValueFlow::Value &, const ValueFlow::Value &, bool)> &compare)
bool astIsContainer(const Token *tok)
static bool isCPPCastKeyword(const Token *tok)
const Token * getIteratorExpression(const Token *tok)
static T * getTokenArgumentFunctionImpl(T *tok, int &argn)
static bool isArray(const Token *tok)
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
static bool astIsCharWithSign(const Token *tok, ValueType::Sign sign)
static bool astIsBoolLike(const Token *tok, const Settings &settings)
bool isOppositeExpression(const Token *const tok1, const Token *const tok2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
static bool isExpressionChangedAt(const F &getExprTok, const Token *tok, int indirect, const nonneg int exprid, bool globalvar, const Settings &settings, int depth)
bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
bool astIsPrimitive(const Token *tok)
bool astIsContainerView(const Token *tok)
bool astIsIntegral(const Token *tok, bool unknown)
Is expression of integral type?
static T * getCondTokImpl(T *tok)
static T * getStepTokImpl(T *tok)
static const Token * getLHSVariableRecursive(const Token *tok)
bool exprDependsOnThis(const Token *expr, bool onVar, nonneg int depth)
bool isTemporary(const Token *tok, const Library *library, bool unknown)
const Token * followReferences(const Token *tok, ErrorPath *errors)
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 astHasVar(const Token *tok, nonneg int varid)
static void getLHSVariablesRecursive(std::vector< const Variable * > &vars, const Token *tok)
bool isUsedAsBool(const Token *const tok, const Settings &settings)
Is token used as boolean, that is to say cast to a bool, or used as a condition in a if/while/for.
static void followVariableExpressionError(const Token *tok1, const Token *tok2, ErrorPath *errors)
bool extractForLoopValues(const Token *forToken, nonneg int &varid, bool &knownInitValue, MathLib::bigint &initValue, bool &partialCond, MathLib::bigint &stepValue, MathLib::bigint &lastValue)
Extract for loop values: loopvar varid, init value, step value, last value (inclusive)
static bool hasNoreturnFunction(const Token *tok, const Library &library, const Token **unknownFunc)
bool astIsPointer(const Token *tok)
bool compareTokenFlags(const Token *tok1, const Token *tok2, bool macro)
Are the tokens' flags equal?
const Token * isInLoopCondition(const Token *tok)
static const Token * getParentLifetimeObject(const Token *tok)
static T * findLambdaEndTokenGeneric(T *first)
bool isStlStringType(const Token *tok)
bool isLikelyStreamRead(const Token *op)
do we see a likely write of rhs through overloaded operator s >> x; a & x;
bool isUniqueExpression(const Token *tok)
bool astIsContainerOwned(const Token *tok)
const Token * findExpressionChanged(const Token *expr, const Token *start, const Token *end, const Settings &settings, int depth)
const Token * findAllocFuncCallToken(const Token *expr, const Library &library)
Find a allocation function call in expression, so result of expression is allocated memory/resource.
bool astIsLHS(const Token *tok)
bool isGlobalData(const Token *expr)
bool isConstFunctionCall(const Token *ftok, const Library &library)
static bool isTrivialConstructor(const Token *tok)
bool astIsBool(const Token *tok)
Is expression of boolean type?
const Token * getArgumentStart(const Token *ftok)
bool isScopeBracket(const Token *tok)
static ExprUsage getFunctionUsage(const Token *tok, int indirect, const Settings &settings)
bool isEscapeFunction(const Token *ftok, const Library *library)
bool isVariableDecl(const Token *tok)
static bool isFunctionCall(const Token *tok)
static bool isInConstructorList(const Token *tok)
static bool hasToken(const Token *startTok, const Token *stopTok, const Token *tok)
static bool match(const Token *tok, const std::string &rhs)
static int getArgumentPos(const Token *ftok, const Token *tokToFind)
bool astIsGenericChar(const Token *tok)
Is expression a char according to valueType?
bool astHasExpr(const Token *tok, nonneg int exprid)
bool isStructuredBindingVariable(const Variable *var)
Token * getInitTok(Token *tok)
const Token * findNextTokenFromBreak(const Token *breakToken)
For a "break" token, locate the next token to execute.
bool isLeafDot(const Token *tok)
bool astIsUniqueSmartPointer(const Token *tok)
static bool isEscaped(const Token *tok, bool functionsScope, const Library &library)
Library::Container::Action astContainerAction(const Token *tok, const Token **ftok)
Library::Container::Yield astFunctionYield(const Token *tok, const Settings &settings, const Token **ftok)
static bool isDifferentKnownValues(const Token *const tok1, const Token *const tok2)
std::vector< const Token * > astFlatten(const Token *tok, const char *op)
bool astIsSmartPointer(const Token *tok)
Token * getCondTokFromEnd(Token *endBlock)
bool isNullOperand(const Token *expr)
const Token * findLambdaStartToken(const Token *last)
bool astHasToken(const Token *root, const Token *tok)
const Token * astParentSkipParens(const Token *tok)
bool isOppositeCond(bool isNot, const Token *const cond1, const Token *const cond2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
Are two conditions opposite.
bool astIsContainerString(const Token *tok)
static bool isForLoopCondition(const Token *const tok)
Token * getCondTok(Token *tok)
bool astIsRHS(const Token *tok)
bool isWithinScope(const Token *tok, const Variable *var, Scope::ScopeType type)
Is tok within a scope of the given type, nested within var's scope?
static std::function< R()> memoize(F f)
static bool functionModifiesArguments(const Function *f)
std::vector< ValueType > getParentValueTypes(const Token *tok, const Settings &settings, const Token **parent)
const Variable * getLHSVariable(const Token *tok)
bool astIsSignedChar(const Token *tok)
Is expression a 'signed char' if no promotion is used.
bool isConstVarExpression(const Token *tok, const std::function< bool(const Token *)> &skipPredicate)
bool isWithoutSideEffects(const Token *tok, bool checkArrayAccess, bool checkReference)
bool astIsFloat(const Token *tok, bool unknown)
Is expression of floating point type?
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
const Token * nextAfterAstRightmostLeaf(const Token *tok)
ExprUsage getExprUsage(const Token *tok, int indirect, const Settings &settings)
bool isThisChanged(const Token *tok, int indirect, const Settings &settings)
static const Token * getVariableInitExpression(const Variable *var)
bool astIsNonStringContainer(const Token *tok)
static std::vector< const Token * > getParentMembers(const Token *tok)
static bool isZeroBoundCond(const Token *const cond)
Token * getStepTok(Token *tok)
bool isVariablesChanged(const Token *start, const Token *end, int indirect, const std::vector< const Variable * > &vars, const Settings &settings)
bool isIteratorPair(const std::vector< const Token * > &args)
Are the arguments a pair of iterators/pointers?
bool isAliasOf(const Token *tok, nonneg int varid, bool *inconclusive)
If token is an alias if another variable.
static const Token * getContainerFunction(const Token *tok)
const Token * getParentMember(const Token *tok)
bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int varid, const Settings &settings, bool *inconclusive)
Is variable changed by function call? In case the answer of the question is inconclusive,...
bool isReturnScope(const Token *const endToken, const Library &library, const Token **unknownFunc, bool functionScope)
Is scope a return scope (scope will unconditionally return)
Token * findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings &settings, int depth)
static bool hasUnknownVars(const Token *startTok)
static bool isEscapedOrJump(const Token *tok, bool functionsScope, const Library &library)
static const Token * followVariableExpression(const Settings &settings, const Token *tok, const Token *end=nullptr)
This takes a token that refers to a variable and it will return the token to the expression that the ...
static bool isSameConstantValue(bool macro, const Token *tok1, const Token *tok2)
bool astIsUnsigned(const Token *tok)
static bool isSameLifetime(const Token *const tok1, const Token *const tok2)
static int findArgumentPosRecursive(const Token *tok, const Token *tokToFind, bool &found, nonneg int depth=0)
bool astIsIterator(const Token *tok)
const Token * previousBeforeAstLeftmostLeaf(const Token *tok)
const Token * findExpressionChangedSkipDeadCode(const Token *expr, const Token *start, const Token *end, const Settings &settings, const std::function< std::vector< MathLib::bigint >(const Token *tok)> &evaluate, int depth)
bool isCPPCast(const Token *tok)
bool isEqualKnownValue(const Token *const tok1, const Token *const tok2)
std::vector< const Variable * > getLHSVariables(const Token *tok)
bool isConstExpression(const Token *tok, const Library &library)
std::vector< const Variable * > getArgumentVars(const Token *tok, int argnr)
static bool isForLoopIncrement(const Token *const tok)
bool isUnevaluated(const Token *tok)
const Token * getLHSVariableToken(const Token *tok)
const Token * getParentLifetime(const Token *tok)
SmallVector< ReferenceToken > followAllReferences(const Token *tok, bool temporary, bool inconclusive, ErrorPath errors, int depth)
static bool isAliased(const Token *startTok, const Token *endTok, nonneg int varid)
bool isLikelyStream(const Token *stream)
std::string astCanonicalType(const Token *expr, bool pointedToType)
Get canonical type of expression.
Library::Container::Yield astContainerYield(const Token *tok, const Token **ftok)
static T * getCondTokFromEndImpl(T *endBlock)
static const Token * findThisChanged(const Token *start, const Token *end, int indirect, const Settings &settings)
static int findArgumentPos(const Token *tok, const Token *tokToFind)
bool astIsUnknownSignChar(const Token *tok)
Is expression a 'char' if no promotion is used?
static const Token * findExpressionChangedImpl(const Token *expr, const Token *start, const Token *end, const Settings &settings, int depth, Find find)
static T * getInitTokImpl(T *tok)
bool succeeds(const Token *tok1, const Token *tok2)
If tok1 comes after tok2.
static T * previousBeforeAstLeftmostLeafGeneric(T *tok)
int numberOfArguments(const Token *ftok)
Determines the number of arguments - if token is a function call or macro.
nonneg int astCount(const Token *tok, const char *op, int depth)
const Token * findExpression(const nonneg int exprid, const Token *start, const Token *end, const std::function< bool(const Token *)> &pred)
bool isVariableChanged(const Token *tok, int indirect, const Settings &settings, int depth)
static T * nextAfterAstRightmostLeafGeneric(T *tok)
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
void astFlattenCopy(T *tok, const char *op, OuputIterator out, nonneg int depth=100)
const Token * findAstNode(const Token *ast, const TFunc &pred)
static int sign(const T v)
static const std::set< std::string > stl_containers_not_const
Set of the STL types whose operator[] is not const.
static std::vector< const Token * > findReturns(const Function *f)
const Scope * functionScope
scope of function body
static bool returnsConst(const Function *function, bool unknown=false)
Type type
constructor, destructor, ...
static bool returnsReference(const Function *function, bool unknown=false, bool includeRValueRef=false)
const Token * retDef
function return type token
const Token * token
function name token in implementation
const ::Type * retType
function return type
const Scope * nestedIn
Scope the function is declared in.
const Token * tokenDef
function name token in class definition
std::list< Variable > argumentList
argument list, must remain list due to clangimport usage!
static bool returnsVoid(const Function *function, bool unknown=false)
Action getAction(const std::string &function) const
Yield getYield(const std::string &function) const
Library definitions handling.
ArgumentChecks::Direction getArgDirection(const Token *ftok, int argnr) const
bool isuninitargbad(const Token *ftok, int argnr, int indirect=0, bool *hasIndirect=nullptr) const
static bool isContainerYield(const Token *const cond, Library::Container::Yield y, const std::string &fallback=emptyString)
bool isnullargbad(const Token *ftok, int argnr) const
bool isnoreturn(const Token *ftok) const
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
const Function * getFunction(const Token *ftok) const
std::string getFunctionName(const Token *ftok) const
Get function name for function call.
const std::string & returnValueType(const Token *ftok) const
std::unordered_map< std::string, Function > functions
bool isFunctionConst(const std::string &functionName, bool pure) const
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 isInt(const std::string &str)
std::list< Function > functionList
std::list< Variable > varlist
static Function * nestedInFunction(const Scope *scope)
Function * function
function info for this function
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
nonneg int numConstructors
const Scope * functionOf
scope this function belongs to
std::vector< const Scope * > findAssociatedScopes() const
bool isClassOrStruct() const
This is just a container for general settings so that we don't need to pass individual values to func...
The token list that the TokenList generates is a linked-list of this class.
bool hasKnownValue() 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.
nonneg int exprId() const
bool isEnumerator() const
const std::string & originalName() const
bool hasKnownIntValue() const
bool isExpandedMacro() const
bool isTemplateArg() const
Is current token a template argument?
static std::pair< const Token *, const Token * > typeDecl(const Token *tok, bool pointedToType=false)
bool isArithmeticalOp() const
std::string stringifyList(const stringifyOptions &options, const std::vector< std::string > *fileNames=nullptr, const Token *end=nullptr) const
bool isIncompleteVar() const
bool isControlFlowKeyword() const
static const ::Type * typeOf(const Token *tok, const Token **typeTok=nullptr)
const ValueType * valueType() const
const Enumerator * enumerator() const
void astOperand1(Token *tok)
void function(const Function *f)
Associate this token with given function.
std::string expressionString() const
bool isUnaryOp(const std::string &s) const
bool isIncompleteConstant() const
static const Token * findsimplematch(const Token *const startTok, const char(&pattern)[count])
const Token * tokAt(int index) const
Token::Type tokType() const
void astOperand2(Token *tok)
void scope(const Scope *s)
Associate this token with given scope.
void link(Token *linkToToken)
Create link to given token.
const Token * linkAt(int index) const
void type(const ::Type *t)
Associate this token with given type.
bool isAssignmentOp() const
bool isStandardType() const
void variable(const Variable *v)
Associate this token with given variable.
bool isComparisonOp() const
const std::list< ValueFlow::Value > & values() const
bool isAttributeConst() const
const Token * nextArgument() const
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
nonneg int fileIndex() const
bool isAttributePure() const
void astParent(Token *tok)
Information about a class type.
const std::string & type() const
bool isIteratorValue() const
bool isLifetimeValue() const
const Token * tokvalue
token value - the token that has the value.
long long intvalue
int value (or sometimes bool value?)
bool equalValue(const ValueFlow::Value &rhs) const
enum ValueType::Type type
const Library::Container * container
If the type is a container defined in a cfg file, this is the used.
bool isConst(nonneg int indirect=0) const
nonneg int constness
bit 0=data, bit 1=*, bit 2=**
Reference reference
Is the outermost indirection of this type a reference or rvalue.
const Library::SmartPointer * smartPointer
Smart pointer.
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
const Token * smartPointerTypeToken
Smart pointer type token.
const Token * containerTypeToken
The container type token.
static ValueType parseDecl(const Token *type, const Settings &settings)
enum ValueType::Sign sign
Information about a member variable.
bool isArgument() const
Is variable a function argument.
bool isEnumType() const
Determine whether it's an enumeration type.
bool isClass() const
Is variable a user defined (or unknown) type.
bool isProtected() const
Is variable protected.
bool isReference() const
Is reference variable.
bool isFloatingType() const
Determine whether it's a floating number type.
bool isRValueReference() const
Is reference variable.
bool isStlType() const
Checks if the variable is an STL type ('std::') E.g.
bool isLocal() const
Is variable local.
const Token * declEndToken() const
Get end token of variable declaration E.g.
const Type * type() const
Get Type pointer of known type.
const Scope * scope() const
Get Scope pointer of enclosing scope.
bool isPublic() const
Is variable public.
const std::string & name() const
Get name string.
bool isConst() const
Is variable const.
bool isArray() const
Is variable an array.
const Token * nameToken() const
Get name token.
bool isPrivate() const
Is variable private.
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
bool isVolatile() const
Is variable volatile.
bool isPointer() const
Is pointer variable.
bool isStatic() const
Is variable static.
const ValueType * valueType() const
#define REQUIRES(msg,...)
T * findToken(T *start, const Token *end, const Predicate &pred)
T * findTokenSkipDeadCode(const Library &library, T *start, const Token *end, const Predicate &pred, const Evaluate &evaluate)
std::pair< const Token *, std::string > ErrorPathItem
const Library::Container * getLibraryContainer(const Token *tok)
std::list< ErrorPathItem > ErrorPath
std::vector< MathLib::bigint > getMinValue(const ValuePtr< InferModel > &model, const std::list< ValueFlow::Value > &values)
CPPCHECKLIB Value getLifetimeObjValue(const Token *tok, bool inconclusive=false)
CPPCHECKLIB ValuePtr< InferModel > makeIntegralInferModel()
static ValueFlow::Value evaluate(const std::string &op, const ValueFlow::Value &lhs, const ValueFlow::Value &rhs)
@ DIR_IN
Input to called function. Data is treated as read-only.
@ DIR_OUT
Output to caller. Data is passed by reference or address and is potentially written.
@ DIR_INOUT
Input to called function, and output to caller. Data is passed by reference or address and is potenti...
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
bool endsWith(const std::string &str, char c)
bool contains(const Range &r, const T &x)