Fix #11744 FN functionConst/functionStatic with recursion (#5105)

* Fix FN functionStatic

* Fix FN functionConst, add test

* Fix build
This commit is contained in:
chrchr-github 2023-06-02 23:33:42 +02:00 committed by GitHub
parent 055489df5a
commit 82e9c076da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 10 deletions

View File

@ -2108,12 +2108,12 @@ void CheckClass::checkConst()
if (!scope->definedType->derivedFrom.empty() && func.isImplicitlyVirtual(true))
continue;
bool memberAccessed = false;
enum MemberAccess memberAccessed = MemberAccess::NONE;
// if nothing non-const was found. write error..
if (!checkConstFunc(scope, &func, memberAccessed))
continue;
const bool suggestStatic = !memberAccessed && !func.isOperator();
const bool suggestStatic = memberAccessed != MemberAccess::MEMBER && !func.isOperator();
if ((returnsPtrOrRef || func.isConst()) && !suggestStatic)
continue;
@ -2293,7 +2293,7 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok)
const std::set<std::string> CheckClass::stl_containers_not_const = { "map", "unordered_map", "std :: map|unordered_map <" }; // start pattern
bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed) const
bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, MemberAccess& memberAccessed) const
{
if (mTokenizer->hasIfdef(func->functionScope->bodyStart, func->functionScope->bodyEnd))
return false;
@ -2312,9 +2312,10 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
auto checkFuncCall = [this, &memberAccessed](const Token* funcTok, const Scope* scope, const Function* func) {
if (isMemberFunc(scope, funcTok) && (funcTok->strAt(-1) != "." || Token::simpleMatch(funcTok->tokAt(-2), "this ."))) {
if (!isConstMemberFunc(scope, funcTok) && func != funcTok->function())
const bool isSelf = func == funcTok->function();
if (!isConstMemberFunc(scope, funcTok) && !isSelf)
return false;
memberAccessed = true;
memberAccessed = (isSelf && memberAccessed != MemberAccess::MEMBER) ? MemberAccess::SELF : MemberAccess::MEMBER;
}
if (const Function* f = funcTok->function()) { // check known function
@ -2361,7 +2362,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
// it can be a const function..
for (const Token *tok1 = func->functionScope->bodyStart; tok1 && tok1 != func->functionScope->bodyEnd; tok1 = tok1->next()) {
if (tok1->isName() && isMemberVar(scope, tok1)) {
memberAccessed = true;
memberAccessed = MemberAccess::MEMBER;
const Variable* v = tok1->variable();
if (v && v->isMutable())
continue;
@ -2476,7 +2477,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
;
} else if (hasOverloadedMemberAccess(end, var->typeScope())) {
;
} else if (!var->typeScope() || !isConstMemberFunc(var->typeScope(), end))
} else if (!var->typeScope() || (end->function() != func && !isConstMemberFunc(var->typeScope(), end)))
return false;
}

View File

@ -319,7 +319,8 @@ private:
bool isMemberVar(const Scope *scope, const Token *tok) const;
static bool isMemberFunc(const Scope *scope, const Token *tok);
static bool isConstMemberFunc(const Scope *scope, const Token *tok);
bool checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed) const;
enum class MemberAccess { NONE, SELF, MEMBER };
bool checkConstFunc(const Scope *scope, const Function *func, MemberAccess& memberAccessed) const;
// constructors helper function
/** @brief Information about a member variable. Used when checking for uninitialized variables */

View File

@ -6539,8 +6539,8 @@ private:
errout.str());
}
void const89() { // #11654
checkConst("struct S {\n"
void const89() {
checkConst("struct S {\n" // #11654
" void f(bool b);\n"
" int i;\n"
"};\n"
@ -6560,6 +6560,23 @@ private:
" f(i);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkConst("struct S {\n" // #11744
" S* p;\n"
" int f() {\n"
" if (p)\n"
" return 1 + p->f();\n"
" return 1;\n"
" }\n"
" int g(int i) {\n"
" if (i > 0)\n"
" return i + g(i - 1);\n"
" return 0;\n"
" }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'S::f' can be const.\n"
"[test.cpp:8]: (performance, inconclusive) Technically the member function 'S::g' can be static (but you may consider moving to unnamed namespace).\n",
errout.str());
}
void const90() { // #11637