Fix #11546 FP danglingTemporaryLifetime with unknown member (#5256)

This commit is contained in:
chrchr-github 2023-08-14 14:32:35 +02:00 committed by GitHub
parent d064f9c243
commit c257c70347
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 11 deletions

View File

@ -4256,28 +4256,33 @@ private:
} }
}; };
static bool isOwningVariables(const std::list<Variable>& vars, int depth = 10) static bool hasBorrowingVariables(const std::list<Variable>& vars, const std::vector<const Token*>& args, int depth = 10)
{ {
if (depth < 0) if (depth < 0)
return false; return false;
return vars.empty() || std::all_of(vars.cbegin(), vars.cend(), [&](const Variable& var) { return std::any_of(vars.cbegin(), vars.cend(), [&](const Variable& var) {
if (var.isReference() || var.isPointer())
return false;
const ValueType* vt = var.valueType(); const ValueType* vt = var.valueType();
if (vt) { 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; return false;
if (vt->pointer > 0)
return true;
if (vt->reference != Reference::None)
return true;
if (vt->isPrimitive()) if (vt->isPrimitive())
return true; return false;
if (vt->isEnum()) if (vt->isEnum())
return true; return false;
// TODO: Check container inner type // TODO: Check container inner type
if (vt->type == ValueType::CONTAINER && vt->container) if (vt->type == ValueType::CONTAINER && vt->container)
return !vt->container->view; return vt->container->view;
if (vt->typeScope) 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 else
ls.byVal(tok, tokenlist, errorLogger, settings); ls.byVal(tok, tokenlist, errorLogger, settings);
}); });
} else if (!isOwningVariables(constructor->nestedIn->varlist)) { } else if (hasBorrowingVariables(constructor->nestedIn->varlist, args)) {
LifetimeStore::forEach(args, LifetimeStore::forEach(args,
"Passed to constructor of '" + name + "'.", "Passed to constructor of '" + name + "'.",
ValueFlow::Value::LifetimeKind::SubObject, ValueFlow::Value::LifetimeKind::SubObject,

View File

@ -3647,6 +3647,19 @@ private:
"}\n", "}\n",
true); true);
ASSERT_EQUALS("", errout.str()); 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() { void danglingLifetimeAggegrateConstructor() {