fix #2567 Unused private function when implemented in different file

This commit is contained in:
Robert Reif 2011-02-11 08:00:41 -05:00
parent b3e8ef9d48
commit b8c5426bb8
2 changed files with 42 additions and 79 deletions

View File

@ -610,7 +610,9 @@ void CheckClass::privateFunctions()
if (!func->hasBody) if (!func->hasBody)
{ {
// empty private copy constructors and assignment operators are OK // empty private copy constructors and assignment operators are OK
if ((func->type == Function::eCopyConstructor || func->type == Function::eOperatorEqual) && func->access == Private) if ((func->type == Function::eCopyConstructor ||
func->type == Function::eOperatorEqual) &&
func->access == Private)
continue; continue;
whole = false; whole = false;
@ -630,98 +632,37 @@ void CheckClass::privateFunctions()
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func)
{ {
// Get private functions.. // Get private functions..
if (func->type == Function::eFunction && if (func->type == Function::eFunction && func->access == Private)
func->access == Private && func->hasBody)
FuncList.push_back(func->tokenDef); FuncList.push_back(func->tokenDef);
} }
} }
// Check that all private functions are used.. // Check that all private functions are used..
bool HasFuncImpl = false; for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func)
bool inclass = false;
int indent_level = 0;
for (const Token *ftok = _tokenizer->tokens(); ftok; ftok = ftok->next())
{ {
if (ftok->str() == "{") const Token *ftok = func->arg->link()->next();
++indent_level; while (ftok->str() != "{")
else if (ftok->str() == "}") ftok = ftok->next();
{ const Token *etok = ftok->link();
if (indent_level > 0)
--indent_level;
if (indent_level == 0)
inclass = false;
}
else if (ftok->str() == "class" && for (; ftok != etok; ftok = ftok->next())
ftok->next()->str() == classname &&
Token::Match(ftok->tokAt(2), ":|{"))
{ {
indent_level = 0; if (Token::Match(ftok, "%var% ("))
inclass = true;
}
// Check member class functions to see what functions are used..
else if ((inclass && indent_level == 1 && Token::Match(ftok, "%var% (")) ||
(ftok->str() == classname && Token::Match(ftok->next(), ":: ~| %var% (")))
{
while (ftok && ftok->str() != ")")
ftok = ftok->next();
if (!ftok)
break;
if (Token::Match(ftok, ") : %var% ("))
{ {
while (!Token::Match(ftok->next(), "[{};]")) // Remove function from FuncList
std::list<const Token *>::iterator it = FuncList.begin();
while (it != FuncList.end())
{ {
if (Token::Match(ftok, "::|,|( %var% ,|)")) if (ftok->str() == (*it)->str())
{ FuncList.erase(it++);
// Remove function from FuncList else
std::list<const Token *>::iterator it = FuncList.begin(); ++it;
while (it != FuncList.end())
{
if (ftok->next()->str() == (*it)->str())
FuncList.erase(it++);
else
++it;
}
}
ftok = ftok->next();
}
}
if (!Token::Match(ftok, ") const| {"))
continue;
if (ftok->fileIndex() == 0)
HasFuncImpl = true;
// Parse function..
int indentlevel2 = 0;
for (const Token *tok2 = ftok; tok2; tok2 = tok2->next())
{
if (tok2->str() == "{")
++indentlevel2;
else if (tok2->str() == "}")
{
--indentlevel2;
if (indentlevel2 < 1)
break;
}
else if (Token::Match(tok2, "%var% ("))
{
// Remove function from FuncList
std::list<const Token *>::iterator it = FuncList.begin();
while (it != FuncList.end())
{
if (tok2->str() == (*it)->str())
FuncList.erase(it++);
else
++it;
}
} }
} }
} }
} }
while (HasFuncImpl && !FuncList.empty()) while (!FuncList.empty())
{ {
// Final check; check if the function pointer is used somewhere.. // Final check; check if the function pointer is used somewhere..
const std::string _pattern("return|(|)|,|= " + FuncList.front()->str()); const std::string _pattern("return|(|)|,|= " + FuncList.front()->str());

View File

@ -65,6 +65,8 @@ private:
TEST_CASE(testDoesNotIdentifyMethodAsFirstFunctionArgument); // #2480 TEST_CASE(testDoesNotIdentifyMethodAsFirstFunctionArgument); // #2480
TEST_CASE(testDoesNotIdentifyMethodAsMiddleFunctionArgument); TEST_CASE(testDoesNotIdentifyMethodAsMiddleFunctionArgument);
TEST_CASE(testDoesNotIdentifyMethodAsLastFunctionArgument); TEST_CASE(testDoesNotIdentifyMethodAsLastFunctionArgument);
TEST_CASE(multiFile);
} }
@ -549,6 +551,26 @@ private:
); );
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void multiFile() // ticket #2567
{
check("#file \"test.h\"\n"
"struct Fred\n"
"{\n"
" Fred()\n"
" {\n"
" Init();\n"
" }\n"
"private:\n"
" void Init();\n"
"};\n"
"#endfile\n"
"void Fred::Init()\n"
"{\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
}; };
REGISTER_TEST(TestUnusedPrivateFunction) REGISTER_TEST(TestUnusedPrivateFunction)