Fix #9861 FN: "static" not suggested for non-const method (#4101)

* Fix #9861 FN: "static" not suggested for non-const method

* Format

* Make functions static

* static
This commit is contained in:
chrchr-github 2022-05-11 20:01:22 +02:00 committed by GitHub
parent 63a1698335
commit e7e8b1baf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 35 deletions

View File

@ -1988,37 +1988,33 @@ void CheckClass::checkConst()
if (func.isFriend() || func.isStatic() || func.hasVirtualSpecifier()) if (func.isFriend() || func.isStatic() || func.hasVirtualSpecifier())
continue; continue;
// don't warn when returning non-const pointer/reference // don't suggest const when returning non-const pointer/reference, but still suggest static
{ auto isPointerOrReference = [this](const Token* start, const Token* end) -> bool {
auto isPointerOrReference = [this](const Token* start, const Token* end) -> bool { bool inTemplArgList = false, isConstTemplArg = false;
bool inTemplArgList = false, isConstTemplArg = false; for (const Token* tok = start; tok != end; tok = tok->next()) {
for (const Token* tok = start; tok != end; tok = tok->next()) { if (tok->str() == "{") // end of trailing return type
if (tok->str() == "{") // end of trailing return type return false;
return false; if (tok->str() == "<") {
if (tok->str() == "<") { if (!tok->link())
if (!tok->link()) mSymbolDatabase->debugMessage(tok, "debug", "CheckClass::checkConst found unlinked template argument list '" + tok->expressionString() + "'.");
mSymbolDatabase->debugMessage(tok, "debug", "CheckClass::checkConst found unlinked template argument list '" + tok->expressionString() + "'."); inTemplArgList = true;
inTemplArgList = true;
}
else if (tok->str() == ">") {
inTemplArgList = false;
isConstTemplArg = false;
}
else if (tok->str() == "const") {
if (!inTemplArgList)
return false;
isConstTemplArg = true;
}
else if (!isConstTemplArg && Token::Match(tok, "*|&"))
return true;
} }
return false; else if (tok->str() == ">") {
}; inTemplArgList = false;
isConstTemplArg = false;
if (isPointerOrReference(func.retDef, func.tokenDef)) }
continue; else if (tok->str() == "const") {
} if (!inTemplArgList)
return false;
isConstTemplArg = true;
}
else if (!isConstTemplArg && Token::Match(tok, "*|&"))
return true;
}
return false;
};
const bool returnsPtrOrRef = isPointerOrReference(func.retDef, func.tokenDef);
if (func.isOperator()) { // Operator without return type: conversion operator if (func.isOperator()) { // Operator without return type: conversion operator
const std::string& opName = func.tokenDef->str(); const std::string& opName = func.tokenDef->str();
@ -2043,7 +2039,8 @@ void CheckClass::checkConst()
if (!checkConstFunc(scope, &func, memberAccessed)) if (!checkConstFunc(scope, &func, memberAccessed))
continue; continue;
if (func.isConst() && (memberAccessed || func.isOperator())) const bool suggestStatic = !memberAccessed && !func.isOperator();
if ((returnsPtrOrRef || func.isConst()) && !suggestStatic)
continue; continue;
std::string classname = scope->className; std::string classname = scope->className;
@ -2062,9 +2059,9 @@ void CheckClass::checkConst()
functionName += "]"; functionName += "]";
if (func.isInline()) if (func.isInline())
checkConstError(func.token, classname, functionName, !memberAccessed && !func.isOperator()); checkConstError(func.token, classname, functionName, suggestStatic);
else // not inline else // not inline
checkConstError2(func.token, func.tokenDef, classname, functionName, !memberAccessed && !func.isOperator()); checkConstError2(func.token, func.tokenDef, classname, functionName, suggestStatic);
} }
} }
} }

View File

@ -65,7 +65,7 @@ struct ReverseTraversal {
return true; return true;
} }
Token* getParentFunction(Token* tok) static Token* getParentFunction(Token* tok)
{ {
if (!tok) if (!tok)
return nullptr; return nullptr;
@ -90,7 +90,7 @@ struct ReverseTraversal {
return nullptr; return nullptr;
} }
Token* getTopFunction(Token* tok) static Token* getTopFunction(Token* tok)
{ {
if (!tok) if (!tok)
return nullptr; return nullptr;

View File

@ -303,7 +303,7 @@ public:
* '; int *p(0);' => '; int *p = 0;' * '; int *p(0);' => '; int *p = 0;'
*/ */
void simplifyInitVar(); void simplifyInitVar();
Token * initVar(Token * tok); static Token* initVar(Token* tok);
/** /**
* Simplify easy constant '?:' operation * Simplify easy constant '?:' operation

View File

@ -195,6 +195,7 @@ private:
TEST_CASE(const76); // ticket #10825 TEST_CASE(const76); // ticket #10825
TEST_CASE(const77); // ticket #10307, #10311 TEST_CASE(const77); // ticket #10307, #10311
TEST_CASE(const78); // ticket #10315 TEST_CASE(const78); // ticket #10315
TEST_CASE(const79); // ticket #9861
TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_handleDefaultParameters);
TEST_CASE(const_passThisToMemberOfOtherClass); TEST_CASE(const_passThisToMemberOfOtherClass);
TEST_CASE(assigningPointerToPointerIsNotAConstOperation); TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
@ -6068,6 +6069,17 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void const79() { // #9861
checkConst("class A {\n"
"public:\n"
" char* f() {\n"
" return nullptr;\n"
" }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'A::f' can be static (but you may consider moving to unnamed namespace).\n",
errout.str());
}
void const_handleDefaultParameters() { void const_handleDefaultParameters() {
checkConst("struct Foo {\n" checkConst("struct Foo {\n"
" void foo1(int i, int j = 0) {\n" " void foo1(int i, int j = 0) {\n"