fix middle-end/26084

Richard Henderson rth@twiddle.net
Wed Mar 22 12:52:00 GMT 2006


Essentially, we forgot to move the eh regions to the new function.
Which turned out to be slightly involved, but there you go.


r~


        PR middle-end/26084
        * except.c (duplicate_eh_regions_0): New.
        (duplicate_eh_region_1): Duplicate the children of the node as
        well as the node itself.  Link them up properly.
        (duplicate_eh_region_2): Merge into ...
        (duplicate_eh_regions): ... here.  Take copy_region argument, and
        copy only a sub-tree if asked.  Simplify copying and fixup.
        (eh_region_outer_p): New.
        * except.h (duplicate_eh_regions): Update decl.
        (eh_region_outer_p): Declare.
        * omp-low.c (lower_omp_single): Fix eh region placement wrt OMP_RETURN.
        (lower_omp_master): Likewise.
        (lower_omp_ordered): Likewise.
        * tree-cfg.c (struct move_stmt_d): Add new_label_map.
        (move_stmt_r): Use it to remap labels.  Handle recursion vs
        remap_decls_p properly.
        (move_block_to_fn): Pass in new_label_map.  Remap RESX_EXPR.
        (find_outermost_region_in_block): New.
        (new_label_mapper): New.
        (move_sese_region_to_fn): Copy eh information to the new function
        properly.
        * tree-inline.c (copy_cfg_body): Update for new duplicate_eh_regions
        argument.
        * tree-pretty-print.c (dump_generic_node): Dump RESX_EXPR region
        number.

--- gcc/except.c	(revision 112292)
+++ gcc/except.c	(local)
@@ -857,84 +857,145 @@ current_function_has_exception_handlers 
   return false;
 }
 
