From cf7f74dfa74abadc2db6c711f0602328c2dd410a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Tue, 10 Sep 2024 11:31:13 +0200 Subject: [PATCH] refs #11342 - Library: avoid redundant lookups in `getarg()` (#6791) --- lib/library.cpp | 33 +++++++++++++++++++-------------- lib/library.h | 6 ++++-- test/testlibrary.cpp | 8 ++++++-- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/lib/library.cpp b/lib/library.cpp index 17ca05ee6cf..21922b0fa65 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -1249,16 +1249,14 @@ int Library::getReallocId(const Token *tok, int arg) const const Library::ArgumentChecks * Library::getarg(const Token *ftok, int argnr) const { - if (isNotLibraryFunction(ftok)) + const Function* func = nullptr; + if (isNotLibraryFunction(ftok, &func)) return nullptr; - const std::unordered_map::const_iterator it1 = mData->mFunctions.find(getFunctionName(ftok)); - if (it1 == mData->mFunctions.cend()) - return nullptr; - const std::map::const_iterator it2 = it1->second.argumentChecks.find(argnr); - if (it2 != it1->second.argumentChecks.cend()) + const std::map::const_iterator it2 = func->argumentChecks.find(argnr); + if (it2 != func->argumentChecks.cend()) return &it2->second; - const std::map::const_iterator it3 = it1->second.argumentChecks.find(-1); - if (it3 != it1->second.argumentChecks.cend()) + const std::map::const_iterator it3 = func->argumentChecks.find(-1); + if (it3 != func->argumentChecks.cend()) return &it3->second; return nullptr; } @@ -1414,7 +1412,7 @@ Library::Container::Yield Library::getContainerYield(const Token* const cond) } // returns true if ftok is not a library function -bool Library::isNotLibraryFunction(const Token *ftok) const +bool Library::isNotLibraryFunction(const Token *ftok, const Function **func) const { if (ftok->isKeyword() || ftok->isStandardType()) return true; @@ -1426,10 +1424,10 @@ bool Library::isNotLibraryFunction(const Token *ftok) const if (ftok->varId()) return true; - return !matchArguments(ftok, getFunctionName(ftok)); + return !matchArguments(ftok, getFunctionName(ftok), func); } -bool Library::matchArguments(const Token *ftok, const std::string &functionName) const +bool Library::matchArguments(const Token *ftok, const std::string &functionName, const Function **func) const { if (functionName.empty()) return false; @@ -1444,10 +1442,17 @@ bool Library::matchArguments(const Token *ftok, const std::string &functionName) if (argCheck.second.optional && (firstOptionalArg == -1 || firstOptionalArg > argCheck.first)) firstOptionalArg = argCheck.first; - if (argCheck.second.formatstr || argCheck.second.variadic) - return args <= callargs; + if (argCheck.second.formatstr || argCheck.second.variadic) { + const bool b = args <= callargs; + if (b && func) + *func = &it->second; + return b; + } } - return (firstOptionalArg < 0) ? args == callargs : (callargs >= firstOptionalArg-1 && callargs <= args); + const bool b = (firstOptionalArg < 0) ? args == callargs : (callargs >= firstOptionalArg-1 && callargs <= args); + if (b && func) + *func = &it->second; + return b; } const std::map& Library::functionwarn() const diff --git a/lib/library.h b/lib/library.h index eaa4003ea24..8e8db581c00 100644 --- a/lib/library.h +++ b/lib/library.h @@ -163,9 +163,11 @@ class CPPCHECKLIB Library { const WarnInfo* getWarnInfo(const Token* ftok) const; + struct Function; + // returns true if ftok is not a library function - bool isNotLibraryFunction(const Token *ftok) const; - bool matchArguments(const Token *ftok, const std::string &functionName) const; + bool isNotLibraryFunction(const Token *ftok, const Function **func = nullptr) const; + bool matchArguments(const Token *ftok, const std::string &functionName, const Function **func = nullptr) const; enum class UseRetValType : std::uint8_t { NONE, DEFAULT, ERROR_CODE }; UseRetValType getUseRetValType(const Token* ftok) const; diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index 6cdabd7f9b1..f7ec83ac323 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -191,7 +191,9 @@ class TestLibrary : public TestFixture { Token::createMutualLinks(tokenList.front()->next(), tokenList.back()->previous()); tokenList.createAst(); - ASSERT(!library.isNotLibraryFunction(tokenList.front())); + const Library::Function* func = nullptr; + ASSERT(!library.isNotLibraryFunction(tokenList.front(), &func)); + ASSERT(func); } { TokenList tokenList(&settings); @@ -200,7 +202,9 @@ class TestLibrary : public TestFixture { Token::createMutualLinks(tokenList.front()->next(), tokenList.back()->previous()); tokenList.createAst(); - ASSERT(!library.isNotLibraryFunction(tokenList.front())); + const Library::Function* func = nullptr; + ASSERT(!library.isNotLibraryFunction(tokenList.front(), &func)); + ASSERT(func); } { TokenList tokenList(&settings);