https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118874
--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, I've tried
--- gcc/coroutines.cc.jj 2025-02-04 09:16:42.820267205 +0100
+++ gcc/coroutines.cc 2025-03-04 11:42:28.004682770 +0100
@@ -5183,6 +5183,15 @@ cp_coroutine_transform::build_ramp_funct
of the relevant function. Here we carry out the first part of
finish_return_expr(). */
input_location = fn_start;
+ if (!aggregate_value_p (gro_type, orig_fn_decl))
+ {
+ /* If get_ro doesn't need to be returned in memory, force it into
+ a TARGET_EXPR and try to return TARGET_EXPR_SLOT of it. See
+ PR118874. */
+ get_ro = force_target_expr (gro_type, get_ro, tf_warning_or_error);
+ finish_expr_stmt (get_ro);
+ get_ro = TARGET_EXPR_SLOT (get_ro);
+ }
r = check_return_expr (get_ro, &no_warning, &dangling);
input_location = UNKNOWN_LOCATION;
gcc_checking_assert (!dangling);
but that actually makes things even worse, not better.
Before that change gimple dump was
_3 = &_Coro_frameptr->_Coro_promise;
<retval> = C::promise_type::get_return_object (_3);
bar (_Coro_frameptr);
return <retval>;
(which is undesirable, we IMO really want for the !aggregate_value_p initialize
a temporary VAR_DECL with what get_return_object returns, then call bar
(_Coro_frameptr); and then return that_temporary;
But with the above patch it emits
try
{
_3 = &_Coro_frameptr->_Coro_promise;
D.8886 = C::promise_type::get_return_object (_3);
}
finally
{
D.8886 = {CLOBBER(eos)};
}
<retval> = D.8886;
bar (_Coro_frameptr);
return <retval>;
which still ICEs the same way but also clobbers the temporary before it is
copied.