-static struct eh_region *
-duplicate_eh_region_1 (struct eh_region *o)
-{
-  struct eh_region *n = ggc_alloc_cleared (sizeof (struct eh_region));
-
-  *n = *o;
+/* A subroutine of duplicate_eh_regions.  Search the region tree under O
+   for the miniumum and maximum region numbers.  Update *MIN and *MAX.  */
 
-  n->region_number = o->region_number + cfun->eh->last_region_number;
-  VEC_replace (eh_region, cfun->eh->region_array, n->region_number, n);
-  gcc_assert (!o->aka);
+static void
+duplicate_eh_regions_0 (eh_region o, int *min, int *max)
+{
+  if (o->region_number < *min)
+    *min = o->region_number;
+  if (o->region_number > *max)
+    *max = o->region_number;
 
-  return n;
+  if (o->inner)
+    {
+      o = o->inner;
+      duplicate_eh_regions_0 (o, min, max);
+      while (o->next_peer)
+	{
+	  o = o->next_peer;
+	  duplicate_eh_regions_0 (o, min, max);
+	}
+    }
 }
 
-static void
-duplicate_eh_region_2 (struct eh_region *o, struct eh_region **n_array,
-		       struct eh_region *prev_try)
+/* A subroutine of duplicate_eh_regions.  Copy the region tree under OLD.
+   Root it at OUTER, and apply EH_OFFSET to the region number.  Don't worry
+   about the other internal pointers just yet, just the tree-like pointers.  */
+
+static eh_region
+duplicate_eh_regions_1 (eh_region old, eh_region outer, int eh_offset)
 {
-  struct eh_region *n = n_array[o->region_number];
+  eh_region ret, n;
 
-  switch (n->type)
-    {
-    case ERT_TRY:
-      if (o->u.try.catch)
-        n->u.try.catch = n_array[o->u.try.catch->region_number];
-      if (o->u.try.last_catch)
-        n->u.try.last_catch = n_array[o->u.try.last_catch->region_number];
-      break;
+  ret = n = ggc_alloc (sizeof (struct eh_region));
 
-    case ERT_CATCH:
-      if (o->u.catch.next_catch)
-	n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
-      if (o->u.catch.prev_catch)
-	n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
-      break;
+  *n = *old;
+  n->outer = outer;
+  gcc_assert (!old->aka);
 
-    case ERT_CLEANUP:
-      if (o->u.cleanup.prev_try)
-	n->u.cleanup.prev_try = n_array[o->u.cleanup.prev_try->region_number];
-      else
-        n->u.cleanup.prev_try = prev_try;
-      break;
+  n->region_number += eh_offset;
+  VEC_replace (eh_region, cfun->eh->region_array, n->region_number, n);
 
-    default:
-      break;
+  if (old->inner)
+    {
+      old = old->inner;
+      n = n->inner = duplicate_eh_regions_1 (old, ret, eh_offset);
+      while (old->next_peer)
+	{
+	  old = old->next_peer;
+	  n = n->next_peer = duplicate_eh_regions_1 (old, ret, eh_offset);
+	}
     }
 
-  if (o->outer)
-    n->outer = n_array[o->outer->region_number];
-  if (o->inner)
-    n->inner = n_array[o->inner->region_number];
-  if (o->next_peer)
-    n->next_peer = n_array[o->next_peer->region_number];
+  return ret;
 }
 
-/* Duplicate the EH regions of IFUN into current function, root the tree in
-   OUTER_REGION and remap labels using MAP callback.  */
+/* Duplicate the EH regions of IFUN, rootted at COPY_REGION, into current
+   function and root the tree below OUTER_REGION.  Remap labels using MAP
+   callback.  The special case of COPY_REGION of 0 means all regions.  */
+
 int
 duplicate_eh_regions (struct function *ifun, duplicate_eh_regions_map map,
-		      void *data, int outer_region)
+		      void *data, int copy_region, int outer_region)
 {
-  int ifun_last_region_number = ifun->eh->last_region_number;
-  struct eh_region **n_array, *root, *cur, *prev_try;
-  int i;
+  eh_region cur, prev_try, outer, *splice;
+  int i, min_region, max_region, eh_offset, cfun_last_region_number;
+  int num_regions;
 
-  if (ifun_last_region_number == 0 || !ifun->eh->region_tree)
+  if (!ifun->eh->region_tree)
     return 0;
 
-  n_array = xcalloc (ifun_last_region_number + 1, sizeof (*n_array));
+  /* Find the range of region numbers to be copied.  The interface we 
+     provide here mandates a single offset to find new number from old,
+     which means we must look at the numbers present, instead of the
+     count or something else.  */
+  if (copy_region > 0)
+    {
+      min_region = INT_MAX;
+      max_region = 0;
+
+      cur = VEC_index (eh_region, ifun->eh->region_array, copy_region);
+      duplicate_eh_regions_0 (cur, &min_region, &max_region);
+    }
+  else
+    min_region = 1, max_region = ifun->eh->last_region_number;
+  num_regions = max_region - min_region + 1;
+  cfun_last_region_number = cfun->eh->last_region_number;
+  eh_offset = cfun_last_region_number + 1 - min_region;
+
+  /* If we've not yet created a region array, do so now.  */
   VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
-		 cfun->eh->last_region_number + 1 + ifun_last_region_number);
+		 cfun_last_region_number + 1 + num_regions);
+  cfun->eh->last_region_number = max_region + eh_offset;
 
-  /* We might've created new cfun->eh->region_array so zero out nonexisting region 0.  */
+  /* We may have just allocated the array for the first time.
+     Make sure that element zero is null.  */
   VEC_replace (eh_region, cfun->eh->region_array, 0, 0);
 
-  for (i = cfun->eh->last_region_number + 1;
-       i < cfun->eh->last_region_number + 1 + ifun_last_region_number; i++)
-    VEC_replace (eh_region, cfun->eh->region_array, i, 0);
+  /* Zero all entries in the range allocated.  */
+  memset (VEC_address (eh_region, cfun->eh->region_array)
+	  + cfun_last_region_number + 1, 0, num_regions);
+
+  /* Locate the spot at which to insert the new tree.  */
+  if (outer_region > 0)
+    {
+      outer = VEC_index (eh_region, cfun->eh->region_array, outer_region);
+      splice = &outer->inner;
+    }
+  else
+    {
+      outer = NULL;
+      splice = &cfun->eh->region_tree;
+    }
+  while (*splice)
+    splice = &(*splice)->next_peer;
+
+  /* Copy all the regions in the subtree.  */
+  if (copy_region > 0)
+    {
+      cur = VEC_index (eh_region, ifun->eh->region_array, copy_region);
+      *splice = duplicate_eh_regions_1 (cur, outer, eh_offset);
+    }
+  else
+    {
+      eh_region n;
+
+      cur = ifun->eh->region_tree;
+      *splice = n = duplicate_eh_regions_1 (cur, outer, eh_offset);
+      while (cur->next_peer)
+	{
+	  cur = cur->next_peer;
+	  n = n->next_peer = duplicate_eh_regions_1 (cur, outer, eh_offset);
+	}
+    }
+
+  /* Remap all the labels in the new regions.  */
+  for (i = cfun_last_region_number + 1;
+       VEC_iterate (eh_region, cfun->eh->region_array, i, cur); ++i)
+    if (cur && cur->tree_label)
+      cur->tree_label = map (cur->tree_label, data);
 
   /* Search for the containing ERT_TRY region to fix up
      the prev_try short-cuts for ERT_CLEANUP regions.  */
