diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 7436a9e18..71f38deae 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3005,16 +3005,18 @@ void CheckOther::checkShadowVariables() continue; if (scope.type == Scope::eFunction && scope.className == var.name()) continue; - shadowVariablesError(var.nameToken(), shadowed); + shadowError(var.nameToken(), shadowed, shadowed->varId() != 0); } } } -void CheckOther::shadowVariablesError(const Token *var, const Token *shadowed) +void CheckOther::shadowError(const Token *var, const Token *shadowed, bool shadowVar) { ErrorPath errorPath; errorPath.push_back(ErrorPathItem(shadowed, "Shadowed declaration")); errorPath.push_back(ErrorPathItem(var, "Shadow variable")); - const std::string &varname = var ? var->str() : "var"; - reportError(errorPath, Severity::style, "shadowLocal", "$symbol:" + varname + "\nLocal variable $symbol shadows outer symbol", CWE398, false); + const std::string &varname = var ? var->str() : (shadowVar ? "var" : "f"); + const char *id = shadowVar ? "shadowVar" : "shadowFunction"; + std::string message = "$symbol:" + varname + "\nLocal variable $symbol shadows outer " + (shadowVar ? "variable" : "function"); + reportError(errorPath, Severity::style, id, message, CWE398, false); } diff --git a/lib/checkother.h b/lib/checkother.h index f75ac7d96..310aaf75d 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -267,7 +267,7 @@ private: void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive); void funcArgNamesDifferent(const std::string & functionName, size_t index, const Token* declaration, const Token* definition); void funcArgOrderDifferent(const std::string & functionName, const Token * declaration, const Token * definition, const std::vector & declarations, const std::vector & definitions); - void shadowVariablesError(const Token *var, const Token *shadowed); + void shadowError(const Token *var, const Token *shadowed, bool shadowVar); void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override { CheckOther c(nullptr, settings, errorLogger); @@ -330,7 +330,8 @@ private: c.accessMovedError(nullptr, "v", nullptr, false); c.funcArgNamesDifferent("function", 1, nullptr, nullptr); c.redundantBitwiseOperationInSwitchError(nullptr, "varname"); - c.shadowVariablesError(nullptr, nullptr); + c.shadowError(nullptr, nullptr, false); + c.shadowError(nullptr, nullptr, true); const std::vector nullvec; c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec); diff --git a/test/testother.cpp b/test/testother.cpp index e228113ff..80d01f6d0 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -217,7 +217,7 @@ private: TEST_CASE(funcArgOrderDifferent); TEST_CASE(cpp11FunctionArgInit); // #7846 - "void foo(int declaration = {}) {" - TEST_CASE(shadowLocal); + TEST_CASE(shadowVariables); } void check(const char code[], const char *filename = nullptr, bool experimental = false, bool inconclusive = true, bool runSimpleChecks=true, Settings* settings = 0) { @@ -5380,7 +5380,7 @@ private: " const int a = getA + 3;\n" " return 0;\n" "}"); - ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:4]: (style) Local variable getA shadows outer symbol\n", errout.str()); + ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:4]: (style) Local variable getA shadows outer function\n", errout.str()); check("class A{public:A(){}};\n" "const A& getA(){static A a;return a;}\n" @@ -7441,14 +7441,20 @@ private: ASSERT_EQUALS("", errout.str()); } - void shadowLocal() { + void shadowVariables() { check("int x;\n" "void f() { int x; }\n"); - ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable x shadows outer symbol\n", errout.str()); + ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable x shadows outer variable\n", errout.str()); check("int x();\n" "void f() { int x; }\n"); - ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable x shadows outer symbol\n", errout.str()); + ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable x shadows outer function\n", errout.str()); + + check("struct C {\n" + " C(int x) : x(x) {}\n" // <- we do not want a FP here + " int x;\n" + "};"); + ASSERT_EQUALS("", errout.str()); check("void f() {\n" " if (cond) {int x;}\n" // <- not a shadow variable