Commit 9f698956 by Andrey Belevantsev Committed by Andrey Belevantsev

re PR middle-end/42859 (ICE in verify_flow_info)

    PR middle-end/42859

    * tree-eh.c: Include pointer-set.h.
    (lower_eh_dispatch): Filter out duplicate case labels and
    remove the unneeded edge when the label is unused.  Return
    true when some edges are removed.
    (execute_lower_eh_dispatch): When any lowering resulted in
    removing an edge, also delete unreachable blocks.

    * g++.dg/eh/pr42859.C: New test.

From-SVN: r157337
parent ff4f03c3
2010-03-10 Andrey Belevantsev <abel@ispras.ru>
PR middle-end/42859
* tree-eh.c: Include pointer-set.h.
(lower_eh_dispatch): Filter out duplicate case labels and
remove the unneeded edge when the label is unused. Return
true when some edges are removed.
(execute_lower_eh_dispatch): When any lowering resulted in
removing an edge, also delete unreachable blocks.
2010-03-10 Jakub Jelinek <jakub@redhat.com> 2010-03-10 Jakub Jelinek <jakub@redhat.com>
PR bootstrap/43287 PR bootstrap/43287
......
2010-03-10 Andrey Belevantsev <abel@ispras.ru>
PR middle-end/42859
* g++.dg/eh/pr42859.C: New test.
2010-03-09 Jakub Jelinek <jakub@redhat.com> 2010-03-09 Jakub Jelinek <jakub@redhat.com>
PR debug/43299 PR debug/43299
......
// { dg-do compile }
void start (void);
void
ptw32_terminate (void)
{
try
{
try
{
start ();
}
catch (int)
{
}
catch (int)
{
}
}
catch (int)
{
}
}
...@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h" #include "flags.h"
#include "function.h" #include "function.h"
#include "except.h" #include "except.h"
#include "pointer-set.h"
#include "tree-flow.h" #include "tree-flow.h"
#include "tree-dump.h" #include "tree-dump.h"
#include "tree-inline.h" #include "tree-inline.h"
...@@ -3038,9 +3039,10 @@ struct gimple_opt_pass pass_lower_resx = ...@@ -3038,9 +3039,10 @@ struct gimple_opt_pass pass_lower_resx =
}; };
/* At the end of inlining, we can lower EH_DISPATCH. */ /* At the end of inlining, we can lower EH_DISPATCH. Return true when
we have found some duplicate labels and removed some edges. */
static void static bool
lower_eh_dispatch (basic_block src, gimple stmt) lower_eh_dispatch (basic_block src, gimple stmt)
{ {
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
...@@ -3048,6 +3050,7 @@ lower_eh_dispatch (basic_block src, gimple stmt) ...@@ -3048,6 +3050,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
eh_region r; eh_region r;
tree filter, fn; tree filter, fn;
gimple x; gimple x;
bool redirected = false;
region_nr = gimple_eh_dispatch_region (stmt); region_nr = gimple_eh_dispatch_region (stmt);
r = get_eh_region_from_number (region_nr); r = get_eh_region_from_number (region_nr);
...@@ -3063,6 +3066,7 @@ lower_eh_dispatch (basic_block src, gimple stmt) ...@@ -3063,6 +3066,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
eh_catch c; eh_catch c;
edge_iterator ei; edge_iterator ei;
edge e; edge e;
struct pointer_set_t *seen_values = pointer_set_create ();
/* Collect the labels for a switch. Zero the post_landing_pad /* Collect the labels for a switch. Zero the post_landing_pad
field becase we'll no longer have anything keeping these labels field becase we'll no longer have anything keeping these labels
...@@ -3071,6 +3075,7 @@ lower_eh_dispatch (basic_block src, gimple stmt) ...@@ -3071,6 +3075,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
{ {
tree tp_node, flt_node, lab = c->label; tree tp_node, flt_node, lab = c->label;
bool have_label = false;
c->label = NULL; c->label = NULL;
tp_node = c->type_list; tp_node = c->type_list;
...@@ -3083,14 +3088,29 @@ lower_eh_dispatch (basic_block src, gimple stmt) ...@@ -3083,14 +3088,29 @@ lower_eh_dispatch (basic_block src, gimple stmt)
} }
do do
{ {
tree t = build3 (CASE_LABEL_EXPR, void_type_node, /* Filter out duplicate labels that arise when this handler
TREE_VALUE (flt_node), NULL, lab); is shadowed by an earlier one. When no labels are
VEC_safe_push (tree, heap, labels, t); attached to the handler anymore, we remove
the corresponding edge and then we delete unreachable
blocks at the end of this pass. */
if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
{
tree t = build3 (CASE_LABEL_EXPR, void_type_node,
TREE_VALUE (flt_node), NULL, lab);
VEC_safe_push (tree, heap, labels, t);
pointer_set_insert (seen_values, TREE_VALUE (flt_node));
have_label = true;
}
tp_node = TREE_CHAIN (tp_node); tp_node = TREE_CHAIN (tp_node);
flt_node = TREE_CHAIN (flt_node); flt_node = TREE_CHAIN (flt_node);
} }
while (tp_node); while (tp_node);
if (! have_label)
{
remove_edge (find_edge (src, label_to_block (lab)));
redirected = true;
}
} }
/* Clean up the edge flags. */ /* Clean up the edge flags. */
...@@ -3132,6 +3152,7 @@ lower_eh_dispatch (basic_block src, gimple stmt) ...@@ -3132,6 +3152,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
VEC_free (tree, heap, labels); VEC_free (tree, heap, labels);
} }
pointer_set_destroy (seen_values);
} }
break; break;
...@@ -3165,6 +3186,7 @@ lower_eh_dispatch (basic_block src, gimple stmt) ...@@ -3165,6 +3186,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
/* Replace the EH_DISPATCH with the SWITCH or COND generated above. */ /* Replace the EH_DISPATCH with the SWITCH or COND generated above. */
gsi_remove (&gsi, true); gsi_remove (&gsi, true);
return redirected;
} }
static unsigned static unsigned
...@@ -3172,6 +3194,7 @@ execute_lower_eh_dispatch (void) ...@@ -3172,6 +3194,7 @@ execute_lower_eh_dispatch (void)
{ {
basic_block bb; basic_block bb;
bool any_rewritten = false; bool any_rewritten = false;
bool redirected = false;
assign_filter_values (); assign_filter_values ();
...@@ -3180,11 +3203,13 @@ execute_lower_eh_dispatch (void) ...@@ -3180,11 +3203,13 @@ execute_lower_eh_dispatch (void)
gimple last = last_stmt (bb); gimple last = last_stmt (bb);
if (last && gimple_code (last) == GIMPLE_EH_DISPATCH) if (last && gimple_code (last) == GIMPLE_EH_DISPATCH)
{ {
lower_eh_dispatch (bb, last); redirected |= lower_eh_dispatch (bb, last);
any_rewritten = true; any_rewritten = true;
} }
} }
if (redirected)
delete_unreachable_blocks ();
return any_rewritten ? TODO_update_ssa_only_virtuals : 0; return any_rewritten ? TODO_update_ssa_only_virtuals : 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment