* Fix FN functionStatic * Fix FN functionConst, add test * Fix build
This commit is contained in:
parent
055489df5a
commit
82e9c076da
|
@ -2108,12 +2108,12 @@ void CheckClass::checkConst()
|
||||||
if (!scope->definedType->derivedFrom.empty() && func.isImplicitlyVirtual(true))
|
if (!scope->definedType->derivedFrom.empty() && func.isImplicitlyVirtual(true))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool memberAccessed = false;
|
enum MemberAccess memberAccessed = MemberAccess::NONE;
|
||||||
// if nothing non-const was found. write error..
|
// if nothing non-const was found. write error..
|
||||||
if (!checkConstFunc(scope, &func, memberAccessed))
|
if (!checkConstFunc(scope, &func, memberAccessed))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const bool suggestStatic = !memberAccessed && !func.isOperator();
|
const bool suggestStatic = memberAccessed != MemberAccess::MEMBER && !func.isOperator();
|
||||||
if ((returnsPtrOrRef || func.isConst()) && !suggestStatic)
|
if ((returnsPtrOrRef || func.isConst()) && !suggestStatic)
|
||||||
continue;
|
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
|
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))
|
if (mTokenizer->hasIfdef(func->functionScope->bodyStart, func->functionScope->bodyEnd))
|
||||||
return false;
|
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) {
|
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 (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;
|
return false;
|
||||||
memberAccessed = true;
|
memberAccessed = (isSelf && memberAccessed != MemberAccess::MEMBER) ? MemberAccess::SELF : MemberAccess::MEMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const Function* f = funcTok->function()) { // check known function
|
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..
|
// it can be a const function..
|
||||||
for (const Token *tok1 = func->functionScope->bodyStart; tok1 && tok1 != func->functionScope->bodyEnd; tok1 = tok1->next()) {
|
for (const Token *tok1 = func->functionScope->bodyStart; tok1 && tok1 != func->functionScope->bodyEnd; tok1 = tok1->next()) {
|
||||||
if (tok1->isName() && isMemberVar(scope, tok1)) {
|
if (tok1->isName() && isMemberVar(scope, tok1)) {
|
||||||
memberAccessed = true;
|
memberAccessed = MemberAccess::MEMBER;
|
||||||
const Variable* v = tok1->variable();
|
const Variable* v = tok1->variable();
|
||||||
if (v && v->isMutable())
|
if (v && v->isMutable())
|
||||||
continue;
|
continue;
|
||||||
|
@ -2476,7 +2477,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
|
||||||
;
|
;
|
||||||
} else if (hasOverloadedMemberAccess(end, var->typeScope())) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -319,7 +319,8 @@ private:
|
||||||
bool isMemberVar(const Scope *scope, const Token *tok) const;
|
bool isMemberVar(const Scope *scope, const Token *tok) const;
|
||||||
static bool isMemberFunc(const Scope *scope, const Token *tok);
|
static bool isMemberFunc(const Scope *scope, const Token *tok);
|
||||||
static bool isConstMemberFunc(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
|
// constructors helper function
|
||||||
/** @brief Information about a member variable. Used when checking for uninitialized variables */
|
/** @brief Information about a member variable. Used when checking for uninitialized variables */
|
||||||
|
|
|
@ -6539,8 +6539,8 @@ private:
|
||||||
errout.str());
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void const89() { // #11654
|
void const89() {
|
||||||
checkConst("struct S {\n"
|
checkConst("struct S {\n" // #11654
|
||||||
" void f(bool b);\n"
|
" void f(bool b);\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
|
@ -6560,6 +6560,23 @@ private:
|
||||||
" f(i);\n"
|
" f(i);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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
|
void const90() { // #11637
|
||||||
|
|
Loading…
Reference in New Issue