diff mbox series

[1/3] c++: stop altering co_awaits converted to void

Message ID 20240828202119.17640-2-arsen@aarsen.me
State New
Headers show
Series [1/3] c++: stop altering co_awaits converted to void | expand

Commit Message

Arsen Arsenović Aug. 28, 2024, 7:59 p.m. UTC
This patch fixes a gcc-15 regression (PR116502) and an inelegance in my
earlier patch related to converting CO_AWAIT_EXPRs to void.

This wasn't noticed anywhere AFAICT, but it was a bit unfortunate.

The other two patches fix an actual regression as well as provide
handling for converting INDIRECT_REFs wrapping CO_AWAIT_EXPRs (which I
noticed was lacking while triaging the regression).

WRT INDIRECT_REFs, I've considered making convert_to_void recurse on the
INDIRECT_REF case, so that special handling doesn't need to be added
when some expression might end up getting wrapped in a INDIRECT_REF.  Is
there a reason why we don't do that?  I've started a regstrap with that
recursion added in order to see whether it is something to possibly
explore.  The change being regstrapped looks like so:

Comments

Jason Merrill Aug. 28, 2024, 10:18 p.m. UTC | #1
On 8/28/24 3:59 PM, Arsen Arsenović wrote:
> This patch fixes a gcc-15 regression (PR116502) and an inelegance in my
> earlier patch related to converting CO_AWAIT_EXPRs to void.
> 
> This wasn't noticed anywhere AFAICT, but it was a bit unfortunate.
> 
> The other two patches fix an actual regression as well as provide
> handling for converting INDIRECT_REFs wrapping CO_AWAIT_EXPRs (which I
> noticed was lacking while triaging the regression).
> 
> WRT INDIRECT_REFs, I've considered making convert_to_void recurse on the
> INDIRECT_REF case, so that special handling doesn't need to be added
> when some expression might end up getting wrapped in a INDIRECT_REF.  Is
> there a reason why we don't do that?

Primarily because that isn't what the language says.  And for instance 
if I have

int *volatile p;
*p;

I think just recursing will wrongly warn about not accessing the value of p.

Better, I think, to teach maybe_warn_nodiscard to look through 
CO_AWAIT_EXPR.

