From afaaa67d427a9df12d7377546a7a5dafc66ed210 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 19 Jan 2011 00:16:16 +0100 Subject: [PATCH] re PR tree-optimization/47290 (memory exhausted compiling a destructor with an infinite 'for (;;);' loop) PR tree-optimization/47290 * tree-eh.c (infinite_empty_loop_p): New function. (cleanup_empty_eh): Use it. * g++.dg/torture/pr47290.C: New test. From-SVN: r168974 --- gcc/ChangeLog | 6 ++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/torture/pr47290.C | 19 ++++++++++++ gcc/tree-eh.c | 40 ++++++++++++++++++++++++-- 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr47290.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6c72e692bbf..c456fb34f5b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-01-19 Jakub Jelinek + + PR tree-optimization/47290 + * tree-eh.c (infinite_empty_loop_p): New function. + (cleanup_empty_eh): Use it. + 2011-01-18 Steve Ellcey PR target/46997 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9c3e8ba99d0..550aee1cef6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-01-19 Jakub Jelinek + + PR tree-optimization/47290 + * g++.dg/torture/pr47290.C: New test. + 2011-01-18 Janus Weil PR fortran/47240 diff --git a/gcc/testsuite/g++.dg/torture/pr47290.C b/gcc/testsuite/g++.dg/torture/pr47290.C new file mode 100644 index 00000000000..b739de5b749 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr47290.C @@ -0,0 +1,19 @@ +// PR tree-optimization/47290 +// { dg-do compile } + +struct V +{ + V (int = 0); + ~V () + { + for (;;) + ; + } + int size (); +}; + +struct S +{ + V a, b; + S () : b (a.size ()) {} +} s; diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 270d76d9480..65d0ff2f9fd 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -1,5 +1,5 @@ /* Exception handling semantics and decomposition for trees. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -3724,6 +3724,42 @@ cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp) return false; } +/* Return true if edge E_FIRST is part of an empty infinite loop + or leads to such a loop through a series of single successor + empty bbs. */ + +static bool +infinite_empty_loop_p (edge e_first) +{ + bool inf_loop = false; + edge e; + + if (e_first->dest == e_first->src) + return true; + + e_first->src->aux = (void *) 1; + for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest)) + { + gimple_stmt_iterator gsi; + if (e->dest->aux) + { + inf_loop = true; + break; + } + e->dest->aux = (void *) 1; + gsi = gsi_after_labels (e->dest); + if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) + gsi_next_nondebug (&gsi); + if (!gsi_end_p (gsi)) + break; + } + e_first->src->aux = NULL; + for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest)) + e->dest->aux = NULL; + + return inf_loop; +} + /* Examine the block associated with LP to determine if it's an empty handler for its EH region. If so, attempt to redirect EH edges to an outer region. Return true the CFG was updated in any way. This @@ -3763,7 +3799,7 @@ cleanup_empty_eh (eh_landing_pad lp) if (gsi_end_p (gsi)) { /* For the degenerate case of an infinite loop bail out. */ - if (e_out->dest == bb) + if (infinite_empty_loop_p (e_out)) return false; return cleanup_empty_eh_unsplit (bb, e_out, lp);