From fb04c8ff842bd4706b68e7b5204269a6f776a3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 4 Nov 2013 23:46:07 +0100 Subject: [PATCH] Fixed #5107 (redundantAssignment when pointer changes) --- lib/checkother.cpp | 20 +++++++++++++++++++- test/testother.cpp | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index b53dcce55..a05d38ff7 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -594,6 +594,18 @@ static void eraseNotLocalArg(std::map& container, co } } +static void eraseMemberAssignments(const unsigned int varId, std::map > &membervars, std::map &varAssignments) +{ + const std::map >::const_iterator it = membervars.find(varId); + if (it != membervars.end()) { + const std::set &v = it->second; + for (std::set::const_iterator vit = v.begin(); vit != v.end(); ++vit) { + varAssignments.erase(*vit); + eraseMemberAssignments(*vit, membervars, varAssignments); + } + } +} + void CheckOther::checkRedundantAssignment() { const bool performance = _settings->isEnabled("performance"); @@ -609,6 +621,7 @@ void CheckOther::checkRedundantAssignment() std::map varAssignments; std::map memAssignments; + std::map > membervars; std::set initialized; const Token* writtenArgumentsEnd = 0; @@ -638,8 +651,11 @@ void CheckOther::checkRedundantAssignment() } const Token *startToken = tok; - while (Token::Match(startToken, "%var%|::|.")) + while (Token::Match(startToken, "%var%|::|.")) { startToken = startToken->previous(); + if (Token::Match(startToken, "%var% . %var%")) + membervars[startToken->varId()].insert(startToken->tokAt(2)->varId()); + } std::map::iterator it = varAssignments.find(tok->varId()); if (tok->next()->isAssignmentOp() && Token::Match(startToken, "[;{}]")) { // Assignment @@ -671,9 +687,11 @@ void CheckOther::checkRedundantAssignment() if (!Token::simpleMatch(tok->tokAt(2), "0 ;") || (tok->variable() && tok->variable()->nameToken() != tok->tokAt(-2))) varAssignments[tok->varId()] = tok; memAssignments.erase(tok->varId()); + eraseMemberAssignments(tok->varId(), membervars, varAssignments); } else if (tok->next()->type() == Token::eIncDecOp || (tok->previous()->type() == Token::eIncDecOp && tok->strAt(1) == ";")) { // Variable incremented/decremented; Prefix-Increment is only suspicious, if its return value is unused varAssignments[tok->varId()] = tok; memAssignments.erase(tok->varId()); + eraseMemberAssignments(tok->varId(), membervars, varAssignments); } else if (!Token::simpleMatch(tok->tokAt(-2), "sizeof (")) { // Other usage of variable if (it != varAssignments.end()) varAssignments.erase(it); diff --git a/test/testother.cpp b/test/testother.cpp index 2382b7ecb..3220c7f0b 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -6347,6 +6347,28 @@ private: " return ab.a;\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("struct AB { int a; int b; };\n" + "\n" + "int f(struct AB *ab) {\n" + " ab->a = 1;\n" + " ab->b = 2;\n" + " ab++;\n" + " ab->a = 1;\n" + " ab->b = 2;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("struct AB { int a; int b; };\n" + "\n" + "int f(struct AB *ab) {\n" + " ab->a = 1;\n" + " ab->b = 2;\n" + " ab = x;\n" + " ab->a = 1;\n" + " ab->b = 2;\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void redundantMemWrite() {