Fixed #8816 (FP shadowLocal - variable shadows a template function?)

This commit is contained in:
Daniel Marjamäki 2018-11-19 07:00:15 +01:00
parent 9ef3c79bc6
commit a8cbbe0e16
3 changed files with 20 additions and 11 deletions

View File

@ -3005,16 +3005,18 @@ void CheckOther::checkShadowVariables()
continue; continue;
if (scope.type == Scope::eFunction && scope.className == var.name()) if (scope.type == Scope::eFunction && scope.className == var.name())
continue; 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 errorPath;
errorPath.push_back(ErrorPathItem(shadowed, "Shadowed declaration")); errorPath.push_back(ErrorPathItem(shadowed, "Shadowed declaration"));
errorPath.push_back(ErrorPathItem(var, "Shadow variable")); errorPath.push_back(ErrorPathItem(var, "Shadow variable"));
const std::string &varname = var ? var->str() : "var"; const std::string &varname = var ? var->str() : (shadowVar ? "var" : "f");
reportError(errorPath, Severity::style, "shadowLocal", "$symbol:" + varname + "\nLocal variable $symbol shadows outer symbol", CWE398, false); 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);
} }

View File

@ -267,7 +267,7 @@ private:
void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive); 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 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<const Token*> & declarations, const std::vector<const Token*> & definitions); void funcArgOrderDifferent(const std::string & functionName, const Token * declaration, const Token * definition, const std::vector<const Token*> & declarations, const std::vector<const Token*> & 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 { void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
CheckOther c(nullptr, settings, errorLogger); CheckOther c(nullptr, settings, errorLogger);
@ -330,7 +330,8 @@ private:
c.accessMovedError(nullptr, "v", nullptr, false); c.accessMovedError(nullptr, "v", nullptr, false);
c.funcArgNamesDifferent("function", 1, nullptr, nullptr); c.funcArgNamesDifferent("function", 1, nullptr, nullptr);
c.redundantBitwiseOperationInSwitchError(nullptr, "varname"); c.redundantBitwiseOperationInSwitchError(nullptr, "varname");
c.shadowVariablesError(nullptr, nullptr); c.shadowError(nullptr, nullptr, false);
c.shadowError(nullptr, nullptr, true);
const std::vector<const Token *> nullvec; const std::vector<const Token *> nullvec;
c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec); c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec);

View File

@ -217,7 +217,7 @@ private:
TEST_CASE(funcArgOrderDifferent); TEST_CASE(funcArgOrderDifferent);
TEST_CASE(cpp11FunctionArgInit); // #7846 - "void foo(int declaration = {}) {" 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) { 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" " const int a = getA + 3;\n"
" return 0;\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" check("class A{public:A(){}};\n"
"const A& getA(){static A a;return a;}\n" "const A& getA(){static A a;return a;}\n"
@ -7441,14 +7441,20 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void shadowLocal() { void shadowVariables() {
check("int x;\n" check("int x;\n"
"void f() { 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" check("int x();\n"
"void f() { 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" check("void f() {\n"
" if (cond) {int x;}\n" // <- not a shadow variable " if (cond) {int x;}\n" // <- not a shadow variable