Refactorization: Use SymbolDatabase to find functions in CheckUnusedFunctions

This commit is contained in:
PKEuS 2014-03-26 08:54:56 +01:00
parent d22da5e683
commit 02f38772cc
2 changed files with 23 additions and 49 deletions

View File

@ -21,6 +21,7 @@
#include "checkunusedfunctions.h" #include "checkunusedfunctions.h"
#include "tokenize.h" #include "tokenize.h"
#include "token.h" #include "token.h"
#include "symboldatabase.h"
#include <cctype> #include <cctype>
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -33,63 +34,36 @@
void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const char FileName[], const Settings *settings) void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const char FileName[], const Settings *settings)
{ {
const SymbolDatabase* symbolDatabase = tokenizer.getSymbolDatabase();
// Function declarations.. // Function declarations..
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { for (std::size_t i = 0; i < symbolDatabase->functionScopes.size(); i++) {
if (tok->fileIndex() != 0) const Scope* scope = symbolDatabase->functionScopes[i];
continue; const Function* func = scope->function;
if (!func || !func->token || scope->classStart->fileIndex() != 0)
// token contains a ':' => skip to next ; or {
if (tok->str().find(":") != std::string::npos) {
while (tok && tok->str().find_first_of(";{"))
tok = tok->next();
if (tok)
continue;
break;
}
// If this is a template function, skip it
if (tok->previous() && tok->previous()->str() == ">")
continue;
const Token *funcname = nullptr;
if (Token::Match(tok, "%type% %var% ("))
funcname = tok->next();
else if (Token::Match(tok, "%type% *|& %var% ("))
funcname = tok->tokAt(2);
else if (Token::Match(tok, "%type% :: %var% (") && !Token::Match(tok, tok->strAt(2).c_str()))
funcname = tok->tokAt(2);
// Don't assume throw as a function name: void foo() throw () {}
if (Token::Match(tok->previous(), ")|const") || funcname == 0)
continue; continue;
// Don't warn about functions that are marked by __attribute__((constructor)) or __attribute__((destructor)) // Don't warn about functions that are marked by __attribute__((constructor)) or __attribute__((destructor))
if (funcname->isAttributeConstructor() || funcname->isAttributeDestructor()) if (func->isAttributeConstructor() || func->isAttributeDestructor() || func->type != Function::eFunction)
continue; continue;
tok = funcname->linkAt(1); // Don't care about templates
if (func->retDef->str() == "template")
continue;
// Check that ") {" is found.. FunctionUsage &usage = _functions[func->name()];
if (! Token::Match(tok, ") const| {") &&
! Token::Match(tok, ") const| throw ( ) {"))
funcname = 0;
if (funcname) { if (!usage.lineNumber)
FunctionUsage &func = _functions[ funcname->str()]; usage.lineNumber = func->token->linenr();
if (!func.lineNumber) // No filename set yet..
func.lineNumber = funcname->linenr(); if (usage.filename.empty()) {
usage.filename = tokenizer.getSourceFilePath();
// No filename set yet.. }
if (func.filename.empty()) { // Multiple files => filename = "+"
func.filename = tokenizer.getSourceFilePath(); else if (usage.filename != tokenizer.getSourceFilePath()) {
} //func.filename = "+";
// Multiple files => filename = "+" usage.usedOtherFile |= usage.usedSameFile;
else if (func.filename != tokenizer.getSourceFilePath()) {
//func.filename = "+";
func.usedOtherFile |= func.usedSameFile;
}
} }
} }

View File

@ -181,7 +181,7 @@ private:
" template<typename T> void foo( T t ) const;\n" " template<typename T> void foo( T t ) const;\n"
"};\n" "};\n"
"template<typename T> void X::foo( T t ) const { }\n"); "template<typename T> void X::foo( T t ) const { }\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) The function 'bar' is never used.\n", errout.str());
} }
void throwIsNotAFunction() { void throwIsNotAFunction() {