coroutines : Adjust constraints on when to build ctors [PR98118].
PR98118 shows that TYPE_NEEDS_CONSTRUCTING is necessary but not sufficient. Use type_build_ctor_call() instead. gcc/cp/ChangeLog: PR c++/98118 * coroutines.cc (build_co_await): Use type_build_ctor_call() to determine cases when a CTOR needs to be built. (flatten_await_stmt): Likewise. (morph_fn_to_coro): Likewise. gcc/testsuite/ChangeLog: PR c++/98118 * g++.dg/coroutines/pr98118.C: New test.
This commit is contained in:
parent
9ee91079fd
commit
3d9577c254
@ -949,7 +949,7 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
|
||||
e_proxy = o;
|
||||
o = NULL_TREE; /* The var is already present. */
|
||||
}
|
||||
else if (CLASS_TYPE_P (o_type) || TYPE_NEEDS_CONSTRUCTING (o_type))
|
||||
else if (type_build_ctor_call (o_type))
|
||||
{
|
||||
e_proxy = get_awaitable_var (suspend_kind, o_type);
|
||||
releasing_vec arg (make_tree_vector_single (rvalue (o)));
|
||||
@ -2965,7 +2965,7 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
|
||||
gcc_checking_assert (!already_present);
|
||||
tree inner = TREE_OPERAND (init, 1);
|
||||
gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
|
||||
if (TYPE_NEEDS_CONSTRUCTING (var_type))
|
||||
if (type_build_ctor_call (var_type))
|
||||
{
|
||||
releasing_vec p_in (make_tree_vector_single (init));
|
||||
init = build_special_member_call (var, complete_ctor_identifier,
|
||||
@ -2977,9 +2977,9 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
|
||||
var_nest_node *ins
|
||||
= new var_nest_node (var, init, n->prev, n);
|
||||
/* We have to replace the target expr... */
|
||||
proxy_replace pr = {TREE_OPERAND (t, 0), var};
|
||||
*v.entry = var;
|
||||
/* ... and any uses of its var. */
|
||||
proxy_replace pr = {TREE_OPERAND (t, 0), var};
|
||||
cp_walk_tree (&n->init, replace_proxy, &pr, NULL);
|
||||
/* Compiler-generated temporaries can also have uses in following
|
||||
arms of compound expressions, which will be listed in 'replace_in'
|
||||
@ -4681,7 +4681,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
|
||||
parm.frame_type, INIT_EXPR,
|
||||
DECL_SOURCE_LOCATION (arg), arg,
|
||||
DECL_ARG_TYPE (arg));
|
||||
else if (TYPE_NEEDS_CONSTRUCTING (parm.frame_type))
|
||||
else if (type_build_ctor_call (parm.frame_type))
|
||||
{
|
||||
vec<tree, va_gc> *p_in;
|
||||
if (CLASS_TYPE_P (parm.frame_type)
|
||||
@ -4739,7 +4739,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
|
||||
false, tf_warning_or_error);
|
||||
|
||||
tree promise_dtor = NULL_TREE;
|
||||
if (TYPE_NEEDS_CONSTRUCTING (promise_type))
|
||||
if (type_build_ctor_call (promise_type))
|
||||
{
|
||||
/* Do a placement new constructor for the promise type (we never call
|
||||
the new operator, just the constructor on the object in place in the
|
||||
@ -4820,7 +4820,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
|
||||
The expression promise.get_return_object() is used to initialize the
|
||||
glvalue result or... (see below)
|
||||
Construct the return result directly. */
|
||||
if (TYPE_NEEDS_CONSTRUCTING (gro_type))
|
||||
if (type_build_ctor_call (gro_type))
|
||||
{
|
||||
vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
|
||||
r = build_special_member_call (DECL_RESULT (orig),
|
||||
@ -4853,7 +4853,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
|
||||
DECL_IGNORED_P (gro) = true;
|
||||
add_decl_expr (gro);
|
||||
gro_bind_vars = gro;
|
||||
if (TYPE_NEEDS_CONSTRUCTING (gro_type))
|
||||
if (type_build_ctor_call (gro_type))
|
||||
{
|
||||
vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
|
||||
r = build_special_member_call (gro, complete_ctor_identifier,
|
||||
|
29
gcc/testsuite/g++.dg/coroutines/pr98118.C
Normal file
29
gcc/testsuite/g++.dg/coroutines/pr98118.C
Normal file
@ -0,0 +1,29 @@
|
||||
namespace std {
|
||||
inline namespace __n4861 {
|
||||
template <typename _Result, typename> struct coroutine_traits : _Result {};
|
||||
template <typename = void> struct coroutine_handle;
|
||||
template <> struct coroutine_handle<> {};
|
||||
template <typename> struct coroutine_handle : coroutine_handle<> {};
|
||||
struct suspend_never {
|
||||
bool await_ready() noexcept;
|
||||
void await_suspend(coroutine_handle<>) noexcept;
|
||||
void await_resume() noexcept;
|
||||
};
|
||||
} // namespace __n4861
|
||||
} // namespace std
|
||||
|
||||
struct fire_and_forget {
|
||||
struct promise_type {
|
||||
fire_and_forget get_return_object();
|
||||
std::suspend_never initial_suspend();
|
||||
std::suspend_never final_suspend() noexcept;
|
||||
void return_void();
|
||||
void unhandled_exception();
|
||||
};
|
||||
};
|
||||
|
||||
struct bug {
|
||||
~bug();
|
||||
};
|
||||
|
||||
fire_and_forget f(bug) { co_return; }
|
Loading…
Reference in New Issue
Block a user