diff mbox series

[6/9] c++, coroutines: Allow convertible get_return_on_allocation_fail [PR109682].

Message ID 1c6f7df8ccf8f2b26dbdddfb3f2b516efcddc53c.1724267239.git.iain@sandoe.co.uk
State New
Headers show
Series c++, coroutines: Patch set for ramp function fixes. | expand

Commit Message

Iain Sandoe Aug. 21, 2024, 7:10 p.m. UTC
We have been requiring the get_return_on_allocation_fail() call to have the
same type as the ramp.  This is not intended by the standard, so relax that
to allow anything convertible to the ramp return.

	PR c++/109682

gcc/cp/ChangeLog:

	* coroutines.cc
	(cp_coroutine_transform::build_ramp_function): Allow for cases where
	get_return_on_allocation_fail has a type convertible to the ramp
	return type.

gcc/testsuite/ChangeLog:

	* g++.dg/coroutines/pr109682.C: New test.

Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
---
 gcc/cp/coroutines.cc                       | 19 +++++----------
 gcc/testsuite/g++.dg/coroutines/pr109682.C | 28 ++++++++++++++++++++++
 2 files changed, 34 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr109682.C

Comments

Jason Merrill Aug. 22, 2024, 3:44 p.m. UTC | #1
On 8/21/24 3:10 PM, Iain Sandoe wrote:
> We have been requiring the get_return_on_allocation_fail() call to have the
> same type as the ramp.  This is not intended by the standard, so relax that
> to allow anything convertible to the ramp return.

OK.

> 	PR c++/109682
> 
> gcc/cp/ChangeLog:
> 
> 	* coroutines.cc
> 	(cp_coroutine_transform::build_ramp_function): Allow for cases where
> 	get_return_on_allocation_fail has a type convertible to the ramp
> 	return type.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/coroutines/pr109682.C: New test.
> 
> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
> ---
>   gcc/cp/coroutines.cc                       | 19 +++++----------
>   gcc/testsuite/g++.dg/coroutines/pr109682.C | 28 ++++++++++++++++++++++
>   2 files changed, 34 insertions(+), 13 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/coroutines/pr109682.C
> 
> diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
> index d152ad20dca..64a08b49132 100644
> --- a/gcc/cp/coroutines.cc
> +++ b/gcc/cp/coroutines.cc
> @@ -4824,25 +4824,18 @@ cp_coroutine_transform::build_ramp_function ()
>   	 control to the caller of the coroutine and the return value is
>   	 obtained by a call to T::get_return_object_on_allocation_failure(),
>   	 where T is the promise type.  */
> -
> -      gcc_checking_assert (same_type_p (fn_return_type, TREE_TYPE (grooaf)));
>         tree if_stmt = begin_if_stmt ();
>         tree cond = build1 (CONVERT_EXPR, frame_ptr_type, nullptr_node);
>         cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
>         finish_if_stmt_cond (cond, if_stmt);
> +      r = NULL_TREE;
>         if (void_ramp_p)
> -	{
> -	  /* Execute the get-return-object-on-alloc-fail call...  */
> -	  finish_expr_stmt (grooaf);
> -	  /* ... but discard the result, since we return void.  */
> -	  finish_return_stmt (NULL_TREE);
> -	}
> +	/* Execute the get-return-object-on-alloc-fail call...  */
> +	finish_expr_stmt (grooaf);
>         else
> -	{
> -	  /* Get the fallback return object.  */
> -	  r = build_cplus_new (fn_return_type, grooaf, tf_warning_or_error);
> -	  finish_return_stmt (r);
> -	}
> +	/* Get the fallback return object.  */
> +	r = grooaf;
> +      finish_return_stmt (r);
>         finish_then_clause (if_stmt);
>         finish_if_stmt (if_stmt);
>       }
> diff --git a/gcc/testsuite/g++.dg/coroutines/pr109682.C b/gcc/testsuite/g++.dg/coroutines/pr109682.C
> new file mode 100644
> index 00000000000..24aab921ab2
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/coroutines/pr109682.C
> @@ -0,0 +1,28 @@
> +
> +#include <coroutine>
> +#include <new>
> +
> +struct test
> +{
> +  test () {}
> +  test (int) {}
> +
> +  struct promise_type {
> +    test get_return_object () { return {}; }
> +    //     vvv
> +    static int get_return_object_on_allocation_failure () { return {}; }
> +    std::suspend_never initial_suspend () noexcept { return {}; }
> +    std::suspend_never final_suspend () noexcept { return {}; }
> +    void return_void () {}
> +    void unhandled_exception () {}
> +  };
> +};
> +
> +test
> +f () { co_return; }
> +
> +int
> +main ()
> +{
> +  f ();
> +}
diff mbox series

Patch

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index d152ad20dca..64a08b49132 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4824,25 +4824,18 @@  cp_coroutine_transform::build_ramp_function ()
 	 control to the caller of the coroutine and the return value is
 	 obtained by a call to T::get_return_object_on_allocation_failure(),
 	 where T is the promise type.  */
-
-      gcc_checking_assert (same_type_p (fn_return_type, TREE_TYPE (grooaf)));
       tree if_stmt = begin_if_stmt ();
       tree cond = build1 (CONVERT_EXPR, frame_ptr_type, nullptr_node);
       cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
       finish_if_stmt_cond (cond, if_stmt);
+      r = NULL_TREE;
       if (void_ramp_p)
-	{
-	  /* Execute the get-return-object-on-alloc-fail call...  */
-	  finish_expr_stmt (grooaf);
-	  /* ... but discard the result, since we return void.  */
-	  finish_return_stmt (NULL_TREE);
-	}
+	/* Execute the get-return-object-on-alloc-fail call...  */
+	finish_expr_stmt (grooaf);
       else
-	{
-	  /* Get the fallback return object.  */
-	  r = build_cplus_new (fn_return_type, grooaf, tf_warning_or_error);
-	  finish_return_stmt (r);
-	}
+	/* Get the fallback return object.  */
+	r = grooaf;
+      finish_return_stmt (r);
       finish_then_clause (if_stmt);
       finish_if_stmt (if_stmt);
     }
diff --git a/gcc/testsuite/g++.dg/coroutines/pr109682.C b/gcc/testsuite/g++.dg/coroutines/pr109682.C
new file mode 100644
index 00000000000..24aab921ab2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr109682.C
@@ -0,0 +1,28 @@ 
+
+#include <coroutine>
+#include <new>
+
+struct test
+{
+  test () {}
+  test (int) {}
+
+  struct promise_type {
+    test get_return_object () { return {}; }
+    //     vvv
+    static int get_return_object_on_allocation_failure () { return {}; }
+    std::suspend_never initial_suspend () noexcept { return {}; }
+    std::suspend_never final_suspend () noexcept { return {}; }
+    void return_void () {}
+    void unhandled_exception () {}
+  };
+};
+
+test
+f () { co_return; }
+
+int
+main ()
+{
+  f ();
+}