allow EH to escape from GIMPLE_EH_ELSE ELSE block

Richard Biener richard.guenther@gmail.com
Fri Jul 12 11:02:00 GMT 2019


On Thu, Jul 11, 2019 at 12:44 PM Alexandre Oliva <oliva@adacore.com> wrote:
>
> ... and here's a patch that uses a try/finally/else gimplefe test to
> demonstrate the GIMPLE_EH_ELSE lowering problem (might_throw3 is tagged
> as [LP 1] rather than [LP 2]), and fixes it.
>
> Regstrapped on x86_64-linux-gnu.  Ok to install?

OK.

Richard.

>
> allow EH to escape from GIMPLE_EH_ELSE ELSE block
>
> The only preexisting use of GIMPLE_EH_ELSE, for transactional memory
> commits, did not allow exceptions to escape from the ELSE path.  The
> trick it uses to allow the ELSE path to see the propagating exception
> does not work very well if the exception cleanup raises further
> exceptions: the ELSE block is configured to handle exceptions in
> itself.  This confuses the heck out of CFG and EH cleanups.
>
> Basing the lowering context for the ELSE block on outer_state, rather
> than this_state, gets us the expected enclosing handler.
>
>
> for  gcc/ChangeLog
>
>         * tree-eh.c (honor_protect_cleanup_actions): Use outer_
>         rather than this_state as the lowering context for the ELSE
>         seq in a GIMPLE_EH_ELSE.
>
> for  gcc/testsuite/ChangeLog
>
>         * gcc.dg/gimplefe-44.c: New.
> ---
>  gcc/testsuite/gcc.dg/gimplefe-44.c |   33 +++++++++++++++++++++++++++++++++
>  gcc/tree-eh.c                      |   13 ++++++++-----
>  2 files changed, 41 insertions(+), 5 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/gimplefe-44.c
>
> diff --git a/gcc/testsuite/gcc.dg/gimplefe-44.c b/gcc/testsuite/gcc.dg/gimplefe-44.c
> new file mode 100644
> index 000000000000..a9a92b1701ec
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gimplefe-44.c
> @@ -0,0 +1,33 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fexceptions -fgimple -fdump-tree-eh-eh" } */
> +
> +void __GIMPLE foo()
> +{
> +  try
> +    {
> +      try
> +       {
> +         extern void might_throw1 ();
> +         might_throw1 ();
> +       }
> +      finally
> +       {
> +         extern void might_throw2 ();
> +         might_throw2 ();
> +       }
> +      else
> +       {
> +         extern void might_throw3 ();
> +         might_throw3 ();
> +       }
> +    }
> +  finally
> +    {
> +      extern void might_throw4 ();
> +      might_throw4 ();
> +    }
> +}
> +
> +/* { dg-final { scan-tree-dump ".LP 1. might_throw1" "eh" } } */
> +/* { dg-final { scan-tree-dump ".LP 2. might_throw2" "eh" } } */
> +/* { dg-final { scan-tree-dump ".LP 2. might_throw3" "eh" } } */
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index fb7d202fc6f9..5bb07e49d285 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -996,11 +996,14 @@ honor_protect_cleanup_actions (struct leh_state *outer_state,
>        gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else));
>        finally = gimple_eh_else_e_body (eh_else);
>
> -      /* Let the ELSE see the exception that's being processed.  */
> -      eh_region save_ehp = this_state->ehp_region;
> -      this_state->ehp_region = this_state->cur_region;
> -      lower_eh_constructs_1 (this_state, &finally);
> -      this_state->ehp_region = save_ehp;
> +      /* Let the ELSE see the exception that's being processed, but
> +        since the cleanup is outside the try block, process it with
> +        outer_state, otherwise it may be used as a cleanup for
> +        itself, and Bad Things (TM) ensue.  */
> +      eh_region save_ehp = outer_state->ehp_region;
> +      outer_state->ehp_region = this_state->cur_region;
> +      lower_eh_constructs_1 (outer_state, &finally);
> +      outer_state->ehp_region = save_ehp;
>      }
>    else
>      {
>
>
> --
> Alexandre Oliva, freedom fighter  he/him   https://FSFLA.org/blogs/lxo
> Be the change, be Free!                 FSF Latin America board member
> GNU Toolchain Engineer                        Free Software Evangelist
> Hay que enGNUrecerse, pero sin perder la terGNUra jamás - Che GNUevara



More information about the Gcc-patches mailing list