parent
d064f9c243
commit
c257c70347
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue