Fixed #7619 (False positive: Redundant assignment)

This commit is contained in:
Daniel Marjamäki 2018-11-19 21:23:36 +01:00
parent 2aecd30cd8
commit c899792232
1 changed files with 36 additions and 22 deletions

View File

@ -473,6 +473,7 @@ static bool checkExceptionHandling(const Token* tok)
void CheckOther::checkRedundantAssignment() void CheckOther::checkRedundantAssignment()
{ {
// TODO: Rewrite this messy checker.
const bool printPerformance = mSettings->isEnabled(Settings::PERFORMANCE); const bool printPerformance = mSettings->isEnabled(Settings::PERFORMANCE);
const bool printStyle = mSettings->isEnabled(Settings::STYLE); const bool printStyle = mSettings->isEnabled(Settings::STYLE);
const bool printWarning = mSettings->isEnabled(Settings::WARNING); const bool printWarning = mSettings->isEnabled(Settings::WARNING);
@ -491,6 +492,7 @@ void CheckOther::checkRedundantAssignment()
std::map<unsigned int, const Token*> memAssignments; std::map<unsigned int, const Token*> memAssignments;
std::map<unsigned int, std::set<unsigned int> > membervars; std::map<unsigned int, std::set<unsigned int> > membervars;
std::set<unsigned int> initialized; std::set<unsigned int> initialized;
std::map<unsigned int, std::set<unsigned int>> dependencies;
const Token* writtenArgumentsEnd = nullptr; const Token* writtenArgumentsEnd = nullptr;
for (const Token* tok = scope.bodyStart->next(); tok && tok != scope.bodyEnd; tok = tok->next()) { for (const Token* tok = scope.bodyStart->next(); tok && tok != scope.bodyEnd; tok = tok->next()) {
@ -503,15 +505,18 @@ void CheckOther::checkRedundantAssignment()
break; break;
varAssignments.clear(); varAssignments.clear();
memAssignments.clear(); memAssignments.clear();
dependencies.clear();
} else if (tok->str() == "{" && tok->strAt(-1) != "{" && tok->strAt(-1) != "=" && tok->strAt(-4) != "case" && tok->strAt(-3) != "default") { // conditional or non-executable inner scope: Skip it and reset status } else if (tok->str() == "{" && tok->strAt(-1) != "{" && tok->strAt(-1) != "=" && tok->strAt(-4) != "case" && tok->strAt(-3) != "default") { // conditional or non-executable inner scope: Skip it and reset status
tok = tok->link(); tok = tok->link();
varAssignments.clear(); varAssignments.clear();
memAssignments.clear(); memAssignments.clear();
dependencies.clear();
} else if (Token::Match(tok, "for|if|while (")) { } else if (Token::Match(tok, "for|if|while (")) {
tok = tok->linkAt(1); tok = tok->linkAt(1);
} else if (Token::Match(tok, "break|return|continue|throw|goto|asm")) { } else if (Token::Match(tok, "break|return|continue|throw|goto|asm")) {
varAssignments.clear(); varAssignments.clear();
memAssignments.clear(); memAssignments.clear();
dependencies.clear();
} else if (Token::Match(tok, "%var% = [ & ] (")) { } else if (Token::Match(tok, "%var% = [ & ] (")) {
const unsigned int lambdaId = tok->varId(); const unsigned int lambdaId = tok->varId();
const Token *lambdaParams = tok->tokAt(5); const Token *lambdaParams = tok->tokAt(5);
@ -523,29 +528,38 @@ void CheckOther::checkRedundantAssignment()
usedByLambda[lambdaId].insert(tok2->varId()); usedByLambda[lambdaId].insert(tok2->varId());
} }
} }
} else if (tok->tokType() == Token::eVariable && !Token::Match(tok, "%name% (")) { } else if (tok->tokType() == Token::eVariable && !Token::Match(tok, "%var% (")) {
const Token *eq = nullptr; const Token *eq = tok;
for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { while (Token::Match(eq->astParent(), ".|::|["))
if (Token::Match(tok2, "[([]")) { eq = eq->astParent();
// bail out if there is a variable in rhs - we only track 1 variable if (Token::simpleMatch(eq->astParent(), "=") && eq == eq->astParent()->astOperand1())
bool bailout = false; eq = eq->astParent();
for (const Token *tok3 = tok2->link(); tok3 != tok2; tok3 = tok3->previous()) { else
if (tok3->varId()) { eq = nullptr;
const Variable *var = tok3->variable();
if (!var || !var->isConst() || var->isReference() || var->isPointer()) { if (eq) {
bailout = true; for (const Token *tok2 = tok->next(); tok2 != eq; tok2 = tok2->next()) {
break; if (tok2->str() == "[")
} tok2 = tok2->link();
} else if (tok2->str() == "]") {
} eq = nullptr;
if (bailout)
break; break;
tok2 = tok2->link(); }
} else if (Token::Match(tok2, "[)];,]")) }
break; }
else if (tok2->str() == "=") {
eq = tok2; if (eq) {
break; bool arrayIndex = false;
for (const Token *tok2 = tok->next(); tok2 != eq; tok2 = tok2->next()) {
if (tok2->str() == "[")
arrayIndex = true;
if (arrayIndex && tok2->varId() != 0)
dependencies[tok2->varId()].insert(tok->varId());
}
for (unsigned int varId : dependencies[tok->varId()]) {
varAssignments.erase(varId);
memAssignments.erase(varId);
} }
} }