Skip to content

Commit ae2816b

Browse files
authored
Fix #14471: Improve check: shadowVariable for function argument (#8303)
1 parent eed1daf commit ae2816b

26 files changed

Lines changed: 191 additions & 143 deletions

.selfcheck_suppressions

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,5 @@ knownConditionTrueFalse:externals/tinyxml2/tinyxml2.cpp
7878
useStlAlgorithm:externals/simplecpp/simplecpp.cpp
7979
funcArgNamesDifferentUnnamed:externals/simplecpp/simplecpp.h
8080
missingMemberCopy:externals/simplecpp/simplecpp.h
81+
shadowFunction:externals/simplecpp/simplecpp.cpp
82+
shadowFunction:externals/simplecpp/simplecpp.h

gui/mainwindow.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ void MainWindow::saveSettings() const
562562
mUI->mResults->saveSettings(mSettings);
563563
}
564564

565-
void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, const bool checkConfiguration)
565+
void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLib, const bool checkConfig)
566566
{
567567
Settings checkSettings;
568568
auto supprs = std::make_shared<Suppressions>();
@@ -606,8 +606,8 @@ void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, cons
606606

607607
mUI->mResults->setCheckDirectory(checkPath);
608608
checkSettings.force = false;
609-
checkSettings.checkLibrary = checkLibrary;
610-
checkSettings.checkConfiguration = checkConfiguration;
609+
checkSettings.checkLibrary = checkLib;
610+
checkSettings.checkConfiguration = checkConfig;
611611

612612
if (mProjectFile)
613613
qDebug() << "Checking project file" << mProjectFile->getFilename();
@@ -634,7 +634,7 @@ void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, cons
634634
mUI->mResults->setCheckSettings(checkSettings);
635635
}
636636

637-
void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrary, const bool checkConfiguration)
637+
void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLib, const bool checkConfig)
638638
{
639639
if (files.isEmpty())
640640
return;
@@ -675,7 +675,7 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar
675675
// TODO: lock UI here?
676676
mUI->mResults->checkingStarted(fdetails.size());
677677
mThread->setFiles(std::move(fdetails));
678-
if (mProjectFile && !checkConfiguration)
678+
if (mProjectFile && !checkConfig)
679679
mThread->setAddonsAndTools(mProjectFile->getAddonsAndTools());
680680
mThread->setSuppressions(mProjectFile ? mProjectFile->getCheckingSuppressions() : QList<SuppressionList::Suppression>());
681681
QDir inf(mCurrentDirectory);
@@ -685,8 +685,8 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar
685685
checkLockDownUI(); // lock UI while checking
686686

687687
mUI->mResults->setCheckDirectory(checkPath);
688-
checkSettings.checkLibrary = checkLibrary;
689-
checkSettings.checkConfiguration = checkConfiguration;
688+
checkSettings.checkLibrary = checkLib;
689+
checkSettings.checkConfiguration = checkConfig;
690690

691691
if (mProjectFile)
692692
qDebug() << "Checking project file" << mProjectFile->getFilename();
@@ -1856,7 +1856,7 @@ bool MainWindow::loadLastResults()
18561856
return true;
18571857
}
18581858

1859-
void MainWindow::analyzeProject(const ProjectFile *projectFile, const QStringList& recheckFiles, const bool checkLibrary, const bool checkConfiguration)
1859+
void MainWindow::analyzeProject(const ProjectFile *projectFile, const QStringList& recheckFiles, const bool checkLib, const bool checkConfig)
18601860
{
18611861
Settings::terminate(false);
18621862

@@ -1961,7 +1961,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile, const QStringLis
19611961
msg.exec();
19621962
return;
19631963
}
1964-
doAnalyzeProject(p, checkLibrary, checkConfiguration); // TODO: avoid copy
1964+
doAnalyzeProject(p, checkLib, checkConfig); // TODO: avoid copy
19651965
return;
19661966
}
19671967

