Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ bool CppCheckExecutor::tryLoadLibrary(Library& destination, const std::string& b
/**
* Execute a shell command and read the output from it. Returns true if command terminated successfully.
*/
// cppcheck-suppress passedByValue - used as callback so we need to preserve the signature
// cppcheck-suppress passedByValueCallback - 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
int CppCheckExecutor::executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output_)
{
Expand Down
2 changes: 1 addition & 1 deletion gui/checkthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
#endif

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

Expand Down
24 changes: 16 additions & 8 deletions lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1366,7 +1366,7 @@ void CheckOther::checkPassByReference()

const bool isConst = var->isConst();
if (isConst) {
passedByValueError(var->nameToken(), var->name(), inconclusive);
passedByValueError(var, inconclusive);
continue;
}

Expand All @@ -1375,18 +1375,26 @@ void CheckOther::checkPassByReference()
continue;

if (canBeConst(var, mSettings)) {
passedByValueError(var->nameToken(), var->name(), inconclusive);
passedByValueError(var, inconclusive);
}
}
}

void CheckOther::passedByValueError(const Token *tok, const std::string &parname, bool inconclusive)
void CheckOther::passedByValueError(const Variable* var, bool inconclusive)
{
reportError(tok, Severity::performance, "passedByValue",
"$symbol:" + parname + "\n"
"Function parameter '$symbol' should be passed by const reference.\n"
"Parameter '$symbol' is passed by value. It could be passed "
"as a const reference which is usually faster and recommended in C++.", CWE398, inconclusive ? Certainty::inconclusive : Certainty::normal);
std::string id = "passedByValue";
std::string msg = "$symbol:" + (var ? var->name() : "") + "\n"
"Function parameter '$symbol' should be passed by const reference.";
ErrorPath errorPath;
if (var && var->scope() && var->scope()->function && var->scope()->function->functionPointerUsage) {
id += "Callback";
errorPath.emplace_front(var->scope()->function->functionPointerUsage, "Function pointer used here.");
msg += " However it seems that '" + var->scope()->function->name() + "' is a callback function.";
}
if (var)
errorPath.emplace_back(var->nameToken(), msg);
msg += "\nParameter '$symbol' is passed by value. It could be passed as a const reference which is usually faster and recommended in C++.";
reportError(errorPath, Severity::performance, id.c_str(), msg, CWE398, inconclusive ? Certainty::inconclusive : Certainty::normal);
}

static bool isUnusedVariable(const Variable *var)
Expand Down
4 changes: 2 additions & 2 deletions lib/checkother.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class CPPCHECKLIB CheckOther : public Check {
void clarifyStatementError(const Token* tok);
void cstyleCastError(const Token *tok);
void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive, bool toIsInt);
void passedByValueError(const Token *tok, const std::string &parname, bool inconclusive);
void passedByValueError(const Variable* var, bool inconclusive);
void constVariableError(const Variable *var, const Function *function);
void constStatementError(const Token *tok, const std::string &type, bool inconclusive);
void signedCharArrayIndexError(const Token *tok);
Expand Down Expand Up @@ -314,7 +314,7 @@ class CPPCHECKLIB CheckOther : public Check {
c.checkComparisonFunctionIsAlwaysTrueOrFalseError(nullptr, "isless","varName",false);
c.checkCastIntToCharAndBackError(nullptr, "func_name");
c.cstyleCastError(nullptr);
c.passedByValueError(nullptr, "parametername", false);
c.passedByValueError(nullptr, false);
c.constVariableError(nullptr, nullptr);
c.constStatementError(nullptr, "type", false);
c.signedCharArrayIndexError(nullptr);
Expand Down
10 changes: 10 additions & 0 deletions test/testother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9884,6 +9884,16 @@ class TestOther : public TestFixture {
check("std::map<int, int> m;\n" // #10817
"void f(const decltype(m)::const_iterator i) {}");
ASSERT_EQUALS("", errout.str());

check("int (*pf) (std::vector<int>) = nullptr;\n" // #12118
"int f(std::vector<int> v) {\n"
" return v.size();\n"
"}\n"
"void g() {\n"
" pf = f;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:2]: (performance) Function parameter 'v' should be passed by const reference. However it seems that 'f' is a callback function.\n",
errout.str());
}

void checkComparisonFunctionIsAlwaysTrueOrFalse() {
Expand Down