diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 9506c5bba30..3b6d12ab0c4 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2209,7 +2209,7 @@ static bool hasNoreturnFunction(const Token* tok, const Library& library, const } else if (Token::Match(ftok, "exit|abort")) { return true; } - if (unknownFunc && !function && library.functions().count(library.getFunctionName(ftok)) == 0) + if (unknownFunc && !function && library.functions().count(ftok->funcname(library)) == 0) *unknownFunc = ftok; return false; } diff --git a/lib/checkassert.cpp b/lib/checkassert.cpp index 3ab55967ede..57bb291ab18 100644 --- a/lib/checkassert.cpp +++ b/lib/checkassert.cpp @@ -78,7 +78,7 @@ void CheckAssert::assertWithSideEffects() f->containerYield == Library::Container::Yield::END_ITERATOR || f->containerYield == Library::Container::Yield::ITERATOR) continue; - sideEffectInAssertError(tmp, mSettings->library.getFunctionName(tmp)); + sideEffectInAssertError(tmp, tmp->funcname(mSettings->library)); } continue; } diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 26ff9736f43..473211994b3 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -655,7 +655,7 @@ void CheckFunctions::checkLibraryMatchFunctions() if (!mSettings->library.isNotLibraryFunction(tok)) continue; - const std::string &functionName = mSettings->library.getFunctionName(tok); + const std::string &functionName = tok->funcname(mSettings->library); if (functionName.empty()) continue; diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 0f30c82147d..f93b0c8f14d 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -142,7 +142,7 @@ void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::paircheckLibrary && functionUsage.second == VarInfo::USED && (!functionUsage.first || !functionUsage.first->function() || !functionUsage.first->function()->hasBody())) { - std::string funcStr = functionUsage.first ? mSettings->library.getFunctionName(functionUsage.first) : "f"; + std::string funcStr = functionUsage.first ? functionUsage.first->funcname(mSettings->library) : "f"; if (funcStr.empty()) funcStr = "unknown::" + functionUsage.first->str(); reportError(tok, @@ -748,7 +748,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, if (ftok->function() && !ftok->function()->isAttributeNoreturn() && !(ftok->function()->functionScope && mTokenizer->isScopeNoReturn(ftok->function()->functionScope->bodyEnd))) // check function scope continue; - const std::string functionName(mSettings->library.getFunctionName(ftok)); + const std::string& functionName(ftok->funcname(mSettings->library)); if (!mSettings->library.isLeakIgnore(functionName) && !mSettings->library.isUse(functionName)) { const VarInfo::Usage usage = Token::simpleMatch(openingPar, "( )") ? VarInfo::NORET : VarInfo::USED; // TODO: check parameters passed to function varInfo.possibleUsageAll({ ftok, usage }); @@ -989,7 +989,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af) { // Ignore function call? - const bool isLeakIgnore = mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)); + const bool isLeakIgnore = mSettings->library.isLeakIgnore(tokName->funcname(mSettings->library)); if (mSettings->library.getReallocFuncInfo(tokName)) return; if (tokName->next()->valueType() && tokName->next()->valueType()->container && tokName->next()->valueType()->container->stdStringLike) diff --git a/lib/library.cpp b/lib/library.cpp index e8b6c40ef9c..3e5ee0c6f74 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -1183,7 +1183,7 @@ bool Library::isnullargbad(const Token *ftok, int argnr) const const ArgumentChecks *arg = getarg(ftok, argnr); if (!arg) { // scan format string argument should not be null - const std::string funcname = getFunctionName(ftok); + const std::string& funcname = ftok->funcname(*this); const auto it = utils::as_const(mData->mFunctions).find(funcname); if (it != mData->mFunctions.cend() && it->second.formatstr && it->second.formatstr_scan) return true; @@ -1196,7 +1196,7 @@ bool Library::isuninitargbad(const Token *ftok, int argnr, int indirect, bool *h const ArgumentChecks *arg = getarg(ftok, argnr); if (!arg) { // non-scan format string argument should not be uninitialized - const std::string funcname = getFunctionName(ftok); + const std::string& funcname = ftok->funcname(*this); const auto it = utils::as_const(mData->mFunctions).find(funcname); if (it != mData->mFunctions.cend() && it->second.formatstr && !it->second.formatstr_scan) return true; @@ -1214,7 +1214,7 @@ const Library::AllocFunc* Library::getAllocFuncInfo(const Token *tok) const tok = tok->astOperand2() ? tok->astOperand2() : tok->astOperand1(); if (!tok) return nullptr; - const std::string funcname = getFunctionName(tok); + const std::string& funcname = tok->funcname(*this); return isNotLibraryFunction(tok) && mData->mFunctions.find(funcname) != mData->mFunctions.end() ? nullptr : getAllocDealloc(mData->mAlloc, funcname); } @@ -1225,7 +1225,7 @@ const Library::AllocFunc* Library::getDeallocFuncInfo(const Token *tok) const tok = tok->astOperand2() ? tok->astOperand2() : tok->astOperand1(); if (!tok) return nullptr; - const std::string funcname = getFunctionName(tok); + const std::string& funcname = tok->funcname(*this); return isNotLibraryFunction(tok) && mData->mFunctions.find(funcname) != mData->mFunctions.end() ? nullptr : getAllocDealloc(mData->mDealloc, funcname); } @@ -1236,7 +1236,7 @@ const Library::AllocFunc* Library::getReallocFuncInfo(const Token *tok) const tok = tok->astOperand2() ? tok->astOperand2() : tok->astOperand1(); if (!tok) return nullptr; - const std::string funcname = getFunctionName(tok); + const std::string& funcname = tok->funcname(*this); return isNotLibraryFunction(tok) && mData->mFunctions.find(funcname) != mData->mFunctions.end() ? nullptr : getAllocDealloc(mData->mRealloc, funcname); } @@ -1443,7 +1443,7 @@ bool Library::isNotLibraryFunction(const Token *ftok, const Function **func) con if (ftok->varId()) return true; - return !matchArguments(ftok, getFunctionName(ftok), func); + return !matchArguments(ftok, ftok->funcname(*this), func); } bool Library::matchArguments(const Token *ftok, const std::string &functionName, const Function **func) const @@ -1483,7 +1483,7 @@ const Library::WarnInfo* Library::getWarnInfo(const Token* ftok) const { if (isNotLibraryFunction(ftok)) return nullptr; - const auto i = utils::as_const(mData->mFunctionwarn).find(getFunctionName(ftok)); + const auto i = utils::as_const(mData->mFunctionwarn).find(ftok->funcname(*this)); if (i == mData->mFunctionwarn.cend()) return nullptr; return &i->second; @@ -1539,7 +1539,7 @@ bool Library::formatstr_function(const Token* ftok) const if (isNotLibraryFunction(ftok)) return false; - const auto it = utils::as_const(mData->mFunctions).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mFunctions).find(ftok->funcname(*this)); if (it != mData->mFunctions.cend()) return it->second.formatstr; return false; @@ -1547,7 +1547,7 @@ bool Library::formatstr_function(const Token* ftok) const int Library::formatstr_argno(const Token* ftok) const { - const std::map& argumentChecksFunc = mData->mFunctions.at(getFunctionName(ftok)).argumentChecks; + const std::map& argumentChecksFunc = mData->mFunctions.at(ftok->funcname(*this)).argumentChecks; auto it = std::find_if(argumentChecksFunc.cbegin(), argumentChecksFunc.cend(), [](const std::pair& a) { return a.second.formatstr; }); @@ -1556,19 +1556,19 @@ int Library::formatstr_argno(const Token* ftok) const bool Library::formatstr_scan(const Token* ftok) const { - return mData->mFunctions.at(getFunctionName(ftok)).formatstr_scan; + return mData->mFunctions.at(ftok->funcname(*this)).formatstr_scan; } bool Library::formatstr_secure(const Token* ftok) const { - return mData->mFunctions.at(getFunctionName(ftok)).formatstr_secure; + return mData->mFunctions.at(ftok->funcname(*this)).formatstr_secure; } const Library::NonOverlappingData* Library::getNonOverlappingData(const Token *ftok) const { if (isNotLibraryFunction(ftok)) return nullptr; - const auto it = utils::as_const(mData->mNonOverlappingData).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mNonOverlappingData).find(ftok->funcname(*this)); return (it != mData->mNonOverlappingData.cend()) ? &it->second : nullptr; } @@ -1586,7 +1586,7 @@ Library::UseRetValType Library::getUseRetValType(const Token *ftok) const } return Library::UseRetValType::NONE; } - const auto it = utils::as_const(mData->mFunctions).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mFunctions).find(ftok->funcname(*this)); if (it != mData->mFunctions.cend()) return it->second.useretval; return Library::UseRetValType::NONE; @@ -1596,7 +1596,7 @@ const std::string& Library::returnValue(const Token *ftok) const { if (isNotLibraryFunction(ftok)) return mEmptyString; - const auto it = utils::as_const(mData->mReturnValue).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mReturnValue).find(ftok->funcname(*this)); return it != mData->mReturnValue.cend() ? it->second : mEmptyString; } @@ -1614,7 +1614,7 @@ const std::string& Library::returnValueType(const Token *ftok) const } return mEmptyString; } - const auto it = utils::as_const(mData->mReturnValueType).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mReturnValueType).find(ftok->funcname(*this)); return it != mData->mReturnValueType.cend() ? it->second : mEmptyString; } @@ -1622,7 +1622,7 @@ int Library::returnValueContainer(const Token *ftok) const { if (isNotLibraryFunction(ftok)) return -1; - const auto it = utils::as_const(mData->mReturnValueContainer).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mReturnValueContainer).find(ftok->funcname(*this)); return it != mData->mReturnValueContainer.cend() ? it->second : -1; } @@ -1630,7 +1630,7 @@ std::vector Library::unknownReturnValues(const Token *ftok) con { if (isNotLibraryFunction(ftok)) return std::vector(); - const auto it = utils::as_const(mData->mUnknownReturnValues).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mUnknownReturnValues).find(ftok->funcname(*this)); return (it == mData->mUnknownReturnValues.cend()) ? std::vector() : it->second; } @@ -1638,7 +1638,7 @@ const Library::Function *Library::getFunction(const Token *ftok) const { if (isNotLibraryFunction(ftok)) return nullptr; - const auto it1 = utils::as_const(mData->mFunctions).find(getFunctionName(ftok)); + const auto it1 = utils::as_const(mData->mFunctions).find(ftok->funcname(*this)); if (it1 == mData->mFunctions.cend()) return nullptr; return &it1->second; @@ -1649,7 +1649,7 @@ bool Library::hasminsize(const Token *ftok) const { if (isNotLibraryFunction(ftok)) return false; - const auto it = utils::as_const(mData->mFunctions).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mFunctions).find(ftok->funcname(*this)); if (it == mData->mFunctions.cend()) return false; return std::any_of(it->second.argumentChecks.cbegin(), it->second.argumentChecks.cend(), [](const std::pair& a) { @@ -1721,7 +1721,7 @@ bool Library::isFunctionConst(const Token *ftok) const } return false; } - const auto it = utils::as_const(mData->mFunctions).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mFunctions).find(ftok->funcname(*this)); return (it != mData->mFunctions.cend() && it->second.isconst); } @@ -1740,7 +1740,7 @@ bool Library::isnoreturn(const Token *ftok) const } return false; } - const auto it = utils::as_const(mData->mNoReturn).find(getFunctionName(ftok)); + const auto it = utils::as_const(mData->mNoReturn).find(ftok->funcname(*this)); if (it == mData->mNoReturn.end()) return false; if (it->second == LibraryData::FalseTrueMaybe::Maybe) @@ -1753,8 +1753,8 @@ bool Library::isnotnoreturn(const Token *ftok) const if (ftok->function() && ftok->function()->isAttributeNoreturn()) return false; if (isNotLibraryFunction(ftok)) - return hasAnyTypeCheck(getFunctionName(ftok)); - const auto it = utils::as_const(mData->mNoReturn).find(getFunctionName(ftok)); + return hasAnyTypeCheck(ftok->funcname(*this)); + const auto it = utils::as_const(mData->mNoReturn).find(ftok->funcname(*this)); if (it == mData->mNoReturn.end()) return false; if (it->second == LibraryData::FalseTrueMaybe::Maybe) diff --git a/lib/token.cpp b/lib/token.cpp index 246fa16d8b7..10342682bb5 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2634,6 +2634,7 @@ const ValueFlow::Value* Token::getContainerSizeValue(const MathLib::bigint val) TokenImpl::~TokenImpl() { delete mMacroName; + delete mFuncName; delete mOriginalName; delete mValueType; delete mValues; @@ -2721,3 +2722,12 @@ Token* findLambdaEndScope(Token* tok) const Token* findLambdaEndScope(const Token* tok) { return findLambdaEndScope(const_cast(tok)); } + +const std::string& Token::funcname(const Library& library) const { + if (!mImpl->mFuncName) + mImpl->mFuncName = new std::string(library.getFunctionName(this)); + const std::string fname = library.getFunctionName(this); + std::cout << this << " astParent: " << astParent() << " previous: " << previous() << " " << stringify(stringifyOptions::forDebug()) << " " << fname << std::endl; + assert(*mImpl->mFuncName == fname); + return *mImpl->mFuncName; +} diff --git a/lib/token.h b/lib/token.h index 59774747f70..0c502cfd938 100644 --- a/lib/token.h +++ b/lib/token.h @@ -53,6 +53,7 @@ class ConstTokenRange; class Token; struct TokensFrontBack; class TokenList; +class Library; struct ScopeInfo2 { ScopeInfo2(std::string name_, const Token *bodyEnd_, std::set usingNamespaces_ = std::set()) : name(std::move(name_)), bodyEnd(bodyEnd_), usingNamespaces(std::move(usingNamespaces_)) {} @@ -104,6 +105,8 @@ struct TokenImpl { // If this token came from a macro replacement list, this is the name of that macro std::string* mMacroName{}; + std::string* mFuncName{}; + // ValueType ValueType* mValueType{}; @@ -1589,6 +1592,8 @@ class CPPCHECKLIB Token { { return mIsC; } + + const std::string& funcname(const Library& library) const; }; Token* findTypeEnd(Token* tok);