Detect shadowed arguments
This commit is contained in:
parent
0be78bbde6
commit
d11d6f112e
|
@ -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)
|
||||
|
|
|
@ -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<const Token*> & declarations, const std::vector<const Token*> & 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);
|
||||
|
||||
|
|
|
@ -634,13 +634,13 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
|
|||
|
||||
picojson::object obj = res.get<picojson::object>();
|
||||
|
||||
const std::string filename = obj["file"].get<std::string>();
|
||||
const std::string fileName = obj["file"].get<std::string>();
|
||||
const int64_t lineNumber = obj["linenr"].get<int64_t>();
|
||||
const int64_t column = obj["col"].get<int64_t>();
|
||||
|
||||
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<std::string>();
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue