From 2a19b1a9c7e6968f87bcff7d3b1fd187de88f091 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 15 Oct 2007 01:21:37 -0400 Subject: [PATCH] tree-eh.c (optimize_double_finally): Don't assume that the cleanup we're duplicating is only one statement. * tree-eh.c (optimize_double_finally): Don't assume that the cleanup we're duplicating is only one statement. From-SVN: r129311 --- gcc/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/eh/ehopt1.C | 44 ++++++++++++++++++++++++++++++++ gcc/tree-eh.c | 10 ++------ 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/eh/ehopt1.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff46a41677d..e45535d349a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2007-10-14 Jason Merrill + + * tree-eh.c (optimize_double_finally): Don't assume that the + cleanup we're duplicating is only one statement. + 2007-10-14 Kazu Hirata * config/fixed-bit.c, config/i386/cpuid.h, config/i386/i386.c, diff --git a/gcc/testsuite/g++.dg/eh/ehopt1.C b/gcc/testsuite/g++.dg/eh/ehopt1.C new file mode 100644 index 00000000000..163d76e814f --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/ehopt1.C @@ -0,0 +1,44 @@ +// ehopt was only copying one statement from the cleanup of the B temporary +// into the following try block, so we lost its destructor call. + +// { dg-do run } + +template +class A; + +bool b; +int count; + +template <> +class A +{ +public: + A(int) { ++count; if (b) throw 1; } + A(const A&) { ++count; if (b) throw 1; } + ~A() { --count; if (b) throw 1; } +}; + +typedef A B; + +template <> +class A +{ +public: + A() { if (b) throw 1; } + A(const B&) { if (b) throw 1; } + ~A() { if (b) throw 1; } +}; + +typedef A C; + +void f() { if (b) throw 1; } + +int +main (void) +{ + { + C a(1); + f(); + } + return count; +} diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 1924353f7b1..71d3d941b79 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -2157,18 +2157,12 @@ optimize_double_finally (tree one, tree two) if (same_handler_p (TREE_OPERAND (oneh, 1), TREE_OPERAND (two, 1))) { - tree twoh; - tree b = TREE_OPERAND (oneh, 0); TREE_OPERAND (one, 1) = b; TREE_SET_CODE (one, TRY_CATCH_EXPR); - b = tsi_stmt (tsi_start (b)); - twoh = TREE_OPERAND (two, 0); - /* same_handler_p only handles single-statement handlers, - so there must only be one statement. */ - i = tsi_start (twoh); - tsi_link_before (&i, unshare_expr (b), TSI_SAME_STMT); + i = tsi_start (TREE_OPERAND (two, 0)); + tsi_link_before (&i, unsave_expr_now (b), TSI_SAME_STMT); } }