Skip to content

Commit c03c262

Browse files
committed
Preparing FwdAnalysis for ValueFlow usage where we want to fetch read locations
1 parent d8fada6 commit c03c262

3 files changed

Lines changed: 48 additions & 19 deletions

File tree

lib/astutils.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,7 @@ static bool hasFunctionCall(const Token *tok)
10531053
return hasFunctionCall(tok->astOperand1()) || hasFunctionCall(tok->astOperand2());
10541054
}
10551055

1056-
FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<unsigned int> &exprVarIds, bool local)
1056+
struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<unsigned int> &exprVarIds, bool local)
10571057
{
10581058
// Parse the given tokens
10591059
for (const Token *tok = startToken; tok != endToken; tok = tok->next()) {
@@ -1098,7 +1098,9 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *
10981098
return Result(Result::Type::BAILOUT);
10991099
}
11001100
if (hasOperand(parent->astParent()->astOperand2(), expr)) {
1101-
return Result(Result::Type::READ);
1101+
if (mReassign)
1102+
return Result(Result::Type::READ);
1103+
continue;
11021104
}
11031105
const bool reassign = isSameExpression(mCpp, false, expr, parent, mLibrary, false, false, nullptr);
11041106
if (reassign)
@@ -1169,3 +1171,18 @@ bool FwdAnalysis::hasOperand(const Token *tok, const Token *lhs) const
11691171
return true;
11701172
return hasOperand(tok->astOperand1(), lhs) || hasOperand(tok->astOperand2(), lhs);
11711173
}
1174+
1175+
const Token *FwdAnalysis::reassign(const Token *expr, const Token *startToken, const Token *endToken)
1176+
{
1177+
mReassign = true;
1178+
Result result = check(expr, startToken, endToken);
1179+
return result.type == FwdAnalysis::Result::Type::WRITE ? result.token : nullptr;
1180+
}
1181+
1182+
std::vector<const Token *> FwdAnalysis::reads(const Token *expr, const Token *startToken, const Token *endToken)
1183+
{
1184+
mReassign = false;
1185+
mReads.clear();
1186+
check(expr, startToken, endToken);
1187+
return mReads;
1188+
}

lib/astutils.h

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,32 +162,44 @@ bool isLikelyStreamRead(bool cpp, const Token *op);
162162

163163
class FwdAnalysis {
164164
public:
165-
FwdAnalysis(bool cpp, const Library &library) : mCpp(cpp), mLibrary(library) {}
165+
FwdAnalysis(bool cpp, const Library &library) : mCpp(cpp), mLibrary(library), mReassign(false) {}
166166

167-
/** Result of forward analysis */
168-
struct Result {
169-
enum class Type { NONE, READ, WRITE, BREAK, RETURN, BAILOUT } type;
170-
Result(Type type) : type(type), token(nullptr) {}
171-
Result(Type type, const Token *token) : type(type), token(token) {}
172-
const Token *token;
173-
};
167+
bool hasOperand(const Token *tok, const Token *lhs) const;
174168

175169
/**
176-
* General purpose forward analysis for "expr". The "expr" can be a tree (x.y[12]) or something like that.
170+
* Check if "expr" is reassigned. The "expr" can be a tree (x.y[12]).
177171
* @param expr Symbolic expression to perform forward analysis for
178172
* @param startToken First token in forward analysis
179173
* @param endToken Last token in forward analysis
180-
* @return A Result struct.
174+
* @return Token where expr is reassigned. If it's not reassigned then nullptr is returned.
181175
*/
182-
struct Result check(const Token *expr, const Token *startToken, const Token *endToken);
176+
const Token *reassign(const Token *expr, const Token *startToken, const Token *endToken);
183177

184-
bool hasOperand(const Token *tok, const Token *lhs) const;
178+
/**
179+
* Get tokens where "expr" is read. The "expr" can be a tree (x.y[12]).
180+
* @param expr Symbolic expression to perform forward analysis for
181+
* @param startToken First token in forward analysis
182+
* @param endToken Last token in forward analysis
183+
* @return vector of read tokens
184+
*/
185+
std::vector<const Token *> reads(const Token *expr, const Token *startToken, const Token *endToken);
185186

186187
private:
188+
/** Result of forward analysis */
189+
struct Result {
190+
enum class Type { NONE, READ, WRITE, BREAK, RETURN, BAILOUT } type;
191+
Result(Type type) : type(type), token(nullptr) {}
192+
Result(Type type, const Token *token) : type(type), token(token) {}
193+
const Token *token;
194+
};
195+
196+
struct Result check(const Token *expr, const Token *startToken, const Token *endToken);
187197
struct Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<unsigned int> &exprVarIds, bool local);
188198

189199
const bool mCpp;
190200
const Library &mLibrary;
201+
bool mReassign;
202+
std::vector<const Token *> mReads;
191203
};
192204

193205
#endif // astutilsH

lib/checkother.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,14 +486,14 @@ void CheckOther::checkRedundantAssignment()
486486
start = tok->findExpressionStartEndTokens().second->next();
487487

488488
// Get next assignment..
489-
FwdAnalysis::Result nextAssign = fwdAnalysis.check(tok->astOperand1(), start, scope->bodyEnd);
489+
const Token *nextAssign = fwdAnalysis.reassign(tok->astOperand1(), start, scope->bodyEnd);
490490

491-
if (nextAssign.type != FwdAnalysis::Result::Type::WRITE || !nextAssign.token)
491+
if (!nextAssign)
492492
continue;
493493

494494
// there is redundant assignment. Is there a case between the assignments?
495495
bool hasCase = false;
496-
for (const Token *tok2 = tok; tok2 != nextAssign.token; tok2 = tok2->next()) {
496+
for (const Token *tok2 = tok; tok2 != nextAssign; tok2 = tok2->next()) {
497497
if (tok2->str() == "case") {
498498
hasCase = true;
499499
break;
@@ -502,9 +502,9 @@ void CheckOther::checkRedundantAssignment()
502502

503503
// warn
504504
if (hasCase)
505-
redundantAssignmentInSwitchError(tok, nextAssign.token, tok->astOperand1()->expressionString());
505+
redundantAssignmentInSwitchError(tok, nextAssign, tok->astOperand1()->expressionString());
506506
else
507-
redundantAssignmentError(tok, nextAssign.token, tok->astOperand1()->expressionString(), inconclusive);
507+
redundantAssignmentError(tok, nextAssign, tok->astOperand1()->expressionString(), inconclusive);
508508
}
509509
}
510510
}

0 commit comments

Comments
 (0)