From 410c0f98d9385f9b7843ebb87d09023f53c168a0 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Sat, 8 Dec 2012 02:46:30 -0800 Subject: [PATCH] Refactorized CheckObsoleteFunctions: - Speedup checkobsoletefunctions by using symboldatabase and by not calling SymbolDatabase::findFunctionByToken() for each function call. -> Benchmark (SQlite amalgamation): CheckObsoleteFunctions::runSimplifiedChecks(): 9s -> 0,016s (562%, 4% on entire runtime) - Fixed false negative when passing function result as parameter --- lib/checkobsoletefunctions.cpp | 62 ++++++++++++++++------------------ test/testobsoletefunctions.cpp | 6 ++++ 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/lib/checkobsoletefunctions.cpp b/lib/checkobsoletefunctions.cpp index 9247d16a8..1647167bb 100644 --- a/lib/checkobsoletefunctions.cpp +++ b/lib/checkobsoletefunctions.cpp @@ -38,42 +38,38 @@ void CheckObsoleteFunctions::obsoleteFunctions() const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); - for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { + // Functions defined somewhere? + for (unsigned int i = 0; i < symbolDatabase->functionScopes.size(); i++) { + const Scope* scope = symbolDatabase->functionScopes[i]; + _obsoleteStandardFunctions.erase(scope->className); + _obsoletePosixFunctions.erase(scope->className); + _obsoleteC99Functions.erase(scope->className); + } - if (tok->isName() && tok->varId()==0 && (tok->next() && tok->next()->str() == "(") && - (!Token::Match(tok->previous(), ".|::|:|,") || Token::simpleMatch(tok->tokAt(-2), "std :: gets"))) { - // c function declaration? - if ((tok->next()->link()->next() && tok->next()->link()->next()->str() == ";") && (tok->previous() && (tok->previous()->str() == "*" || tok->previous()->isName()))) { - continue; - } + for (unsigned int i = 0; i < symbolDatabase->functionScopes.size(); i++) { + const Scope* scope = symbolDatabase->functionScopes[i]; + for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { + if (tok->isName() && tok->varId()==0 && (tok->next() && tok->next()->str() == "(") && + (!Token::Match(tok->previous(), ".|::") || Token::simpleMatch(tok->tokAt(-2), "std ::"))) { - // function declaration? - const Function * function = symbolDatabase->findFunctionByToken(tok); - if (function && function->hasBody) { - _obsoleteStandardFunctions.erase(tok->str()); - _obsoletePosixFunctions.erase(tok->str()); - continue; - } - - std::map::const_iterator it = _obsoleteStandardFunctions.find(tok->str()); - if (it != _obsoleteStandardFunctions.end()) { - // If checking an old code base it might be uninteresting to update obsolete functions. - // Therefore this is "information" - reportError(tok->next(), Severity::style, "obsoleteFunctions"+it->first, it->second); - } else { - if (_settings->standards.posix) { - it = _obsoletePosixFunctions.find(tok->str()); - if (it != _obsoletePosixFunctions.end()) { - // If checking an old code base it might be uninteresting to update obsolete functions. - // Therefore this is "information" - reportError(tok->next(), Severity::style, "obsoleteFunctions"+it->first, it->second); + std::map::const_iterator it = _obsoleteStandardFunctions.find(tok->str()); + if (it != _obsoleteStandardFunctions.end()) { + // If checking an old code base it might be uninteresting to update obsolete functions. + reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second); + } else { + if (_settings->standards.posix) { + it = _obsoletePosixFunctions.find(tok->str()); + if (it != _obsoletePosixFunctions.end()) { + // If checking an old code base it might be uninteresting to update obsolete functions. + reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second); + } } - } - if (_settings->standards.c >= Standards::C99) { - // alloca : this function is obsolete in C but not in C++ (#4382) - it = _obsoleteC99Functions.find(tok->str()); - if (it != _obsoleteC99Functions.end() && !(tok->str() == "alloca" && _tokenizer->isCPP())) { - reportError(tok->next(), Severity::style, "obsoleteFunctions"+it->first, it->second); + if (_settings->standards.c >= Standards::C99) { + // alloca : this function is obsolete in C but not in C++ (#4382) + it = _obsoleteC99Functions.find(tok->str()); + if (it != _obsoleteC99Functions.end() && !(tok->str() == "alloca" && _tokenizer->isCPP())) { + reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second); + } } } } diff --git a/test/testobsoletefunctions.cpp b/test/testobsoletefunctions.cpp index 273c5655d..103d5fb64 100644 --- a/test/testobsoletefunctions.cpp +++ b/test/testobsoletefunctions.cpp @@ -214,6 +214,12 @@ private: " char *x = gets();\n" "}\n"); ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str()); + + check("void f()\n" + "{\n" + " foo(x, gets());\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str()); } void testalloca() {