Fix FN passedByValue with array access, range-based for (#4922)

* Fix FN passedByValue with array access, range-based for

* Format

* Fix/suppress new warnings
This commit is contained in:
chrchr-github 2023-03-30 07:24:23 +02:00 committed by GitHub
parent fc24f760cc
commit 3836367d95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 9 deletions

View File

@ -45,7 +45,7 @@
#include <QSettings> #include <QSettings>
// NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature // NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature
static bool executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output) static bool executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output) // cppcheck-suppress passedByValue
{ {
output.clear(); output.clear();

View File

@ -1158,7 +1158,7 @@ void MainWindow::checkConfiguration()
analyzeProject(mProjectFile, false, true); analyzeProject(mProjectFile, false, true);
} }
void MainWindow::reAnalyzeSelected(QStringList files) void MainWindow::reAnalyzeSelected(const QStringList& files)
{ {
if (files.empty()) if (files.empty())
return; return;

View File

@ -251,7 +251,7 @@ private:
* @brief Reanalyze selected files * @brief Reanalyze selected files
* @param files list of selected files * @param files list of selected files
*/ */
void reAnalyzeSelected(QStringList files); void reAnalyzeSelected(const QStringList& files);
/** /**
* @brief Analyze the project. * @brief Analyze the project.

View File

@ -1176,6 +1176,14 @@ static int estimateSize(const Type* type, const Settings* settings, const Symbol
}); });
} }
static bool isConstRangeBasedFor(const Token* tok) {
if (astIsRangeBasedForDecl(tok)) {
const Variable* loopVar = tok->astParent()->astOperand1()->variable();
return loopVar && (!loopVar->isReference() || loopVar->isConst());
}
return false;
}
static bool canBeConst(const Variable *var, const Settings* settings) static bool canBeConst(const Variable *var, const Settings* settings)
{ {
if (!var->scope()) if (!var->scope())
@ -1201,6 +1209,8 @@ static bool canBeConst(const Variable *var, const Settings* settings)
continue; continue;
const Token* parent = tok2->astParent(); const Token* parent = tok2->astParent();
while (Token::simpleMatch(parent, "["))
parent = parent->astParent();
if (!parent) if (!parent)
continue; continue;
if (Token::simpleMatch(tok2->next(), ";") && tok2->next()->isSplittedVarDeclEq()) { if (Token::simpleMatch(tok2->next(), ";") && tok2->next()->isSplittedVarDeclEq()) {
@ -1249,9 +1259,12 @@ static bool canBeConst(const Variable *var, const Settings* settings)
(parent->astOperand2() && settings->library.isFunctionConst(parent->astOperand2()))) (parent->astOperand2() && settings->library.isFunctionConst(parent->astOperand2())))
continue; continue;
else if (parent->isAssignmentOp()) { else if (parent->isAssignmentOp()) {
if (parent->astOperand1() == tok2) const Token* assignee = parent->astOperand1();
while (Token::simpleMatch(assignee, "["))
assignee = assignee->astOperand1();
if (assignee == tok2)
return false; return false;
const Variable* assignedVar = parent->astOperand1() ? parent->astOperand1()->variable() : nullptr; const Variable* assignedVar = assignee ? assignee->variable() : nullptr;
if (assignedVar && if (assignedVar &&
!assignedVar->isConst() && !assignedVar->isConst() &&
assignedVar->isReference() && assignedVar->isReference() &&
@ -1263,7 +1276,9 @@ static bool canBeConst(const Variable *var, const Settings* settings)
continue; continue;
else else
return false; return false;
} else } else if (isConstRangeBasedFor(tok2))
continue;
else
return false; return false;
} }

View File

@ -274,7 +274,7 @@ static std::string unescape(const std::string &in)
return out; return out;
} }
void ImportProject::FileSettings::parseCommand(std::string command) void ImportProject::FileSettings::parseCommand(const std::string& command)
{ {
std::string defs; std::string defs;

View File

@ -78,7 +78,7 @@ public:
bool msc; bool msc;
bool useMfc; bool useMfc;
void parseCommand(std::string command); void parseCommand(const std::string& command);
void setDefines(std::string defs); void setDefines(std::string defs);
void setIncludePaths(const std::string &basepath, const std::list<std::string> &in, std::map<std::string, std::string, cppcheck::stricmp> &variables); void setIncludePaths(const std::string &basepath, const std::list<std::string> &in, std::map<std::string, std::string, cppcheck::stricmp> &variables);
}; };

View File

@ -1993,6 +1993,36 @@ private:
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("int x(int);\n"
"void f(std::vector<int> v, int& j) {\n"
" for (int i : v)\n"
" j = i;\n"
"}\n"
"void fn(std::vector<int> v) {\n"
" for (int& i : v)\n"
" i = x(i);\n"
"}\n"
"void g(std::vector<int> v, int& j) {\n"
" for (int i = 0; i < v.size(); ++i)\n"
" j = v[i];\n"
"}\n"
"void gn(std::vector<int> v) {\n"
" for (int i = 0; i < v.size(); ++i)\n"
" v[i] = x(i);\n"
"}\n"
"void h(std::vector<std::vector<int>> v, int& j) {\n"
" for (int i = 0; i < v.size(); ++i)\n"
" j = v[i][0];\n"
"}\n"
"void hn(std::vector<std::vector<int>> v) {\n"
" for (int i = 0; i < v.size(); ++i)\n"
" v[i][0] = x(i);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 'v' should be passed by const reference.\n"
"[test.cpp:10]: (performance) Function parameter 'v' should be passed by const reference.\n"
"[test.cpp:18]: (performance) Function parameter 'v' should be passed by const reference.\n",
errout.str());
Settings settings1; Settings settings1;
PLATFORM(settings1.platform, cppcheck::Platform::Type::Win64); PLATFORM(settings1.platform, cppcheck::Platform::Type::Win64);
check("using ui64 = unsigned __int64;\n" check("using ui64 = unsigned __int64;\n"
@ -2194,7 +2224,7 @@ private:
" const int& i = x[0];\n" " const int& i = x[0];\n"
" return i;\n" " return i;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'x' should be passed by const reference.\n", errout.str());
check("int f(std::vector<int> x) {\n" check("int f(std::vector<int> x) {\n"
" static int& i = x[0];\n" " static int& i = x[0];\n"