From c257c70347020b9f4ee00d5d02dd3823015ef3bb Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 14 Aug 2023 14:32:35 +0200 Subject: [PATCH] Fix #11546 FP danglingTemporaryLifetime with unknown member (#5256) --- lib/valueflow.cpp | 27 ++++++++++++++++----------- test/testautovariables.cpp | 13 +++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 713b2dad9..c6ba15f68 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4256,28 +4256,33 @@ private: } }; -static bool isOwningVariables(const std::list& vars, int depth = 10) +static bool hasBorrowingVariables(const std::list& vars, const std::vector& args, int depth = 10) { if (depth < 0) return false; - return vars.empty() || std::all_of(vars.cbegin(), vars.cend(), [&](const Variable& var) { - if (var.isReference() || var.isPointer()) - return false; + return std::any_of(vars.cbegin(), vars.cend(), [&](const Variable& var) { const ValueType* vt = var.valueType(); if (vt) { - if (vt->pointer > 0) + if (vt->pointer > 0 && + std::none_of(args.begin(), args.end(), [vt](const Token* arg) { + return arg->valueType() && arg->valueType()->type == vt->type; + })) return false; + if (vt->pointer > 0) + return true; + if (vt->reference != Reference::None) + return true; if (vt->isPrimitive()) - return true; + return false; if (vt->isEnum()) - return true; + return false; // TODO: Check container inner type if (vt->type == ValueType::CONTAINER && vt->container) - return !vt->container->view; + return vt->container->view; if (vt->typeScope) - return isOwningVariables(vt->typeScope->varlist, depth - 1); + return hasBorrowingVariables(vt->typeScope->varlist, args, depth - 1); } - return false; + return true; }); } @@ -4354,7 +4359,7 @@ static void valueFlowLifetimeUserConstructor(Token* tok, else ls.byVal(tok, tokenlist, errorLogger, settings); }); - } else if (!isOwningVariables(constructor->nestedIn->varlist)) { + } else if (hasBorrowingVariables(constructor->nestedIn->varlist, args)) { LifetimeStore::forEach(args, "Passed to constructor of '" + name + "'.", ValueFlow::Value::LifetimeKind::SubObject, diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 0ee1d8413..159782782 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -3647,6 +3647,19 @@ private: "}\n", true); ASSERT_EQUALS("", errout.str()); + + check("struct S {\n" + " explicit S(const char* p) { m = p; }\n" + " void g();\n" + " std::string m;\n" + " int* t{};\n" + "};\n" + "void f(const std::stringstream& buffer) {\n" + " S s(buffer.str().c_str());\n" + " s.g();\n" + "}\n", + true); + ASSERT_EQUALS("", errout.str()); } void danglingLifetimeAggegrateConstructor() {