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());
|
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
|
// Parse the given tokens
|
||||||
for (const Token *tok = startToken; tok != endToken; tok = tok->next()) {
|
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);
|
return Result(Result::Type::BAILOUT);
|
||||||
}
|
}
|
||||||
if (hasOperand(parent->astParent()->astOperand2(), expr)) {
|
if (hasOperand(parent->astParent()->astOperand2(), expr)) {
|
||||||
|
if (mReassign)
|
||||||
return Result(Result::Type::READ);
|
return Result(Result::Type::READ);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
const bool reassign = isSameExpression(mCpp, false, expr, parent, mLibrary, false, false, nullptr);
|
const bool reassign = isSameExpression(mCpp, false, expr, parent, mLibrary, false, false, nullptr);
|
||||||
if (reassign)
|
if (reassign)
|
||||||
|
@ -1169,3 +1171,18 @@ bool FwdAnalysis::hasOperand(const Token *tok, const Token *lhs) const
|
||||||
return true;
|
return true;
|
||||||
return hasOperand(tok->astOperand1(), lhs) || hasOperand(tok->astOperand2(), lhs);
|
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 {
|
class FwdAnalysis {
|
||||||
public:
|
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 */
|
/** Result of forward analysis */
|
||||||
struct Result {
|
struct Result {
|
||||||
enum class Type { NONE, READ, WRITE, BREAK, RETURN, BAILOUT } type;
|
enum class Type { NONE, READ, WRITE, BREAK, RETURN, BAILOUT } type;
|
||||||
|
@ -172,22 +193,13 @@ public:
|
||||||
const Token *token;
|
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);
|
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);
|
struct Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<unsigned int> &exprVarIds, bool local);
|
||||||
|
|
||||||
const bool mCpp;
|
const bool mCpp;
|
||||||
const Library &mLibrary;
|
const Library &mLibrary;
|
||||||
|
bool mReassign;
|
||||||
|
std::vector<const Token *> mReads;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // astutilsH
|
#endif // astutilsH
|
||||||
|
|
|
@ -486,14 +486,14 @@ void CheckOther::checkRedundantAssignment()
|
||||||
start = tok->findExpressionStartEndTokens().second->next();
|
start = tok->findExpressionStartEndTokens().second->next();
|
||||||
|
|
||||||
// Get next assignment..
|
// 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;
|
continue;
|
||||||
|
|
||||||
// there is redundant assignment. Is there a case between the assignments?
|
// there is redundant assignment. Is there a case between the assignments?
|
||||||
bool hasCase = false;
|
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") {
|
if (tok2->str() == "case") {
|
||||||
hasCase = true;
|
hasCase = true;
|
||||||
break;
|
break;
|
||||||
|
@ -502,9 +502,9 @@ void CheckOther::checkRedundantAssignment()
|
||||||
|
|
||||||
// warn
|
// warn
|
||||||
if (hasCase)
|
if (hasCase)
|
||||||
redundantAssignmentInSwitchError(tok, nextAssign.token, tok->astOperand1()->expressionString());
|
redundantAssignmentInSwitchError(tok, nextAssign, tok->astOperand1()->expressionString());
|
||||||
else
|
else
|
||||||
redundantAssignmentError(tok, nextAssign.token, tok->astOperand1()->expressionString(), inconclusive);
|
redundantAssignmentError(tok, nextAssign, tok->astOperand1()->expressionString(), inconclusive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue