diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index a321dbfa4..b0f2f22b9 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4079,19 +4079,20 @@ struct LifetimeStore { } template - void byDerefCopy(Token* tok, + bool byDerefCopy(Token* tok, TokenList* tokenlist, ErrorLogger* errorLogger, const Settings* settings, Predicate pred, SourceLocation loc = SourceLocation::current()) const { + bool update = false; if (!settings->certainty.isEnabled(Certainty::inconclusive) && inconclusive) - return; + return update; if (!argtok) - return; + return update; if (!tok) - return; + return update; for (const ValueFlow::Value &v : argtok->values()) { if (!v.isLifetimeValue()) continue; @@ -4105,20 +4106,22 @@ struct LifetimeStore { const Token * const varDeclEndToken = var->declEndToken(); for (const Token *tok3 = tok; tok3 && tok3 != varDeclEndToken; tok3 = tok3->previous()) { if (tok3->varId() == var->declarationId()) { - LifetimeStore{tok3, message, type, inconclusive}.byVal(tok, tokenlist, errorLogger, settings, pred, loc); + update |= LifetimeStore{tok3, message, type, inconclusive} + .byVal(tok, tokenlist, errorLogger, settings, pred, loc); break; } } } + return update; } - void byDerefCopy(Token* tok, + bool byDerefCopy(Token* tok, TokenList* tokenlist, ErrorLogger* errorLogger, const Settings* settings, SourceLocation loc = SourceLocation::current()) const { - byDerefCopy( + return byDerefCopy( tok, tokenlist, errorLogger, @@ -4348,9 +4351,14 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog ls.forward = false; ls.errorPath = v.errorPath; ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + "."); - if (v.lifetimeScope == ValueFlow::Value::LifetimeScope::ThisValue) + int thisIndirect = v.lifetimeScope == ValueFlow::Value::LifetimeScope::ThisValue ? 0 : 1; + if (derefShared(memtok->astParent())) + thisIndirect--; + if (thisIndirect == -1) + update |= ls.byDerefCopy(tok->next(), tokenlist, errorLogger, settings); + else if (thisIndirect == 0) update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings); - else + else if (thisIndirect == 1) update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings); continue; } diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index db887c133..e6b0c3769 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -2004,6 +2004,24 @@ private: ASSERT_EQUALS( "[test.cpp:11] -> [test.cpp:2] -> [test.cpp:11] -> [test.cpp:12]: (error) Using reference to dangling temporary.\n", errout.str()); + + check("struct C {\n" + " std::vector> v;\n" + "};\n" + "struct P {\n" + " std::vector::const_iterator find() const { return pv.begin(); }\n" + " std::vector pv;\n" + "};\n" + "struct M {\n" + " const P* get() const { return p; }\n" + " P* p;\n" + "};\n" + "void f(const M* m) {\n" + " auto it = m->get()->find();\n" + " auto e = (*it)->v.begin();\n" + " const int& x = (*e)[1];\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void testglobalnamespace() {