diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index af9ee1ec081e..ab5754948964 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3875,10 +3875,10 @@ 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, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings); static void valueFlowLifetimeConstructor(Token *tok, - TokenList &tokenlist, + const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings); @@ -3957,7 +3957,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, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings) { // Forward lifetimes to constructed variable if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) { @@ -4055,13 +4055,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, @@ -4075,23 +4068,24 @@ struct LifetimeStore { {} template - static void forEach(const std::vector& argtoks, + static void forEach(const 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::map 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(arg, ls.forwardTok); } for (const auto& p : forwardToks) { - const Context& c = p.second; - valueFlowForwardLifetime(c.tok, *c.tokenlist, *c.errorLogger, *c.settings); + const auto tok = p.second; + valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); } } @@ -4120,7 +4114,7 @@ struct LifetimeStore { template bool byRef(Token* tok, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, Predicate pred, @@ -4161,7 +4155,7 @@ struct LifetimeStore { } bool byRef(Token* tok, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const @@ -4179,7 +4173,7 @@ struct LifetimeStore { template bool byVal(Token* tok, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, Predicate pred, @@ -4256,7 +4250,7 @@ struct LifetimeStore { } bool byVal(Token* tok, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const @@ -4274,7 +4268,7 @@ struct LifetimeStore { template bool byDerefCopy(Token* tok, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, Predicate pred, @@ -4310,7 +4304,7 @@ struct LifetimeStore { } bool byDerefCopy(Token* tok, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const @@ -4327,14 +4321,9 @@ struct LifetimeStore { } private: - Context* mContext{}; - 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; - } + mutable Token* forwardTok{}; + void forwardLifetime(Token* tok, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) const { + forwardTok = tok; valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); } }; @@ -4372,7 +4361,7 @@ static void valueFlowLifetimeUserConstructor(Token* tok, const Function* constructor, const std::string& name, const std::vector& args, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { @@ -4428,7 +4417,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) { @@ -4442,7 +4434,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) { @@ -4456,7 +4451,7 @@ static void valueFlowLifetimeUserConstructor(Token* tok, } } -static void valueFlowLifetimeFunction(Token *tok, TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings) +static void valueFlowLifetimeFunction(Token *tok, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings) { if (!Token::Match(tok, "%name% (")) return; @@ -4647,7 +4642,7 @@ static const Function* findConstructor(const Scope* scope, const Token* tok, con static void valueFlowLifetimeClassConstructor(Token* tok, const Type* t, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { @@ -4663,7 +4658,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) { @@ -4681,6 +4679,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, @@ -4706,7 +4707,7 @@ static void valueFlowLifetimeClassConstructor(Token* tok, } } -static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) +static void valueFlowLifetimeConstructor(Token* tok, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { if (!Token::Match(tok, "(|{")) return; @@ -4725,7 +4726,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) { @@ -4738,6 +4742,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, @@ -4745,7 +4752,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) {