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)))
109 bool updateRecursive(
Token* start) {
110 bool continueB =
true;
117 continueB &= update(tok);
138 for (
const Token* tok = start; tok && tok != end; tok = tok->
next()) {
170 bool checkThen, checkElse;
171 std::tie(checkThen, checkElse) = evalCond(condTok);
173 if (parent->
str() ==
"?") {
174 if (checkElse && opSide == 1)
176 if (checkThen && opSide == 2)
179 if (!checkThen && parent->
str() ==
"&&")
181 if (!checkElse && parent->
str() ==
"||")
187 void traverse(
Token* start,
const Token* end =
nullptr) {
190 std::size_t i = start->
index();
192 if (tok->
index() >= i)
195 if (tok == start || (tok->
str() ==
"{" && (tok->
scope()->type == Scope::ScopeType::eFunction ||
196 tok->
scope()->type == Scope::ScopeType::eLambda))) {
213 if (!assignTok->astOperand1() || !assignTok->astOperand2())
215 Token* assignTop = assignTok;
216 bool continueB =
true;
219 continueB &= updateRecursive(assignTop->
astOperand1());
226 if (
Token* parent = isDeadCode(assignTok)) {
231 if (assignTok->str() ==
"=" && (assignTok->astParent() == assignTop || assignTok == assignTop)) {
237 if (rhsAction.
isRead() && !lhsAction.
isInvalid() && assignTok->astOperand1()->exprId() > 0) {
238 const std::string info =
"Assignment from '" + assignTok->expressionString() +
"'";
249 }
else if (lhsAction.
matches() && !assignTok->astOperand2()->hasKnownIntValue() &&
250 assignTok->astOperand2()->exprId() > 0 &&
252 const std::string info =
"Assignment to '" + assignTok->expressionString() +
"'";
273 if (
Token* top = getTopFunction(tok->
link())) {
274 if (!updateRecursive(top))
282 if (tok->
str() ==
"}") {
299 thenEnd = tok->
link()->tokAt(-2);
307 elseAction = analyzeRange(tok->
link(), tok);
312 analyzer->assume(condTok, hasElse);
314 analyzer->assume(condTok, !hasElse);
324 else if (condAction.
isRead())
332 if (tok->
str() ==
"{") {
356 if (
Token* parent = isDeadCode(tok)) {
360 if (tok->
str() ==
"case") {
402 ReverseTraversal rt{a, tokenlist, errorLogger, settings};
403 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.