aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-08-03 16:15:51 -0700
committerRichard Henderson <rth@gcc.gnu.org>2001-08-03 16:15:51 -0700
commit949f197fa6853615f92ded3def63db5e77ed9af2 (patch)
tree51fcc575dc9325d75e35147a2bf8537fbc68a91c /gcc
parentc99fa40fbe95dc94e7e55b374f778cc154fd4864 (diff)
downloadgcc-949f197fa6853615f92ded3def63db5e77ed9af2.zip
gcc-949f197fa6853615f92ded3def63db5e77ed9af2.tar.gz
gcc-949f197fa6853615f92ded3def63db5e77ed9af2.tar.bz2
except.c (collect_one_action_chain): Add an explicit cleanup action if regions surrounding a catch were encoded...
* except.c (collect_one_action_chain): Add an explicit cleanup action if regions surrounding a catch were encoded entirely within the call-site entry. * g++.dg/eh/filter1.C, g++.dg/eh/filter2.C: New tests. From-SVN: r44616
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/except.c21
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/eh/filter1.C43
-rw-r--r--gcc/testsuite/g++.dg/eh/filter2.C59
5 files changed, 132 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b2eb17f..65f73d0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2001-08-03 Richard Henderson <rth@redhat.com>
+ * except.c (collect_one_action_chain): Add an explicit cleanup
+ action if regions surrounding a catch were encoded entirely
+ within the call-site entry.
+
+2001-08-03 Richard Henderson <rth@redhat.com>
+
* dbxout.c (dbxout_symbol_location): Flatten subregs first;
don't take REGNO of a non-register.
diff --git a/gcc/except.c b/gcc/except.c
index e24a901..4397cfc 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -3020,6 +3020,17 @@ expand_eh_return ()
emit_label (around_label);
}
+/* In the following functions, we represent entries in the action table
+ as 1-based indicies. Special cases are:
+
+ 0: null action record, non-null landing pad; implies cleanups
+ -1: null action record, null landing pad; implies no action
+ -2: no call-site entry; implies must_not_throw
+ -3: we have yet to process outer regions
+
+ Further, no special cases apply to the "next" field of the record.
+ For next, 0 means end of list. */
+
struct action_record
{
int offset;
@@ -3123,8 +3134,16 @@ collect_one_action_chain (ar_hash, region)
if (next == -3)
{
next = collect_one_action_chain (ar_hash, region->outer);
- if (next < 0)
+
+ /* 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);
}
next = add_action_record (ar_hash, c->u.catch.filter, next);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c03e7e3..2424e74 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-08-03 Richard Henderson <rth@redhat.com>
+
+ * g++.dg/eh/filter1.C, g++.dg/eh/filter2.C: New tests.
+
2001-08-02 Neil Booth <neil@daikokuya.demon.co.uk>
* gcc.dg/cpp/19951025-1.c: Update.
diff --git a/gcc/testsuite/g++.dg/eh/filter1.C b/gcc/testsuite/g++.dg/eh/filter1.C
new file mode 100644
index 0000000..6ff0574
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/filter1.C
@@ -0,0 +1,43 @@
+// Test that cleanups get run when a catch filter fails to match.
+// { dg-do run }
+
+extern "C" void exit(int);
+extern "C" void abort();
+
+struct a
+{
+ a();
+ ~a();
+};
+
+struct e1 {};
+struct e2 {};
+
+void
+ex_test ()
+{
+ a aa;
+ try
+ {
+ throw e1 ();
+ }
+ catch (e2 &)
+ {
+ }
+}
+
+int
+main ()
+{
+ try
+ {
+ ex_test ();
+ }
+ catch (...)
+ {
+ }
+ abort ();
+}
+
+a::a() { }
+a::~a() { exit (0); }
diff --git a/gcc/testsuite/g++.dg/eh/filter2.C b/gcc/testsuite/g++.dg/eh/filter2.C
new file mode 100644
index 0000000..fe87cc9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/filter2.C
@@ -0,0 +1,59 @@
+// Test that terminate gets run when a catch filter fails to match while
+// running destructors. Original bug depended on a::~a being inlined.
+// { dg-do run }
+// { dg-options -O }
+
+#include <exception>
+#include <cstdlib>
+
+struct e1 {};
+struct e2 {};
+
+struct a
+{
+ a () { }
+
+ ~a ()
+ {
+ try
+ {
+ throw e1();
+ }
+ catch (e2 &)
+ {
+ }
+ }
+};
+
+void
+ex_test ()
+{
+ a aa;
+ try
+ {
+ throw e1 ();
+ }
+ catch (e2 &)
+ {
+ }
+}
+
+void my_terminate ()
+{
+ std::exit (0);
+}
+
+int
+main ()
+{
+ std::set_terminate (my_terminate);
+
+ try
+ {
+ ex_test ();
+ }
+ catch (...)
+ {
+ }
+ abort ();
+}