public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-8437] c++: co_await and initializer_list [PR109227]
@ 2024-01-25 20:22 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2024-01-25 20:22 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:44868e7298de5048d6f04d7fa098d5bc767c8cb8

commit r14-8437-g44868e7298de5048d6f04d7fa098d5bc767c8cb8
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jan 25 14:45:35 2024 -0500

    c++: co_await and initializer_list [PR109227]
    
    Here we end up with an initializer_list of 'aa', a type with a non-trivial
    destructor, and need to destroy it.  The code called
    build_special_member_call for cleanups, but that doesn't work for arrays, so
    use cxx_maybe_build_cleanup instead.  Let's go ahead and do that
    everywhere that has been calling the destructor directly.
    
            PR c++/109227
    
    gcc/cp/ChangeLog:
    
            * coroutines.cc (build_co_await): Use cxx_maybe_build_cleanup.
            (build_actor_fn, process_conditional, maybe_promote_temps)
            (morph_fn_to_coro): Likewise.
            (expand_one_await_expression): Use build_cleanup.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/coroutines/co-await-initlist2.C: New test.

Diff:
---
 gcc/cp/coroutines.cc                               | 118 +++++++--------------
 .../g++.dg/coroutines/co-await-initlist2.C         |  29 +++++
 2 files changed, 67 insertions(+), 80 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index ba6e6989d06a..3194c911e8cd 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -932,19 +932,14 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
 
 	  /* We now know that the final suspend object is distinct from the
 	     final awaiter, so check for a non-throwing DTOR where needed.  */
-	  tree a_type = TREE_TYPE (a);
-	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (a_type))
-	    if (tree dummy
-		= build_special_member_call (a, complete_dtor_identifier,
-					     NULL, a_type, LOOKUP_NORMAL,
-					     tf_none))
-	      {
-		if (CONVERT_EXPR_P (dummy))
-		  dummy = TREE_OPERAND (dummy, 0);
-		dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
-		if (coro_diagnose_throwing_fn (dummy))
-		  return error_mark_node;
-	      }
+	  if (tree dummy = cxx_maybe_build_cleanup (a, tf_none))
+	    {
+	      if (CONVERT_EXPR_P (dummy))
+		dummy = TREE_OPERAND (dummy, 0);
+	      dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
+	      if (coro_diagnose_throwing_fn (dummy))
+		return error_mark_node;
+	    }
 	}
     }
   else
@@ -1096,18 +1091,14 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
 	return error_mark_node;
       if (coro_diagnose_throwing_fn (awrs_func))
 	return error_mark_node;
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (o_type))
-	if (tree dummy
-	    = build_special_member_call (e_proxy, complete_dtor_identifier,
-					 NULL, o_type, LOOKUP_NORMAL,
-					 tf_none))
-	  {
-	    if (CONVERT_EXPR_P (dummy))
-	      dummy = TREE_OPERAND (dummy, 0);
-	    dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
-	    if (coro_diagnose_throwing_fn (dummy))
-	      return error_mark_node;
-	  }
+      if (tree dummy = cxx_maybe_build_cleanup (e_proxy, tf_none))
+	{
+	  if (CONVERT_EXPR_P (dummy))
+	    dummy = TREE_OPERAND (dummy, 0);
+	  dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
+	  if (coro_diagnose_throwing_fn (dummy))
+	    return error_mark_node;
+	}
     }
 
   /* We now have three call expressions, in terms of the promise, handle and
@@ -1662,7 +1653,6 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
   tree resume_label = create_named_label_with_ctx (loc, buf, actor);
   tree empty_list = build_empty_stmt (loc);
 
-  tree await_type = TREE_TYPE (var);
   tree stmt_list = NULL;
   tree r;
   tree *await_init = NULL;
@@ -1791,9 +1781,7 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
   append_to_statement_list (destroy_label, &body_list);
   if (needs_dtor)
     {
-      tree dtor = build_special_member_call (var, complete_dtor_identifier,
-					     NULL, await_type, LOOKUP_NORMAL,
-					     tf_warning_or_error);
+      tree dtor = build_cleanup (var);
       append_to_statement_list (dtor, &body_list);
     }
   r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
@@ -1821,9 +1809,7 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
   tree *revised = tsi_stmt_ptr (tsi_last (stmt_list));
   if (needs_dtor)
     {
-      tree dtor = build_special_member_call (var, complete_dtor_identifier,
-					     NULL, await_type, LOOKUP_NORMAL,
-					     tf_warning_or_error);
+      tree dtor = build_cleanup (var);
       append_to_statement_list (dtor, &stmt_list);
     }
   data->index += 2;
@@ -2330,10 +2316,8 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
   add_stmt (r);
 
   /* Destructors for the things we built explicitly.  */
-  r = build_special_member_call (promise_proxy, complete_dtor_identifier, NULL,
-				 promise_type, LOOKUP_NORMAL,
-				 tf_warning_or_error);
-  add_stmt (r);
+  if (tree c = cxx_maybe_build_cleanup (promise_proxy, tf_warning_or_error))
+    add_stmt (c);
 
   tree del_frame_label
     = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
@@ -2362,12 +2346,8 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
 	    = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
 	  tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
 						   false, tf_warning_or_error);
