diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 64b3eebde..5f70bf8bb 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2798,26 +2798,43 @@ void CheckOther::checkShadowVariables() for (const Scope & scope : symbolDatabase->scopeList) { if (!scope.isExecutable() || scope.type == Scope::eLambda) continue; + const Scope *functionScope = &scope; + while (functionScope && functionScope->type != Scope::ScopeType::eFunction && functionScope->type != Scope::ScopeType::eLambda) + functionScope = functionScope->nestedIn; for (const Variable &var : scope.varlist) { + if (functionScope && functionScope->type == Scope::ScopeType::eFunction && functionScope->function) { + bool shadowArg = false; + for (const Variable &arg : functionScope->function->argumentList) { + if (arg.nameToken() && var.name() == arg.name()) { + shadowError(var.nameToken(), arg.nameToken(), "argument"); + shadowArg = true; + break; + } + } + if (shadowArg) + continue; + } + const Token *shadowed = findShadowed(scope.nestedIn, var.name(), var.nameToken()->linenr()); if (!shadowed) continue; if (scope.type == Scope::eFunction && scope.className == var.name()) continue; - shadowError(var.nameToken(), shadowed, shadowed->varId() != 0); + shadowError(var.nameToken(), shadowed, (shadowed->varId() != 0) ? "variable" : "function"); } } } -void CheckOther::shadowError(const Token *var, const Token *shadowed, bool shadowVar) +void CheckOther::shadowError(const Token *var, const Token *shadowed, std::string type) { ErrorPath errorPath; errorPath.push_back(ErrorPathItem(shadowed, "Shadowed declaration")); errorPath.push_back(ErrorPathItem(var, "Shadow variable")); - 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); + const std::string &varname = var ? var->str() : type; + const std::string Type = char(std::toupper(type[0])) + type.substr(1); + const std::string id = "shadow" + Type; + const std::string message = "$symbol:" + varname + "\nLocal variable \'$symbol\' shadows outer " + type; + reportError(errorPath, Severity::style, id.c_str(), message, CWE398, false); } static bool isVariableExpression(const Token* tok) diff --git a/lib/checkother.h b/lib/checkother.h index 8f0cd789c..699431d2c 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -259,7 +259,7 @@ private: void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive); void funcArgNamesDifferent(const std::string & functionName, nonneg int 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 shadowError(const Token *var, const Token *shadowed, bool shadowVar); + void shadowError(const Token *var, const Token *shadowed, std::string type); void constArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value); void comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2); @@ -323,8 +323,9 @@ private: c.accessMovedError(nullptr, "v", nullptr, false); c.funcArgNamesDifferent("function", 1, nullptr, nullptr); c.redundantBitwiseOperationInSwitchError(nullptr, "varname"); - c.shadowError(nullptr, nullptr, false); - c.shadowError(nullptr, nullptr, true); + c.shadowError(nullptr, nullptr, "variable"); + c.shadowError(nullptr, nullptr, "function"); + c.shadowError(nullptr, nullptr, "argument"); c.constArgumentError(nullptr, nullptr, nullptr); c.comparePointersError(nullptr, nullptr, nullptr); diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 6f5d7c067..6822e5234 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -634,13 +634,13 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string picojson::object obj = res.get(); - const std::string filename = obj["file"].get(); + const std::string fileName = obj["file"].get(); const int64_t lineNumber = obj["linenr"].get(); const int64_t column = obj["col"].get(); ErrorLogger::ErrorMessage errmsg; - errmsg._callStack.emplace_back(ErrorLogger::ErrorMessage::FileLocation(filename, lineNumber)); + errmsg._callStack.emplace_back(ErrorLogger::ErrorMessage::FileLocation(fileName, lineNumber)); errmsg._callStack.back().col = column; errmsg._id = obj["errorId"].get(); @@ -650,7 +650,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string errmsg._severity = Severity::fromString(severity); if (errmsg._severity == Severity::SeverityType::none) continue; - errmsg.file0 = filename; + errmsg.file0 = fileName; reportErr(errmsg); } diff --git a/test/testother.cpp b/test/testother.cpp index 8292a3cac..c24cf1e85 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2918,7 +2918,7 @@ private: "}"); ASSERT_EQUALS("", errout.str()); - check("void foo(int x) {\n" + check("void foo(int arg) {\n" " printf(\"%i\", ({int x = do_something(); x == 0;}));\n" "}"); ASSERT_EQUALS("", errout.str()); @@ -7573,6 +7573,9 @@ private: " auto f = [](){ int x; }" "}"); ASSERT_EQUALS("", errout.str()); + + check("void f(int x) { int x; }"); + ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (style) Local variable 'x' shadows outer argument\n", errout.str()); } void constArgument() {