diff options
author | Richard Henderson <rth@redhat.com> | 2001-08-03 16:15:51 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-08-03 16:15:51 -0700 |
commit | 949f197fa6853615f92ded3def63db5e77ed9af2 (patch) | |
tree | 51fcc575dc9325d75e35147a2bf8537fbc68a91c /gcc | |
parent | c99fa40fbe95dc94e7e55b374f778cc154fd4864 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/except.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/filter1.C | 43 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/filter2.C | 59 |
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 (); +} |