Skip to content

Commit 10b55cc

Browse files
Fix #11654 FN functionConst if only non-const member usage is call to itself (#5092)
* Fix #11654 FN functionConst if only non-const member usage is call to itself * Format * Add const
1 parent c039d23 commit 10b55cc

6 files changed

Lines changed: 33 additions & 9 deletions

File tree

lib/checkclass.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ bool CheckClass::isBaseClassMutableMemberFunc(const Token *tok, const Scope *sco
741741
return false;
742742
}
743743

744-
void CheckClass::initializeVarList(const Function &func, std::list<const Function *> &callstack, const Scope *scope, std::vector<Usage> &usage)
744+
void CheckClass::initializeVarList(const Function &func, std::list<const Function *> &callstack, const Scope *scope, std::vector<Usage> &usage) const
745745
{
746746
if (!func.functionScope)
747747
return;
@@ -2310,9 +2310,9 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
23102310
return nullptr;
23112311
};
23122312

2313-
auto checkFuncCall = [this, &memberAccessed](const Token* funcTok, const Scope* scope) {
2313+
auto checkFuncCall = [this, &memberAccessed](const Token* funcTok, const Scope* scope, const Function* func) {
23142314
if (isMemberFunc(scope, funcTok) && (funcTok->strAt(-1) != "." || Token::simpleMatch(funcTok->tokAt(-2), "this ."))) {
2315-
if (!isConstMemberFunc(scope, funcTok))
2315+
if (!isConstMemberFunc(scope, funcTok) && func != funcTok->function())
23162316
return false;
23172317
memberAccessed = true;
23182318
}
@@ -2490,7 +2490,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
24902490
return false;
24912491

24922492
tok1 = jumpBackToken?jumpBackToken:end; // Jump back to first [ to check inside, or jump to end of expression
2493-
if (tok1 == end && Token::Match(end->previous(), ". %name% ( !!)") && !checkFuncCall(tok1, scope)) // function call on member
2493+
if (tok1 == end && Token::Match(end->previous(), ". %name% ( !!)") && !checkFuncCall(tok1, scope, func)) // function call on member
24942494
return false;
24952495
}
24962496

@@ -2509,7 +2509,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
25092509

25102510
// function/constructor call, return init list
25112511
else if (const Token* funcTok = getFuncTok(tok1)) {
2512-
if (!checkFuncCall(funcTok, scope))
2512+
if (!checkFuncCall(funcTok, scope, func))
25132513
return false;
25142514
} else if (Token::simpleMatch(tok1, "> (") && (!tok1->link() || !Token::Match(tok1->link()->previous(), "static_cast|const_cast|dynamic_cast|reinterpret_cast"))) {
25152515
return false;

lib/checkclass.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ class CPPCHECKLIB CheckClass : public Check {
392392
* @param scope pointer to variable Scope
393393
* @param usage reference to usage vector
394394
*/
395-
void initializeVarList(const Function &func, std::list<const Function *> &callstack, const Scope *scope, std::vector<Usage> &usage);
395+
void initializeVarList(const Function &func, std::list<const Function *> &callstack, const Scope *scope, std::vector<Usage> &usage) const;
396396

397397
/**
398398
* @brief gives a list of tokens where virtual functions are called directly or indirectly

lib/checkuninitvar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
827827
return false;
828828
}
829829

830-
const Token *CheckUninitVar::checkExpr(const Token *tok, const Variable& var, const Alloc alloc, bool known, bool *bailout)
830+
const Token* CheckUninitVar::checkExpr(const Token* tok, const Variable& var, const Alloc alloc, bool known, bool* bailout) const
831831
{
832832
if (!tok)
833833
return nullptr;

lib/checkuninitvar.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class CPPCHECKLIB CheckUninitVar : public Check {
8282
void checkStruct(const Token *tok, const Variable &structvar);
8383
enum Alloc { NO_ALLOC, NO_CTOR_CALL, CTOR_CALL, ARRAY };
8484
bool checkScopeForVariable(const Token *tok, const Variable& var, bool* const possibleInit, bool* const noreturn, Alloc* const alloc, const std::string &membervar, std::map<nonneg int, VariableValue> variableValue);
85-
const Token *checkExpr(const Token *tok, const Variable& var, const Alloc alloc, bool known, bool *bailout=nullptr);
85+
const Token* checkExpr(const Token* tok, const Variable& var, const Alloc alloc, bool known, bool* bailout = nullptr) const;
8686
bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, Alloc alloc, const std::string &membervar);
8787
bool checkLoopBody(const Token *tok, const Variable& var, const Alloc alloc, const std::string &membervar, const bool suppressErrors);
8888
const Token* checkLoopBodyRecursive(const Token *start, const Variable& var, const Alloc alloc, const std::string &membervar, bool &bailout) const;

lib/tokenize.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class CPPCHECKLIB Tokenizer {
195195
* \param only_k_r_fpar Only simplify K&R function parameters
196196
*/
197197
void simplifyVarDecl(const bool only_k_r_fpar);
198-
void simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, const bool only_k_r_fpar);
198+
void simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, const bool only_k_r_fpar); // cppcheck-suppress functionConst // has side effects
199199

200200
/**
201201
* Simplify variable initialization

test/testclass.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ class TestClass : public TestFixture {
198198
TEST_CASE(const85);
199199
TEST_CASE(const86);
200200
TEST_CASE(const87);
201+
TEST_CASE(const89);
201202

202203
TEST_CASE(const_handleDefaultParameters);
203204
TEST_CASE(const_passThisToMemberOfOtherClass);
@@ -6414,6 +6415,29 @@ class TestClass : public TestFixture {
64146415
errout.str());
64156416
}
64166417

6418+
void const89() { // #11654
6419+
checkConst("struct S {\n"
6420+
" void f(bool b);\n"
6421+
" int i;\n"
6422+
"};\n"
6423+
"void S::f(bool b) {\n"
6424+
" if (i && b)\n"
6425+
" f(false);\n"
6426+
"}\n");
6427+
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (style, inconclusive) Technically the member function 'S::f' can be const.\n", errout.str());
6428+
6429+
checkConst("struct S {\n"
6430+
" void f(int& r);\n"
6431+
" int i;\n"
6432+
"};\n"
6433+
"void S::f(int& r) {\n"
6434+
" r = 0;\n"
6435+
" if (i)\n"
6436+
" f(i);\n"
6437+
"}\n");
6438+
ASSERT_EQUALS("", errout.str());
6439+
}
6440+
64176441
void const_handleDefaultParameters() {
64186442
checkConst("struct Foo {\n"
64196443
" void foo1(int i, int j = 0) {\n"

0 commit comments

Comments
 (0)