Fix 11298: FP danglingTemporaryLifetime when constructing from const char* (#4479)
* Fix 11298: FP danglingTemporaryLifetime when constructing from const char* * Format
This commit is contained in:
parent
de7d02293f
commit
09944c0b7e
|
@ -4014,6 +4014,31 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool isOwningVariables(const std::list<Variable>& vars, int depth = 10)
|
||||||
|
{
|
||||||
|
if (depth < 0)
|
||||||
|
return false;
|
||||||
|
return vars.empty() || std::all_of(vars.begin(), vars.end(), [&](const Variable& var) {
|
||||||
|
if (var.isReference() || var.isPointer())
|
||||||
|
return false;
|
||||||
|
const ValueType* vt = var.valueType();
|
||||||
|
if (vt) {
|
||||||
|
if (vt->pointer > 0)
|
||||||
|
return false;
|
||||||
|
if (vt->isPrimitive())
|
||||||
|
return true;
|
||||||
|
if (vt->isEnum())
|
||||||
|
return true;
|
||||||
|
// TODO: Check container inner type
|
||||||
|
if (vt->type == ValueType::CONTAINER && vt->container)
|
||||||
|
return !vt->container->view;
|
||||||
|
if (vt->typeScope)
|
||||||
|
return isOwningVariables(vt->typeScope->varlist, depth - 1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static void valueFlowLifetimeUserConstructor(Token* tok,
|
static void valueFlowLifetimeUserConstructor(Token* tok,
|
||||||
const Function* constructor,
|
const Function* constructor,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
|
@ -4087,7 +4112,7 @@ static void valueFlowLifetimeUserConstructor(Token* tok,
|
||||||
else
|
else
|
||||||
ls.byVal(tok, tokenlist, errorLogger, settings);
|
ls.byVal(tok, tokenlist, errorLogger, settings);
|
||||||
});
|
});
|
||||||
} else if (!constructor->nestedIn->varlist.empty()) {
|
} else if (!isOwningVariables(constructor->nestedIn->varlist)) {
|
||||||
LifetimeStore::forEach(args,
|
LifetimeStore::forEach(args,
|
||||||
"Passed to constructor of '" + name + "'.",
|
"Passed to constructor of '" + name + "'.",
|
||||||
ValueFlow::Value::LifetimeKind::SubObject,
|
ValueFlow::Value::LifetimeKind::SubObject,
|
||||||
|
@ -4299,7 +4324,7 @@ static void valueFlowLifetimeClassConstructor(Token* tok,
|
||||||
const Scope* scope = t->classScope;
|
const Scope* scope = t->classScope;
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return;
|
return;
|
||||||
// Only support aggregate constructors for now
|
// Aggregate constructor
|
||||||
if (t->derivedFrom.empty() && (t->isClassType() || t->isStructType())) {
|
if (t->derivedFrom.empty() && (t->isClassType() || t->isStructType())) {
|
||||||
std::vector<const Token*> args = getArguments(tok);
|
std::vector<const Token*> args = getArguments(tok);
|
||||||
if (scope->numConstructors == 0) {
|
if (scope->numConstructors == 0) {
|
||||||
|
|
|
@ -3656,6 +3656,26 @@ private:
|
||||||
" return c.get();\n"
|
" return c.get();\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:7] -> [test.cpp:8]: (error) Using object that is a temporary.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:7] -> [test.cpp:8]: (error) Using object that is a temporary.\n", errout.str());
|
||||||
|
|
||||||
|
// #11298
|
||||||
|
check("struct S {\n"
|
||||||
|
" std::string g(); \n"
|
||||||
|
"};\n"
|
||||||
|
"struct T {\n"
|
||||||
|
" void f(); \n"
|
||||||
|
" S* p = nullptr;\n"
|
||||||
|
"};\n"
|
||||||
|
"struct U {\n"
|
||||||
|
" explicit U(const char* s);\n"
|
||||||
|
" bool h();\n"
|
||||||
|
" int i;\n"
|
||||||
|
"};\n"
|
||||||
|
"void T::f() {\n"
|
||||||
|
" U u(p->g().c_str());\n"
|
||||||
|
" if (u.h()) {}\n"
|
||||||
|
"}\n",
|
||||||
|
true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void danglingLifetimeBorrowedMembers()
|
void danglingLifetimeBorrowedMembers()
|
||||||
|
|
Loading…
Reference in New Issue