33 static bool isUnchanged(
const Token *startToken,
const Token *endToken,
const std::set<nonneg int> &exprVarIds,
bool local)
35 for (
const Token *tok = startToken; tok != endToken; tok = tok->
next()) {
39 if (tok->varId() == 0 || exprVarIds.find(tok->varId()) == exprVarIds.end())
41 const Token *parent = tok;
49 if (parent->
astParent()->tokType() == Token::Type::eIncDecOp)
51 if (parent->
astParent()->isAssignmentOp() && parent == parent->
astParent()->astOperand1())
86 [&ret](
const Token *tok) {
102 for (
const Token* tok = startToken;
precedes(tok, endToken); tok = tok->next()) {
115 if (!inInnerClass && tok->str() ==
"{" && tok->scope()->isClassOrStruct()) {
123 if (tok->str() ==
"continue")
128 tok = lambdaEndToken;
129 const Result lambdaResult =
checkRecursive(expr, lambdaEndToken->
link()->next(), lambdaEndToken, exprVarIds, local, inInnerClass, depth);
143 checkRecursive(expr, startEndTokens.first, startEndTokens.second->
next(), exprVarIds, local,
true, depth);
156 if (tok->str() ==
"}") {
158 if (tok->scope() == expr->
scope())
161 if (tok->scope()->isLoopScope()) {
163 const Token *conditionStart =
nullptr;
164 const Token *conditionEnd =
nullptr;
166 conditionEnd = tok->
link()->previous();
167 conditionStart = conditionEnd->
link();
169 conditionStart = tok->
tokAt(2);
170 conditionEnd = conditionStart->
link();
172 if (conditionStart && conditionEnd) {
174 for (
const Token *condTok = conditionStart; condTok != conditionEnd; condTok = condTok->
next()) {
175 if (exprVarIds.find(condTok->varId()) != exprVarIds.end()) {
192 tok = tok->linkAt(1);
198 const Token *bodyStart =
nullptr;
199 const Token *conditionStart =
nullptr;
201 bodyStart = tok->
next();
203 conditionStart = bodyStart->
link()->tokAt(2);
205 conditionStart = tok->
next();
207 bodyStart = conditionStart->
link()->next();
210 if (!bodyStart || !conditionStart)
214 if (!
isUnchanged(conditionStart, conditionStart->
link(), exprVarIds, local))
224 const Token *conditionStart = tok->
next();
227 const bool cond = condTok->
values().front().intvalue;
233 bodyStart = bodyStart->
link()->tokAt(2);
239 tok = bodyStart->
link();
243 tok = tok->linkAt(2);
248 if (!
isUnchanged(conditionStart, conditionStart->
link(), exprVarIds, local))
266 !
isUnchanged(tok, tok->astParent()->astParent()->link(), exprVarIds, local))
270 if (expr->
isName() &&
Token::Match(tok,
"%name% (") && tok->str().find(
'<') != std::string::npos && tok->str().find(expr->
str()) != std::string::npos)
273 if (exprVarIds.find(tok->varId()) != exprVarIds.end()) {
274 const Token *parent = tok;
279 if (parent->
str() ==
"(" && !parent->
isCast())
311 const auto startEnd = parent->
astParent()->astOperand2()->findExpressionStartEndTokens();
312 for (
const Token* tok2 = startEnd.first; tok2 != startEnd.second; tok2 = tok2->
next()) {
342 const std::vector<const Token *> args =
getArguments(ftok);
344 while (argnr < args.size() && args[argnr] != parent)
346 if (argnr < args.size()) {
375 const Result &result2 =
checkRecursive(expr, scopeEndToken->
next(), endToken, exprVarIds, local, inInnerClass, depth);
389 tok = elseStart->
link();
391 tok = tok->linkAt(1);
402 std::set<nonneg int> exprVarIds;
404 bool unknownVarId =
false;
406 [&](
const Token *tok) {
412 return ChildrenToVisit::none;
414 if (tok->
varId() > 0) {
415 exprVarIds.insert(tok->varId());
416 if (!Token::simpleMatch(tok->previous(),
".")) {
417 const Variable *var = tok->variable();
418 if (var && var->isReference() && var->isLocal() && Token::Match(var->nameToken(),
"%var% [=(]") && !isGlobalData(var->nameToken()->next()->astOperand2()))
419 return ChildrenToVisit::none;
420 const bool deref = tok->astParent() && (tok->astParent()->isUnaryOp(
"*") || (tok->astParent()->str() ==
"[" && tok == tok->astParent()->astOperand1()));
421 local &= !nonLocal(tok->variable(), deref);
429 *unknownVarIdOut = unknownVarId;
437 bool unknownVarId =
false;
438 std::set<nonneg int> exprVarIds =
getExprVarIds(expr, &local, &unknownVarId);
458 result =
checkRecursive(expr, scopeEndToken->
next(), endToken, exprVarIds, local,
false);
504 const bool macro =
false;
505 const bool pure =
false;
506 const bool followVar =
false;
507 for (
const Token *tok = startToken; tok; tok = tok->
previous()) {
511 const std::vector<const Token*> args =
getArguments(tok);
512 for (
int argnr = 0; argnr < args.size(); ++argnr) {
515 if (tok->function() && tok->function()->getArgumentVar(argnr) && !tok->function()->getArgumentVar(argnr)->isReference() && !tok->function()->isConst())
517 for (
const Token *subexpr = expr; subexpr; subexpr = subexpr->
astOperand1()) {
528 const Token *addrOf =
nullptr;
531 else if (tok->isUnaryOp(
"&"))
535 else if (tok->valueType() && tok->valueType()->pointer &&
538 addrOf = tok->
tokAt(2);
542 for (
const Token *subexpr = expr; subexpr; subexpr = subexpr->
astOperand1()) {
552 for (
const Token *subexpr = expr; subexpr; subexpr = subexpr->
astOperand1()) {
554 if (!val.isLocalLifetimeValue())
556 const Variable* var = val.tokvalue->variable();
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
bool astIsContainerView(const Token *tok)
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
bool isGlobalData(const Token *expr)
const Token * findNextTokenFromBreak(const Token *breakToken)
For a "break" token, locate the next token to execute.
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
bool isReturnScope(const Token *const endToken, const Library &library, const Token **unknownFunc, bool functionScope)
Is scope a return scope (scope will unconditionally return)
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
const Settings & mSettings
bool possiblyAliased(const Token *expr, const Token *startToken) const
Is there some possible alias for given expression.
std::vector< KnownAndToken > mValueFlow
bool hasOperand(const Token *tok, const Token *lhs) const
enum FwdAnalysis::What mWhat
static bool isEscapedAlias(const Token *expr)
Result check(const Token *expr, const Token *startToken, const Token *endToken)
Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set< nonneg int > &exprVarIds, bool local, bool inInnerClass, int depth=0)
std::set< nonneg int > getExprVarIds(const Token *expr, bool *localOut=nullptr, bool *unknownVarIdOut=nullptr) const
const Token * reassign(const Token *expr, const Token *startToken, const Token *endToken)
Check if "expr" is reassigned.
bool unusedValue(const Token *expr, const Token *startToken, const Token *endToken)
Check if "expr" is used.
const Function * getFunction(const Token *ftok) const
std::list< Variable > varlist
The token list that the TokenList generates is a linked-list of this class.
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
bool hasKnownIntValue() const
const ValueType * valueType() const
void astOperand1(Token *tok)
std::pair< const Token *, const Token * > findExpressionStartEndTokens() const
bool isUnaryOp(const std::string &s) const
const Token * tokAt(int index) 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 variable(const Variable *v)
Associate this token with given variable.
const std::list< ValueFlow::Value > & values() const
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
void astParent(Token *tok)
Reference reference
Is the outermost indirection of this type a reference or rvalue.
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
Information about a member variable.
bool isArgument() const
Is variable a function argument.
bool isExtern() const
Is variable extern.
bool isReference() const
Is reference variable.
bool isLocal() const
Is variable local.
bool isPointer() const
Is pointer variable.
bool isStatic() const
Is variable static.
static bool hasFunctionCall(const Token *tok)
static bool hasVolatileCastOrVar(const Token *expr)
static bool nonLocal(const Variable *var, bool deref)
static bool isUnchanged(const Token *startToken, const Token *endToken, const std::set< nonneg int > &exprVarIds, bool local)
static bool hasGccCompoundStatement(const Token *tok)
Result of forward analysis.
enum FwdAnalysis::Result::Type type
@ DIR_OUT
Output to caller. Data is passed by reference or address and is potentially written.
std::map< int, ArgumentChecks > argumentChecks