https://gcc.gnu.org/g:5dbf5f9f4f83b0048e7c3af8fbaefb503d56928e

commit r14-11734-g5dbf5f9f4f83b0048e7c3af8fbaefb503d56928e
Author: Iain Sandoe <i...@sandoe.co.uk>
Date:   Sat Aug 31 13:08:42 2024 +0100

    c++, coroutines: Revise promise construction/destruction.
    
    In examining the coroutine testcases for unexpected diagnostic output
    for 'Wall', I found a 'statement has no effect' warning for the promise
    construction in one case.  In particular, the case is where the users
    promise type has an implicit CTOR but a user-provided DTOR. Further, the
    type does not actually need constructing.
    
    In very early versions of the coroutines code we used to check
    TYPE_NEEDS_CONSTRUCTING() to determine whether to attempt to build
    a constructor call for the promise.  During review, it was suggested
    to use type_build_ctor_call () instead.
    
    This latter call checks the constructors in the type (both user-defined
    and implicit) and returns true, amongst other cases if any of the found
    CTORs are marked as deprecated.
    
    In a number of places (for example [class.copy.ctor] / 6) the standard
    says that some version of an implicit CTOR is deprecated when the user
    provides a DTOR.
    
    Thus, for this specific arrangement of promise type, type_build_ctor_call
    returns true, because of (for example) a deprecated implicit copy CTOR.
    
    We are not going to use any of the deprecated CTORs and thus will not
    see warnings from this - however, since the call returned true, we have
    now determined that we should attempt to build a constructor call.
    
    Note as above, the type does not actually require construction and thus
    one might expect either a NULL_TREE or error_mark_node in response to
    the build_special_member_call ().  However, in practice the function
    returns the original instance object instead of a call or some error.
    
    When we add that as a statement it triggers the 'statement has no effect'
    warning.
    
    The patch here rearranges the promise construction/destruction code to
    allow for the case that a DTOR is required independently of a CTOR. In
    addition, we check that the return from build_special_member_call ()
    has side effects before we add it as a statement.
    
    gcc/cp/ChangeLog:
    
            * coroutines.cc
            (cp_coroutine_transform::build_ramp_function): Separate the
            build of promise constructor and destructor.  When evaluating
            the constructor, check that build_special_member_call returns
            an expression with side effects before adding it.
    
    Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>
    (cherry picked from commit 7d1483921941d21d91f929ef0d59a9794b1946b4)

Diff:
---
 gcc/cp/coroutines.cc | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 4b13f904ff0e..e0e312265c10 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -5108,16 +5108,12 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
   tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
                                           false, tf_warning_or_error);
 
-  tree promise_dtor = NULL_TREE;
   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
-        frame).
+      /* Construct the promise object [dcl.fct.def.coroutine] / 5.7.
 
-        First try to find a constructor with the same parameter list as the
-        original function (if it has params), failing that find a constructor
-        with no parameter list.  */
+        First try to find a constructor with an argument list comprised of
+        the parameter copies.  */
 
       if (DECL_ARGUMENTS (orig))
        {
@@ -5129,20 +5125,27 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
       else
        r = NULL_TREE;
 
+      /* If that fails then the promise constructor argument list is empty.  */
       if (r == NULL_TREE || r == error_mark_node)
        r = build_special_member_call (p, complete_ctor_identifier, NULL,
                                       promise_type, LOOKUP_NORMAL,
                                       tf_warning_or_error);
 
-      r = coro_build_cvt_void_expr_stmt (r, fn_start);
-      finish_expr_stmt (r);
+      /* If type_build_ctor_call() encounters deprecated implicit CTORs it will
+        return true, and therefore we will execute this code path.  However,
+        we might well not actually require a CTOR and under those conditions
+        the build call above will not return a call expression, but the
+        original instance object.  Do not attempt to add the statement unless
+        it has side-effects.  */
+      if (r && r != error_mark_node && TREE_SIDE_EFFECTS (r))
+       finish_expr_stmt (r);
+    }
 
-      r = build_modify_expr (fn_start, coro_promise_live, boolean_type_node,
-                            INIT_EXPR, fn_start, boolean_true_node,
-                            boolean_type_node);
+  tree promise_dtor = cxx_maybe_build_cleanup (p, tf_warning_or_error);;
+  if (flag_exceptions && promise_dtor)
+    {
+      r = cp_build_init_expr (coro_promise_live, boolean_true_node);
       finish_expr_stmt (r);
-
-      promise_dtor = cxx_maybe_build_cleanup (p, tf_warning_or_error);
     }
 
   /* Set up a new bind context for the GRO.  */

Reply via email to