Skip to content
Open
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
18 changes: 13 additions & 5 deletions lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2030,8 +2030,11 @@ void CheckOtherImpl::checkConstPointer()
nonConstPointers.emplace(var);
}
for (const Variable *p: pointers) {
bool foundAllBaseClasses = true;
if (p->isArgument()) {
if (!p->scope() || !p->scope()->function || p->scope()->function->isImplicitlyVirtual(true) || p->scope()->function->hasVirtualSpecifier())
if (!p->scope() || !p->scope()->function || p->scope()->function->hasVirtualSpecifier())
continue;
if (p->scope()->function->isImplicitlyVirtual(true, &foundAllBaseClasses) && foundAllBaseClasses)
continue;
if (p->isMaybeUnused())
continue;
Expand All @@ -2048,12 +2051,12 @@ void CheckOtherImpl::checkConstPointer()
continue;
if (p->typeStartToken() && p->typeStartToken()->isSimplifiedTypedef() && !(Token::simpleMatch(p->typeEndToken(), "*") && !p->typeEndToken()->isSimplifiedTypedef()))
continue;
constVariableError(p, p->isArgument() ? p->scope()->function : nullptr);
constVariableError(p, p->isArgument() ? p->scope()->function : nullptr, foundAllBaseClasses);
}
}
}

void CheckOtherImpl::constVariableError(const Variable *var, const Function *function)
void CheckOtherImpl::constVariableError(const Variable *var, const Function *function, bool foundAllBaseClasses)
{
if (!var) {
reportError(nullptr, Severity::style, "constParameter", "Parameter 'x' can be declared with const");
Expand All @@ -2066,13 +2069,18 @@ void CheckOtherImpl::constVariableError(const Variable *var, const Function *fun
return;
}

const std::string vartype(var->isArgument() ? "Parameter" : "Variable");
std::string vartype(var->isArgument() ? "Parameter" : "Variable");
const std::string& varname(var->name());
const std::string ptrRefArray = var->isArray() ? "const array" : (var->isPointer() ? "pointer to const" : "reference to const");

ErrorPath errorPath;
std::string id = "const" + vartype;
std::string message = "$symbol:" + varname + "\n" + vartype + " '$symbol' can be declared as " + ptrRefArray;
std::string message = "$symbol:" + varname + "\n";
if (!foundAllBaseClasses) {
message += "Either there is a missing override/final keyword, or the ";
vartype[0] = std::tolower(vartype[0]);
}
message += vartype + " '$symbol' can be declared as " + ptrRefArray;
errorPath.emplace_back(var->nameToken(), message);
if (var->isArgument() && function && function->functionPointerUsage) {
errorPath.emplace_front(function->functionPointerUsage, "You might need to cast the function pointer here");
Expand Down
2 changes: 1 addition & 1 deletion lib/checkother.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class CPPCHECKLIB CheckOtherImpl : public CheckImpl {
void suspiciousFloatingPointCastError(const Token *tok);
void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive, bool toIsInt);
void passedByValueError(const Variable* var, bool inconclusive, bool isRangeBasedFor = false);
void constVariableError(const Variable *var, const Function *function);
void constVariableError(const Variable *var, const Function *function, bool foundAllBaseClasses = true);
void constStatementError(const Token *tok, const std::string &type, bool inconclusive);
void signedCharArrayIndexError(const Token *tok);
void unknownSignCharArrayIndexError(const Token *tok);
Expand Down
12 changes: 12 additions & 0 deletions test/testother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4894,6 +4894,18 @@ class TestOther : public TestFixture {
"}\n");
ASSERT_EQUALS("[test.cpp:6:10]: (style) Parameter 's' can be declared as reference to const [constParameterReference]\n",
errout_str());

check("struct S : U {\n" // #13944
" void f(int* p) const {\n"
" if (m == p) {}\n"
" }\n"
" void g(int* p) final {\n"
" if (m == p) {}\n"
" }\n"
" int* m;\n"
"};\n");
ASSERT_EQUALS("[test.cpp:2:13]: (style) Either there is a missing override/final keyword, or the parameter 'p' can be declared as pointer to const [constParameterPointer]\n",
errout_str());
}

void constArray() {
Expand Down