diff options
author | Jan Hubicka <jh@suse.cz> | 2009-05-09 12:52:24 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2009-05-09 10:52:24 +0000 |
commit | 0afd721984444224c371c811504d7db8eccf9fce (patch) | |
tree | a32d4999485d8f15ac31567a5b4910e7ca7f29f7 /gcc | |
parent | 7925c06c0b5cfd69e7b07581468006b1b3aa50a1 (diff) | |
download | gcc-0afd721984444224c371c811504d7db8eccf9fce.zip gcc-0afd721984444224c371c811504d7db8eccf9fce.tar.gz gcc-0afd721984444224c371c811504d7db8eccf9fce.tar.bz2 |
re PR middle-end/40043 (ICE with nested try/catch)
* g++.dg/eh/nested-try.C: New test.
PR middle-end/40043
* except.c (copy_eh_region): Always set prev_try.
(redirect_eh_edge_to_label): Find outer try.
(foreach_reachable_handler): When looking for prev try
handle case where previous try is not going to be taken.
From-SVN: r147317
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/except.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/nested-try.C | 25 |
4 files changed, 56 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dccd02f..2c5b52e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-05-09 Jan Hubicka <jh@suse.cz> + + PR middle-end/40043 + * except.c (copy_eh_region): Always set prev_try. + (redirect_eh_edge_to_label): Find outer try. + (foreach_reachable_handler): When looking for prev try + handle case where previous try is not going to be taken. + 2009-05-07 Michael Meissner <meissner@linux.vnet.ibm.com> PR tree-optimization/40049 diff --git a/gcc/except.c b/gcc/except.c index 3ba3b67..df28a98 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1410,9 +1410,9 @@ copy_eh_region (struct eh_region *old, struct eh_region *new_outer, { gcc_assert (old->type != ERT_TRY); r = copy_eh_region_1 (old, new_outer); - if (r->type == ERT_CLEANUP && prev_try_map) + if (r->type == ERT_CLEANUP) { - gcc_assert (r->u.cleanup.prev_try); + gcc_assert (r->u.cleanup.prev_try || !prev_try_map); r->u.cleanup.prev_try = prev_try_map; } return r; @@ -1477,7 +1477,7 @@ struct eh_region * redirect_eh_edge_to_label (edge e, tree new_dest_label, bool is_resx, bool inlinable_call, int region_number) { - struct eh_region *outer, *prev_try_map = NULL; + struct eh_region *outer, *prev_try_map; struct eh_region *region; VEC (eh_region, heap) * trace = NULL; int i; @@ -1539,6 +1539,7 @@ redirect_eh_edge_to_label (edge e, tree new_dest_label, bool is_resx, } outer = VEC_index (eh_region, trace, start_here)->outer; gcc_assert (start_here >= 0); + prev_try_map = find_prev_try (outer); /* And now do the dirty job! */ for (i = start_here; i >= 0; i--) @@ -3120,8 +3121,20 @@ foreach_reachable_handler (int region_number, bool is_resx, bool inlinable_call, to the next outer cleanup region, so the flow graph will be accurate. */ if (region->type == ERT_CLEANUP) - region = region->u.cleanup.prev_try; - else + { + enum reachable_code code = RNL_NOT_CAUGHT; + region = region->u.cleanup.prev_try; + /* Continue looking for outer TRY region until we find one + that might cath something. */ + while (region + && (code = reachable_next_level (region, type_thrown, &info, + inlinable_call || is_resx)) + == RNL_NOT_CAUGHT) + region = find_prev_try (region->outer); + if (code >= RNL_CAUGHT) + break; + } + if (region) region = region->outer; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3099e1b..c2fb1d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-05-09 Jan Hubicka <jh@suse.cz> + + PR middle-end/40043 + * g++.dg/eh/nested-try.C: New test. + 2009-05-08 Michael Meissner <meissner@linux.vnet.ibm.com> PR tree-optimization/40049 diff --git a/gcc/testsuite/g++.dg/eh/nested-try.C b/gcc/testsuite/g++.dg/eh/nested-try.C new file mode 100644 index 0000000..5796f9a --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/nested-try.C @@ -0,0 +1,25 @@ +// { dg-do compile } +// Nested try statements shadowing each other was crashing in EH edge redirection. +// PR middle-end/40043 +struct A +{ + ~A(); + void foo(); +}; + +void bar() +{ + A a; + + try + { + A b; + + try + { + b.foo(); + } + catch (int) {} + } + catch (int) {} +} |