diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 8dfd03596d3..6365e108589 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2338,14 +2338,14 @@ bool isWithinScope(const Token* tok, const Variable* var, ScopeType type) return false; } -bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int varid, const Settings &settings, bool *inconclusive) +bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int varid, const Library &library, bool *inconclusive) { if (!tok) return false; if (tok->varId() == varid) - return isVariableChangedByFunctionCall(tok, indirect, settings, inconclusive); - return isVariableChangedByFunctionCall(tok->astOperand1(), indirect, varid, settings, inconclusive) || - isVariableChangedByFunctionCall(tok->astOperand2(), indirect, varid, settings, inconclusive); + return isVariableChangedByFunctionCall(tok, indirect, library, inconclusive); + return isVariableChangedByFunctionCall(tok->astOperand1(), indirect, varid, library, inconclusive) || + isVariableChangedByFunctionCall(tok->astOperand2(), indirect, varid, library, inconclusive); } bool isScopeBracket(const Token* tok) @@ -2526,7 +2526,7 @@ bool isMutableExpression(const Token* tok) return true; } -bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Settings &settings, bool *inconclusive) +bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Library &library, bool *inconclusive) { if (!tok) return false; @@ -2566,13 +2566,13 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti if (!tok->function() && !tok->variable() && tok->isName()) { // Check if direction (in, out, inout) is specified in the library configuration and use that - const Library::ArgumentChecks::Direction argDirection = settings.library.getArgDirection(tok, 1 + argnr, indirect); + const Library::ArgumentChecks::Direction argDirection = library.getArgDirection(tok, 1 + argnr, indirect); if (argDirection == Library::ArgumentChecks::Direction::DIR_IN) return false; if (argDirection == Library::ArgumentChecks::Direction::DIR_OUT || argDirection == Library::ArgumentChecks::Direction::DIR_INOUT) return true; - const bool requireNonNull = settings.library.isnullargbad(tok, 1 + argnr); + const bool requireNonNull = library.isnullargbad(tok, 1 + argnr); if (Token::simpleMatch(tok->tokAt(-2), "std :: tie")) return true; // if the library says 0 is invalid @@ -2798,7 +2798,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings &settings, if (indirect == 0 && astIsLHS(tok2) && Token::Match(ptok, ". %var%") && astIsPointer(ptok->next())) pindirect = 1; bool inconclusive = false; - bool isChanged = isVariableChangedByFunctionCall(ptok, pindirect, settings, &inconclusive); + bool isChanged = isVariableChangedByFunctionCall(ptok, pindirect, settings.library, &inconclusive); isChanged |= inconclusive; if (isChanged) return true; @@ -3423,7 +3423,7 @@ bool isConstVarExpression(const Token *tok, const std::functionastParent() && tok->astParent()->isUnaryOp("&"); @@ -3485,14 +3485,14 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings } else if (ftok->str() == "{") { return indirect == 0 ? ExprUsage::Used : ExprUsage::Inconclusive; } else { - const bool isnullbad = settings.library.isnullargbad(ftok, argnr + 1); + const bool isnullbad = library.isnullargbad(ftok, argnr + 1); if (indirect == 0 && astIsPointer(tok) && !addressOf && isnullbad) return ExprUsage::Used; bool hasIndirect = false; - const bool isuninitbad = settings.library.isuninitargbad(ftok, argnr + 1, indirect, &hasIndirect); + const bool isuninitbad = library.isuninitargbad(ftok, argnr + 1, indirect, &hasIndirect); if (isuninitbad && (!addressOf || isnullbad)) return ExprUsage::Used; - const Library::ArgumentChecks::Direction argDirection = settings.library.getArgDirection(ftok, argnr + 1, indirect); + const Library::ArgumentChecks::Direction argDirection = library.getArgDirection(ftok, argnr + 1, indirect); if (argDirection == Library::ArgumentChecks::Direction::DIR_IN) // TODO: DIR_INOUT? return ExprUsage::Used; if (argDirection == Library::ArgumentChecks::Direction::DIR_OUT) @@ -3562,7 +3562,7 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings& settings) (astIsLHS(tok) || Token::simpleMatch(parent, "( )"))) return ExprUsage::Used; } - return getFunctionUsage(tok, indirect, settings); + return getFunctionUsage(tok, indirect, settings.library); } static void getLHSVariablesRecursive(std::vector& vars, const Token* tok) diff --git a/lib/astutils.h b/lib/astutils.h index 617e01f0415..2c6650068b5 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -327,20 +327,20 @@ bool isMutableExpression(const Token* tok); * * @param tok ast tree * @param varid Variable Id - * @param settings program settings + * @param library library configurations * @param inconclusive pointer to output variable which indicates that the answer of the question is inconclusive */ -bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int varid, const Settings &settings, bool *inconclusive); +bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int varid, const Library &library, bool *inconclusive); /** Is variable changed by function call? * In case the answer of the question is inconclusive, e.g. because the function declaration is not known * the return value is false and the output parameter inconclusive is set to true * - * @param tok token of variable in function call - * @param settings program settings + * @param tok token of variable in function call + * @param library library configurations * @param inconclusive pointer to output variable which indicates that the answer of the question is inconclusive */ -CPPCHECKLIB bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Settings &settings, bool *inconclusive); +CPPCHECKLIB bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Library &library, bool *inconclusive); /** Is variable changed in block of code? */ CPPCHECKLIB bool isVariableChanged(const Token *start, const Token *end, nonneg int exprid, bool globalvar, const Settings &settings, int depth = 20); diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index b848928ebf4..de70772a279 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -139,14 +139,14 @@ static bool isAutoVarArray(const Token *tok) return false; } -static bool isLocalContainerBuffer(const Token* tok, const Settings& settings) +static bool isLocalContainerBuffer(const Token* tok, const Library& library) { if (!tok) return false; // x+y if (tok->str() == "+") - return isLocalContainerBuffer(tok->astOperand1(), settings) || isLocalContainerBuffer(tok->astOperand2(), settings); + return isLocalContainerBuffer(tok->astOperand1(), library) || isLocalContainerBuffer(tok->astOperand2(), library); if (tok->str() != "(" || !Token::simpleMatch(tok->astOperand1(), ".")) return false; @@ -157,7 +157,7 @@ static bool isLocalContainerBuffer(const Token* tok, const Settings& settings) if (!var || !var->isLocal() || var->isStatic()) return false; - const Library::Container::Yield yield = astContainerYield(tok, settings.library); + const Library::Container::Yield yield = astContainerYield(tok, library); return yield == Library::Container::Yield::BUFFER || yield == Library::Container::Yield::BUFFER_NT; } @@ -233,8 +233,8 @@ void CheckAutoVariablesImpl::assignFunctionArg() } } -static bool isAutoVariableRHS(const Token* tok, const Settings& settings) { - return isAddressOfLocalVariable(tok) || isAutoVarArray(tok) || isLocalContainerBuffer(tok, settings); +static bool isAutoVariableRHS(const Token* tok, const Library& library) { + return isAddressOfLocalVariable(tok) || isAutoVarArray(tok) || isLocalContainerBuffer(tok, library); } static bool hasOverloadedAssignment(const Token* tok, bool& inconclusive) @@ -257,7 +257,7 @@ static bool hasOverloadedAssignment(const Token* tok, bool& inconclusive) return true; } -static bool isMemberAssignment(const Token* tok, const Token*& rhs, const Settings& settings) +static bool isMemberAssignment(const Token* tok, const Token*& rhs, const Library& library) { const Token *endBracket = nullptr; if (!Token::Match(tok, "[;{}] %var% . %var%")) { @@ -274,7 +274,7 @@ static bool isMemberAssignment(const Token* tok, const Token*& rhs, const Settin assign = assign->astParent(); if (!Token::simpleMatch(assign, "=")) return false; - if (!isAutoVariableRHS(assign->astOperand2(), settings)) + if (!isAutoVariableRHS(assign->astOperand2(), library)) return false; rhs = assign->astOperand2(); return true; @@ -295,15 +295,15 @@ void CheckAutoVariablesImpl::autoVariables() } // Critical assignment const Token* rhs{}; - if (Token::Match(tok, "[;{}] %var% =") && isRefPtrArg(tok->next()) && isAutoVariableRHS(tok->tokAt(2)->astOperand2(), mSettings)) { + if (Token::Match(tok, "[;{}] %var% =") && isRefPtrArg(tok->next()) && isAutoVariableRHS(tok->tokAt(2)->astOperand2(), mSettings.library)) { checkAutoVariableAssignment(tok->next(), false); - } else if (Token::Match(tok, "[;{}] * %var% =") && isPtrArg(tok->tokAt(2)) && isAutoVariableRHS(tok->tokAt(3)->astOperand2(), mSettings)) { + } else if (Token::Match(tok, "[;{}] * %var% =") && isPtrArg(tok->tokAt(2)) && isAutoVariableRHS(tok->tokAt(3)->astOperand2(), mSettings.library)) { const Token* lhs = tok->tokAt(2); bool inconclusive = false; if (!hasOverloadedAssignment(lhs, inconclusive) || (printInconclusive && inconclusive)) checkAutoVariableAssignment(tok->next(), inconclusive); tok = tok->tokAt(4); - } else if (isMemberAssignment(tok, rhs, mSettings)) { + } else if (isMemberAssignment(tok, rhs, mSettings.library)) { const Token* lhs = tok->tokAt(3); bool inconclusive = false; if (!hasOverloadedAssignment(lhs, inconclusive) || (printInconclusive && inconclusive)) @@ -311,7 +311,7 @@ void CheckAutoVariablesImpl::autoVariables() tok = rhs; } else if (Token::Match(tok, "[;{}] %var% [") && Token::simpleMatch(tok->linkAt(2), "] =") && (isPtrArg(tok->next()) || isArrayArg(tok->next(), mSettings)) && - isAutoVariableRHS(tok->linkAt(2)->next()->astOperand2(), mSettings)) { + isAutoVariableRHS(tok->linkAt(2)->next()->astOperand2(), mSettings.library)) { errorAutoVariableAssignment(tok->next(), false); } // Invalid pointer deallocation diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index d278208fcc3..b6e0e28b3cd 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -133,7 +133,7 @@ static int getMinFormatStringOutputLength(const std::vector ¶m case 's': parameterLength = 0; if (inputArgNr < parameters.size()) - parameterLength = ValueFlow::valueFlowGetStrLength(parameters[inputArgNr], settings); + parameterLength = ValueFlow::valueFlowGetStrLength(parameters[inputArgNr], settings.library); handleNextParameter = true; break; diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 7d3fa5c51ec..d3fd9ef4978 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1059,7 +1059,7 @@ void CheckClassImpl::initializeVarList(const Function &func, std::listnext(); if (tok2->str() == "&") tok2 = tok2->next(); - if (isVariableChangedByFunctionCall(tok2, tok2->strAt(-1) == "&", tok2->varId(), mSettings, nullptr)) + if (isVariableChangedByFunctionCall(tok2, tok2->strAt(-1) == "&", tok2->varId(), mSettings.library, nullptr)) assignVar(usage, tok2->varId()); } } diff --git a/lib/checkio.cpp b/lib/checkio.cpp index f632ca99e9e..f52336dc037 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -855,7 +855,7 @@ void CheckIOImpl::checkFormatString(const Token * const tok, // Perform type checks ArgumentInfo argInfo(argListTok, mSettings, mTokenizer->isCPP()); - if ((argInfo.typeToken && !argInfo.isLibraryType(mSettings)) || *i == ']') { + if ((argInfo.typeToken && !argInfo.isLibraryType(mSettings.library)) || *i == ']') { if (scan) { std::string specifier; bool done = false; @@ -1857,9 +1857,9 @@ bool CheckIOImpl::ArgumentInfo::isKnownType() const return typeToken->isStandardType() || Token::Match(typeToken, "std :: string|wstring"); } -bool CheckIOImpl::ArgumentInfo::isLibraryType(const Settings &settings) const +bool CheckIOImpl::ArgumentInfo::isLibraryType(const Library &library) const { - return typeToken && typeToken->isStandardType() && settings.library.podtype(typeToken->str()); + return typeToken && typeToken->isStandardType() && library.podtype(typeToken->str()); } void CheckIOImpl::wrongPrintfScanfArgumentsError(const Token* tok, diff --git a/lib/checkio.h b/lib/checkio.h index dff49006bab..e72adc5e37d 100644 --- a/lib/checkio.h +++ b/lib/checkio.h @@ -35,6 +35,7 @@ class Token; class Variable; class ErrorLogger; class Tokenizer; +class Library; enum class Severity : std::uint8_t; /// @addtogroup Checks @@ -101,7 +102,7 @@ class CPPCHECKLIB CheckIOImpl : public CheckImpl { bool isKnownType() const; bool isStdVectorOrString(); bool isStdContainer(const Token *tok); - bool isLibraryType(const Settings &settings) const; + bool isLibraryType(const Library &library) const; const Variable* variableInfo{}; const Token* typeToken{}; diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 2fd16e85eaa..f8a91de27e7 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -267,7 +267,7 @@ static const Token * isFunctionCall(const Token * nameToken) return nullptr; } -static const Token* getOutparamAllocation(const Token* tok, const Settings& settings) +static const Token* getOutparamAllocation(const Token* tok, const Library& library) { if (!tok) return nullptr; @@ -275,16 +275,16 @@ static const Token* getOutparamAllocation(const Token* tok, const Settings& sett const Token* ftok = getTokenArgumentFunction(tok, argn); if (!ftok) return nullptr; - if (const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(ftok)) { + if (const Library::AllocFunc* allocFunc = library.getAllocFuncInfo(ftok)) { if (allocFunc->arg == argn + 1) return ftok; } return nullptr; } -static const Token* getReturnValueFromOutparamAlloc(const Token* alloc, const Settings& settings) +static const Token* getReturnValueFromOutparamAlloc(const Token* alloc, const Library& library) { - if (const Token* ftok = getOutparamAllocation(alloc, settings)) { + if (const Token* ftok = getOutparamAllocation(alloc, library)) { if (Token::simpleMatch(ftok->astParent()->astParent(), "=")) return ftok->next()->astParent()->astOperand1(); } @@ -623,7 +623,7 @@ bool CheckLeakAutoVarImpl::checkScope(const Token * const startToken, if (std::any_of(varInfo1.alloctype.begin(), varInfo1.alloctype.end(), [&](const std::pair& info) { if (info.second.status != VarInfo::ALLOC) return false; - const Token* ret = getReturnValueFromOutparamAlloc(info.second.allocTok, mSettings); + const Token* ret = getReturnValueFromOutparamAlloc(info.second.allocTok, mSettings.library); return ret && vartok && ret->varId() && ret->varId() == vartok->varId(); })) { varInfo1.clear(); @@ -896,7 +896,7 @@ const Token * CheckLeakAutoVarImpl::checkTokenInsideExpression(const Token * con if (var != varInfo.alloctype.end()) { bool unknown = false; if (var->second.status == VarInfo::DEALLOC && tok->valueType() && tok->valueType()->pointer && - CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings, /*checkNullArg*/ false) && !unknown) { + CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings.library, /*checkNullArg*/ false) && !unknown) { deallocUseError(tok, tok->str()); } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) { varInfo.erase(tok->varId()); @@ -1232,7 +1232,7 @@ void CheckLeakAutoVarImpl::ret(const Token *tok, VarInfo &varInfo, const bool is // don't warn when returning after checking return value of outparam allocation const Token* outparamFunc{}; if ((tok->scope()->type == ScopeType::eIf || tok->scope()->type== ScopeType::eElse) && - (outparamFunc = getOutparamAllocation(it->second.allocTok, mSettings))) { + (outparamFunc = getOutparamAllocation(it->second.allocTok, mSettings.library))) { const Scope* scope = tok->scope(); if (scope->type == ScopeType::eElse) { scope = scope->bodyStart->tokAt(-2)->scope(); diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 9790f7f2724..8c0d3a05c17 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -130,10 +130,10 @@ namespace { bool CheckNullPointerImpl::isPointerDeRef(const Token *tok, bool &unknown) const { - return isPointerDeRef(tok, unknown, mSettings); + return isPointerDeRef(tok, unknown, mSettings.library); } -bool CheckNullPointerImpl::isPointerDeRef(const Token *tok, bool &unknown, const Settings &settings, bool checkNullArg) +bool CheckNullPointerImpl::isPointerDeRef(const Token *tok, bool &unknown, const Library &library, bool checkNullArg) { unknown = false; @@ -146,7 +146,7 @@ bool CheckNullPointerImpl::isPointerDeRef(const Token *tok, bool &unknown, const ftok = ftok->previous(); } if (ftok && ftok->previous()) { - const std::list varlist = CheckNullPointerImpl::parseFunctionCall(*ftok->previous(), settings.library, checkNullArg); + const std::list varlist = CheckNullPointerImpl::parseFunctionCall(*ftok->previous(), library, checkNullArg); if (std::find(varlist.cbegin(), varlist.cend(), tok) != varlist.cend()) { return true; } @@ -161,7 +161,7 @@ bool CheckNullPointerImpl::isPointerDeRef(const Token *tok, bool &unknown, const return false; const bool addressOf = parent->astParent() && parent->astParent()->str() == "&"; if (parent->str() == "." && astIsRHS(tok)) - return isPointerDeRef(parent, unknown, settings); + return isPointerDeRef(parent, unknown, library); const bool firstOperand = parent->astOperand1() == tok; parent = astParentSkipParens(tok); if (!parent) @@ -298,7 +298,7 @@ void CheckNullPointerImpl::nullPointerByDeRefAndCheck() // Pointer dereference. bool unknown = false; - if (!CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings)) { + if (!CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings.library)) { if (unknown) nullPointerError(tok, tok->expressionString(), value, true); continue; @@ -578,7 +578,7 @@ static bool isUnsafeUsage(const Settings &settings, const Token *vartok, CTU::Fi { (void)value; bool unknown = false; - return CheckNullPointerImpl::isPointerDeRef(vartok, unknown, settings); + return CheckNullPointerImpl::isPointerDeRef(vartok, unknown, settings.library); } // a Clang-built executable will crash when using the anonymous MyFileInfo later on - so put it in a unique namespace for now diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index bc494dad70f..ed6a617d81a 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -92,7 +92,7 @@ class CPPCHECKLIB CheckNullPointerImpl : public CheckImpl { */ bool isPointerDeRef(const Token *tok, bool &unknown) const; - static bool isPointerDeRef(const Token *tok, bool &unknown, const Settings &settings, bool checkNullArg = true); + static bool isPointerDeRef(const Token *tok, bool &unknown, const Library &library, bool checkNullArg = true); /** * @brief parse a function call and extract information about variable usage diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 551c3a47543..30939d04919 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1793,7 +1793,7 @@ void CheckOtherImpl::checkConstVariable() continue; } else if (const Token* ftok = getTokenArgumentFunction(tok, argn)) { bool inconclusive{}; - if (var->valueType() && !isVariableChangedByFunctionCall(ftok, var->valueType()->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive) + if (var->valueType() && !isVariableChangedByFunctionCall(ftok, var->valueType()->pointer, var->declarationId(), mSettings.library, &inconclusive) && !inconclusive) continue; } usedInAssignment = true; @@ -1986,7 +1986,7 @@ void CheckOtherImpl::checkConstPointer() continue; else if (const Token* ftok = getTokenArgumentFunction(parent, argn)) { bool inconclusive{}; - if (!isVariableChangedByFunctionCall(ftok->next(), vt->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive) + if (!isVariableChangedByFunctionCall(ftok->next(), vt->pointer, var->declarationId(), mSettings.library, &inconclusive) && !inconclusive) continue; } } else { @@ -2011,7 +2011,7 @@ void CheckOtherImpl::checkConstPointer() const Variable* argVar = ftok->function()->getArgumentVar(argn); if (argVar && argVar->valueType() && argVar->valueType()->isConst(vt->pointer)) { bool inconclusive{}; - if (!isVariableChangedByFunctionCall(ftok, vt->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive) + if (!isVariableChangedByFunctionCall(ftok, vt->pointer, var->declarationId(), mSettings.library, &inconclusive) && !inconclusive) continue; } } @@ -3970,7 +3970,7 @@ void CheckOtherImpl::checkAccessOfMovedVariable() if (usage == ExprUsage::Used) accessOfMoved = true; if (usage == ExprUsage::PassedByReference) - accessOfMoved = !isVariableChangedByFunctionCall(tok, 0, mSettings, &inconclusive); + accessOfMoved = !isVariableChangedByFunctionCall(tok, 0, mSettings.library, &inconclusive); else if (usage == ExprUsage::Inconclusive) inconclusive = true; } diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index c8fcca48f1a..52bc5613843 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -2550,7 +2550,7 @@ void CheckStlImpl::checkDereferenceInvalidIterator2() emptyAdvance = tok->astParent(); } } - if (!CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings) && !isInvalidIterator && !emptyAdvance) { + if (!CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings.library) && !isInvalidIterator && !emptyAdvance) { if (!unknown) continue; inconclusive = true; @@ -2869,10 +2869,10 @@ namespace { struct LoopAnalyzer { const Token* bodyTok = nullptr; const Token* loopVar = nullptr; - const Settings* settings = nullptr; + const Settings& settings; std::set varsChanged; - explicit LoopAnalyzer(const Token* tok, const Settings* psettings) + explicit LoopAnalyzer(const Token* tok, const Settings& psettings) : bodyTok(tok->linkAt(1)->next()), settings(psettings) { const Token* splitTok = tok->next()->astOperand2(); @@ -2894,11 +2894,11 @@ namespace { int n = 1 + (astIsPointer(tok) ? 1 : 0); for (int i = 0; i < n; i++) { bool inconclusive = false; - if (isVariableChangedByFunctionCall(tok, i, *settings, &inconclusive)) + if (isVariableChangedByFunctionCall(tok, i, settings.library, &inconclusive)) return true; if (inconclusive) return true; - if (isVariableChanged(tok, i, *settings)) + if (isVariableChanged(tok, i, settings)) return true; } return false; @@ -3044,7 +3044,7 @@ void CheckStlImpl::useStlAlgorithm() continue; if (!Token::simpleMatch(tok->linkAt(1), ") {")) continue; - LoopAnalyzer a{tok, &mSettings}; + LoopAnalyzer a{tok, mSettings}; std::string algoName = a.findAlgo(); if (!algoName.empty()) { useStlAlgorithmError(tok, algoName); diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 6bc2a86b8a5..d05ea3fbd28 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1664,7 +1664,7 @@ void CheckUninitVarImpl::valueFlowUninit() if (yield != Library::Container::Yield::AT_INDEX && yield != Library::Container::Yield::ITEM) continue; } - const bool deref = CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings); + const bool deref = CheckNullPointerImpl::isPointerDeRef(tok, unknown, mSettings.library); uninitderef = deref && v->indirect == 0; const bool isleaf = isLeafDot(tok) || uninitderef; if (!isleaf && Token::Match(tok->astParent(), ". %name%") && @@ -1681,7 +1681,7 @@ void CheckUninitVarImpl::valueFlowUninit() isVariableChanged(tok, v->indirect, mSettings)) continue; bool inconclusive = false; - if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings, &inconclusive) || inconclusive) + if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings.library, &inconclusive) || inconclusive) continue; } uninitvarError(tok, *v); diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index 5965de1aada..4177a13a013 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -65,11 +65,11 @@ static bool isRecursiveCall(const Token* ftok) return ftok->function() && ftok->function() == Scope::nestedInFunction(ftok->scope()); } -void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Settings &settings) +void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Library &library) { const char * const FileName = tokenizer.list.getFiles().front().c_str(); - const bool doMarkup = settings.library.markupFile(FileName); + const bool doMarkup = library.markupFile(FileName); // Function declarations.. if (!doMarkup) { @@ -139,8 +139,8 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting lambdaEndToken = findLambdaEndToken(tok); // parsing of library code to find called functions - if (settings.library.isexecutableblock(FileName, tok->str())) { - const Token * markupVarToken = tok->tokAt(settings.library.blockstartoffset(FileName)); + if (library.isexecutableblock(FileName, tok->str())) { + const Token * markupVarToken = tok->tokAt(library.blockstartoffset(FileName)); // not found if (!markupVarToken) continue; @@ -148,12 +148,12 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting bool start = true; // find all function calls in library code (starts with '(', not if or while etc) while ((scope || start) && markupVarToken) { - if (markupVarToken->str() == settings.library.blockstart(FileName)) { + if (markupVarToken->str() == library.blockstart(FileName)) { scope++; start = false; - } else if (markupVarToken->str() == settings.library.blockend(FileName)) + } else if (markupVarToken->str() == library.blockend(FileName)) scope--; - else if (!settings.library.iskeyword(FileName, markupVarToken->str())) { + else if (!library.iskeyword(FileName, markupVarToken->str())) { mFunctionCalls.insert(markupVarToken->str()); if (mFunctions.find(markupVarToken->str()) != mFunctions.end()) mFunctions[markupVarToken->str()].usedOtherFile = true; @@ -171,10 +171,10 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting } if (!doMarkup // only check source files - && settings.library.isexporter(tok->str()) && tok->next() != nullptr) { + && library.isexporter(tok->str()) && tok->next() != nullptr) { const Token * propToken = tok->next(); while (propToken && propToken->str() != ")") { - if (settings.library.isexportedprefix(tok->str(), propToken->str())) { + if (library.isexportedprefix(tok->str(), propToken->str())) { const Token* nextPropToken = propToken->next(); const std::string& value = nextPropToken->str(); if (mFunctions.find(value) != mFunctions.end()) { @@ -182,7 +182,7 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting } mFunctionCalls.insert(value); } - if (settings.library.isexportedsuffix(tok->str(), propToken->str())) { + if (library.isexportedsuffix(tok->str(), propToken->str())) { const Token* prevPropToken = propToken->previous(); const std::string& value = prevPropToken->str(); if (value != ")" && mFunctions.find(value) != mFunctions.end()) { @@ -194,7 +194,7 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting } } - if (doMarkup && settings.library.isimporter(FileName, tok->str()) && tok->next()) { + if (doMarkup && library.isimporter(FileName, tok->str()) && tok->next()) { const Token * propToken = tok->next(); if (propToken->next()) { propToken = propToken->next(); @@ -210,8 +210,8 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting } } - if (settings.library.isreflection(tok->str())) { - const int argIndex = settings.library.reflectionArgument(tok->str()); + if (library.isreflection(tok->str())) { + const int argIndex = library.reflectionArgument(tok->str()); if (argIndex >= 0) { const Token * funcToken = tok->next(); int index = 0; @@ -366,7 +366,7 @@ void CheckUnusedFunctions::staticFunctionError(ErrorLogger& errorLogger, errorLogger.reportErr(errmsg); \ } while (false) -bool CheckUnusedFunctions::check(const Settings& settings, ErrorLogger& errorLogger) const +bool CheckUnusedFunctions::check(const Library& library, ErrorLogger& errorLogger) const { logChecker("CheckUnusedFunctions::check"); // unusedFunction @@ -379,7 +379,7 @@ bool CheckUnusedFunctions::check(const Settings& settings, ErrorLogger& errorLog const FunctionUsage &func = it->second; if (func.usedOtherFile || func.filename.empty()) continue; - if (settings.library.isentrypoint(it->first)) + if (library.isentrypoint(it->first)) continue; if (!func.usedSameFile) { if (isOperatorFunction(it->first)) diff --git a/lib/checkunusedfunctions.h b/lib/checkunusedfunctions.h index 5c5b369c194..1b560cfb7cb 100644 --- a/lib/checkunusedfunctions.h +++ b/lib/checkunusedfunctions.h @@ -33,6 +33,7 @@ class ErrorLogger; class Function; class Settings; class Tokenizer; +class Library; /** @brief Check for functions never called */ /// @{ @@ -44,7 +45,7 @@ class CPPCHECKLIB CheckUnusedFunctions { // Parse current tokens and determine.. // * Check what functions are used // * What functions are declared - void parseTokens(const Tokenizer &tokenizer, const Settings &settings); + void parseTokens(const Tokenizer &tokenizer, const Library &library); std::string analyzerInfo(const Tokenizer &tokenizer) const; @@ -56,7 +57,7 @@ class CPPCHECKLIB CheckUnusedFunctions { } // Return true if an error is reported. - bool check(const Settings& settings, ErrorLogger& errorLogger) const; + bool check(const Library& library, ErrorLogger& errorLogger) const; void updateFunctionData(const CheckUnusedFunctions& checkUnusedFunctions); diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index b7ab1f99039..afca559a02e 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -976,7 +976,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str tokenlist.createTokens(std::move(tokens)); // this is not a real source file - we just want to tokenize it. treat it as C anyways as the language needs to be determined. Tokenizer tokenizer(std::move(tokenlist), mErrorLogger); - mUnusedFunctionsCheck->parseTokens(tokenizer, mSettings); + mUnusedFunctionsCheck->parseTokens(tokenizer, mSettings.library); if (analyzerInformation) { mLogger->setAnalyzerInfo(nullptr); @@ -1357,10 +1357,10 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer, AnalyzerInformation } if (mSettings.checks.isEnabled(Checks::unusedFunction) && !mSettings.buildDir.empty()) { - unusedFunctionsChecker.parseTokens(tokenizer, mSettings); + unusedFunctionsChecker.parseTokens(tokenizer, mSettings.library); } if (mUnusedFunctionsCheck && mSettings.useSingleJob() && mSettings.buildDir.empty()) { - mUnusedFunctionsCheck->parseTokens(tokenizer, mSettings); + mUnusedFunctionsCheck->parseTokens(tokenizer, mSettings.library); } if (mSettings.clang) { @@ -1829,7 +1829,7 @@ bool CppCheck::analyseWholeProgram() } if (mUnusedFunctionsCheck) - errors |= mUnusedFunctionsCheck->check(mSettings, mErrorLogger); + errors |= mUnusedFunctionsCheck->check(mSettings.library, mErrorLogger); return errors && (mLogger->exitcode() > 0); } @@ -1840,7 +1840,7 @@ unsigned int CppCheck::analyseWholeProgram(const std::string &buildDir, const st CheckUnusedFunctions::analyseWholeProgram(mSettings, mErrorLogger, buildDir); if (mUnusedFunctionsCheck) - mUnusedFunctionsCheck->check(mSettings, mErrorLogger); + mUnusedFunctionsCheck->check(mSettings.library, mErrorLogger); if (Settings::unusedFunctionOnly()) return mLogger->exitcode(); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 68e989c0738..c0392400cb1 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -6155,7 +6155,7 @@ static bool isContainerSizeChangedByFunction(const Token* tok, } bool inconclusive = false; - const bool isChanged = isVariableChangedByFunctionCall(tok, indirect, settings, &inconclusive); + const bool isChanged = isVariableChangedByFunctionCall(tok, indirect, settings.library, &inconclusive); return (isChanged || inconclusive); } @@ -6822,17 +6822,17 @@ static void valueFlowContainerSize(const TokenList& tokenlist, } else if (tok->str() == "+=" && astIsContainer(tok->astOperand1())) { const Token* containerTok = tok->astOperand1(); const Token* valueTok = tok->astOperand2(); - const MathLib::bigint size = ValueFlow::valueFlowGetStrLength(valueTok, settings); + const MathLib::bigint size = ValueFlow::valueFlowGetStrLength(valueTok, settings.library); forwardMinimumContainerSize(size, tok, containerTok); } else if (tok->str() == "=" && Token::simpleMatch(tok->astOperand2(), "+") && astIsContainerString(tok)) { const Token* tok2 = tok->astOperand2(); MathLib::bigint size = 0; while (Token::simpleMatch(tok2, "+") && tok2->astOperand2()) { - size += ValueFlow::valueFlowGetStrLength(tok2->astOperand2(), settings); + size += ValueFlow::valueFlowGetStrLength(tok2->astOperand2(), settings.library); tok2 = tok2->astOperand1(); } - size += ValueFlow::valueFlowGetStrLength(tok2, settings); + size += ValueFlow::valueFlowGetStrLength(tok2, settings.library); forwardMinimumContainerSize(size, tok, tok->astOperand1()); } } diff --git a/lib/vf_analyzers.cpp b/lib/vf_analyzers.cpp index a50a3b1d4a4..c6abfd5dba8 100644 --- a/lib/vf_analyzers.cpp +++ b/lib/vf_analyzers.cpp @@ -222,7 +222,7 @@ struct ValueFlowAnalyzer : Analyzer { return Action::Read; } bool inconclusive = false; - if (isVariableChangedByFunctionCall(tok, getIndirect(tok), getSettings(), &inconclusive)) + if (isVariableChangedByFunctionCall(tok, getIndirect(tok), getSettings().library, &inconclusive)) return Action::Read | Action::Invalid; if (inconclusive) return Action::Read | Action::Inconclusive; @@ -1547,7 +1547,7 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer { case Library::Container::Action::APPEND: { std::vector args = getArguments(tok->astParent()->tokAt(2)); if (args.size() == 1) // TODO: handle overloads - n = ValueFlow::valueFlowGetStrLength(tok->astParent()->tokAt(3), settings); + n = ValueFlow::valueFlowGetStrLength(tok->astParent()->tokAt(3), settings.library); if (n == 0) // TODO: handle known empty append val->setPossible(); break; diff --git a/lib/vf_common.cpp b/lib/vf_common.cpp index 56f928bcbd8..ebcefe4322b 100644 --- a/lib/vf_common.cpp +++ b/lib/vf_common.cpp @@ -392,7 +392,7 @@ namespace ValueFlow v.debugPath.emplace_back(tok, std::move(s)); } - MathLib::bigint valueFlowGetStrLength(const Token* tok, const Settings& settings) + MathLib::bigint valueFlowGetStrLength(const Token* tok, const Library& library) { if (tok->tokType() == Token::eString) return Token::getStrLength(tok); @@ -402,10 +402,10 @@ namespace ValueFlow return v->intvalue; if (const Value* v = tok->getKnownValue(Value::ValueType::TOK)) { if (v->tokvalue != tok) - return valueFlowGetStrLength(v->tokvalue, settings); + return valueFlowGetStrLength(v->tokvalue, library); } - if (const Token* cont = settings.library.getContainerFromYield(tok, Library::Container::Yield::BUFFER_NT)) - return valueFlowGetStrLength(cont, settings); + if (const Token* cont = library.getContainerFromYield(tok, Library::Container::Yield::BUFFER_NT)) + return valueFlowGetStrLength(cont, library); return 0; } } diff --git a/lib/vf_common.h b/lib/vf_common.h index 9859955cbfe..aca438a0dff 100644 --- a/lib/vf_common.h +++ b/lib/vf_common.h @@ -30,6 +30,7 @@ class Token; class Settings; class Platform; +class Library; namespace ValueFlow { @@ -53,7 +54,7 @@ namespace ValueFlow const Token* tok, SourceLocation local = SourceLocation::current()); - MathLib::bigint valueFlowGetStrLength(const Token* tok, const Settings& settings); + MathLib::bigint valueFlowGetStrLength(const Token* tok, const Library& library); } #endif // vfCommonH diff --git a/test/testastutils.cpp b/test/testastutils.cpp index 904ea92b466..6a6e0624587 100644 --- a/test/testastutils.cpp +++ b/test/testastutils.cpp @@ -259,7 +259,7 @@ class TestAstUtils : public TestFixture { const Token * const argtok = Token::findmatch(tokenizer.tokens(), pattern); ASSERT_LOC(argtok, file, line); int indirect = (argtok->variable() && argtok->variable()->isArray()); - return (isVariableChangedByFunctionCall)(argtok, indirect, settingsDefault, inconclusive); + return (isVariableChangedByFunctionCall)(argtok, indirect, settingsDefault.library, inconclusive); } void isVariableChangedByFunctionCallTest() { diff --git a/test/testunusedfunctions.cpp b/test/testunusedfunctions.cpp index 3e78b119012..938a1394394 100644 --- a/test/testunusedfunctions.cpp +++ b/test/testunusedfunctions.cpp @@ -111,8 +111,8 @@ class TestUnusedFunctions : public TestFixture { // Check for unused functions.. CheckUnusedFunctions checkUnusedFunctions; - checkUnusedFunctions.parseTokens(tokenizer, settings1); - (checkUnusedFunctions.check)(settings1, *this); // TODO: check result + checkUnusedFunctions.parseTokens(tokenizer, settings1.library); + (checkUnusedFunctions.check)(settings1.library, *this); // TODO: check result } // TODO: get rid of this @@ -123,8 +123,8 @@ class TestUnusedFunctions : public TestFixture { // Check for unused functions.. CheckUnusedFunctions checkUnusedFunctions; - checkUnusedFunctions.parseTokens(tokenizer, settings); - (checkUnusedFunctions.check)(settings, *this); // TODO: check result + checkUnusedFunctions.parseTokens(tokenizer, settings.library); + (checkUnusedFunctions.check)(settings.library, *this); // TODO: check result } void incondition() { @@ -602,11 +602,11 @@ class TestUnusedFunctions : public TestFixture { SimpleTokenizer tokenizer{settings, *this, fname}; ASSERT(tokenizer.tokenize(code)); - c.parseTokens(tokenizer, settings); + c.parseTokens(tokenizer, settings.library); } // Check for unused functions.. - (c.check)(settings, *this); // TODO: check result + (c.check)(settings.library, *this); // TODO: check result ASSERT_EQUALS("[test1.cpp:1:13]: (style) The function 'f' is never used. [unusedFunction]\n", errout_str()); }