39 struct ReverseTraversal {
41 : analyzer(analyzer), tokenlist(tokenlist), errorLogger(errorLogger), settings(settings)
48 std::pair<bool, bool> evalCond(
const Token* tok)
const {
49 std::vector<MathLib::bigint> result = analyzer->evaluate(tok);
51 const bool checkThen = std::any_of(result.cbegin(), result.cend(), [](
int x) {
54 const bool checkElse = std::any_of(result.cbegin(), result.cend(), [](
int x) {
57 return std::make_pair(checkThen, checkElse);
60 bool update(
Token* tok) {
82 if (ftok->index() >= tok->
index())
84 if (!ftok->link() || ftok->str() ==
")")
87 ftok = ftok->
link()->next();
104 while ((parent = getParentFunction(parent)))
120 bool updateRecursive(
Token* start) {
121 bool continueB =
true;
128 continueB &= update(tok);
149 for (
const Token* tok = start; tok && tok != end; tok = tok->
next()) {
181 bool checkThen, checkElse;
182 std::tie(checkThen, checkElse) = evalCond(condTok);
184 if (parent->
str() ==
"?") {
185 if (checkElse && opSide == 1)
187 if (checkThen && opSide == 2)
190 if (!checkThen && parent->
str() ==
"&&")
192 if (!checkElse && parent->
str() ==
"||")
198 void traverse(
Token* start,
const Token* end =
nullptr) {
201 std::size_t i = start->
index();
203 if (tok->
index() >= i)
206 if (tok == start || (tok->
str() ==
"{" && (tok->
scope()->type == Scope::ScopeType::eFunction ||
207 tok->
scope()->type == Scope::ScopeType::eLambda))) {
224 if (!assignTok->astOperand1() || !assignTok->astOperand2())
226 Token* assignTop = assignTok;
227 bool continueB =
true;
230 continueB &= updateRecursive(assignTop->
astOperand1());
237 if (
Token* parent = isDeadCode(assignTok)) {
242 if (assignTok->str() ==
"=" && (assignTok->astParent() == assignTop || assignTok == assignTop)) {
248 if (rhsAction.
isRead() && !lhsAction.
isInvalid() && assignTok->astOperand1()->exprId() > 0) {
249 const std::string info =
"Assignment from '" + assignTok->expressionString() +
"'";
260 }
else if (lhsAction.
matches() && !assignTok->astOperand2()->hasKnownIntValue() &&
261 assignTok->astOperand2()->exprId() > 0 &&
263 const std::string info =
"Assignment to '" + assignTok->expressionString() +
"'";
284 if (
Token* top = getTopFunction(tok->
link())) {
285 if (!updateRecursive(top))
293 if (tok->
str() ==
"}") {
310 thenEnd = tok->
link()->tokAt(-2);
318 elseAction = analyzeRange(tok->
link(), tok);
323 analyzer->assume(condTok, hasElse);
325 analyzer->assume(condTok, !hasElse);
335 else if (condAction.
isRead())
340 tok = jumpToStart(tok->
link());
343 if (tok->
str() ==
"{") {
357 tok = jumpToStart(tok);
364 if (
Token* parent = isDeadCode(tok)) {
368 if (tok->
str() ==
"case") {
410 ReverseTraversal rt{a, tokenlist, errorLogger, settings};
411 rt.traverse(start, end);
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 astIsLHS(const Token *tok)
Token * getCondTokFromEnd(Token *endBlock)
bool astIsRHS(const Token *tok)
const Token * nextAfterAstRightmostLeaf(const Token *tok)
const Token * previousBeforeAstLeftmostLeaf(const Token *tok)
bool isConstExpression(const Token *tok, const Library &library)
bool isUnevaluated(const Token *tok)
bool succeeds(const Token *tok1, const Token *tok2)
If tok1 comes after tok2.
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
This is an interface, which the class responsible of error logging should implement.
const Token * constructorMemberInitialization() const
bool isConstructor() const
const Token * bodyStart
'{' token
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.
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 const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
const std::string & strAt(int index) const
void astOperand1(Token *tok)
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
bool isAssignmentOp() 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)
Analyzer::Result valueFlowGenericForward(Token *start, const Token *end, const ValuePtr< Analyzer > &a, const TokenList &tokenList, ErrorLogger &errorLogger, const Settings &settings)
static const Token * assignExpr(const Token *tok)
void valueFlowGenericReverse(Token *start, const Token *end, const ValuePtr< Analyzer > &a, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings)
bool isInconclusive() const
bool isIdempotent() const
Simple container to be thrown when internal error is detected.