allow EH to escape from GIMPLE_EH_ELSE ELSE block
authorAlexandre Oliva <oliva@adacore.com>
Fri, 12 Jul 2019 13:51:00 +0000 (13:51 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Fri, 12 Jul 2019 13:51:00 +0000 (13:51 +0000)
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.

From-SVN: r273444

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/gimplefe-44.c [new file with mode: 0644]
gcc/tree-eh.c

index 43b52489921e4fe47c211d5d5dd3f915fd21cf6a..2d1d29f005c1f09fd544cc4e31b19620ba91ee4d 100644 (file)
@@ -1,3 +1,9 @@
+2019-07-12  Alexandre Oliva <oliva@adacore.com>
+
+       * 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.
+
 2019-07-12  Richard Sandiford  <richard.sandiford@arm.com>
 
        * vector-builder.h (vector_builder::elt): Allow already-supplied
index c2352005a370bcdd0104cd1655989949e20b55b4..debec92a89fdc5a3a3fb1733e2624a7b1429f191 100644 (file)
@@ -1,5 +1,7 @@
 2019-07-12  Alexandre Oliva <oliva@adacore.com>
 
+       * gcc.dg/gimplefe-44.c: New.
+
        * gcc.dg/gimplefe-43.c: New.
 
 2019-07-12  Richard Biener  <rguenther@suse.de>
diff --git a/gcc/testsuite/gcc.dg/gimplefe-44.c b/gcc/testsuite/gcc.dg/gimplefe-44.c
new file mode 100644 (file)
index 0000000..a9a92b1
--- /dev/null
@@ -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" } } */
index fb7d202fc6f9f76ffe586a757ef3b9c93ee175db..5bb07e49d285918dba6017af32480523519ea561 100644 (file)
@@ -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
     {