The must-not-throw wrapper for protect_cleanup_actions gets in
the way of being able to access __builtin_eh_pointer without
confusion as the identit of the exception to which we are
referring (b_eh_p has no usable argument up to this point).

Since EH_ELSE never comes from user derived code, let's drop
the c++ specific wrapping.

This fixes a problem wherein _ITM_commitTransactionEH was
always receiving a NULL pointer for the current exception.
We'd been working around that in the library, but that's
somewhat silly...

Tested on x86_64 and committed.


r~
	* tree-eh.c (honor_protect_cleanup_actions): Do not wrap
	eh_else in a must-not-throw; set ehp_region for it too.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231908 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog |  3 ++
 gcc/tree-eh.c | 97 ++++++++++++++++++++++++++++++-----------------------------
 2 files changed, 52 insertions(+), 48 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a9e73f4..473119a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -33,6 +33,9 @@
 	(ipa_tm_scan_calls_transaction): ... not here.
 	(ipa_uninstrument_transaction): Remove.
 
+	* tree-eh.c (honor_protect_cleanup_actions): Do not wrap eh_else
+	in a must-not-throw; set ehp_region for it too.
+
 2015-12-22  Peter Bergner  <berg...@vnet.ibm.com>
 
 	PR target/68772
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 9f68f31..5552fc1 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -986,64 +986,65 @@ honor_protect_cleanup_actions (struct leh_state *outer_state,
 			       struct leh_state *this_state,
 			       struct leh_tf_state *tf)
 {
-  tree protect_cleanup_actions;
-  gimple_stmt_iterator gsi;
-  bool finally_may_fallthru;
-  gimple_seq finally;
-  gimple *x;
-  geh_mnt *eh_mnt;
-  gtry *try_stmt;
-  geh_else *eh_else;
-
-  /* First check for nothing to do.  */
-  if (lang_hooks.eh_protect_cleanup_actions == NULL)
-    return;
-  protect_cleanup_actions = lang_hooks.eh_protect_cleanup_actions ();
-  if (protect_cleanup_actions == NULL)
-    return;
-
-  finally = gimple_try_cleanup (tf->top_p);
-  eh_else = get_eh_else (finally);
+  gimple_seq finally = gimple_try_cleanup (tf->top_p);
 
-  /* Duplicate the FINALLY block.  Only need to do this for try-finally,
-     and not for cleanups.  If we've got an EH_ELSE, extract it now.  */
-  if (eh_else)
+  /* EH_ELSE doesn't come from user code; only compiler generated stuff.
+     It does need to be handled here, so as to separate the (different)
+     EH path from the normal path.  But we should not attempt to wrap
+     it with a must-not-throw node (which indeed gets in the way).  */
+  if (geh_else *eh_else = get_eh_else (finally))
     {
-      finally = gimple_eh_else_e_body (eh_else);
       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;
     }
-  else if (this_state)
-    finally = lower_try_finally_dup_block (finally, outer_state,
-	gimple_location (tf->try_finally_expr));
-  finally_may_fallthru = gimple_seq_may_fallthru (finally);
-
-  /* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
-     set, the handler of the TRY_CATCH_EXPR is another cleanup which ought
-     to be in an enclosing scope, but needs to be implemented at this level
-     to avoid a nesting violation (see wrap_temporary_cleanups in
-     cp/decl.c).  Since it's logically at an outer level, we should call
-     terminate before we get to it, so strip it away before adding the
-     MUST_NOT_THROW filter.  */
-  gsi = gsi_start (finally);
-  x = gsi_stmt (gsi);
-  if (gimple_code (x) == GIMPLE_TRY
-      && gimple_try_kind (x) == GIMPLE_TRY_CATCH
-      && gimple_try_catch_is_cleanup (x))
+  else
     {
-      gsi_insert_seq_before (&gsi, gimple_try_eval (x), GSI_SAME_STMT);
-      gsi_remove (&gsi, false);
-    }
+      /* First check for nothing to do.  */
+      if (lang_hooks.eh_protect_cleanup_actions == NULL)
+	return;
+      tree actions = lang_hooks.eh_protect_cleanup_actions ();
+      if (actions == NULL)
+	return;
+
+      if (this_state)
+	finally = lower_try_finally_dup_block (finally, outer_state,
+	  gimple_location (tf->try_finally_expr));
+
+      /* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
+	 set, the handler of the TRY_CATCH_EXPR is another cleanup which ought
+	 to be in an enclosing scope, but needs to be implemented at this level
+	 to avoid a nesting violation (see wrap_temporary_cleanups in
+	 cp/decl.c).  Since it's logically at an outer level, we should call
+	 terminate before we get to it, so strip it away before adding the
+	 MUST_NOT_THROW filter.  */
+      gimple_stmt_iterator gsi = gsi_start (finally);
+      gimple *x = gsi_stmt (gsi);
+      if (gimple_code (x) == GIMPLE_TRY
+	  && gimple_try_kind (x) == GIMPLE_TRY_CATCH
+	  && gimple_try_catch_is_cleanup (x))
+	{
+	  gsi_insert_seq_before (&gsi, gimple_try_eval (x), GSI_SAME_STMT);
+	  gsi_remove (&gsi, false);
+	}
 
-  /* Wrap the block with protect_cleanup_actions as the action.  */
-  eh_mnt = gimple_build_eh_must_not_throw (protect_cleanup_actions);
-  try_stmt = gimple_build_try (finally, gimple_seq_alloc_with_stmt (eh_mnt),
-			       GIMPLE_TRY_CATCH);
-  finally = lower_eh_must_not_throw (outer_state, try_stmt);
+      /* Wrap the block with protect_cleanup_actions as the action.  */
+      geh_mnt *eh_mnt = gimple_build_eh_must_not_throw (actions);
+      gtry *try_stmt = gimple_build_try (finally,
+					 gimple_seq_alloc_with_stmt (eh_mnt),
+					 GIMPLE_TRY_CATCH);
+      finally = lower_eh_must_not_throw (outer_state, try_stmt);
+    }
 
   /* Drop all of this into the exception sequence.  */
   emit_post_landing_pad (&eh_seq, tf->region);
   gimple_seq_add_seq (&eh_seq, finally);
-  if (finally_may_fallthru)
+  if (gimple_seq_may_fallthru (finally))
     emit_resx (&eh_seq, tf->region);
 
   /* Having now been handled, EH isn't to be considered with
-- 
2.5.0

Reply via email to