Skip to content

Commit 40dfd48

Browse files
committed
Fix #14471
1 parent 04af809 commit 40dfd48

2 files changed

Lines changed: 38 additions & 22 deletions

File tree

lib/checkother.cpp

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4144,46 +4144,61 @@ void CheckOther::checkShadowVariables()
41444144
const Scope *functionScope = &scope;
41454145
while (functionScope && functionScope->type != ScopeType::eFunction && functionScope->type != ScopeType::eLambda)
41464146
functionScope = functionScope->nestedIn;
4147-
for (const Variable &var : scope.varlist) {
4148-
if (var.nameToken() && var.nameToken()->isExpandedMacro()) // #8903
4149-
continue;
4147+
const auto checkVar = [&](const Variable &var) {
4148+
if (!var.nameToken())
4149+
return;
41504150

4151-
if (functionScope && functionScope->type == ScopeType::eFunction && functionScope->function) {
4151+
if (var.nameToken()->isExpandedMacro()) // #8903
4152+
return;
4153+
4154+
if (!var.isArgument() && functionScope && functionScope->type == ScopeType::eFunction && functionScope->function) {
41524155
const auto & argList = functionScope->function->argumentList;
41534156
auto it = std::find_if(argList.cbegin(), argList.cend(), [&](const Variable& arg) {
41544157
return arg.nameToken() && var.name() == arg.name();
41554158
});
41564159
if (it != argList.end()) {
4157-
shadowError(var.nameToken(), it->nameToken(), "argument");
4158-
continue;
4160+
shadowError(var.nameToken(), "local variable", it->nameToken(), "argument");
4161+
return;
41594162
}
41604163
}
41614164

41624165
const Token *shadowed = findShadowed(scope.nestedIn, var, var.nameToken()->linenr());
41634166
if (!shadowed)
41644167
shadowed = findShadowed(scope.functionOf, var, var.nameToken()->linenr());
41654168
if (!shadowed)
4166-
continue;
4169+
return;
41674170
if (scope.type == ScopeType::eFunction && scope.className == var.name())
4168-
continue;
4171+
return;
41694172
if (functionScope->functionOf && functionScope->functionOf->isClassOrStructOrUnion() && functionScope->function &&
41704173
(functionScope->function->isStatic() || functionScope->function->isFriend()) &&
41714174
shadowed->variable() && !shadowed->variable()->isLocal())
4172-
continue;
4173-
shadowError(var.nameToken(), shadowed, (shadowed->varId() != 0) ? "variable" : "function");
4174-
}
4175+
return;
4176+
if (var.scope() && var.scope()->function && var.scope()->function->isConstructor()
4177+
&& shadowed->variable() && shadowed->variable()->isMember())
4178+
return;
4179+
shadowError(var.nameToken(), var.isArgument() ? "argument" : "local variable",
4180+
shadowed, (shadowed->varId() != 0) ?
4181+
(shadowed->variable()->isMember() ? "member" : "variable") : "function");
4182+
};
4183+
for (const Variable &var : scope.varlist)
4184+
checkVar(var);
4185+
if (functionScope && functionScope->type == ScopeType::eFunction && functionScope->function)
4186+
for (const Variable &arg: functionScope->function->argumentList)
4187+
checkVar(arg);
41754188
}
41764189
}
41774190

4178-
void CheckOther::shadowError(const Token *var, const Token *shadowed, const std::string& type)
4191+
void CheckOther::shadowError(const Token *shadows, const std::string &shadowsType,
4192+
const Token *shadowed, const std::string &shadowedType)
41794193
{
41804194
ErrorPath errorPath;
4181-
errorPath.emplace_back(shadowed, "Shadowed declaration");
4182-
errorPath.emplace_back(var, "Shadow variable");
4183-
const std::string &varname = var ? var->str() : type;
4184-
const std::string Type = char(std::toupper(type[0])) + type.substr(1);
4185-
const std::string id = "shadow" + Type;
4186-
const std::string message = "$symbol:" + varname + "\nLocal variable \'$symbol\' shadows outer " + type;
4195+
errorPath.emplace_back(shadowed, "Shadowed " + shadowedType);
4196+
errorPath.emplace_back(shadows, "Shadow " + shadowsType);
4197+
const std::string &varname = shadows ? shadows->str() : shadowsType;
4198+
const std::string ShadowsType = char(std::toupper(shadowsType[0])) + shadowsType.substr(1);
4199+
const std::string ShadowedType = char(std::toupper(shadowedType[0])) + shadowedType.substr(1);
4200+
const std::string id = "shadow" + ShadowedType;
4201+
const std::string message = "$symbol:" + varname + "\n" + ShadowsType + " \'$symbol\' shadows outer " + shadowedType;
41874202
reportError(std::move(errorPath), Severity::style, id.c_str(), message, CWE398, Certainty::normal);
41884203
}
41894204

@@ -4865,9 +4880,10 @@ void CheckOther::getErrorMessages(ErrorLogger *errorLogger, const Settings *sett
48654880
c.accessMovedError(nullptr, "v", nullptr, false);
48664881
c.funcArgNamesDifferent("function", 1, nullptr, nullptr);
48674882
c.redundantBitwiseOperationInSwitchError(nullptr, "varname");
4868-
c.shadowError(nullptr, nullptr, "variable");
4869-
c.shadowError(nullptr, nullptr, "function");
4870-
c.shadowError(nullptr, nullptr, "argument");
4883+
c.shadowError(nullptr, "local variable", nullptr, "variable");
4884+
c.shadowError(nullptr, "local variable", nullptr, "argument");
4885+
c.shadowError(nullptr, "local variable", nullptr, "function");
4886+
c.shadowError(nullptr, "local variable", nullptr, "member");
48714887
c.knownArgumentError(nullptr, nullptr, nullptr, "x", false);
48724888
c.knownPointerToBoolError(nullptr, nullptr);
48734889
c.comparePointersError(nullptr, nullptr, nullptr);

lib/checkother.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class CPPCHECKLIB CheckOther : public Check {
258258
void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive);
259259
void funcArgNamesDifferent(const std::string & functionName, nonneg int index, const Token* declaration, const Token* definition);
260260
void funcArgOrderDifferent(const std::string & functionName, const Token * declaration, const Token * definition, const std::vector<const Token*> & declarations, const std::vector<const Token*> & definitions);
261-
void shadowError(const Token *var, const Token *shadowed, const std::string& type);
261+
void shadowError(const Token *shadows, const std::string &shadowsType, const Token *shadowed, const std::string &shadowedType);
262262
void knownArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value, const std::string &varexpr, bool isVariableExpressionHidden);
263263
void knownPointerToBoolError(const Token* tok, const ValueFlow::Value* value);
264264
void comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2);

0 commit comments

Comments
 (0)