Preparing FwdAnalysis for ValueFlow usage where we want to fetch read locations
This commit is contained in:
parent
d8fada6702
commit
c03c262058
|
@ -1053,7 +1053,7 @@ static bool hasFunctionCall(const Token *tok)
|
|||
return hasFunctionCall(tok->astOperand1()) || hasFunctionCall(tok->astOperand2());
|
||||
}
|
||||
|
||||
FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<unsigned int> &exprVarIds, bool local)
|
||||
struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<unsigned int> &exprVarIds, bool local)
|
||||
{
|
||||
// Parse the given tokens
|
||||
for (const Token *tok = startToken; tok != endToken; tok = tok->next()) {
|
||||
|
@ -1098,7 +1098,9 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *
|
|||
return Result(Result::Type::BAILOUT);
|
||||
}
|
||||
if (hasOperand(parent->astParent()->astOperand2(), expr)) {
|
||||
return Result(Result::Type::READ);
|
||||
if (mReassign)
|
||||
return Result(Result::Type::READ);
|
||||
continue;
|
||||
}
|
||||
const bool reassign = isSameExpression(mCpp, false, expr, parent, mLibrary, false, false, nullptr);
|
||||
if (reassign)
|
||||
|
@ -1169,3 +1171,18 @@ bool FwdAnalysis::hasOperand(const Token *tok, const Token *lhs) const
|
|||
return true;
|
||||
return hasOperand(tok->astOperand1(), lhs) || hasOperand(tok->astOperand2(), lhs);
|
||||
}
|
||||
|
||||
const Token *FwdAnalysis::reassign(const Token *expr, const Token *startToken, const Token *endToken)
|
||||
{
|
||||
mReassign = true;
|
||||
Result result = check(expr, startToken, endToken);
|
||||
return result.type == FwdAnalysis::Result::Type::WRITE ? result.token : nullptr;
|
||||
}
|
||||
|
||||
std::vector<const Token *> FwdAnalysis::reads(const Token *expr, const Token *startToken, const Token *endToken)
|
||||
{
|
||||
mReassign = false;
|
||||
mReads.clear();
|
||||
check(expr, startToken, endToken);
|
||||
return mReads;
|
||||
}
|
||||
|
|
|
@ -162,8 +162,29 @@ bool isLikelyStreamRead(bool cpp, const Token *op);
|
|||
|
||||
class FwdAnalysis {
|
||||
public:
|
||||
FwdAnalysis(bool cpp, const Library &library) : mCpp(cpp), mLibrary(library) {}
|
||||
FwdAnalysis(bool cpp, const Library &library) : mCpp(cpp), mLibrary(library), mReassign(false) {}
|
||||
|
||||
bool hasOperand(const Token *tok, const Token *lhs) const;
|
||||
|
||||
/**
|
||||
* Check if "expr" is reassigned. The "expr" can be a tree (x.y[12]).
|
||||
* @param expr Symbolic expression to perform forward analysis for
|
||||
* @param startToken First token in forward analysis
|
||||
* @param endToken Last token in forward analysis
|
||||
* @return Token where expr is reassigned. If it's not reassigned then nullptr is returned.
|
||||
*/
|
||||
const Token *reassign(const Token *expr, const Token *startToken, const Token *endToken);
|
||||
|
||||
/**
|
||||
* Get tokens where "expr" is read. The "expr" can be a tree (x.y[12]).
|
||||
* @param expr Symbolic expression to perform forward analysis for
|
||||
* @param startToken First token in forward analysis
|
||||
* @param endToken Last token in forward analysis
|
||||
* @return vector of read tokens
|
||||
*/
|
||||
std::vector<const Token *> reads(const Token *expr, const Token *startToken, const Token *endToken);
|
||||
|
||||
private:
|
||||
/** Result of forward analysis */
|
||||
struct Result {
|
||||
enum class Type { NONE, READ, WRITE, BREAK, RETURN, BAILOUT } type;
|
||||
|
@ -172,22 +193,13 @@ public:
|
|||
const Token *token;
|
||||
};
|
||||
|
||||
/**
|
||||
* General purpose forward analysis for "expr". The "expr" can be a tree (x.y[12]) or something like that.
|
||||
* @param expr Symbolic expression to perform forward analysis for
|
||||
* @param startToken First token in forward analysis
|
||||
* @param endToken Last token in forward analysis
|
||||
* @return A Result struct.
|
||||
*/
|
||||
struct Result check(const Token *expr, const Token *startToken, const Token *endToken);
|
||||
|
||||
bool hasOperand(const Token *tok, const Token *lhs) const;
|
||||
|
||||
private:
|
||||
struct Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<unsigned int> &exprVarIds, bool local);
|
||||
|
||||
const bool mCpp;
|
||||
const Library &mLibrary;
|
||||
bool mReassign;
|
||||
std::vector<const Token *> mReads;
|
||||
};
|
||||
|
||||
#endif // astutilsH
|
||||
|
|
|
@ -486,14 +486,14 @@ void CheckOther::checkRedundantAssignment()
|
|||
start = tok->findExpressionStartEndTokens().second->next();
|
||||
|
||||
// Get next assignment..
|
||||
FwdAnalysis::Result nextAssign = fwdAnalysis.check(tok->astOperand1(), start, scope->bodyEnd);
|
||||
const Token *nextAssign = fwdAnalysis.reassign(tok->astOperand1(), start, scope->bodyEnd);
|
||||
|
||||
if (nextAssign.type != FwdAnalysis::Result::Type::WRITE || !nextAssign.token)
|
||||
if (!nextAssign)
|
||||
continue;
|
||||
|
||||
// there is redundant assignment. Is there a case between the assignments?
|
||||
bool hasCase = false;
|
||||
for (const Token *tok2 = tok; tok2 != nextAssign.token; tok2 = tok2->next()) {
|
||||
for (const Token *tok2 = tok; tok2 != nextAssign; tok2 = tok2->next()) {
|
||||
if (tok2->str() == "case") {
|
||||
hasCase = true;
|
||||
break;
|
||||
|
@ -502,9 +502,9 @@ void CheckOther::checkRedundantAssignment()
|
|||
|
||||
// warn
|
||||
if (hasCase)
|
||||
redundantAssignmentInSwitchError(tok, nextAssign.token, tok->astOperand1()->expressionString());
|
||||
redundantAssignmentInSwitchError(tok, nextAssign, tok->astOperand1()->expressionString());
|
||||
else
|
||||
redundantAssignmentError(tok, nextAssign.token, tok->astOperand1()->expressionString(), inconclusive);
|
||||
redundantAssignmentError(tok, nextAssign, tok->astOperand1()->expressionString(), inconclusive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue