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
This commit is contained in:
Jason Merrill 2010-05-21 15:32:29 -04:00 committed by Jason Merrill
parent 14db98d4a6
commit d3f2891085
6 changed files with 69 additions and 14 deletions

View File

@ -1,3 +1,9 @@
2010-05-21 Jason Merrill <jason@redhat.com>
* tree-eh.c (cleanup_is_dead_in): New.
(lower_try_finally): Don't generate a dead cleanup region.
(lower_cleanup): Likewise.
2010-05-21 Jakub Jelinek <jakub@redhat.com>
PR debug/44223

View File

@ -28,6 +28,7 @@ environment); refer to their documentation for details.
@menu
* Conditionally-supported behavior::
* Exception handling::
@end menu
@node Conditionally-supported behavior
@ -45,3 +46,16 @@ constructor or destructor can be passed to ... (C++0x 5.2.2).}
Such argument passing is not supported.
@end itemize
@node Exception handling
@section Exception handling
@itemize @bullet
@item
@cite{In the situation where no matching handler is found, it is
implementation-defined whether or not the stack is unwound before
std::terminate() is called (C++98 15.5.1).}
The stack is not unwound before std::terminate is called.
@end itemize

View File

@ -187,7 +187,7 @@ in the following sections.
-fno-implicit-templates @gol
-fno-implicit-inline-templates @gol
-fno-implement-inlines -fms-extensions @gol
-fno-nonansi-builtins -fno-operator-names @gol
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol
-fno-optional-diags -fpermissive @gol
-fno-pretty-templates @gol
-frepo -fno-rtti -fstats -ftemplate-depth=@var{n} @gol
@ -1933,10 +1933,13 @@ ANSI/ISO C@. These include @code{ffs}, @code{alloca}, @code{_exit},
@opindex fnothrow-opt
Treat a @code{throw()} exception specification as though it were a
@code{noexcept} specification to reduce or eliminate the text size
overhead relative to a function with no exception specification. The
semantic effect is that an exception thrown out of a function with
such an exception specification will result in a call to
@code{terminate} rather than @code{unexpected}.
overhead relative to a function with no exception specification. If
the function has local variables of types with non-trivial
destructors, the exception specification will actually make the
function smaller because the EH cleanups for those variables can be
optimized away. The semantic effect is that an exception thrown out of
a function with such an exception specification will result in a call
to @code{terminate} rather than @code{unexpected}.
@item -fno-operator-names
@opindex fno-operator-names

View File

@ -1,3 +1,7 @@
2010-05-21 Jason Merrill <jason@redhat.com>
* g++.dg/eh/spec11.C: Test cleanup optimization.
2010-05-21 Jakub Jelinek <jakub@redhat.com>
PR debug/44223

View File

@ -1,5 +1,8 @@
// Make sure that we force an LSDA for a throw() spec with -fnothrow-opt so
// that the personality routine will call terminate.
// that the personality routine will call terminate. Also check that we
// optimize away the EH cleanup for var because the personality routine
// will call terminate before unwinding: there should not be an EH region
// (i.e. LEHB/LEHE labels) around the call to g().
// { dg-final { scan-assembler-not "_ZSt9terminatev" } }
// { dg-final { scan-assembler-not "EHB" } }
@ -7,5 +10,10 @@
// { dg-options "-fnothrow-opt" }
struct A { ~A(); };
void g();
void f() throw() { g(); }
void f() throw()
{
A var;
g();
}

View File

@ -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