@@ -1974,7 +1974,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile, const QStringLis
19741974
if (paths.isEmpty()) {
19751975
paths << mCurrentDirectory;
19761976
}
1977-
doAnalyzeFiles(paths, checkLibrary, checkConfiguration);
1977+
doAnalyzeFiles(paths, checkLib, checkConfig);
19781978
}
19791979

19801980
void MainWindow::newProjectFile()

gui/mainwindow.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,10 @@ private slots:
267267
* @brief Analyze the project.
268268
* @param projectFile Pointer to the project to analyze.
269269
* @param recheckFiles files to recheck, empty => check all files
270-
* @param checkLibrary Flag to indicate if the library should be checked.
271-
* @param checkConfiguration Flag to indicate if the configuration should be checked.
270+
* @param checkLib Flag to indicate if the library should be checked.
271+
* @param checkConfig Flag to indicate if the configuration should be checked.
272272
*/
273-
void analyzeProject(const ProjectFile *projectFile, const QStringList& recheckFiles, bool checkLibrary = false, bool checkConfiguration = false);
273+
void analyzeProject(const ProjectFile *projectFile, const QStringList& recheckFiles, bool checkLib = false, bool checkConfig = false);
274274

275275
/**
276276
* @brief Set current language
@@ -306,19 +306,19 @@ private slots:
306306
/**
307307
* @brief Analyze project
308308
* @param p imported project
309-
* @param checkLibrary Flag to indicate if library should be checked
310-
* @param checkConfiguration Flag to indicate if the configuration should be checked.
309+
* @param checkLib Flag to indicate if library should be checked
310+
* @param checkConfig Flag to indicate if the configuration should be checked.
311311
*/
312-
void doAnalyzeProject(ImportProject p, bool checkLibrary = false, bool checkConfiguration = false);
312+
void doAnalyzeProject(ImportProject p, bool checkLib = false, bool checkConfig = false);
313313

314314
/**
315315
* @brief Analyze all files specified in parameter files
316316
*
317317
* @param files List of files and/or directories to analyze
318-
* @param checkLibrary Flag to indicate if library should be checked
319-
* @param checkConfiguration Flag to indicate if the configuration should be checked.
318+
* @param checkLib Flag to indicate if library should be checked
319+
* @param checkConfig Flag to indicate if the configuration should be checked.
320320
*/
321-
void doAnalyzeFiles(const QStringList &files, bool checkLibrary = false, bool checkConfiguration = false);
321+
void doAnalyzeFiles(const QStringList &files, bool checkLib = false, bool checkConfig = false);
322322

