Fix #11616 false negative: functionConst (#4887)

This commit is contained in:
chrchr-github 2023-03-27 17:54:19 +02:00 committed by GitHub
parent 5791561a45
commit 7bf6b359b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 11 deletions

View File

@ -2328,7 +2328,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
tok = tok->link(); tok = tok->link();
else if ((tok->isName() && isMemberVar(scope, tok)) || (tok->isUnaryOp("&") && (tok = tok->astOperand1()) && isMemberVar(scope, tok))) { else if ((tok->isName() && isMemberVar(scope, tok)) || (tok->isUnaryOp("&") && (tok = tok->astOperand1()) && isMemberVar(scope, tok))) {
const Variable* var = tok->variable(); const Variable* var = tok->variable();
if ((!var || !var->isMutable()) && mayModifyArgs) if ((!var || (!var->isMutable() && !var->isConst())) && mayModifyArgs)
return false; // TODO: Only bailout if function takes argument as non-const reference return false; // TODO: Only bailout if function takes argument as non-const reference
} }
} }

View File

@ -141,7 +141,7 @@ void VarInfo::possibleUsageAll(const std::string &functionName)
} }
void CheckLeakAutoVar::leakError(const Token *tok, const std::string &varname, int type) void CheckLeakAutoVar::leakError(const Token *tok, const std::string &varname, int type) const
{ {
const CheckMemoryLeak checkmemleak(mTokenizer, mErrorLogger, mSettings); const CheckMemoryLeak checkmemleak(mTokenizer, mErrorLogger, mSettings);
if (Library::isresource(type)) if (Library::isresource(type))
@ -150,14 +150,14 @@ void CheckLeakAutoVar::leakError(const Token *tok, const std::string &varname, i
checkmemleak.memleakError(tok, varname); checkmemleak.memleakError(tok, varname);
} }
void CheckLeakAutoVar::mismatchError(const Token *deallocTok, const Token *allocTok, const std::string &varname) void CheckLeakAutoVar::mismatchError(const Token *deallocTok, const Token *allocTok, const std::string &varname) const
{ {
const CheckMemoryLeak c(mTokenizer, mErrorLogger, mSettings); const CheckMemoryLeak c(mTokenizer, mErrorLogger, mSettings);
const std::list<const Token *> callstack = { allocTok, deallocTok }; const std::list<const Token *> callstack = { allocTok, deallocTok };
c.mismatchAllocDealloc(callstack, varname); c.mismatchAllocDealloc(callstack, varname);
} }
void CheckLeakAutoVar::deallocUseError(const Token *tok, const std::string &varname) void CheckLeakAutoVar::deallocUseError(const Token *tok, const std::string &varname) const
{ {
const CheckMemoryLeak c(mTokenizer, mErrorLogger, mSettings); const CheckMemoryLeak c(mTokenizer, mErrorLogger, mSettings);
c.deallocuseError(tok, varname); c.deallocuseError(tok, varname);
@ -842,7 +842,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
} }
void CheckLeakAutoVar::changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocInfo> &alloctype, const Token *fTok, const Token *retTok) void CheckLeakAutoVar::changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocInfo> &alloctype, const Token *fTok, const Token *retTok) const
{ {
const Library::AllocFunc* f = mSettings->library.getReallocFuncInfo(fTok); const Library::AllocFunc* f = mSettings->library.getReallocFuncInfo(fTok);
if (f && f->arg == -1 && f->reallocArg > 0 && f->reallocArg <= numberOfArguments(fTok)) { if (f && f->arg == -1 && f->reallocArg > 0 && f->reallocArg <= numberOfArguments(fTok)) {

View File

@ -144,7 +144,7 @@ private:
void changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Token* tok, const Token* arg); void changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Token* tok, const Token* arg);
/** update allocation status if reallocation function */ /** update allocation status if reallocation function */
void changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocInfo> &alloctype, const Token *fTok, const Token *retTok); void changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocInfo> &alloctype, const Token *fTok, const Token *retTok) const;
/** return. either "return" or end of variable scope is seen */ /** return. either "return" or end of variable scope is seen */
void ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope = false); void ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope = false);
@ -152,9 +152,9 @@ private:
/** if variable is allocated then there is a leak */ /** if variable is allocated then there is a leak */
void leakIfAllocated(const Token *vartok, const VarInfo &varInfo); void leakIfAllocated(const Token *vartok, const VarInfo &varInfo);
void leakError(const Token* tok, const std::string &varname, int type); void leakError(const Token* tok, const std::string &varname, int type) const;
void mismatchError(const Token* deallocTok, const Token* allocTok, const std::string &varname); void mismatchError(const Token* deallocTok, const Token* allocTok, const std::string &varname) const;
void deallocUseError(const Token *tok, const std::string &varname); void deallocUseError(const Token *tok, const std::string &varname) const;
void deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname); void deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname);
void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type); void doubleFreeError(const Token *tok, const Token *prevFreeTok, const std::string &varname, int type);

View File

@ -1454,7 +1454,7 @@ public:
nonneg int sizeOfType(const Token *type) const; nonneg int sizeOfType(const Token *type) const;
/** Set array dimensions when valueflow analysis is completed */ /** Set array dimensions when valueflow analysis is completed */
void setArrayDimensionsUsingValueFlow(); void setArrayDimensionsUsingValueFlow(); // cppcheck-suppress functionConst // has side effects
void clangSetVariables(const std::vector<const Variable *> &variableList); void clangSetVariables(const std::vector<const Variable *> &variableList);
void createSymbolDatabaseExprIds(); void createSymbolDatabaseExprIds();

View File

@ -198,6 +198,7 @@ private:
TEST_CASE(const82); // ticket #11513 TEST_CASE(const82); // ticket #11513
TEST_CASE(const83); TEST_CASE(const83);
TEST_CASE(const84); TEST_CASE(const84);
TEST_CASE(const85);
TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_handleDefaultParameters);
TEST_CASE(const_passThisToMemberOfOtherClass); TEST_CASE(const_passThisToMemberOfOtherClass);
@ -6361,7 +6362,27 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void const84() { // #11618 void const84() {
checkConst("class S {};\n" // #11616
"struct T {\n"
" T(const S*);\n"
" T(const S&);\n"
"};\n"
"struct C {\n"
" const S s;\n"
" void f1() {\n"
" T t(&s);\n"
" }\n"
" void f2() {\n"
" T t(s);\n"
" }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:8]: (style, inconclusive) Technically the member function 'C::f1' can be const.\n"
"[test.cpp:11]: (style, inconclusive) Technically the member function 'C::f2' can be const.\n",
errout.str());
}
void const85() { // #11618
checkConst("struct S {\n" checkConst("struct S {\n"
" int a[2], b[2];\n" " int a[2], b[2];\n"
" void f() { f(a, b); }\n" " void f() { f(a, b); }\n"