diff --git a/lib/astutils.cpp b/lib/astutils.cpp index de1184368..ad0fe37ac 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -1053,21 +1053,8 @@ static bool hasFunctionCall(const Token *tok) return hasFunctionCall(tok->astOperand1()) || hasFunctionCall(tok->astOperand2()); } -FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *assign1, const Token *startToken, const Token *endToken) +FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set &exprVarIds, bool local) { - // all variable ids in assign1 LHS. - std::set assign1LhsVarIds; - bool local = true; - visitAstNodes(assign1->astOperand1(), - [&](const Token *tok) { - if (tok->varId() > 0) { - assign1LhsVarIds.insert(tok->varId()); - if (!Token::simpleMatch(tok->previous(), ".")) - local &= !nonLocal(tok->variable()); - } - return ChildrenToVisit::op1_and_op2; - }); - // Parse the given tokens for (const Token *tok = startToken; tok != endToken; tok = tok->next()) { if (Token::simpleMatch(tok, "try {")) { @@ -1101,7 +1088,7 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *assign1, const Toke return Result(Result::Type::BAILOUT); } - if (assign1LhsVarIds.find(tok->varId()) != assign1LhsVarIds.end()) { + if (exprVarIds.find(tok->varId()) != exprVarIds.end()) { const Token *parent = tok; while (Token::Match(parent->astParent(), ".|::|[")) parent = parent->astParent(); @@ -1110,10 +1097,10 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *assign1, const Toke // TODO: this is a quick bailout return Result(Result::Type::BAILOUT); } - if (hasOperand(parent->astParent()->astOperand2(), assign1->astOperand1())) { + if (hasOperand(parent->astParent()->astOperand2(), expr)) { return Result(Result::Type::READ); } - const bool reassign = isSameExpression(mCpp, false, assign1->astOperand1(), parent, mLibrary, false, false, nullptr); + const bool reassign = isSameExpression(mCpp, false, expr, parent, mLibrary, false, false, nullptr); if (reassign) return Result(Result::Type::WRITE, parent->astParent()); return Result(Result::Type::READ); @@ -1124,12 +1111,12 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *assign1, const Toke } if (Token::Match(tok, ") {")) { - const Result &result1 = checkRecursive(assign1, tok->tokAt(2), tok->linkAt(1)); + const Result &result1 = checkRecursive(expr, tok->tokAt(2), tok->linkAt(1), exprVarIds, local); if (result1.type == Result::Type::READ || result1.type == Result::Type::BAILOUT) return result1; if (Token::simpleMatch(tok->linkAt(1), "} else {")) { const Token *elseStart = tok->linkAt(1)->tokAt(2); - const Result &result2 = checkRecursive(assign1, elseStart, elseStart->link()); + const Result &result2 = checkRecursive(expr, elseStart, elseStart->link(), exprVarIds, local); if (result2.type == Result::Type::READ || result2.type == Result::Type::BAILOUT) return result2; if (result1.type == Result::Type::WRITE && result2.type == Result::Type::WRITE) @@ -1144,9 +1131,22 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *assign1, const Toke return Result(Result::Type::NONE); } -FwdAnalysis::Result FwdAnalysis::check(const Token *assign1, const Token *startToken, const Token *endToken) +FwdAnalysis::Result FwdAnalysis::check(const Token *expr, const Token *startToken, const Token *endToken) { - Result result = checkRecursive(assign1, startToken, endToken); + // all variable ids in expr. + std::set exprVarIds; + bool local = true; + visitAstNodes(expr, + [&](const Token *tok) { + if (tok->varId() > 0) { + exprVarIds.insert(tok->varId()); + if (!Token::simpleMatch(tok->previous(), ".")) + local &= !nonLocal(tok->variable()); + } + return ChildrenToVisit::op1_and_op2; + }); + + Result result = checkRecursive(expr, startToken, endToken, exprVarIds, local); // Break => continue checking in outer scope while (result.type == FwdAnalysis::Result::Type::BREAK) { @@ -1155,7 +1155,7 @@ FwdAnalysis::Result FwdAnalysis::check(const Token *assign1, const Token *startT s = s->nestedIn; if (s->type != Scope::eSwitch) break; - result = checkRecursive(assign1, s->bodyEnd->next(), endToken); + result = checkRecursive(expr, s->bodyEnd->next(), endToken, exprVarIds, local); } return result; diff --git a/lib/astutils.h b/lib/astutils.h index 83c96f76b..76b8e03bd 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -172,13 +172,19 @@ public: const Token *token; }; - /** forward analysis */ - struct Result check(const Token *assign1, const Token *startToken, const Token *endToken); + /** + * 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 *assign1, const Token *startToken, const Token *endToken); + struct Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set &exprVarIds, bool local); const bool mCpp; const Library &mLibrary; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 1971b3564..82be9b1ef 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -486,7 +486,7 @@ void CheckOther::checkRedundantAssignment() start = tok->findExpressionStartEndTokens().second->next(); // Get next assignment.. - FwdAnalysis::Result nextAssign = fwdAnalysis.check(tok, start, scope->bodyEnd); + FwdAnalysis::Result nextAssign = fwdAnalysis.check(tok->astOperand1(), start, scope->bodyEnd); if (nextAssign.type != FwdAnalysis::Result::Type::WRITE || !nextAssign.token) continue;