-	  tree t = TREE_TYPE (a);
-	  tree dtor;
-	  dtor
-	    = build_special_member_call (a, complete_dtor_identifier, NULL, t,
-					 LOOKUP_NORMAL, tf_warning_or_error);
-	  add_stmt (dtor);
+	  if (tree dtor = cxx_maybe_build_cleanup (a, tf_warning_or_error))
+	    add_stmt (dtor);
 	}
     }
 
@@ -3045,16 +3025,14 @@ process_conditional (var_nest_node *n, tree& vlist)
       tree *flag = var_flags.get (var);
       if (!flag)
 	continue;
-      tree var_type = TREE_TYPE (var);
-      tree cleanup
-	= build_special_member_call (var, complete_dtor_identifier,
-				     NULL, var_type, LOOKUP_NORMAL,
-				     tf_warning_or_error);
-      tree cond_cleanup = begin_if_stmt ();
-      finish_if_stmt_cond (*flag, cond_cleanup);
-      finish_expr_stmt (cleanup);
-      finish_then_clause (cond_cleanup);
-      finish_if_stmt (cond_cleanup);
+      if (tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error))
+	{
+	  tree cond_cleanup = begin_if_stmt ();
+	  finish_if_stmt_cond (*flag, cond_cleanup);
+	  finish_expr_stmt (cleanup);
+	  finish_then_clause (cond_cleanup);
+	  finish_if_stmt (cond_cleanup);
+	}
     }
   final_actions = pop_stmt_list (final_actions);
   tree try_finally
@@ -3135,13 +3113,8 @@ maybe_promote_temps (tree *stmt, void *d)
 	    process_conditional (t, vlist);
 	  else
 	    finish_expr_stmt (t->init);
-	  tree var_type = TREE_TYPE (var);
-	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type))
+	  if (tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error))
 	    {
-	      tree cleanup
-		= build_special_member_call (var, complete_dtor_identifier,
-					     NULL, var_type, LOOKUP_NORMAL,
-					     tf_warning_or_error);
 	      tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var);
 	      add_stmt (cl); /* push this onto the level above.  */
 	    }
@@ -4903,10 +4876,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
 	      vec_safe_push (param_dtor_list, parm.field_id);
 	      /* Cleanup this frame copy on exception.  */
 	      parm.fr_copy_dtor
-		= build_special_member_call (fld_idx, complete_dtor_identifier,
-					     NULL, parm.frame_type,
-					     LOOKUP_NORMAL,
-					     tf_warning_or_error);
+		= cxx_maybe_build_cleanup (fld_idx, tf_warning_or_error);
 	      if (flag_exceptions)
 		{
 		  /* This var is now live.  */
@@ -4961,10 +4931,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
 			     boolean_type_node);
       finish_expr_stmt (r);
 
-      promise_dtor
-	= build_special_member_call (p, complete_dtor_identifier,
-				     NULL, promise_type, LOOKUP_NORMAL,
-				     tf_warning_or_error);
+      promise_dtor = cxx_maybe_build_cleanup (p, tf_warning_or_error);
     }
 
   /* Set up a new bind context for the GRO.  */
@@ -5025,11 +4992,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
 	/* If some part of the initalization code (prior to the await_resume
 	     of the initial suspend expression), then we need to clean up the
 	     return value.  */
-	gro_ret_dtor
-	  = build_special_member_call (DECL_RESULT (orig),
-				       complete_dtor_identifier, NULL,
-				       gro_type, LOOKUP_NORMAL,
-				       tf_warning_or_error);
+	gro_ret_dtor = cxx_maybe_build_cleanup (DECL_RESULT (orig),
+						tf_warning_or_error);
     }
   else
     {
@@ -5042,15 +5006,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
       r = cp_build_modify_expr (input_location, gro, INIT_EXPR, get_ro,
 				tf_warning_or_error);
       /* The constructed object might require a cleanup.  */
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
-	{
-	  gro_cleanup_stmt
-	    = build_special_member_call (gro, complete_dtor_identifier,
-					 NULL, gro_type, LOOKUP_NORMAL,
-					 tf_warning_or_error);
-	  gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
-					 gro_cleanup_stmt, gro);
-	}
+      if (tree cleanup = cxx_maybe_build_cleanup (gro, tf_warning_or_error))
+	gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
+				       cleanup, gro);
     }
   finish_expr_stmt (r);
 
diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-initlist2.C b/gcc/testsuite/g++.dg/coroutines/co-await-initlist2.C
new file mode 100644
index 000000000000..7bdfa678df0f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/co-await-initlist2.C
@@ -0,0 +1,29 @@
+// PR c++/109227
+// { dg-do compile { target c++20 } }
+
+#include <initializer_list>
+#include <coroutine>
+
+struct awaitable {
+  bool await_ready();
+  void await_suspend(std::coroutine_handle<> h);
+  void await_resume();
+};
+awaitable async_new_session(int capabilities);
+struct aa { ~aa(); };
+aa f(void);
+struct Capabilities {
+  Capabilities(std::initializer_list<aa> __l);
+};
+int g(Capabilities);
+struct task {
+  struct promise_type {
+    std::suspend_never initial_suspend();
+    std::suspend_never final_suspend() noexcept;
+    void unhandled_exception();
+    task get_return_object() noexcept;
+  };
+};
+task make() {
+  co_await async_new_session(g({aa()}));
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-01-25 20:22 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-25 20:22 [gcc r14-8437] c++: co_await and initializer_list [PR109227] Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).