Fixed #2282 (Improve check: Function can be const)

This commit is contained in:
Robert Reif 2010-12-07 19:42:30 +01:00 committed by Daniel Marjamäki
parent 3527c04cfb
commit 980a90071c
3 changed files with 92 additions and 6 deletions

View File

@ -534,7 +534,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Token **funcStart, const
return false; return false;
} }
bool SymbolDatabase::argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const bool SymbolDatabase::argsMatch(const SpaceInfo *info, const Token *first, const Token *second, const std::string &path, unsigned int depth) const
{ {
bool match = false; bool match = false;
while (first->str() == second->str()) while (first->str() == second->str())
@ -608,6 +608,14 @@ bool SymbolDatabase::argsMatch(const Token *first, const Token *second, const st
} }
} }
// nested class variable
else if (depth == 0 && Token::Match(first->next(), "%var%") &&
second->next()->str() == info->className && second->strAt(2) == "::" &&
first->next()->str() == second->strAt(3))
{
second = second->tokAt(2);
}
first = first->next(); first = first->next();
second = second->next(); second = second->next();
} }
@ -689,7 +697,7 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke
(*tok)->str() == "operator" && (*tok)->str() == "operator" &&
func->tokenDef->str() == (*tok)->strAt(1)) func->tokenDef->str() == (*tok)->strAt(1))
{ {
if (argsMatch(func->tokenDef->tokAt(2), (*tok)->tokAt(3), path, path_length)) if (argsMatch(info1, func->tokenDef->tokAt(2), (*tok)->tokAt(3), path, path_length))
{ {
func->hasBody = true; func->hasBody = true;
func->token = (*tok)->next(); func->token = (*tok)->next();
@ -700,7 +708,7 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke
(*tok)->previous()->str() == "~" && (*tok)->previous()->str() == "~" &&
func->tokenDef->str() == (*tok)->str()) func->tokenDef->str() == (*tok)->str())
{ {
if (argsMatch(func->tokenDef->next(), (*tok)->next(), path, path_length)) if (argsMatch(info1, func->tokenDef->next(), (*tok)->next(), path, path_length))
{ {
func->hasBody = true; func->hasBody = true;
func->token = *tok; func->token = *tok;
@ -709,7 +717,7 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke
} }
else if (func->tokenDef->str() == (*tok)->str() && (*tok)->previous()->str() != "~") else if (func->tokenDef->str() == (*tok)->str() && (*tok)->previous()->str() != "~")
{ {
if (argsMatch(func->tokenDef->next(), (*tok)->next(), path, path_length)) if (argsMatch(info1, func->tokenDef->next(), (*tok)->next(), path, path_length))
{ {
// normal function? // normal function?
if (!func->retFuncPtr && (*tok)->next()->link()) if (!func->retFuncPtr && (*tok)->next()->link())
@ -1866,7 +1874,7 @@ bool SymbolDatabase::isVirtualFunc(const SymbolDatabase::SpaceInfo *info, const
} }
// check for matching function parameters // check for matching function parameters
if (returnMatch && argsMatch(tok->tokAt(2), functionToken->tokAt(2), std::string(""), 0)) if (returnMatch && argsMatch(info, tok->tokAt(2), functionToken->tokAt(2), std::string(""), 0))
{ {
return true; return true;
} }

View File

@ -250,7 +250,7 @@ private:
void addNewFunction(SpaceInfo **info, const Token **tok); void addNewFunction(SpaceInfo **info, const Token **tok);
bool isFunction(const Token *tok, const Token **funcStart, const Token **argStart) const; bool isFunction(const Token *tok, const Token **funcStart, const Token **argStart) const;
bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const; bool argsMatch(const SpaceInfo *info, const Token *first, const Token *second, const std::string &path, unsigned int depth) const;
const SpaceInfo *findVarType(const SpaceInfo *start, const Token *type) const; const SpaceInfo *findVarType(const SpaceInfo *start, const Token *type) const;

View File

@ -158,6 +158,7 @@ private:
TEST_CASE(const39); TEST_CASE(const39);
TEST_CASE(const40); // ticket #2228 TEST_CASE(const40); // ticket #2228
TEST_CASE(const41); // ticket #2255 TEST_CASE(const41); // ticket #2255
TEST_CASE(const42); // ticket #2282
TEST_CASE(constoperator1); // operator< can often be const TEST_CASE(constoperator1); // operator< can often be const
TEST_CASE(constoperator2); // operator<< TEST_CASE(constoperator2); // operator<<
TEST_CASE(constoperator3); TEST_CASE(constoperator3);
@ -4703,6 +4704,83 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void const42() // ticket #2282
{
checkConst("class Fred\n"
"{\n"
"public:\n"
" struct AB { };\n"
" bool f(AB * ab);\n"
"};\n"
"bool Fred::f(Fred::AB * ab)\n"
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (style) The function 'Fred::f' can be const\n", errout.str());
checkConst("class Fred\n"
"{\n"
"public:\n"
" struct AB {\n"
" struct CD { };\n"
" };\n"
" bool f(AB::CD * cd);\n"
"};\n"
"bool Fred::f(Fred::AB::CD * cd)\n"
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:7]: (style) The function 'Fred::f' can be const\n", errout.str());
checkConst("namespace NS {\n"
" class Fred\n"
" {\n"
" public:\n"
" struct AB {\n"
" struct CD { };\n"
" };\n"
" bool f(AB::CD * cd);\n"
" };\n"
" bool Fred::f(Fred::AB::CD * cd)\n"
" {\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:8]: (style) The function 'NS::Fred::f' can be const\n", errout.str());
checkConst("namespace NS {\n"
" class Fred\n"
" {\n"
" public:\n"
" struct AB {\n"
" struct CD { };\n"
" };\n"
" bool f(AB::CD * cd);\n"
" };\n"
"}\n"
"bool NS::Fred::f(NS::Fred::AB::CD * cd)\n"
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (style) The function 'NS::Fred::f' can be const\n", errout.str());
checkConst("class Foo {\n"
" class Fred\n"
" {\n"
" public:\n"
" struct AB {\n"
" struct CD { };\n"
" };\n"
" bool f(AB::CD * cd);\n"
" };\n"
"};\n"
"bool Foo::Fred::f(Foo::Fred::AB::CD * cd)\n"
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (style) The function 'Foo::Fred::f' can be const\n", errout.str());
}
// increment/decrement => not const // increment/decrement => not const
void constincdec() void constincdec()
{ {