From 82eec11898197a380e1a643eba78e6ca68b27bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 25 Aug 2019 09:45:39 +0200 Subject: [PATCH] Created redundantInitialization id --- lib/checkother.cpp | 13 +++++++++++++ lib/checkother.h | 4 +++- test/testother.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 8b60d446d..a4d079784 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -433,7 +433,9 @@ void CheckOther::checkRedundantAssignment() // Do not warn about redundant initialization when rhs is trivial // TODO : do not simplify the variable declarations + bool isInitialization = false; 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()) { + isInitialization = true; bool trivial = true; visitAstNodes(tok->astOperand2(), [&](const Token *rhs) { @@ -507,6 +509,8 @@ void CheckOther::checkRedundantAssignment() // warn if (hasCase) redundantAssignmentInSwitchError(tok, nextAssign, tok->astOperand1()->expressionString()); + else if (isInitialization) + redundantInitializationError(tok, nextAssign, tok->astOperand1()->expressionString(), inconclusive); else redundantAssignmentError(tok, nextAssign, tok->astOperand1()->expressionString(), inconclusive); } @@ -544,6 +548,15 @@ void CheckOther::redundantAssignmentError(const Token *tok1, const Token* tok2, "Variable '$symbol' is reassigned a value before the old one has been used.", CWE563, false); } +void CheckOther::redundantInitializationError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive) +{ + const std::list callstack = { tok1, tok2 }; + reportError(callstack, Severity::style, "redundantInitialization", + "$symbol:" + var + "\nRedundant initialization for '$symbol'. The initialized value is never used.", + CWE563, + inconclusive); +} + void CheckOther::redundantAssignmentInSwitchError(const Token *tok1, const Token* tok2, const std::string &var) { const std::list callstack = { tok1, tok2 }; diff --git a/lib/checkother.h b/lib/checkother.h index aac4ec5c9..a3d31d6e6 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -230,6 +230,7 @@ private: void zerodivError(const Token *tok, const ValueFlow::Value *value); void nanInArithmeticExpressionError(const Token *tok); void redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive); + void redundantInitializationError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive); void redundantAssignmentInSwitchError(const Token *tok1, const Token *tok2, const std::string &var); void redundantCopyError(const Token *tok1, const Token* tok2, const std::string& var); void redundantCopyInSwitchError(const Token *tok1, const Token* tok2, const std::string &var); @@ -285,7 +286,6 @@ private: //performance c.redundantCopyError(nullptr, "varname"); c.redundantCopyError(nullptr, nullptr, "var"); - c.redundantAssignmentError(nullptr, nullptr, "var", false); // style/warning c.checkComparisonFunctionIsAlwaysTrueOrFalseError(nullptr, "isless","varName",false); @@ -333,6 +333,8 @@ private: c.shadowError(nullptr, nullptr, "argument"); c.constArgumentError(nullptr, nullptr, nullptr); c.comparePointersError(nullptr, nullptr, nullptr); + c.redundantAssignmentError(nullptr, nullptr, "var", false); + c.redundantInitializationError(nullptr, nullptr, "var", false); const std::vector nullvec; c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec); diff --git a/test/testother.cpp b/test/testother.cpp index eebe94da5..a7e09b6a2 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -171,6 +171,7 @@ private: TEST_CASE(redundantVarAssignment_after_switch); TEST_CASE(redundantVarAssignment_pointer); TEST_CASE(redundantVarAssignment_pointer_parameter); + TEST_CASE(redundantInitialization); TEST_CASE(redundantMemWrite); TEST_CASE(varFuncNullUB); @@ -6548,6 +6549,32 @@ private: ASSERT_EQUALS("", errout.str()); } + void redundantInitialization() { + check("void f() {\n" + " int err = -ENOMEM;\n" + " err = dostuff();\n" + "}"); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Redundant initialization for 'err'. The initialized value is never used.\n", errout.str()); + + check("void f() {\n" + " struct S s = {1,2,3};\n" + " s = dostuff();\n" + "}"); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Redundant initialization for 's'. The initialized value is never used.\n", errout.str()); + + check("void f() {\n" + " int *p = NULL;\n" + " p = dostuff();\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void f() {\n" + " struct S s = {0};\n" + " s = dostuff();\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void redundantMemWrite() { return; // FIXME: temporary hack