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:
parent
14db98d4a6
commit
d3f2891085
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue