coroutines : Adjust constraints on when to build ctors [PR98118].

Message ID FFD6490E-E932-4E8D-9CDF-9F999D2434B3@sandoe.co.uk
State New
Headers show
Series
  • coroutines : Adjust constraints on when to build ctors [PR98118].
Related show

Commit Message

Iain Sandoe March 4, 2021, 7:59 p.m.
Hi,

PR98118 shows that TYPE_NEEDS_CONSTRUCTING is a necessary, but not
sufficient, condition for determining when we need to build a constructor.
Use type_build_ctor_call() instead.

tested on x86_64-darwin, x86_64-linux-gnu,

[ ice on valid ]
OK for master / 10.x?
thanks
Iain

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:

        * g++.dg/coroutines/pr98118.C: New test.
---
 gcc/cp/coroutines.cc                      | 14 +++++------
 gcc/testsuite/g++.dg/coroutines/pr98118.C | 29 +++++++++++++++++++++++
 2 files changed, 36 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr98118.C

-- 
2.24.1

Comments

Nathan Sidwell March 4, 2021, 8:02 p.m. | #1
On 3/4/21 2:59 PM, Iain Sandoe wrote:
> Hi,

> 

> PR98118 shows that TYPE_NEEDS_CONSTRUCTING is a necessary, but not

> sufficient, condition for determining when we need to build a constructor.

> Use type_build_ctor_call() instead.

> 

> tested on x86_64-darwin, x86_64-linux-gnu,

> 

> [ ice on valid ]

> OK for master / 10.x?

> thanks

> Iain

> 

> 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.


ok, thanks


-- 
Nathan Sidwell

Patch

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index f79ac60dc77..2f4208fe57c 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -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'
@@ -4680,7 +4680,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)
@@ -4738,7 +4738,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
@@ -4819,7 +4819,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),
@@ -4852,7 +4852,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,
diff --git a/gcc/testsuite/g++.dg/coroutines/pr98118.C b/gcc/testsuite/g++.dg/coroutines/pr98118.C
new file mode 100644
index 00000000000..d09ffff2142
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr98118.C
@@ -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; }