323323
/**
324324
* @brief Get our default cppcheck settings and read project file.

lib/checkcondition.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,10 +2085,10 @@ void CheckCondition::checkCompareValueOutOfTypeRange()
20852085
}
20862086
}
20872087

2088-
void CheckCondition::compareValueOutOfTypeRangeError(const Token *comparison, const std::string &type, MathLib::bigint value, bool result)
2088+
void CheckCondition::compareValueOutOfTypeRangeError(const Token *comparisonTok, const std::string &type, MathLib::bigint value, bool result)
20892089
{
20902090
reportError(
2091-
comparison,
2091+
comparisonTok,
20922092
Severity::style,
20932093
"compareValueOutOfTypeRangeError",
20942094
"Comparing expression of type '" + type + "' against value " + MathLib::toString(value) + ". Condition is always " + bool_to_string(result) + ".",

lib/checkcondition.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class CPPCHECKLIB CheckCondition : public Check {
156156
void assignmentInCondition(const Token *eq);
157157

158158
void checkCompareValueOutOfTypeRange();
159-
void compareValueOutOfTypeRangeError(const Token *comparison, const std::string &type, MathLib::bigint value, bool result);
159+
void compareValueOutOfTypeRangeError(const Token *comparisonTok, const std::string &type, MathLib::bigint value, bool result);
160160

161161
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override;
162162

lib/checkother.cpp

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4168,46 +4168,65 @@ void CheckOther::checkShadowVariables()
41684168
const Scope *functionScope = &scope;
41694169
while (functionScope && functionScope->type != ScopeType::eFunction && functionScope->type != ScopeType::eLambda)
41704170
functionScope = functionScope->nestedIn;
4171-
for (const Variable &var : scope.varlist) {
4172-
if (var.nameToken() && var.nameToken()->isExpandedMacro()) // #8903
4173-
continue;
4171+
const auto checkVar = [&](const Variable &var) {
4172+
if (!var.nameToken())
4173+
return;
4174+
4175+
if (var.nameToken()->isExpandedMacro()) // #8903
4176+
return;
41744177

4175-
if (functionScope && functionScope->type == ScopeType::eFunction && functionScope->function) {
4178+
if (!var.isArgument() && functionScope && functionScope->type == ScopeType::eFunction && functionScope->function) {
41764179
const auto & argList = functionScope->function->argumentList;
41774180
auto it = std::find_if(argList.cbegin(), argList.cend(), [&](const Variable& arg) {
41784181
return arg.nameToken() && var.name() == arg.name();
41794182
});
41804183
if (it != argList.end()) {
4181-
shadowError(var.nameToken(), it->nameToken(), "argument");
4182-
continue;
4184+
shadowError(var.nameToken(), "local variable", it->nameToken(), "argument");
4185+
return;
41834186
}
41844187
}
41854188

41864189
const Token *shadowed = findShadowed(scope.nestedIn, var, var.nameToken()->linenr());
41874190
if (!shadowed)
41884191
shadowed = findShadowed(scope.functionOf, var, var.nameToken()->linenr());
41894192
if (!shadowed)
4190-
continue;
4193+
return;
41914194
if (scope.type == ScopeType::eFunction && scope.className == var.name())
4192-
continue;
4195+
return;
41934196
if (functionScope->functionOf && functionScope->functionOf->isClassOrStructOrUnion() && functionScope->function &&
41944197
(functionScope->function->isStatic() || functionScope->function->isFriend()) &&
41954198
shadowed->variable() && !shadowed->variable()->isLocal())
4196-
continue;
4197-
shadowError(var.nameToken(), shadowed, (shadowed->varId() != 0) ? "variable" : "function");
4198-
}
4199+
return;
4200+
if (var.scope() && var.scope()->function && var.scope()->function->isConstructor()) {
4201+
if (shadowed->variable() && shadowed->variable()->isMember())
4202+
return;
4203+
if (shadowed->function() && shadowed->function()->nestedIn &&
4204+
shadowed->function()->nestedIn->isClassOrStruct())
4205+
return;
4206+
}
4207+
shadowError(var.nameToken(), var.isArgument() ? "argument" : "local variable",
4208+
shadowed, (shadowed->varId() != 0) ?
4209+
(shadowed->variable()->isMember() ? "member" : "variable") : "function");
4210+
};
4211+
for (const Variable &var : scope.varlist)
4212+
checkVar(var);
4213+
if (functionScope && functionScope->type == ScopeType::eFunction && functionScope->function)
4214+
for (const Variable &arg: functionScope->function->argumentList)
4215+
checkVar(arg);
41994216
}
42004217
}
42014218

4202-
void CheckOther::shadowError(const Token *var, const Token *shadowed, const std::string& type)
4219+
void CheckOther::shadowError(const Token *shadows, const std::string &shadowsType,
4220+
const Token *shadowed, const std::string &shadowedType)
42034221
{
42044222
ErrorPath errorPath;
4205-
errorPath.emplace_back(shadowed, "Shadowed declaration");
4206-
errorPath.emplace_back(var, "Shadow variable");
4207-
const std::string &varname = var ? var->str() : type;
4208-
const std::string Type = char(std::toupper(type[0])) + type.substr(1);
4209-
const std::string id = "shadow" + Type;
4210-
const std::string message = "$symbol:" + varname + "\nLocal variable \'$symbol\' shadows outer " + type;
4223+
errorPath.emplace_back(shadowed, "Shadowed " + shadowedType);
4224+
errorPath.emplace_back(shadows, "Shadow " + shadowsType);
4225+
const std::string &varname = shadows ? shadows->str() : shadowsType;
4226+
const std::string ShadowsType = char(std::toupper(shadowsType[0])) + shadowsType.substr(1);
4227+
const std::string ShadowedType = char(std::toupper(shadowedType[0])) + shadowedType.substr(1);
4228+
const std::string id = "shadow" + ShadowedType;
4229+
const std::string message = "$symbol:" + varname + "\n" + ShadowsType + " \'$symbol\' shadows outer " + shadowedType;
42114230
reportError(std::move(errorPath), Severity::style, id.c_str(), message, CWE398, Certainty::normal);
42124231
}
42134232

@@ -4889,9 +4908,10 @@ void CheckOther::getErrorMessages(ErrorLogger *errorLogger, const Settings *sett
48894908
c.accessMovedError(nullptr, "v", nullptr, false);
48904909
c.funcArgNamesDifferent("function", 1, nullptr, nullptr);
48914910
c.redundantBitwiseOperationInSwitchError(nullptr, "varname");
4892-
c.shadowError(nullptr, nullptr, "variable");
4893-
c.shadowError(nullptr, nullptr, "function");
4894-
c.shadowError(nullptr, nullptr, "argument");
4911+
c.shadowError(nullptr, "local variable", nullptr, "variable");
4912+
c.shadowError(nullptr, "local variable", nullptr, "argument");
4913+
c.shadowError(nullptr, "local variable", nullptr, "function");
4914+
c.shadowError(nullptr, "local variable", nullptr, "member");
48954915
c.knownArgumentError(nullptr, nullptr, nullptr, "x", false);
48964916
c.knownPointerToBoolError(nullptr, nullptr);
48974917
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);

lib/checkunusedfunctions.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,9 @@ void CheckUnusedFunctions::analyseWholeProgram(const Settings &settings, ErrorLo
505505
}
506506
}
507507

508-
void CheckUnusedFunctions::updateFunctionData(const CheckUnusedFunctions& check)
508+
void CheckUnusedFunctions::updateFunctionData(const CheckUnusedFunctions& checkUnusedFunctions)
509509
{
510-
for (const auto& entry : check.mFunctions)
510+
for (const auto& entry : checkUnusedFunctions.mFunctions)
511511
{
512512
FunctionUsage &usage = mFunctions[entry.first];
513513
if (!usage.lineNumber) {
@@ -521,6 +521,6 @@ void CheckUnusedFunctions::updateFunctionData(const CheckUnusedFunctions& check)
521521
usage.usedOtherFile |= entry.second.usedOtherFile;
522522
usage.usedSameFile |= entry.second.usedSameFile;
523523
}
524-
mFunctionDecl.insert(mFunctionDecl.cend(), check.mFunctionDecl.cbegin(), check.mFunctionDecl.cend());
525-
mFunctionCalls.insert(check.mFunctionCalls.cbegin(), check.mFunctionCalls.cend());
524+
mFunctionDecl.insert(mFunctionDecl.cend(), checkUnusedFunctions.mFunctionDecl.cbegin(), checkUnusedFunctions.mFunctionDecl.cend());
525+
mFunctionCalls.insert(checkUnusedFunctions.mFunctionCalls.cbegin(), checkUnusedFunctions.mFunctionCalls.cend());
526526
}

lib/checkunusedfunctions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class CPPCHECKLIB CheckUnusedFunctions {
5858
// Return true if an error is reported.
5959
bool check(const Settings& settings, ErrorLogger& errorLogger) const;
6060

61-
void updateFunctionData(const CheckUnusedFunctions& check);
61+
void updateFunctionData(const CheckUnusedFunctions& checkUnusedFunctions);
6262

6363
private:
6464
static void unusedFunctionError(ErrorLogger& errorLogger,

lib/filesettings.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ class FileWithDetails
9191
return mFsFileId;
9292
}
9393

94-
void setFsFileId(std::size_t fsFileId)
94+
void setFsFileId(std::size_t id)
9595
{
96-
mFsFileId = fsFileId;
96+
mFsFileId = id;
9797
}
9898
private:
9999
std::string mPath;

0 commit comments

Comments
 (0)