diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 434ecc4e6..a6d032a19 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -560,13 +560,25 @@ void CheckOther::checkRedundantAssignment() if (tok->astParent()) continue; - // Do not warn about redundant initialization + // Do not warn about redundant initialization when rhs is trivial // TODO : do not simplify the variable declarations - if (Token::Match(tok->tokAt(-3), "%var% ; %var% =") && tok->previous()->variable() && tok->previous()->variable()->nameToken() == tok->tokAt(-3)) - continue; + if (Token::Match(tok->tokAt(-3), "%var% ; %var% =") && tok->previous()->variable() && tok->previous()->variable()->nameToken() == tok->tokAt(-3) && tok->tokAt(-3)->linenr() == tok->previous()->linenr()) { + bool trivial = true; + visitAstNodes(tok->astOperand2(), + [&](const Token *rhs) { + if (Token::Match(rhs, "%str%|%num%|%name%")) + return ChildrenToVisit::op1_and_op2; + if (rhs->str() == "(" && !rhs->previous()->isName()) + return ChildrenToVisit::op1_and_op2; + trivial = false; + return ChildrenToVisit::done; + }); + if (trivial) + continue; + } // Do not warn about assignment with 0 / NULL - if (Token::simpleMatch(tok->astOperand2(), "0")) + if (Token::Match(tok->astOperand2(), "0|NULL|nullptr")) continue; if (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isReference()) diff --git a/test/testother.cpp b/test/testother.cpp index 04d289e47..0bca64f58 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -5602,15 +5602,13 @@ private: check("void f() {\n" " int i;\n" - " dostuff();\n" " i = 1;\n" " i = 1;\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style) Variable 'i' is reassigned a value before the old one has been used.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Variable 'i' is reassigned a value before the old one has been used.\n", errout.str()); check("void f() {\n" " static int i;\n" - " dostuff();\n" " i = 1;\n" " i = 1;\n" "}"); @@ -5686,12 +5684,11 @@ private: check("void f() {\n" " int i;\n" - " dostuff();\n" " i = 1;\n" " bar();\n" " i = 1;\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (style) Variable 'i' is reassigned a value before the old one has been used.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Variable 'i' is reassigned a value before the old one has been used.\n", errout.str()); check("void bar(int i) {}\n" "void f(int i) {\n" @@ -5778,17 +5775,15 @@ private: // from #3103 (avoid a false negative) check("int foo(){\n" " int x;\n" - " dostuff();\n" " x = 1;\n" " x = 1;\n" " return x + 1;\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style) Variable 'x' is reassigned a value before the old one has been used.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Variable 'x' is reassigned a value before the old one has been used.\n", errout.str()); // from #3103 (avoid a false positive) check("int foo(){\n" " int x;\n" - " dostuff();\n" " x = 1;\n" " if (y)\n" // <-- cppcheck does not know anything about 'y' " x = 2;\n" @@ -6016,11 +6011,10 @@ private: check("class C { void operator=(int x); };\n" // #8368 - assignment operator might have side effects => inconclusive "void f() {\n" " C c;\n" - " dostuff();\n" " c = x;\n" " c = x;\n" "}"); - ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:6]: (style, inconclusive) Variable 'c' is reassigned a value before the old one has been used if variable is no semaphore variable.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style, inconclusive) Variable 'c' is reassigned a value before the old one has been used if variable is no semaphore variable.\n", errout.str()); } void redundantVarAssignment_stackoverflow() {