summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
47086a6)
(lower_try_finally): Don't generate a dead cleanup region.
(lower_cleanup): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159682
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
2010-05-21 Jakub Jelinek <jakub@redhat.com>
PR debug/44223
@menu
* Conditionally-supported behavior::
@menu
* Conditionally-supported behavior::
@end menu
@node Conditionally-supported behavior
@end menu
@node Conditionally-supported behavior
Such argument passing is not supported.
@end itemize
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
-fno-implicit-templates @gol
-fno-implicit-inline-templates @gol
-fno-implement-inlines -fms-extensions @gol
-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
-fno-optional-diags -fpermissive @gol
-fno-pretty-templates @gol
-frepo -fno-rtti -fstats -ftemplate-depth=@var{n} @gol
@opindex fnothrow-opt
Treat a @code{throw()} exception specification as though it were a
@code{noexcept} specification to reduce or eliminate the text size
@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
@item -fno-operator-names
@opindex fno-operator-names
+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
2010-05-21 Jakub Jelinek <jakub@redhat.com>
PR debug/44223
// Make sure that we force an LSDA for a throw() spec with -fnothrow-opt so
// 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" } }
// { dg-final { scan-assembler-not "_ZSt9terminatev" } }
// { dg-final { scan-assembler-not "EHB" } }
// { dg-options "-fnothrow-opt" }
// { dg-options "-fnothrow-opt" }
-void f() throw() { g(); }
+void f() throw()
+{
+ A var;
+ g();
+}
return f_estimate < 40 || f_estimate * 2 < sw_estimate * 3;
}
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
/* 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
this_tf.try_finally_expr = tp;
this_tf.top_p = tp;
this_tf.outer = state;
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;
+ }
+ {
+ 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;
this_state.ehp_region = state->ehp_region;
this_state.tf = &this_tf;
this_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp));
/* Determine if any exceptions are possible within the try block. */
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)
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);
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);
eh_region this_region = NULL;
struct leh_tf_state fake_tf;
gimple_seq result;
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 && !cleanup_dead)
{
this_region = gen_eh_region_cleanup (state->cur_region);
this_state.cur_region = this_region;
{
this_region = gen_eh_region_cleanup (state->cur_region);
this_state.cur_region = this_region;
lower_eh_constructs_1 (&this_state, gimple_try_eval (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
return gimple_try_eval (tp);
/* Build enough of a try-finally state so that we can reuse