Fixed false positives about const correctness caused by incorrect handling of default arguments
This commit is contained in:
parent
f803a18d50
commit
ea601ef2b0
|
@ -1280,6 +1280,29 @@ static unsigned int countParameters(const Token *tok)
|
||||||
return numpar;
|
return numpar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int countMinArgs(const Token* argList)
|
||||||
|
{
|
||||||
|
if (!argList)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
argList = argList->next();
|
||||||
|
if (argList->str() == ")")
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned int count = 1;
|
||||||
|
for (; argList; argList = argList->next()) {
|
||||||
|
if (argList->link() && Token::Match(argList, "(|[|{|<"))
|
||||||
|
argList = argList->link();
|
||||||
|
else if (argList->str() == ",")
|
||||||
|
count++;
|
||||||
|
else if (argList->str() == "=")
|
||||||
|
return count-1;
|
||||||
|
else if (argList->str() == ")")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok)
|
bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok)
|
||||||
{
|
{
|
||||||
unsigned int args = countParameters(tok);
|
unsigned int args = countParameters(tok);
|
||||||
|
@ -1287,7 +1310,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok)
|
||||||
for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||||
/** @todo we need to look at the argument types when there are overloaded functions
|
/** @todo we need to look at the argument types when there are overloaded functions
|
||||||
* with the same number of arguments */
|
* with the same number of arguments */
|
||||||
if (func->tokenDef->str() == tok->str() && func->argCount() == args) {
|
if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1321,7 +1344,7 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok)
|
||||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||||
/** @todo we need to look at the argument types when there are overloaded functions
|
/** @todo we need to look at the argument types when there are overloaded functions
|
||||||
* with the same number of arguments */
|
* with the same number of arguments */
|
||||||
if (func->tokenDef->str() == tok->str() && func->argCount() == args) {
|
if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) {
|
||||||
matches++;
|
matches++;
|
||||||
if (func->isConst)
|
if (func->isConst)
|
||||||
consts++;
|
consts++;
|
||||||
|
|
|
@ -134,6 +134,7 @@ private:
|
||||||
TEST_CASE(const56); // ticket #3149
|
TEST_CASE(const56); // ticket #3149
|
||||||
TEST_CASE(const57); // ticket #2669
|
TEST_CASE(const57); // ticket #2669
|
||||||
TEST_CASE(const58); // ticket #2698
|
TEST_CASE(const58); // ticket #2698
|
||||||
|
TEST_CASE(const_handleDefaultParameters);
|
||||||
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
||||||
TEST_CASE(assigningArrayElementIsNotAConstOperation);
|
TEST_CASE(assigningArrayElementIsNotAConstOperation);
|
||||||
TEST_CASE(constoperator1); // operator< can often be const
|
TEST_CASE(constoperator1); // operator< can often be const
|
||||||
|
@ -4318,6 +4319,40 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void const_handleDefaultParameters() {
|
||||||
|
checkConst("struct Foo {\n"
|
||||||
|
" void foo1(int i, int j = 0) {\n"
|
||||||
|
" return func(this);\n"
|
||||||
|
" }\n"
|
||||||
|
" int bar1() {\n"
|
||||||
|
" return foo1(1);\n"
|
||||||
|
" }\n"
|
||||||
|
" int bar2() {\n"
|
||||||
|
" return foo1(1, 2);\n"
|
||||||
|
" }\n"
|
||||||
|
" int bar3() {\n"
|
||||||
|
" return foo1(1, 2, 3);\n"
|
||||||
|
" }\n"
|
||||||
|
" int bar4() {\n"
|
||||||
|
" return foo1();\n"
|
||||||
|
" }\n"
|
||||||
|
" void foo2(int i = 0) {\n"
|
||||||
|
" return func(this);\n"
|
||||||
|
" }\n"
|
||||||
|
" int bar5() {\n"
|
||||||
|
" return foo2();\n"
|
||||||
|
" }\n"
|
||||||
|
" void foo3() {\n"
|
||||||
|
" return func(this);\n"
|
||||||
|
" }\n"
|
||||||
|
" int bar6() {\n"
|
||||||
|
" return foo3();\n"
|
||||||
|
" }\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("[test.cpp:11]: (style, inconclusive) Technically the member function 'Foo::bar3' can be const.\n"
|
||||||
|
"[test.cpp:14]: (style, inconclusive) Technically the member function 'Foo::bar4' can be const.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void assigningPointerToPointerIsNotAConstOperation() {
|
void assigningPointerToPointerIsNotAConstOperation() {
|
||||||
checkConst("struct s\n"
|
checkConst("struct s\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
Loading…
Reference in New Issue