@@ -945,67 +1006,77 @@ duplicate_eh_regions (struct function *i
 	 prev_try = prev_try->outer)
       ;
 
-  for (i = 1; i <= ifun_last_region_number; ++i)
-    {
-      cur = VEC_index (eh_region, ifun->eh->region_array, i);
-      if (!cur || cur->region_number != i)
-	continue;
-      n_array[i] = duplicate_eh_region_1 (cur);
-      if (cur->tree_label)
-	{
-	  tree newlabel = map (cur->tree_label, data);
-	  n_array[i]->tree_label = newlabel;
-	}
-      else
-	n_array[i]->tree_label = NULL;
-    }
-  for (i = 1; i <= ifun_last_region_number; ++i)
+  /* Remap all of the internal catch and cleanup linkages.  Since we 
+     duplicate entire subtrees, all of the referenced regions will have
+     been copied too.  And since we renumbered them as a block, a simple
+     bit of arithmetic finds us the index for the replacement region.  */
+  for (i = cfun_last_region_number + 1;
+       VEC_iterate (eh_region, cfun->eh->region_array, i, cur); ++i)
     {
-      cur = VEC_index (eh_region, ifun->eh->region_array, i);
-      if (!cur || cur->region_number != i)
+      if (cur == NULL)
 	continue;
-      duplicate_eh_region_2 (cur, n_array, prev_try);
-    }
 
-  root = n_array[ifun->eh->region_tree->region_number];
-  gcc_assert (root->outer == NULL);
-  if (outer_region > 0)
-    {
-      struct eh_region *cur
-         = VEC_index (eh_region, cfun->eh->region_array, outer_region);
-      struct eh_region *p = cur->inner;
-
-      if (p)
-	{
-	  while (p->next_peer)
-	    p = p->next_peer;
-	  p->next_peer = root;
-	}
-      else
-        cur->inner = root;
-      for (i = 1; i <= ifun_last_region_number; ++i)
-	if (n_array[i] && n_array[i]->outer == NULL)
-	  n_array[i]->outer = cur;
-    }
-  else
-    {
-      struct eh_region *p = cfun->eh->region_tree;
-      if (p)
+#define REMAP(REG) \
+	(REG) = VEC_index (eh_region, cfun->eh->region_array, \
+			   (REG)->region_number + eh_offset)
+
+      switch (cur->type)
 	{
-	  while (p->next_peer)
-	    p = p->next_peer;
-	  p->next_peer = root;
+	case ERT_TRY:
+	  if (cur->u.try.catch)
+	    REMAP (cur->u.try.catch);
+	  if (cur->u.try.last_catch)
+	    REMAP (cur->u.try.last_catch);
+	  break;
+
+	case ERT_CATCH:
+	  if (cur->u.catch.next_catch)
+	    REMAP (cur->u.catch.next_catch);
+	  if (cur->u.catch.prev_catch)
+	    REMAP (cur->u.catch.prev_catch);
+	  break;
+
+	case ERT_CLEANUP:
+	  if (cur->u.cleanup.prev_try)
+	    REMAP (cur->u.cleanup.prev_try);
+	  else
+	    cur->u.cleanup.prev_try = prev_try;
+	  break;
+
+	default:
+	  break;
 	}
-      else
-        cfun->eh->region_tree = root;
+
+#undef REMAP
     }
 
-  free (n_array);
+  return eh_offset;
+}
 
-  i = cfun->eh->last_region_number;
-  cfun->eh->last_region_number = i + ifun_last_region_number;
+/* Return true if REGION_A is outer to REGION_B in IFUN.  */
 
-  return i;
+bool
+eh_region_outer_p (struct function *ifun, int region_a, int region_b)
+{
+  struct eh_region *rp_a, *rp_b;
+
+  gcc_assert (ifun->eh->last_region_number > 0);
+  gcc_assert (ifun->eh->region_tree);
+
+  rp_a = VEC_index (eh_region, ifun->eh->region_array, region_a);
+  rp_b = VEC_index (eh_region, ifun->eh->region_array, region_b);
+  gcc_assert (rp_a != NULL);
+  gcc_assert (rp_b != NULL);
+
+  do
+    {
+      if (rp_a == rp_b)
+	return true;
+      rp_b = rp_b->outer;
+    }
+  while (rp_b);
+
+  return false;
 }
 
 static int
