aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-03-15 16:35:17 -0800
committerRichard Henderson <rth@gcc.gnu.org>2004-03-15 16:35:17 -0800
commit0977ab3aa6121253392b15c02679a86615f05e1b (patch)
tree6f83cb950f53a1df02dec8609a2cc0e4816e0d90
parent199f5c2b84b096f5f2925029d9728bd422eb36da (diff)
downloadgcc-0977ab3aa6121253392b15c02679a86615f05e1b.zip
gcc-0977ab3aa6121253392b15c02679a86615f05e1b.tar.gz
gcc-0977ab3aa6121253392b15c02679a86615f05e1b.tar.bz2
re PR middle-end/14535 (exception throwing in virtual function doesn't turn on the local destructors)
PR middle-end/14535 * except.c (collect_one_action_chain): Record action for cleanup outer of exception spec. * g++.dg/eh/spec7.C: New. From-SVN: r79521
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/except.c14
-rw-r--r--gcc/testsuite/g++.dg/eh/spec7.C35
3 files changed, 53 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 458ae13..69a0bcc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2004-03-15 Richard Henderson <rth@redhat.com>
+
+ PR middle-end/14535
+ * except.c (collect_one_action_chain): Record action for cleanup
+ outer of exception spec.
+
2004-03-15 Ian Lance Taylor <ian@wasabisystems.com>
* config/rs6000/host-darwin.c (darwin_rs6000_gt_pch_use_address):
diff --git a/gcc/except.c b/gcc/except.c
index 4e38df2..c739650 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -3365,8 +3365,18 @@ collect_one_action_chain (htab_t ar_hash, struct eh_region *region)
/* An exception specification adds its filter to the
beginning of the chain. */
next = collect_one_action_chain (ar_hash, region->outer);
- return add_action_record (ar_hash, region->u.allowed.filter,
- next < 0 ? 0 : next);
+
+ /* If there is no next action, terminate the chain. */
+ if (next == -1)
+ next = 0;
+ /* If all outer actions are cleanups or must_not_throw,
+ we'll have no action record for it, since we had wanted
+ to encode these states in the call-site record directly.
+ Add a cleanup action to the chain to catch these. */
+ else if (next <= 0)
+ next = add_action_record (ar_hash, 0, 0);
+
+ return add_action_record (ar_hash, region->u.allowed.filter, next);
case ERT_MUST_NOT_THROW:
/* A must-not-throw region with no inner handlers or cleanups
diff --git a/gcc/testsuite/g++.dg/eh/spec7.C b/gcc/testsuite/g++.dg/eh/spec7.C
new file mode 100644
index 0000000..08586a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/spec7.C
@@ -0,0 +1,35 @@
+// PR 14535
+// { dg-do run }
+// { dg-options "-O -finline" }
+//
+// Original test case failure required that Raiser constructor be inlined.
+
+extern "C" void abort();
+bool destructor_called = false;
+
+struct B {
+ virtual void Run(){};
+};
+
+struct D : public B {
+ virtual void Run()
+ {
+ struct O {
+ ~O() { destructor_called = true; };
+ } o;
+
+ struct Raiser {
+ Raiser() throw( int ) {throw 1;};
+ } raiser;
+ };
+};
+
+int main() {
+ try {
+ D d;
+ static_cast<B&>(d).Run();
+ } catch (...) {}
+
+ if (!destructor_called)
+ abort ();
+}