> I've started a regstrap with that
> recursion added in order to see whether it is something to possibly
> explore.  The change being regstrapped looks like so:
> 
> diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
> index ce26cb8ef30..8f874f4f4dc 100644
> --- a/gcc/cp/cvt.cc
> +++ b/gcc/cp/cvt.cc
> @@ -1432,11 +1432,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
>                   && !is_reference)
>                 warning_at (loc, OPT_Wunused_value, "value computed is not used");
>               expr = TREE_OPERAND (expr, 0);
> -           if (TREE_CODE (expr) == CALL_EXPR
> -               && (complain & tf_warning))
> -             maybe_warn_nodiscard (expr, implicit);
> -           else if (TREE_CODE (expr) == CO_AWAIT_EXPR)
> -             convert_co_await_to_void (expr, implicit, complain);
> +           return convert_to_void (expr, implicit, complain);
>             }
> 
>          break;
> 
> At any rate, the patchset was tested as-is on x86_64-pc-linux-gnu also.
> If the above shouldn't be done for whatever reason, is the current set
> OK for trunk?
> 
> TIA, have a lovely evening.
> ---------- >8 ----------
> As of r15-2318-g2664c1bf83855b, we started altering co_await expressions
> cast to void so that their constituent await-resume expression is also
> cast to void.  This leads to the TREE_TYPE of the CO_AWAIT_EXPR being
> wrong, because it should be the same as the await-resume expression, but
> it ended up being void.  While this appears not to cause trouble
> currently, it could induce bugs in the future, without being necessary.
> 
> gcc/cp/ChangeLog:
> 
> 	* coroutines.cc (co_await_get_resume_call): Don't return a
> 	pointer to the await-resume expression.
> 	* cp-tree.h (co_await_get_resume_call): Change return type to a
> 	non-pointer 'tree'.
> 	* cvt.cc (convert_to_void): Adjust according to the above.
> ---
>   gcc/cp/coroutines.cc | 4 ++--
>   gcc/cp/cp-tree.h     | 2 +-
>   gcc/cp/cvt.cc        | 4 ++--
>   3 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
> index f243fe9adae2..166978ab464b 100644
> --- a/gcc/cp/coroutines.cc
> +++ b/gcc/cp/coroutines.cc
> @@ -728,14 +728,14 @@ coro_get_destroy_function (tree decl)
>   
>   /* Given a CO_AWAIT_EXPR AWAIT_EXPR, return its resume call.  */
>   
> -tree*
> +tree
>   co_await_get_resume_call (tree await_expr)
>   {
>     gcc_checking_assert (TREE_CODE (await_expr) == CO_AWAIT_EXPR);
>     tree vec = TREE_OPERAND (await_expr, 3);
>     if (!vec)
>       return nullptr;
> -  return &TREE_VEC_ELT (vec, 2);
> +  return TREE_VEC_ELT (vec, 2);
>   }
>   
>   
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 2eeb5e3e8b16..417ed4919c39 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -8776,7 +8776,7 @@ extern tree coro_get_actor_function		(tree);
>   extern tree coro_get_destroy_function		(tree);
>   extern tree coro_get_ramp_function		(tree);
>   
> -extern tree* co_await_get_resume_call		(tree await_expr);
> +extern tree co_await_get_resume_call		(tree await_expr);
>   
>   
>   /* contracts.cc */
> diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
> index 7b4bd8a9dc44..b6b35ef9cacf 100644
> --- a/gcc/cp/cvt.cc
> +++ b/gcc/cp/cvt.cc
> @@ -1505,8 +1505,8 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
>       case CO_AWAIT_EXPR:
>         {
>   	auto awr = co_await_get_resume_call (expr);
> -	if (awr && *awr)
> -	  *awr = convert_to_void (*awr, implicit, complain);
> +	if (awr)
> +	  awr = convert_to_void (awr, implicit, complain);

After this change you don't need the assignment at all, it's a dead store.

>   	break;
Arsen Arsenović Aug. 28, 2024, 11:46 p.m. UTC | #2
Jason Merrill <jason@redhat.com> writes:

> On 8/28/24 3:59 PM, Arsen Arsenović wrote:
>> This patch fixes a gcc-15 regression (PR116502) and an inelegance in my
>> earlier patch related to converting CO_AWAIT_EXPRs to void.
>> This wasn't noticed anywhere AFAICT, but it was a bit unfortunate.
>> The other two patches fix an actual regression as well as provide
>> handling for converting INDIRECT_REFs wrapping CO_AWAIT_EXPRs (which I
>> noticed was lacking while triaging the regression).
>> WRT INDIRECT_REFs, I've considered making convert_to_void recurse on the
>> INDIRECT_REF case, so that special handling doesn't need to be added
>> when some expression might end up getting wrapped in a INDIRECT_REF.  Is
>> there a reason why we don't do that?
>
> Primarily because that isn't what the language says.  And for instance if I
> have
>
> int *volatile p;
> *p;
>
> I think just recursing will wrongly warn about not accessing the value of p.

Hmm, with the change in the OP I didn't get that warning, but that
reason is compelling enough for me.

> Better, I think, to teach maybe_warn_nodiscard to look through CO_AWAIT_EXPR.

The reason I didn't originally extend maybe_warn_nodiscard to also cover
CO_AWAIT_EXPR is because the await-resume of a CO_AWAIT_EXPR sometimes
isn't a (possibly wrapped) CALL_EXPR, and might contain a COMPOUND_EXPR,
for instance, when it is the initial suspend await (see 'if
(initial_await != error_mark_node)' in wrap_original_function_body), so
I wanted to avoid duplicating that logic.  I could extend
maybe_warn_nodiscard to handle CO_AWAIT_EXPRs if that's preferred,
though.

>> diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
>> index 7b4bd8a9dc44..b6b35ef9cacf 100644
>> --- a/gcc/cp/cvt.cc
>> +++ b/gcc/cp/cvt.cc
>> @@ -1505,8 +1505,8 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
>>       case CO_AWAIT_EXPR:
>>         {
>>   	auto awr = co_await_get_resume_call (expr);
>> -	if (awr && *awr)
>> -	  *awr = convert_to_void (*awr, implicit, complain);
>> +	if (awr)
>> +	  awr = convert_to_void (awr, implicit, complain);
>
> After this change you don't need the assignment at all, it's a dead store.

Ah, yeah, whoops.  Seems that I removed it later (when extracting this
into its own function) but never amended the original.  Will fix.
diff mbox series

Patch

diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index ce26cb8ef30..8f874f4f4dc 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1432,11 +1432,7 @@  convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
                 && !is_reference)
               warning_at (loc, OPT_Wunused_value, "value computed is not used");
             expr = TREE_OPERAND (expr, 0);
-           if (TREE_CODE (expr) == CALL_EXPR
-               && (complain & tf_warning))
-             maybe_warn_nodiscard (expr, implicit);
-           else if (TREE_CODE (expr) == CO_AWAIT_EXPR)
-             convert_co_await_to_void (expr, implicit, complain);
+           return convert_to_void (expr, implicit, complain);
           }

        break;

At any rate, the patchset was tested as-is on x86_64-pc-linux-gnu also.
If the above shouldn't be done for whatever reason, is the current set
OK for trunk?

TIA, have a lovely evening.
---------- >8 ----------
As of r15-2318-g2664c1bf83855b, we started altering co_await expressions
cast to void so that their constituent await-resume expression is also
cast to void.  This leads to the TREE_TYPE of the CO_AWAIT_EXPR being
wrong, because it should be the same as the await-resume expression, but
it ended up being void.  While this appears not to cause trouble
currently, it could induce bugs in the future, without being necessary.

gcc/cp/ChangeLog:

	* coroutines.cc (co_await_get_resume_call): Don't return a
	pointer to the await-resume expression.
	* cp-tree.h (co_await_get_resume_call): Change return type to a
	non-pointer 'tree'.
	* cvt.cc (convert_to_void): Adjust according to the above.
---
 gcc/cp/coroutines.cc | 4 ++--
 gcc/cp/cp-tree.h     | 2 +-
 gcc/cp/cvt.cc        | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index f243fe9adae2..166978ab464b 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -728,14 +728,14 @@  coro_get_destroy_function (tree decl)
 
 /* Given a CO_AWAIT_EXPR AWAIT_EXPR, return its resume call.  */
 
-tree*
+tree
 co_await_get_resume_call (tree await_expr)
 {
   gcc_checking_assert (TREE_CODE (await_expr) == CO_AWAIT_EXPR);
   tree vec = TREE_OPERAND (await_expr, 3);
   if (!vec)
     return nullptr;
-  return &TREE_VEC_ELT (vec, 2);
+  return TREE_VEC_ELT (vec, 2);
 }
 
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2eeb5e3e8b16..417ed4919c39 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8776,7 +8776,7 @@  extern tree coro_get_actor_function		(tree);
 extern tree coro_get_destroy_function		(tree);
 extern tree coro_get_ramp_function		(tree);
 
-extern tree* co_await_get_resume_call		(tree await_expr);
+extern tree co_await_get_resume_call		(tree await_expr);
 
 
 /* contracts.cc */
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index 7b4bd8a9dc44..b6b35ef9cacf 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1505,8 +1505,8 @@  convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
     case CO_AWAIT_EXPR:
       {
 	auto awr = co_await_get_resume_call (expr);
-	if (awr && *awr)
-	  *awr = convert_to_void (*awr, implicit, complain);
+	if (awr)
+	  awr = convert_to_void (awr, implicit, complain);
 	break;
       }