--- gcc/except.h	(revision 112292)
+++ gcc/except.h	(local)
@@ -82,7 +82,8 @@ extern rtx expand_builtin_extend_pointer
 extern rtx get_exception_pointer (struct function *);
 extern rtx get_exception_filter (struct function *);
 typedef tree (*duplicate_eh_regions_map) (tree, void *);
-extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, void *, int);
+extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map,
+				 void *, int, int);
 
 extern void sjlj_emit_function_exit_after (rtx);
 extern void default_init_unwind_resume_libfunc (void);
@@ -106,6 +107,7 @@ extern void collect_eh_region_array (voi
 extern void expand_resx_expr (tree);
 extern void verify_eh_tree (struct function *);
 extern void dump_eh_tree (FILE *, struct function *);
+extern bool eh_region_outer_p (struct function *, int, int);
 
 /* tree-eh.c */
 extern void add_stmt_to_eh_region_fn (struct function *, tree, int);
--- gcc/omp-low.c	(revision 112292)
+++ gcc/omp-low.c	(local)
@@ -3464,6 +3464,9 @@ lower_omp_sections (tree *stmt_p, omp_co
   new_body = alloc_stmt_list ();
   append_to_statement_list (ilist, &new_body);
   append_to_statement_list (stmt, &new_body);
+  /* ??? The OMP_RETURN doesn't logically belong here, but in
+     expand_omp_sections we expect this marker to be where the
+     individual sections join after completing the loop.  */
   append_to_statement_list (region_exit, &new_body);
   append_to_statement_list (olist, &new_body);
   append_to_statement_list (dlist, &new_body);
@@ -3610,9 +3613,9 @@ lower_omp_single (tree *stmt_p, omp_cont
     lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
 
   append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
+  maybe_catch_exception (&BIND_EXPR_BODY (bind));
   t = make_node (OMP_RETURN_EXPR);
   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
-  maybe_catch_exception (&BIND_EXPR_BODY (bind));
   pop_gimplify_context (bind);
 
   BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
@@ -3647,9 +3650,9 @@ lower_omp_master (tree *stmt_p, omp_cont
 
   x = build1 (LABEL_EXPR, void_type_node, lab);
   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
+  maybe_catch_exception (&BIND_EXPR_BODY (bind));
   x = make_node (OMP_RETURN_EXPR);
   append_to_statement_list (x, &BIND_EXPR_BODY (bind));
-  maybe_catch_exception (&BIND_EXPR_BODY (bind));
   pop_gimplify_context (bind);
 
   BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
@@ -3683,9 +3686,9 @@ lower_omp_ordered (tree *stmt_p, omp_con
   x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
   x = build_function_call_expr (x, NULL);
   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
+  maybe_catch_exception (&BIND_EXPR_BODY (bind));
   x = make_node (OMP_RETURN_EXPR);
   append_to_statement_list (x, &BIND_EXPR_BODY (bind));
-  maybe_catch_exception (&BIND_EXPR_BODY (bind));
   pop_gimplify_context (bind);
 
   BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
--- gcc/tree-cfg.c	(revision 112292)
+++ gcc/tree-cfg.c	(local)
@@ -4591,6 +4591,7 @@ struct move_stmt_d
   tree from_context;
   tree to_context;
   bitmap vars_to_remove;
+  htab_t new_label_map;
   bool remap_decls_p;
 };
 
@@ -4599,39 +4600,62 @@ struct move_stmt_d
    variable referenced in *TP.  */
 
 static tree
-move_stmt_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
+move_stmt_r (tree *tp, int *walk_subtrees, void *data)
 {
   struct move_stmt_d *p = (struct move_stmt_d *) data;
+  tree t = *tp;
 
-  if (p->block && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (*tp))))
-    TREE_BLOCK (*tp) = p->block;
+  if (p->block && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))))
+    TREE_BLOCK (t) = p->block;
 
