diff options
author | Jason Merrill <jason@redhat.com> | 2010-05-21 15:32:29 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-05-21 15:32:29 -0400 |
commit | d3f28910851bee99e959d8841c818417109d0a33 (patch) | |
tree | 910f63348f513f24157b7b8f6b170ad11a410c48 /gcc/tree-eh.c | |
parent | 14db98d4a6349271ab34e894c9b0780cb985666b (diff) | |
download | gcc-d3f28910851bee99e959d8841c818417109d0a33.zip gcc-d3f28910851bee99e959d8841c818417109d0a33.tar.gz gcc-d3f28910851bee99e959d8841c818417109d0a33.tar.bz2 |
tree-eh.c (cleanup_is_dead_in): New.
* tree-eh.c (cleanup_is_dead_in): New.
(lower_try_finally): Don't generate a dead cleanup region.
(lower_cleanup): Likewise.
From-SVN: r159682
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r-- | gcc/tree-eh.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 2cc03d3..e5d76c8 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -1517,6 +1517,20 @@ decide_copy_try_finally (int ndests, gimple_seq finally) return f_estimate < 40 || f_estimate * 2 < sw_estimate * 3; } +/* REG is the enclosing region for a possible cleanup region, or the region + itself. Returns TRUE if such a region would be unreachable. + + Cleanup regions within a must-not-throw region aren't actually reachable + even if there are throwing stmts within them, because the personality + routine will call terminate before unwinding. */ + +static bool +cleanup_is_dead_in (eh_region reg) +{ + while (reg && reg->type == ERT_CLEANUP) + reg = reg->outer; + return (reg && reg->type == ERT_MUST_NOT_THROW); +} /* A subroutine of lower_eh_constructs_1. Lower a GIMPLE_TRY_FINALLY nodes to a sequence of labels and blocks, plus the exception region trees @@ -1537,12 +1551,17 @@ lower_try_finally (struct leh_state *state, gimple tp) this_tf.try_finally_expr = tp; this_tf.top_p = tp; this_tf.outer = state; - if (using_eh_for_cleanups_p) - this_tf.region = gen_eh_region_cleanup (state->cur_region); + if (using_eh_for_cleanups_p && !cleanup_is_dead_in (state->cur_region)) + { + this_tf.region = gen_eh_region_cleanup (state->cur_region); + this_state.cur_region = this_tf.region; + } else - this_tf.region = NULL; + { + this_tf.region = NULL; + this_state.cur_region = state->cur_region; + } - this_state.cur_region = this_tf.region; this_state.ehp_region = state->ehp_region; this_state.tf = &this_tf; @@ -1555,7 +1574,7 @@ lower_try_finally (struct leh_state *state, gimple tp) this_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp)); /* Determine if any exceptions are possible within the try block. */ - if (using_eh_for_cleanups_p) + if (this_tf.region) this_tf.may_throw = eh_region_may_contain_throw (this_tf.region); if (this_tf.may_throw) honor_protect_cleanup_actions (state, &this_state, &this_tf); @@ -1779,8 +1798,9 @@ lower_cleanup (struct leh_state *state, gimple tp) eh_region this_region = NULL; struct leh_tf_state fake_tf; gimple_seq result; + bool cleanup_dead = cleanup_is_dead_in (state->cur_region); - if (flag_exceptions) + if (flag_exceptions && !cleanup_dead) { this_region = gen_eh_region_cleanup (state->cur_region); this_state.cur_region = this_region; @@ -1788,7 +1808,7 @@ lower_cleanup (struct leh_state *state, gimple tp) lower_eh_constructs_1 (&this_state, gimple_try_eval (tp)); - if (!eh_region_may_contain_throw (this_region)) + if (cleanup_dead || !eh_region_may_contain_throw (this_region)) return gimple_try_eval (tp); /* Build enough of a try-finally state so that we can reuse |