From d6e12b8835d4c167603712de8db8b2b7b542446e Mon Sep 17 00:00:00 2001 From: firewave Date: Tue, 7 Mar 2023 15:31:27 +0100 Subject: [PATCH 1/9] ValueFlow: pass `ErrorLogger` by reference into `ValueFlow::setValues()` --- lib/cppcheck.cpp | 2 +- lib/forwardanalyzer.cpp | 16 +++--- lib/forwardanalyzer.h | 4 +- lib/reverseanalyzer.cpp | 6 +- lib/reverseanalyzer.h | 2 +- lib/tokenize.cpp | 4 +- lib/valueflow.cpp | 124 ++++++++++++++++++++-------------------- lib/valueflow.h | 2 +- 8 files changed, 79 insertions(+), 81 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 3127d024e39..377e9149505 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -513,7 +513,7 @@ unsigned int CppCheck::checkClang(const std::string &path) clangimport::parseClangAstDump(tokenizer, ast); ValueFlow::setValues(tokenizer.list, const_cast(*tokenizer.getSymbolDatabase()), - this, + *this, mSettings, &s_timerResults); if (mSettings.debugnormal) diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 92eedbe5098..c5cb8eaf3ee 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -47,12 +47,12 @@ namespace { struct ForwardTraversal { enum class Progress { Continue, Break, Skip }; enum class Terminate { None, Bail, Inconclusive }; - ForwardTraversal(const ValuePtr& analyzer, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings) + ForwardTraversal(const ValuePtr& analyzer, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) : analyzer(analyzer), tokenList(tokenList), errorLogger(errorLogger), settings(settings) {} ValuePtr analyzer; const TokenList& tokenList; - ErrorLogger* const errorLogger; + ErrorLogger& errorLogger; const Settings& settings; Analyzer::Action actions; bool analyzeOnly{}; @@ -839,11 +839,9 @@ namespace { } void reportError(Severity severity, const std::string& id, const std::string& msg) { - if (errorLogger) { - ErrorMessage::FileLocation loc(tokenList.getSourceFilePath(), 0, 0); - const ErrorMessage errmsg({std::move(loc)}, tokenList.getSourceFilePath(), severity, msg, id, Certainty::normal); - errorLogger->reportErr(errmsg); - } + ErrorMessage::FileLocation loc(tokenList.getSourceFilePath(), 0, 0); + const ErrorMessage errmsg({std::move(loc)}, tokenList.getSourceFilePath(), severity, msg, id, Certainty::normal); + errorLogger.reportErr(errmsg); } static bool isFunctionCall(const Token* tok) @@ -904,7 +902,7 @@ namespace { }; } -Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings) +Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) { if (a->invalid()) return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail}; @@ -915,7 +913,7 @@ Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const V return Analyzer::Result{ ft.actions, ft.terminate }; } -Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings) +Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) { if (Settings::terminated()) throw TerminateException(); diff --git a/lib/forwardanalyzer.h b/lib/forwardanalyzer.h index f378d852d57..2e760830d89 100644 --- a/lib/forwardanalyzer.h +++ b/lib/forwardanalyzer.h @@ -31,9 +31,9 @@ Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenList, - ErrorLogger* const errorLogger, + ErrorLogger& errorLogger, const Settings& settings); -Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings); +Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings); #endif diff --git a/lib/reverseanalyzer.cpp b/lib/reverseanalyzer.cpp index a94e1679bb7..5bbbbcabe49 100644 --- a/lib/reverseanalyzer.cpp +++ b/lib/reverseanalyzer.cpp @@ -37,12 +37,12 @@ namespace { struct ReverseTraversal { - ReverseTraversal(const ValuePtr& analyzer, const TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings) + ReverseTraversal(const ValuePtr& analyzer, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) : analyzer(analyzer), tokenlist(tokenlist), errorLogger(errorLogger), settings(settings) {} ValuePtr analyzer; const TokenList& tokenlist; - ErrorLogger* const errorLogger; + ErrorLogger& errorLogger; const Settings& settings; std::pair evalCond(const Token* tok) const { @@ -395,7 +395,7 @@ namespace { }; } -void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings) +void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { if (a->invalid()) return; diff --git a/lib/reverseanalyzer.h b/lib/reverseanalyzer.h index c35315de0d9..2b251c0d076 100644 --- a/lib/reverseanalyzer.h +++ b/lib/reverseanalyzer.h @@ -27,6 +27,6 @@ class TokenList; template class ValuePtr; -void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings); +void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings); #endif diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index e921e997dcc..257f4a2d3c3 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3409,9 +3409,9 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) if (doValueFlow) { if (mTimerResults) { Timer t("Tokenizer::simplifyTokens1::ValueFlow", mSettings.showtime, mTimerResults); - ValueFlow::setValues(list, *mSymbolDatabase, mErrorLogger, mSettings, mTimerResults); + ValueFlow::setValues(list, *mSymbolDatabase, *mErrorLogger, mSettings, mTimerResults); } else { - ValueFlow::setValues(list, *mSymbolDatabase, mErrorLogger, mSettings, mTimerResults); + ValueFlow::setValues(list, *mSymbolDatabase, *mErrorLogger, mSettings, mTimerResults); } arraySizeAfterValueFlow(); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 9876461df2c..4132ccfd334 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -128,7 +128,7 @@ #include #include -static void bailoutInternal(const std::string& type, const TokenList &tokenlist, ErrorLogger *errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function) +static void bailoutInternal(const std::string& type, const TokenList &tokenlist, ErrorLogger &errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function) { if (function.find("operator") != std::string::npos) function = "(valueFlow)"; @@ -136,7 +136,7 @@ static void bailoutInternal(const std::string& type, const TokenList &tokenlist, const std::string location = Path::stripDirectoryPart(file) + ":" + std::to_string(line) + ":"; ErrorMessage errmsg({std::move(loc)}, tokenlist.getSourceFilePath(), Severity::debug, (file.empty() ? "" : location) + function + " bailout: " + what, type, Certainty::normal); - errorLogger->reportErr(errmsg); + errorLogger.reportErr(errmsg); } #define bailout2(type, tokenlist, errorLogger, tok, what) bailoutInternal((type), (tokenlist), (errorLogger), (tok), (what), __FILE__, __LINE__, __func__) @@ -2115,7 +2115,7 @@ static Analyzer::Result valueFlowForward(Token* startToken, const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2134,7 +2134,7 @@ static Analyzer::Result valueFlowForward(Token* startToken, const Token* exprTok, std::list values, const TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2150,7 +2150,7 @@ static Analyzer::Result valueFlowForward(Token* startToken, const Token* exprTok, ValueOrValues v, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2165,7 +2165,7 @@ static Analyzer::Result valueFlowForwardRecursive(Token* top, const Token* exprTok, std::list values, const TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2184,7 +2184,7 @@ static void valueFlowReverse(Token* tok, const Token* const varToken, std::list values, const TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2200,7 +2200,7 @@ static void valueFlowReverse(const TokenList& tokenlist, Token* tok, const Token* const varToken, ValueFlow::Value val, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -3871,11 +3871,11 @@ bool ValueFlow::isLifetimeBorrowed(const Token *tok, const Settings &settings) return true; } -static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings); +static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings); static void valueFlowLifetimeConstructor(Token *tok, TokenList &tokenlist, - ErrorLogger *errorLogger, + ErrorLogger &errorLogger, const Settings &settings); static bool isRangeForScope(const Scope* scope) @@ -3953,7 +3953,7 @@ const Token* ValueFlow::getEndOfExprScope(const Token* tok, const Scope* default return end; } -static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings) { // Forward lifetimes to constructed variable if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) { @@ -4087,11 +4087,11 @@ struct LifetimeStore { } for (const auto& p : forwardToks) { const Context& c = p.second; - valueFlowForwardLifetime(c.tok, *c.tokenlist, c.errorLogger, *c.settings); + valueFlowForwardLifetime(c.tok, *c.tokenlist, *c.errorLogger, *c.settings); } } - static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, const TokenList &tokenlist, const Settings& settings, ErrorLogger *errorLogger) { + static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, const TokenList &tokenlist, const Settings& settings, ErrorLogger &errorLogger) { if (!var) return LifetimeStore{}; if (!var->isArgument()) @@ -4117,7 +4117,7 @@ struct LifetimeStore { template bool byRef(Token* tok, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, Predicate pred, SourceLocation loc = SourceLocation::current()) const @@ -4158,7 +4158,7 @@ struct LifetimeStore { bool byRef(Token* tok, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { @@ -4176,7 +4176,7 @@ struct LifetimeStore { template bool byVal(Token* tok, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, Predicate pred, SourceLocation loc = SourceLocation::current()) const @@ -4253,7 +4253,7 @@ struct LifetimeStore { bool byVal(Token* tok, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { @@ -4271,7 +4271,7 @@ struct LifetimeStore { template bool byDerefCopy(Token* tok, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, Predicate pred, SourceLocation loc = SourceLocation::current()) const @@ -4307,7 +4307,7 @@ struct LifetimeStore { bool byDerefCopy(Token* tok, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { @@ -4324,11 +4324,11 @@ struct LifetimeStore { private: Context* mContext{}; - void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings& settings) const { + void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) const { if (mContext) { mContext->tok = tok; mContext->tokenlist = &tokenlist; - mContext->errorLogger = errorLogger; + mContext->errorLogger = &errorLogger; mContext->settings = &settings; } valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); @@ -4369,7 +4369,7 @@ static void valueFlowLifetimeUserConstructor(Token* tok, const std::string& name, const std::vector& args, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings) { if (!constructor) @@ -4452,7 +4452,7 @@ static void valueFlowLifetimeUserConstructor(Token* tok, } } -static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings) { if (!Token::Match(tok, "%name% (")) return; @@ -4644,7 +4644,7 @@ static const Function* findConstructor(const Scope* scope, const Token* tok, con static void valueFlowLifetimeClassConstructor(Token* tok, const Type* t, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings) { if (!Token::Match(tok, "(|{")) @@ -4702,7 +4702,7 @@ static void valueFlowLifetimeClassConstructor(Token* tok, } } -static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings& settings) +static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { if (!Token::Match(tok, "(|{")) return; @@ -4848,7 +4848,7 @@ static bool isContainerOfPointers(const Token* tok, const Settings& settings) return vt.pointer > 0; } -static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings) { for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (!tok->scope()) @@ -5181,7 +5181,7 @@ static Token* findEndOfFunctionCallForParameter(Token* parameterToken) return nextAfterAstRightmostLeaf(parent); } -static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings) +static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) { if (!tokenlist.isCPP() || settings.standards.cpp < Standards::CPP11) return; @@ -5330,7 +5330,7 @@ static const Scope* getLoopScope(const Token* tok) } // -static void valueFlowConditionExpressions(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowConditionExpressions(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger &errorLogger, const Settings &settings) { if (!settings.daca && (settings.checkLevel == Settings::CheckLevel::normal)) return; @@ -5464,7 +5464,7 @@ static std::set getVarIds(const Token* tok) return result; } -static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings) +static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) { for (const Scope* scope : symboldatabase.functionScopes) { for (auto* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { @@ -5821,7 +5821,7 @@ static void valueFlowForwardAssign(Token* const tok, std::list values, const bool init, TokenList& tokenlist, - ErrorLogger* const errorLogger, + ErrorLogger& errorLogger, const Settings& settings) { if (Token::simpleMatch(tok->astParent(), "return")) @@ -5931,7 +5931,7 @@ static void valueFlowForwardAssign(Token* const tok, const bool /*unused*/, const bool init, TokenList& tokenlist, - ErrorLogger* const errorLogger, + ErrorLogger& errorLogger, const Settings& settings) { valueFlowForwardAssign(tok, var->nameToken(), {var}, values, init, tokenlist, errorLogger, settings); @@ -6013,7 +6013,7 @@ static bool intersects(const C1& c1, const C2& c2) static void valueFlowAfterAssign(TokenList &tokenlist, const SymbolDatabase& symboldatabase, - ErrorLogger *errorLogger, + ErrorLogger &errorLogger, const Settings &settings, const std::set& skippedFunctions) { @@ -6150,7 +6150,7 @@ static std::vector getVariables(const Token* tok) static void valueFlowAfterSwap(TokenList& tokenlist, const SymbolDatabase& symboldatabase, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings) { for (const Scope* scope : symboldatabase.functionScopes) { @@ -6293,7 +6293,7 @@ struct ConditionHandler { const Token* exprTok, const std::list& values, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { @@ -6304,7 +6304,7 @@ struct ConditionHandler { const Token* exprTok, const std::list& values, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { @@ -6316,7 +6316,7 @@ struct ConditionHandler { const Token* exprTok, const std::list& values, TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { @@ -6362,7 +6362,7 @@ struct ConditionHandler { void beforeCondition(TokenList& tokenlist, const SymbolDatabase& symboldatabase, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, const std::set& skippedFunctions) const { traverseCondition(symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* tok, const Scope*) { @@ -6510,7 +6510,7 @@ struct ConditionHandler { void afterCondition(TokenList& tokenlist, const SymbolDatabase& symboldatabase, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, const std::set& skippedFunctions) const { traverseCondition(symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* condTok, const Scope* scope) { @@ -6842,7 +6842,7 @@ struct ConditionHandler { static void valueFlowCondition(const ValuePtr& handler, TokenList& tokenlist, SymbolDatabase& symboldatabase, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, const std::set& skippedFunctions) { @@ -7138,7 +7138,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart, bool globalvar, const MathLib::bigint value, const TokenList& tokenlist, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings) { // TODO: Refactor this to use arbitrary expressions @@ -7238,7 +7238,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart, } } -static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, ErrorLogger * const errorLogger, const Settings& settings) +static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, ErrorLogger & errorLogger, const Settings& settings) { const Token *vartok = nullptr; for (const Token *tok = fortok; tok; tok = tok->next()) { @@ -7266,7 +7266,7 @@ static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const } } -static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger &errorLogger, const Settings &settings) { for (const Scope &scope : symboldatabase.scopeList) { if (scope.type != Scope::eFor) @@ -7546,7 +7546,7 @@ static bool productParams(const Settings& settings, const std::unordered_map>& vars) @@ -7565,7 +7565,7 @@ static void valueFlowInjectParameter(TokenList& tokenlist, } static void valueFlowInjectParameter(const TokenList& tokenlist, - ErrorLogger* const errorLogger, + ErrorLogger& errorLogger, const Settings& settings, const Variable* arg, const Scope* functionScope, @@ -7589,7 +7589,7 @@ static void valueFlowInjectParameter(const TokenList& tokenlist, settings); } -static void valueFlowSwitchVariable(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowSwitchVariable(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger &errorLogger, const Settings &settings) { for (const Scope &scope : symboldatabase.scopeList) { if (scope.type != Scope::ScopeType::eSwitch) @@ -7724,7 +7724,7 @@ static IteratorRange MakeIteratorRange(Iterator start, Iterator last) return {start, last}; } -static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings) +static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) { int id = 0; for (const Scope* scope : MakeIteratorRange(symboldatabase.functionScopes.crbegin(), symboldatabase.functionScopes.crend())) { @@ -7806,7 +7806,7 @@ static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase& symboldat } } -static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings) +static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) { if (!tokenlist.isCPP()) return; @@ -7875,7 +7875,7 @@ static void setFunctionReturnValue(const Function* f, Token* tok, ValueFlow::Val setTokenValue(tok, std::move(v), settings); } -static void valueFlowFunctionReturn(TokenList &tokenlist, ErrorLogger *errorLogger, const Settings& settings) +static void valueFlowFunctionReturn(TokenList &tokenlist, ErrorLogger &errorLogger, const Settings& settings) { for (Token *tok = tokenlist.back(); tok; tok = tok->previous()) { if (tok->str() != "(" || !tok->astOperand1() || tok->isCast()) @@ -8043,7 +8043,7 @@ static Token* findStartToken(const Variable* var, Token* start, const Library* l return tok; } -static void valueFlowUninit(TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings) +static void valueFlowUninit(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (!tok->scope()->isExecutable()) @@ -8441,7 +8441,7 @@ static bool isContainerSizeChanged(const Token* expr, return false; } -static void valueFlowSmartPointer(TokenList &tokenlist, ErrorLogger * errorLogger, const Settings &settings) +static void valueFlowSmartPointer(TokenList &tokenlist, ErrorLogger & errorLogger, const Settings &settings) { for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (!tok->scope()) @@ -8754,7 +8754,7 @@ static std::vector getContainerSizeFromConstructor(const Token return getContainerSizeFromConstructorArgs(args, valueType->container, known); } -static void valueFlowContainerSetTokValue(TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings, const Token* tok, Token* initList) +static void valueFlowContainerSetTokValue(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, const Token* tok, Token* initList) { ValueFlow::Value value; value.valueType = ValueFlow::Value::ValueType::TOK; @@ -8794,7 +8794,7 @@ static MathLib::bigint valueFlowGetStrLength(const Token* tok) static void valueFlowContainerSize(TokenList& tokenlist, const SymbolDatabase& symboldatabase, - ErrorLogger* const errorLogger, + ErrorLogger& errorLogger, const Settings& settings, const std::set& skippedFunctions) { @@ -9021,7 +9021,7 @@ struct ContainerConditionHandler : ConditionHandler { } }; -static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings) +static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) { auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint { MathLib::bigint sizeValue = -1; @@ -9190,7 +9190,7 @@ static bool getMinMaxValues(const std::string &typestr, const Settings &settings return getMinMaxValues(&vt, settings.platform, minvalue, maxvalue); } -static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings) +static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) { for (const Scope *functionScope : symboldatabase.functionScopes) { if (!functionScope->bodyStart) @@ -9317,7 +9317,7 @@ static void valueFlowUnknownFunctionReturn(TokenList &tokenlist, const Settings } } -static void valueFlowDebug(TokenList& tokenlist, ErrorLogger* errorLogger, const Settings& settings) +static void valueFlowDebug(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { if (!settings.debugnormal && !settings.debugwarnings) return; @@ -9331,7 +9331,7 @@ static void valueFlowDebug(TokenList& tokenlist, ErrorLogger* errorLogger, const ErrorPath errorPath = v.errorPath; errorPath.insert(errorPath.end(), v.debugPath.cbegin(), v.debugPath.cend()); errorPath.emplace_back(tok, ""); - errorLogger->reportErr({errorPath, &tokenlist, Severity::debug, "valueFlow", msg, CWE{0}, Certainty::normal}); + errorLogger.reportErr({errorPath, &tokenlist, Severity::debug, "valueFlow", msg, CWE{0}, Certainty::normal}); } } } @@ -9349,14 +9349,14 @@ const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(Token *expr, const S struct ValueFlowState { explicit ValueFlowState(TokenList& tokenlist, SymbolDatabase& symboldatabase, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings) : tokenlist(tokenlist), symboldatabase(symboldatabase), errorLogger(errorLogger), settings(settings) {} TokenList& tokenlist; SymbolDatabase& symboldatabase; - ErrorLogger* errorLogger = nullptr; + ErrorLogger& errorLogger; const Settings& settings; std::set skippedFunctions; }; @@ -9411,7 +9411,7 @@ struct ValueFlowPassRunner { "ValueFlow maximum iterations exceeded", "valueFlowMaxIterations", Certainty::normal); - state.errorLogger->reportErr(errmsg); + state.errorLogger.reportErr(errmsg); } } return false; @@ -9471,7 +9471,7 @@ struct ValueFlowPassRunner { "Please specify --check-level=exhaustive to perform full analysis.", "checkLevelNormal", Certainty::normal); - state.errorLogger->reportErr(errmsg); + state.errorLogger.reportErr(errmsg); } } } @@ -9518,7 +9518,7 @@ static ValueFlowPassAdaptor makeValueFlowPassAdaptor(const char* name, bool c (cpp), \ [](TokenList& tokenlist, \ SymbolDatabase& symboldatabase, \ - ErrorLogger* errorLogger, \ + ErrorLogger& errorLogger, \ const Settings& settings, \ const std::set& skippedFunctions) { \ (void)tokenlist; \ @@ -9534,7 +9534,7 @@ static ValueFlowPassAdaptor makeValueFlowPassAdaptor(const char* name, bool c void ValueFlow::setValues(TokenList& tokenlist, SymbolDatabase& symboldatabase, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, TimerResultsIntf* timerResults) { diff --git a/lib/valueflow.h b/lib/valueflow.h index 6e32dac31f9..acd785a3432 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -53,7 +53,7 @@ namespace ValueFlow { /// Perform valueflow analysis. void setValues(TokenList& tokenlist, SymbolDatabase& symboldatabase, - ErrorLogger* errorLogger, + ErrorLogger& errorLogger, const Settings& settings, TimerResultsIntf* timerResults); From 4595196b876e54259e99bd1f4a289b69593f5032 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 7 Aug 2023 19:38:12 +0200 Subject: [PATCH 2/9] avoid some unchecked pointer dereferences --- lib/symboldatabase.cpp | 4 ++-- lib/tokenize.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b8451b90005..da98549e5c3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2133,7 +2133,7 @@ void SymbolDatabase::validateExecutableScopes() const for (std::size_t i = 0; i < functions; ++i) { const Scope* const scope = functionScopes[i]; const Function* const function = scope->function; - if (scope->isExecutable() && !function) { + if (mErrorLogger && scope->isExecutable() && !function) { const std::list callstack(1, scope->classDef); const std::string msg = std::string("Executable scope '") + scope->classDef->str() + "' with unknown function."; const ErrorMessage errmsg(callstack, &mTokenizer.list, Severity::debug, @@ -2198,7 +2198,7 @@ void SymbolDatabase::debugSymbolDatabase() const for (const Token* tok = mTokenizer.list.front(); tok != mTokenizer.list.back(); tok = tok->next()) { if (tok->astParent() && tok->astParent()->getTokenDebug() == tok->getTokenDebug()) continue; - if (tok->getTokenDebug() == TokenDebug::ValueType) { + if (mErrorLogger && tok->getTokenDebug() == TokenDebug::ValueType) { std::string msg = "Value type is "; ErrorPath errorPath; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 257f4a2d3c3..f2ccf62ba5a 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1149,7 +1149,7 @@ void Tokenizer::simplifyTypedefCpp() return; if (maxTime > 0 && std::time(nullptr) > maxTime) { - if (mSettings.debugwarnings) { + if (mErrorLogger && mSettings.debugwarnings) { ErrorMessage::FileLocation loc(list.getFiles()[0], 0, 0); ErrorMessage errmsg({std::move(loc)}, emptyString, @@ -3407,6 +3407,7 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) const bool doValueFlow = !disableValueflowEnv || (std::strcmp(disableValueflowEnv, "1") != 0); if (doValueFlow) { + assert(mErrorLogger); if (mTimerResults) { Timer t("Tokenizer::simplifyTokens1::ValueFlow", mSettings.showtime, mTimerResults); ValueFlow::setValues(list, *mSymbolDatabase, *mErrorLogger, mSettings, mTimerResults); @@ -6070,7 +6071,8 @@ void Tokenizer::dump(std::ostream &out) const out << outs; outs.clear(); - mSymbolDatabase->printXml(out); + if (mSymbolDatabase) + mSymbolDatabase->printXml(out); containers.erase(nullptr); if (!containers.empty()) { From e27d171a1501566160452f57d85e001b3ef363b9 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 7 Aug 2023 19:45:03 +0200 Subject: [PATCH 3/9] testrunner: adjusted several `Tokenizer` creations --- test/testlibrary.cpp | 12 ++++++------ test/testtokenize.cpp | 24 ++++++++++++------------ test/testtokenrange.cpp | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index 09f2a3a5e53..c9e2a9b8c83 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -558,7 +558,7 @@ class TestLibrary : public TestFixture { } } - void function_method() const { + void function_method() { constexpr char xmldata[] = "\n" "\n" " \n" @@ -571,21 +571,21 @@ class TestLibrary : public TestFixture { ASSERT_EQUALS(library.functions.size(), 1U); { - Tokenizer tokenizer(settings, nullptr); + Tokenizer tokenizer(settings, this); std::istringstream istr("CString str; str.Format();"); ASSERT(tokenizer.tokenize(istr, "test.cpp")); ASSERT(library.isnotnoreturn(Token::findsimplematch(tokenizer.tokens(), "Format"))); } { - Tokenizer tokenizer(settings, nullptr); + Tokenizer tokenizer(settings, this); std::istringstream istr("HardDrive hd; hd.Format();"); ASSERT(tokenizer.tokenize(istr, "test.cpp")); ASSERT(!library.isnotnoreturn(Token::findsimplematch(tokenizer.tokens(), "Format"))); } } - void function_baseClassMethod() const { + void function_baseClassMethod() { constexpr char xmldata[] = "\n" "\n" " \n" @@ -597,14 +597,14 @@ class TestLibrary : public TestFixture { ASSERT(loadxmldata(library, xmldata, sizeof(xmldata))); { - Tokenizer tokenizer(settings, nullptr); + Tokenizer tokenizer(settings, this); std::istringstream istr("struct X : public Base { void dostuff() { f(0); } };"); ASSERT(tokenizer.tokenize(istr, "test.cpp")); ASSERT(library.isnullargbad(Token::findsimplematch(tokenizer.tokens(), "f"),1)); } { - Tokenizer tokenizer(settings, nullptr); + Tokenizer tokenizer(settings, this); std::istringstream istr("struct X : public Base { void dostuff() { f(1,2); } };"); ASSERT(tokenizer.tokenize(istr, "test.cpp")); ASSERT(!library.isnullargbad(Token::findsimplematch(tokenizer.tokens(), "f"),1)); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3bcf6796ad0..7c12119f962 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -5909,9 +5909,9 @@ class TestTokenizer : public TestFixture { Z3 }; - std::string testAst(const char code[], AstStyle style = AstStyle::Simple) const { + std::string testAst(const char code[], AstStyle style = AstStyle::Simple) { // tokenize given code.. - Tokenizer tokenizer(settings0, nullptr); + Tokenizer tokenizer(settings0, this); std::istringstream istr(code); if (!tokenizer.list.createTokens(istr,"test.cpp")) return "ERROR"; @@ -5958,7 +5958,7 @@ class TestTokenizer : public TestFixture { return ret; } - void astexpr() const { // simple expressions with arithmetical ops + void astexpr() { // simple expressions with arithmetical ops ASSERT_EQUALS("12+3+", testAst("1+2+3")); ASSERT_EQUALS("12*3+", testAst("1*2+3")); ASSERT_EQUALS("123*+", testAst("1+2*3")); @@ -6220,7 +6220,7 @@ class TestTokenizer : public TestFixture { ASSERT_NO_THROW(tokenizeAndStringify(code)); } - void astnewdelete() const { + void astnewdelete() { ASSERT_EQUALS("aintnew=", testAst("a = new int;")); ASSERT_EQUALS("aint4[new=", testAst("a = new int[4];")); ASSERT_EQUALS("aFoobar(new=", testAst("a = new Foo(bar);")); @@ -6445,7 +6445,7 @@ class TestTokenizer : public TestFixture { "}\n")); } - void astbrackets() const { // [] + void astbrackets() { // [] ASSERT_EQUALS("a23+[4+", testAst("a[2+3]+4")); ASSERT_EQUALS("a1[0[", testAst("a[1][0]")); ASSERT_EQUALS("ab0[=", testAst("a=(b)[0];")); @@ -6453,7 +6453,7 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("ab0[1[=", testAst("a=b[0][1];")); } - void astvardecl() const { + void astvardecl() { // Variable declaration ASSERT_EQUALS("a1[\"\"=", testAst("char a[1]=\"\";")); ASSERT_EQUALS("charp*(3[char5[3[new=", testAst("char (*p)[3] = new char[5][3];")); @@ -6491,7 +6491,7 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("", testAst("void f(bool& var){}")); } - void astunaryop() const { // unary operators + void astunaryop() { // unary operators ASSERT_EQUALS("1a--+", testAst("1 + --a")); ASSERT_EQUALS("1a--+", testAst("1 + a--")); ASSERT_EQUALS("ab+!", testAst("!(a+b)")); @@ -6517,7 +6517,7 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("int0{1&return", testAst("int g() { return int{ 0 } & 1; }")); } - void astfunction() const { // function calls + void astfunction() { // function calls ASSERT_EQUALS("1f(+2+", testAst("1+f()+2")); ASSERT_EQUALS("1f2(+3+", testAst("1+f(2)+3")); ASSERT_EQUALS("1f23,(+4+", testAst("1+f(2,3)+4")); @@ -6583,7 +6583,7 @@ class TestTokenizer : public TestFixture { "}\n")); } - void astcast() const { + void astcast() { ASSERT_EQUALS("ac&(=", testAst("a = (long)&c;")); ASSERT_EQUALS("ac*(=", testAst("a = (Foo*)*c;")); ASSERT_EQUALS("ac-(=", testAst("a = (long)-c;")); @@ -6769,14 +6769,14 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("sf.{(i[{={", testAst("void g(int i) { S s{ .f = { [i]() {} } }; }")); } - void astcase() const { + void astcase() { ASSERT_EQUALS("0case", testAst("case 0:")); ASSERT_EQUALS("12+case", testAst("case 1+2:")); ASSERT_EQUALS("xyz:?case", testAst("case (x?y:z):")); ASSERT_EQUALS("switchx( 1case y++ 2case", testAst("switch(x){case 1:{++y;break;case 2:break;}}")); } - void astrefqualifier() const { + void astrefqualifier() { ASSERT_EQUALS("b(int.", testAst("class a { auto b() -> int&; };")); ASSERT_EQUALS("b(int.", testAst("class a { auto b() -> int&&; };")); ASSERT_EQUALS("b(", testAst("class a { void b() &&; };")); @@ -6787,7 +6787,7 @@ class TestTokenizer : public TestFixture { //Verify that returning a newly constructed object generates the correct AST even when the class name is scoped //Addresses https://trac.cppcheck.net/ticket/9700 - void astnewscoped() const { + void astnewscoped() { ASSERT_EQUALS("(return (new A))", testAst("return new A;", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( A)))", testAst("return new A();", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( A true)))", testAst("return new A(true);", AstStyle::Z3)); diff --git a/test/testtokenrange.cpp b/test/testtokenrange.cpp index 4843591654b..63c4173c1f7 100644 --- a/test/testtokenrange.cpp +++ b/test/testtokenrange.cpp @@ -97,8 +97,8 @@ class TestTokenRange : public TestFixture { ASSERT_EQUALS("", testTokenRange(ConstTokenRange{ start, end }, start, end)); } - void scopeExample() const { - Tokenizer tokenizer(settingsDefault); + void scopeExample() { + Tokenizer tokenizer(settingsDefault, this); std::istringstream sample("void a(){} void main(){ if(true){a();} }"); ASSERT(tokenizer.tokenize(sample, "test.cpp")); From eef052c46fdce799eaa8cea7dddce2b92d7cadc0 Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 9 Mar 2024 23:53:32 +0100 Subject: [PATCH 4/9] valueflow.cpp: removed need for `LifetimeStore::Context` --- lib/valueflow.cpp | 65 +++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 4132ccfd334..5a9cddd2eee 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4051,13 +4051,6 @@ struct LifetimeStore { bool inconclusive{}; bool forward = true; - struct Context { - Token* tok{}; - TokenList* tokenlist{}; - ErrorLogger* errorLogger{}; - const Settings* settings{}; - }; - LifetimeStore() = default; LifetimeStore(const Token* argtok, @@ -4071,23 +4064,23 @@ struct LifetimeStore { {} template - static void forEach(const std::vector& argtoks, + static void forEach(TokenList& tokenlist, + ErrorLogger& errorLogger, + const Settings& settings, + const std::vector& argtoks, const std::string& message, ValueFlow::Value::LifetimeKind type, F f) { - std::map forwardToks; + std::set forwardToks; for (const Token* arg : argtoks) { LifetimeStore ls{arg, message, type}; - Context c{}; - ls.mContext = &c; ls.forward = false; f(ls); - if (c.tok) - forwardToks[c.tok] = c; + if (ls.forwardTok) + forwardToks.emplace(ls.forwardTok); } - for (const auto& p : forwardToks) { - const Context& c = p.second; - valueFlowForwardLifetime(c.tok, *c.tokenlist, *c.errorLogger, *c.settings); + for (auto* tok : forwardToks) { + valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); } } @@ -4323,14 +4316,9 @@ struct LifetimeStore { } private: - Context* mContext{}; + mutable Token* forwardTok{}; void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) const { - if (mContext) { - mContext->tok = tok; - mContext->tokenlist = &tokenlist; - mContext->errorLogger = &errorLogger; - mContext->settings = &settings; - } + forwardTok = tok; valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); } }; @@ -4424,7 +4412,10 @@ static void valueFlowLifetimeUserConstructor(Token* tok, } } // TODO: Use SubExpressionAnalyzer for members - LifetimeStore::forEach(args, + LifetimeStore::forEach(tokenlist, + errorLogger, + settings, + args, "Passed to constructor of '" + name + "'.", ValueFlow::Value::LifetimeKind::SubObject, [&](const LifetimeStore& ls) { @@ -4438,7 +4429,10 @@ static void valueFlowLifetimeUserConstructor(Token* tok, ls.byVal(tok, tokenlist, errorLogger, settings); }); } else if (hasBorrowingVariables(constructor->nestedIn->varlist, args)) { - LifetimeStore::forEach(args, + LifetimeStore::forEach(tokenlist, + errorLogger, + settings, + args, "Passed to constructor of '" + name + "'.", ValueFlow::Value::LifetimeKind::SubObject, [&](LifetimeStore& ls) { @@ -4659,7 +4653,10 @@ static void valueFlowLifetimeClassConstructor(Token* tok, // If the type is unknown then assume it captures by value in the // constructor, but make each lifetime inconclusive std::vector args = getArguments(tok); - LifetimeStore::forEach(args, + LifetimeStore::forEach(tokenlist, + errorLogger, + settings, + args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](LifetimeStore& ls) { @@ -4677,6 +4674,9 @@ static void valueFlowLifetimeClassConstructor(Token* tok, if (scope->numConstructors == 0) { auto it = scope->varlist.cbegin(); LifetimeStore::forEach( + tokenlist, + errorLogger, + settings, args, "Passed to constructor of '" + t->name() + "'.", ValueFlow::Value::LifetimeKind::SubObject, @@ -4721,7 +4721,10 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, Error for (const ValueType& vt : vts) { if (vt.pointer > 0) { std::vector args = getArguments(tok); - LifetimeStore::forEach(args, + LifetimeStore::forEach(tokenlist, + errorLogger, + settings, + args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](const LifetimeStore& ls) { @@ -4734,6 +4737,9 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, Error .byRef(tok, tokenlist, errorLogger, settings); } else if (args.size() == 2 && astIsIterator(args[0]) && astIsIterator(args[1])) { LifetimeStore::forEach( + tokenlist, + errorLogger, + settings, args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, @@ -4741,7 +4747,10 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, Error ls.byDerefCopy(tok, tokenlist, errorLogger, settings); }); } else if (vt.container->hasInitializerListConstructor) { - LifetimeStore::forEach(args, + LifetimeStore::forEach(tokenlist, + errorLogger, + settings, + args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](const LifetimeStore& ls) { From 76a459a75be4e1eec2f65ed1fee90fd5bfc5a6b6 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 11 Mar 2024 05:10:58 +0100 Subject: [PATCH 5/9] Tokenizer: made `ErrorLogger` parameter mandatory in constructor --- lib/importproject.cpp | 2 +- lib/tokenize.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/importproject.cpp b/lib/importproject.cpp index 754dcb812d8..0eebe0bdb0a 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -562,7 +562,7 @@ namespace { // TODO: evaluate without using the Tokenizer const Settings s; - Tokenizer tokenizer(s); + Tokenizer tokenizer(s, nullptr); std::istringstream istr(c); tokenizer.tokenize(istr,"vcxproj.c"); for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { diff --git a/lib/tokenize.h b/lib/tokenize.h index de8b6e8a1bc..d6155fefb6b 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -54,7 +54,7 @@ class CPPCHECKLIB Tokenizer { friend class TemplateSimplifier; public: - explicit Tokenizer(const Settings & settings, ErrorLogger *errorLogger = nullptr, const Preprocessor *preprocessor = nullptr); + explicit Tokenizer(const Settings & settings, ErrorLogger *errorLogger, const Preprocessor *preprocessor = nullptr); ~Tokenizer(); void setTimerResults(TimerResults *tr) { From c8de69bed9ed51b5f907395e8a2b942a25aa2c1d Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 11 Mar 2024 11:08:19 +0100 Subject: [PATCH 6/9] importproject.cpp: use `TokenList` instead of `Tokenizer` in `ItemDefinitionGroup::conditionIsTrue()` --- lib/importproject.cpp | 11 +++++++---- test/testimportproject.cpp | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/lib/importproject.cpp b/lib/importproject.cpp index 0eebe0bdb0a..34780f7cd49 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -553,6 +553,8 @@ namespace { } } + // see https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-conditions + // properties are .NET String objects and you can call any of its members on them bool conditionIsTrue(const ProjectConfiguration &p) const { if (condition.empty()) return true; @@ -560,13 +562,14 @@ namespace { replaceAll(c, "$(Configuration)", p.configuration); replaceAll(c, "$(Platform)", p.platformStr); - // TODO: evaluate without using the Tokenizer + // TODO: improve evaluation const Settings s; - Tokenizer tokenizer(s, nullptr); + TokenList tokenlist(&s); std::istringstream istr(c); - tokenizer.tokenize(istr,"vcxproj.c"); - for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { + tokenlist.createTokens(istr, Standards::Language::C); // TODO: check result + for (const Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (tok->str() == "(" && tok->astOperand1() && tok->astOperand2()) { + // TODO: this is wrong - it is Contains() not Equals() if (tok->astOperand1()->expressionString() == "Configuration.Contains") return ('\'' + p.configuration + '\'') == tok->astOperand2()->str(); } diff --git a/test/testimportproject.cpp b/test/testimportproject.cpp index a21819c60ec..577faf0c493 100644 --- a/test/testimportproject.cpp +++ b/test/testimportproject.cpp @@ -389,6 +389,27 @@ class TestImportProject : public TestFixture { } // TODO: test fsParseCommand() + + // TODO: test vcxproj conditions + /* + + + + + Debug + x64 + + + + + CPPCHECKLIB_IMPORT + + + + + + + */ }; REGISTER_TEST(TestImportProject) From 92cbc6c23ab02111816c7f8ade23c537a0ccfac0 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 11 Mar 2024 11:16:26 +0100 Subject: [PATCH 7/9] tokenize.cpp: mitigated `unusedFunction` selfcheck warning --- lib/tokenize.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index f2ccf62ba5a..b1c6c76f64d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3440,6 +3440,7 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) return true; } +// cppcheck-suppress unusedFunction - used in tests only bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::string &configuration) From 127d36179d36b7bf055b5bb5617a01de12c665ba Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 11 Mar 2024 16:02:20 +0100 Subject: [PATCH 8/9] valueflow.cpp: mitigated `naming-privateMemberVariable` selfcheck warning --- lib/valueflow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5a9cddd2eee..2853e1feb07 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4316,6 +4316,7 @@ struct LifetimeStore { } private: + // cppcheck-suppress naming-privateMemberVariable mutable Token* forwardTok{}; void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) const { forwardTok = tok; From 589d6f3797aa42525b61a3f97f9be0f52ca3cfb3 Mon Sep 17 00:00:00 2001 From: firewave Date: Tue, 2 Apr 2024 21:36:02 +0200 Subject: [PATCH 9/9] valueflow.cpp: removed `mutable` from `lifetimeStore::forwardTok` --- lib/valueflow.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 2853e1feb07..ee8ad0d0d14 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4113,7 +4113,7 @@ struct LifetimeStore { ErrorLogger& errorLogger, const Settings& settings, Predicate pred, - SourceLocation loc = SourceLocation::current()) const + SourceLocation loc = SourceLocation::current()) { if (!argtok) return false; @@ -4153,7 +4153,7 @@ struct LifetimeStore { TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, - SourceLocation loc = SourceLocation::current()) const + SourceLocation loc = SourceLocation::current()) { return byRef( tok, @@ -4172,7 +4172,7 @@ struct LifetimeStore { ErrorLogger& errorLogger, const Settings& settings, Predicate pred, - SourceLocation loc = SourceLocation::current()) const + SourceLocation loc = SourceLocation::current()) { if (!argtok) return false; @@ -4248,7 +4248,7 @@ struct LifetimeStore { TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, - SourceLocation loc = SourceLocation::current()) const + SourceLocation loc = SourceLocation::current()) { return byVal( tok, @@ -4317,8 +4317,8 @@ struct LifetimeStore { private: // cppcheck-suppress naming-privateMemberVariable - mutable Token* forwardTok{}; - void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) const { + Token* forwardTok{}; + void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { forwardTok = tok; valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); } @@ -4419,7 +4419,7 @@ static void valueFlowLifetimeUserConstructor(Token* tok, args, "Passed to constructor of '" + name + "'.", ValueFlow::Value::LifetimeKind::SubObject, - [&](const LifetimeStore& ls) { + [&](LifetimeStore& ls) { const Variable* paramVar = argToParam.at(ls.argtok); if (paramCapture.count(paramVar) == 0) return; @@ -4681,7 +4681,7 @@ static void valueFlowLifetimeClassConstructor(Token* tok, args, "Passed to constructor of '" + t->name() + "'.", ValueFlow::Value::LifetimeKind::SubObject, - [&](const LifetimeStore& ls) { + [&](LifetimeStore& ls) { // Skip static variable it = std::find_if(it, scope->varlist.cend(), [](const Variable& var) { return !var.isStatic(); @@ -4728,7 +4728,7 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, Error args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, - [&](const LifetimeStore& ls) { + [&](LifetimeStore& ls) { ls.byVal(tok, tokenlist, errorLogger, settings); }); } else if (vt.container && vt.type == ValueType::CONTAINER) { @@ -4754,7 +4754,7 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, Error args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, - [&](const LifetimeStore& ls) { + [&](LifetimeStore& ls) { ls.byVal(tok, tokenlist, errorLogger, settings); }); }