-  if (OMP_DIRECTIVE_P (*tp))
+  if (OMP_DIRECTIVE_P (t) && TREE_CODE (t) != OMP_RETURN_EXPR)
     {
       /* Do not remap variables inside OMP directives.  Variables
 	 referenced in clauses and directive header belong to the
 	 parent function and should not be moved into the child
 	 function.  */
+      bool save_remap_decls_p = p->remap_decls_p;
       p->remap_decls_p = false;
-    }
+      *walk_subtrees = 0;
+
+      walk_tree (&OMP_BODY (t), move_stmt_r, p, NULL);
 
-  if (p->remap_decls_p
-      && DECL_P (*tp)
-      && DECL_CONTEXT (*tp) == p->from_context)
+      p->remap_decls_p = save_remap_decls_p;
+    }
+  else if (DECL_P (t) && DECL_CONTEXT (t) == p->from_context)
     {
-      DECL_CONTEXT (*tp) = p->to_context;
+      if (TREE_CODE (t) == LABEL_DECL)
+	{
+	  if (p->new_label_map)
+	    {
+	      struct tree_map in, *out;
+	      in.from = t;
+	      out = htab_find_with_hash (p->new_label_map, &in, DECL_UID (t));
+	      if (out)
+		*tp = t = out->to;
+	    }
 
-      if (TREE_CODE (*tp) == VAR_DECL)
+	  DECL_CONTEXT (t) = p->to_context;
+	}
+      else if (p->remap_decls_p)
 	{
-	  struct function *f = DECL_STRUCT_FUNCTION (p->to_context);
-	  f->unexpanded_var_list = tree_cons (0, *tp, f->unexpanded_var_list);
+	  DECL_CONTEXT (t) = p->to_context;
 
-	  /* Mark *TP to be removed from the original function,
-	     otherwise it will be given a DECL_RTL when the original
-	     function is expanded.  */
-	  bitmap_set_bit (p->vars_to_remove, DECL_UID (*tp));
+	  if (TREE_CODE (t) == VAR_DECL)
+	    {
+	      struct function *f = DECL_STRUCT_FUNCTION (p->to_context);
+	      f->unexpanded_var_list
+		= tree_cons (0, t, f->unexpanded_var_list);
+
+	      /* Mark T to be removed from the original function,
+	         otherwise it will be given a DECL_RTL when the
+		 original function is expanded.  */
+	      bitmap_set_bit (p->vars_to_remove, DECL_UID (t));
+	    }
 	}
     }
+  else if (TYPE_P (t))
+    *walk_subtrees = 0;
 
   return NULL_TREE;
 }
@@ -4650,7 +4674,7 @@ move_stmt_r (tree *tp, int *walk_subtree
 static void
 move_block_to_fn (struct function *dest_cfun, basic_block bb,
 		  basic_block after, bool update_edge_count_p,
-		  bitmap vars_to_remove)
+		  bitmap vars_to_remove, htab_t new_label_map, int eh_offset)
 {
   struct control_flow_graph *cfg;
   edge_iterator ei;
@@ -4701,10 +4725,12 @@ move_block_to_fn (struct function *dest_
   for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
     {
       tree stmt = bsi_stmt (si);
+      int region;
 
       d.from_context = cfun->decl;
       d.to_context = dest_cfun->decl;
       d.remap_decls_p = true;
+      d.new_label_map = new_label_map;
       if (TREE_BLOCK (stmt))
 	d.block = DECL_INITIAL (dest_cfun->decl);
 
@@ -4736,11 +4762,66 @@ move_block_to_fn (struct function *dest_
 	  if (uid >= dest_cfun->last_label_uid)
 	    dest_cfun->last_label_uid = uid + 1;
 	}
+      else if (TREE_CODE (stmt) == RESX_EXPR && eh_offset != 0)
+	TREE_OPERAND (stmt, 0) =
+	  build_int_cst (NULL_TREE,
+			 TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0))
+			 + eh_offset);
+
+      region = lookup_stmt_eh_region (stmt);
+      if (region >= 0)
+	{
+	  add_stmt_to_eh_region_fn (dest_cfun, stmt, region + eh_offset);
+	  remove_stmt_from_eh_region (stmt);
+	}
+    }
+}
+
+/* Examine the statements in BB (which is in SRC_CFUN); find and return
+   the outermost EH region.  Use REGION as the incoming base EH region.  */
+
+static int
+find_outermost_region_in_block (struct function *src_cfun,
+				basic_block bb, int region)
+{
+  block_stmt_iterator si;
+  
+  for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+    {
+      tree stmt = bsi_stmt (si);
+      int stmt_region;
 
-      remove_stmt_from_eh_region (stmt);
+      stmt_region = lookup_stmt_eh_region_fn (src_cfun, stmt);
+      if (stmt_region > 0
+	  && (region < 0 || eh_region_outer_p (src_cfun, stmt_region, region)))
+	region = stmt_region;
     }
+
+  return region;
 }
 
+static tree
+new_label_mapper (tree decl, void *data)
+{
+  htab_t hash = (htab_t) data;
+  struct tree_map *m;
+  void **slot;
+
+  gcc_assert (TREE_CODE (decl) == LABEL_DECL);
+
+  m = xmalloc (sizeof (struct tree_map));
+  m->hash = DECL_UID (decl);
+  m->from = decl;
+  m->to = create_artificial_label ();
+  LABEL_DECL_UID (m->to) = LABEL_DECL_UID (decl);
+
+  slot = htab_find_slot_with_hash (hash, m, m->hash, INSERT);
+  gcc_assert (*slot == NULL);
+
+  *slot = m;
+
+  return m->to;
+}
 
 /* Move a single-entry, single-exit region delimited by ENTRY_BB and
    EXIT_BB to function DEST_CFUN.  The whole region is replaced by a
@@ -4763,11 +4844,12 @@ move_sese_region_to_fn (struct function 
   VEC(basic_block,heap) *bbs;
   basic_block after, bb, *entry_pred, *exit_succ;
   struct function *saved_cfun;
-  int *entry_flag, *exit_flag;
+  int *entry_flag, *exit_flag, eh_offset;
   unsigned i, num_entry_edges, num_exit_edges;
   edge e;
   edge_iterator ei;
   bitmap vars_to_remove;
+  htab_t new_label_map;
 
   saved_cfun = cfun;
 
@@ -4813,7 +4895,28 @@ move_sese_region_to_fn (struct function 
   /* Switch context to the child function to initialize DEST_FN's CFG.  */
   gcc_assert (dest_cfun->cfg == NULL);
   cfun = dest_cfun;
+
   init_empty_tree_cfg ();
+
+  /* Initialize EH information for the new function.  */
+  eh_offset = 0;
+  new_label_map = NULL;
+  if (saved_cfun->eh)
+    {
+      int region = -1;
+
+      for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
+	region = find_outermost_region_in_block (saved_cfun, bb, region);
+
+      init_eh_for_function ();
+      if (region != -1)
+	{
+	  new_label_map = htab_create (17, tree_map_hash, tree_map_eq, free);
+	  eh_offset = duplicate_eh_regions (saved_cfun, new_label_mapper,
+					    new_label_map, region, 0);
+	}
+    }
+
   cfun = saved_cfun;
 
   /* Move blocks from BBS into DEST_CFUN.  */
@@ -4825,10 +4928,14 @@ move_sese_region_to_fn (struct function 
       /* No need to update edge counts on the last block.  It has
 	 already been updated earlier when we detached the region from
 	 the original CFG.  */
-      move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_to_remove);
+      move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_to_remove,
+	                new_label_map, eh_offset);
       after = bb;
     }
 
+  if (new_label_map)
+    htab_delete (new_label_map);
+
   /* Remove the variables marked in VARS_TO_REMOVE from
      CFUN->UNEXPANDED_VAR_LIST.  Otherwise, they will be given a
      DECL_RTL in the context of CFUN.  */
--- gcc/tree-inline.c	(revision 112292)
+++ gcc/tree-inline.c	(local)
@@ -924,7 +924,8 @@ copy_cfg_body (copy_body_data * id, gcov
       if (id->transform_new_cfg)
         init_eh_for_function ();
       id->eh_region_offset
-	= duplicate_eh_regions (cfun_to_copy, remap_decl_1, id, id->eh_region);
+	= duplicate_eh_regions (cfun_to_copy, remap_decl_1, id,
+				0, id->eh_region);
     }
   /* Use aux pointers to map the original blocks to copy.  */
   FOR_EACH_BB_FN (bb, cfun_to_copy)
--- gcc/tree-pretty-print.c	(revision 112292)
+++ gcc/tree-pretty-print.c	(local)
@@ -1557,8 +1557,8 @@ dump_generic_node (pretty_printer *buffe
       break;
 
     case RESX_EXPR:
-      pp_string (buffer, "resx");
-      /* ??? Any sensible way to present the eh region?  */
+      pp_string (buffer, "resx ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
       break;
 
     case ASM_EXPR:



More information about the Gcc-patches mailing list