From 072c87d17058df5073c7cb7e9e46809b7c5c0515 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 25 Sep 2009 13:49:08 -0700 Subject: [PATCH] re PR middle-end/41469 (-fexceptions ICE in expand_gimple_stmt_1, at cfgexpand.c:1947) PR middle-end/41469 * tree-eh.c (lower_resx): Resolve RESX with no source region to __builtin_trap. (gate_lower_resx): New. (gate_lower_eh_dispatch): Rename from gate_lower_ehcontrol. From-SVN: r152185 --- gcc/ChangeLog | 8 +++++ gcc/testsuite/gcc.c-torture/compile/pr41469.c | 12 +++++++ gcc/tree-eh.c | 36 +++++++++++++++---- 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr41469.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53a8332c267..7e7367faa9d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-09-25 Richard Henderson + + PR middle-end/41469 + * tree-eh.c (lower_resx): Resolve RESX with no source region to + __builtin_trap. + (gate_lower_resx): New. + (gate_lower_eh_dispatch): Rename from gate_lower_ehcontrol. + 2009-09-25 Anatoly Sokolov * config/v850/v850.h (FUNCTION_VALUE): Remove. diff --git a/gcc/testsuite/gcc.c-torture/compile/pr41469.c b/gcc/testsuite/gcc.c-torture/compile/pr41469.c new file mode 100644 index 00000000000..7813cb3d66d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr41469.c @@ -0,0 +1,12 @@ +void +af (void *a) +{ +} +void +bf (void) +{ + int i = 1; + char v[i]; + af (v); +} + diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index a1aa4b21571..70c009d6bb2 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -2849,10 +2849,26 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map) dst_r = NULL; src_r = get_eh_region_from_number (gimple_resx_region (stmt)); - src_nr = build_int_cst (NULL, src_r->index); gsi = gsi_last_bb (bb); - if (dst_r) + if (src_r == NULL) + { + /* We can wind up with no source region when pass_cleanup_eh shows + that there are no entries into an eh region and deletes it, but + then the block that contains the resx isn't removed. This can + happen without optimization when the switch statement created by + lower_try_finally_switch isn't simplified to remove the eh case. + + Resolve this by expanding the resx node to an abort. */ + + fn = implicit_built_in_decls[BUILT_IN_TRAP]; + x = gimple_build_call (fn, 0); + gsi_insert_before (&gsi, x, GSI_SAME_STMT); + + while (EDGE_COUNT (bb->succs) > 0) + remove_edge (EDGE_SUCC (bb, 0)); + } + else if (dst_r) { /* When we have a destination region, we resolve this by copying the excptr and filter values into place, and changing the edge @@ -2903,6 +2919,7 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map) tree dst_nr = build_int_cst (NULL, dst_r->index); fn = implicit_built_in_decls[BUILT_IN_EH_COPY_VALUES]; + src_nr = build_int_cst (NULL, src_r->index); x = gimple_build_call (fn, 2, dst_nr, src_nr); gsi_insert_before (&gsi, x, GSI_SAME_STMT); @@ -2948,6 +2965,7 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map) case 0: fn = implicit_built_in_decls[BUILT_IN_EH_POINTER]; + src_nr = build_int_cst (NULL, src_r->index); x = gimple_build_call (fn, 1, src_nr); var = create_tmp_var (ptr_type_node, NULL); var = make_ssa_name (var, x); @@ -3000,9 +3018,9 @@ execute_lower_resx (void) } static bool -gate_lower_ehcontrol (void) +gate_lower_resx (void) { - return cfun->eh->region_tree != NULL; + return flag_exceptions != 0; } struct gimple_opt_pass pass_lower_resx = @@ -3010,7 +3028,7 @@ struct gimple_opt_pass pass_lower_resx = { GIMPLE_PASS, "resx", /* name */ - gate_lower_ehcontrol, /* gate */ + gate_lower_resx, /* gate */ execute_lower_resx, /* execute */ NULL, /* sub */ NULL, /* next */ @@ -3175,12 +3193,18 @@ execute_lower_eh_dispatch (void) return any_rewritten ? TODO_update_ssa_only_virtuals : 0; } +static bool +gate_lower_eh_dispatch (void) +{ + return cfun->eh->region_tree != NULL; +} + struct gimple_opt_pass pass_lower_eh_dispatch = { { GIMPLE_PASS, "ehdisp", /* name */ - gate_lower_ehcontrol, /* gate */ + gate_lower_eh_dispatch, /* gate */ execute_lower_eh_dispatch, /* execute */ NULL, /* sub */ NULL, /* next */