Fixed #2282 (Improve check: Function can be const)
This commit is contained in:
parent
3527c04cfb
commit
980a90071c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue