diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8586bf10c..2dddc9c23 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1400,6 +1400,8 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s // Split up variable declarations. simplifyVarDecl(); + simplifyVariableMultipleAssign(); + // Change initialisation of variable to assignment simplifyInitVar(); @@ -4645,6 +4647,43 @@ void Tokenizer::simplifyIfAssign() } +void Tokenizer::simplifyVariableMultipleAssign() +{ + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (Token::Match(tok, "%var% = %var% = %num% ;") || + Token::Match(tok, "%var% = %var% = %var% ;")) + { + + // skip intermediate assignments + Token *tok2 = tok->previous(); + while (tok2 && + tok2->str() == "=" && + Token::Match(tok2->previous(), "%var%")) + { + tok2 = tok2->tokAt(-2); + } + + if (tok2->str() != ";") + { + continue; + } + + Token *stopAt = tok->tokAt(2); + const Token *valueTok = tok->tokAt(4); + const std::string value(valueTok->str()); + tok2 = tok2->next(); + + while (tok2 != stopAt) + { + tok2->next()->insertToken(";"); + tok2->next()->insertToken(value); + tok2 = tok2->tokAt(4); + } + } + } +} + void Tokenizer::simplifyIfNot() { diff --git a/lib/tokenize.h b/lib/tokenize.h index 6b79b0064..0de654c5a 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -187,6 +187,12 @@ public: */ void simplifyIfAssign(); + /** + * Simplify multiple assignmetns. + * Example: "a = b = c = 0;" => "a = 0; b = 0; c = 0;" + */ + void simplifyVariableMultipleAssign(); + /** * simplify if-not * Example: "if(0==x);" => "if(!x);" diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 5775ece94..c3005ae97 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -74,6 +74,7 @@ private: TEST_CASE(localvar9); // ticket #1605 TEST_CASE(localvar10); TEST_CASE(localvar11); + TEST_CASE(localvar12); TEST_CASE(localvaralias1); TEST_CASE(localvaralias2); // ticket #1637 TEST_CASE(localvarasm); @@ -892,7 +893,11 @@ private: " int a, b, c;\n" " a = b = c = 0;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n", errout.str()); + ASSERT_EQUALS( + "[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'b' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'c' is assigned a value that is never used\n", + errout.str()); functionVariableUsage("int * foo()\n" "{\n" @@ -998,6 +1003,42 @@ private: ASSERT_EQUALS("", errout.str()); } + void localvar12() + { + // ticket #1574 + functionVariableUsage("void foo()\n" + "{\n" + " int a, b, c, d, e, f;\n" + " a = b = c = d = e = f = 0;\n" + "\n" + "}\n"); + ASSERT_EQUALS( + "[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'b' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'c' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'd' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'e' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'f' is assigned a value that is never used\n", + errout.str()); + + functionVariableUsage("void foo()\n" + "{\n" + " int a, b, c = 0;\n" + " a = b = c;\n" + "\n" + "}\n"); + ASSERT_EQUALS( + "[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'b' is assigned a value that is never used\n", + errout.str()); + + TODO_ASSERT_EQUALS( + "[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'b' is assigned a value that is never used\n" + "[test.cpp:3]: (style) Variable 'c' is assigned a value that is never used\n", + errout.str()); + } + void localvaralias1() { functionVariableUsage("void foo()\n"