OSDN Git Service

PR middle-end/43365
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 16 Mar 2010 23:02:35 +0000 (23:02 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 16 Mar 2010 23:02:35 +0000 (23:02 +0000)
        * tree-eh.c (replace_goto_queue): Also replace in the eh_seq.
        (lower_try_finally): Save and restore eh_seq around the expansion
        of the try-finally.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@157499 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/g++.dg/eh/pr43365.C [new file with mode: 0644]
gcc/tree-eh.c

index a160365..6d39e6d 100644 (file)
@@ -1,3 +1,10 @@
+2010-03-16  Richard Henderson  <rth@redhat.com>
+
+       PR middle-end/43365
+       * tree-eh.c (replace_goto_queue): Also replace in the eh_seq.
+       (lower_try_finally): Save and restore eh_seq around the expansion
+       of the try-finally.
+
 2010-03-16  Aldy Hernandez  <aldyh@redhat.com>
 
        * graphite-sese-to-poly.c (split_reduction_stmt): Skip debug
diff --git a/gcc/testsuite/g++.dg/eh/pr43365.C b/gcc/testsuite/g++.dg/eh/pr43365.C
new file mode 100644 (file)
index 0000000..32346d5
--- /dev/null
@@ -0,0 +1,30 @@
+extern "C" void abort();
+
+class Counter
+{
+public:
+  static int count;
+  ~Counter() { count += 1; }
+};
+
+int Counter::count = 0;
+
+void func()
+{
+  Counter c;
+
+  try {
+    throw 1;
+  }
+  catch (const int&) {
+    return;
+  }
+}
+
+int main()
+{
+  func();
+  if (Counter::count != 1)
+    abort();
+  return 0;
+}
index 5ae47f0..a1aca98 100644 (file)
@@ -564,6 +564,7 @@ replace_goto_queue (struct leh_tf_state *tf)
   if (tf->goto_queue_active == 0)
     return;
   replace_goto_queue_stmt_list (tf->top_p_seq, tf);
+  replace_goto_queue_stmt_list (eh_seq, tf);
 }
 
 /* Add a new record to the goto queue contained in TF. NEW_STMT is the
@@ -644,7 +645,6 @@ record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label)
      labels. */
   new_stmt = stmt;
   record_in_goto_queue (tf, new_stmt, index, true);
-
 }
 
 /* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally
@@ -1531,6 +1531,7 @@ lower_try_finally (struct leh_state *state, gimple tp)
   struct leh_tf_state this_tf;
   struct leh_state this_state;
   int ndests;
+  gimple_seq old_eh_seq;
 
   /* Process the try block.  */
 
@@ -1547,6 +1548,9 @@ lower_try_finally (struct leh_state *state, gimple tp)
   this_state.ehp_region = state->ehp_region;
   this_state.tf = &this_tf;
 
+  old_eh_seq = eh_seq;
+  eh_seq = NULL;
+
   lower_eh_constructs_1 (&this_state, gimple_try_eval(tp));
 
   /* Determine if the try block is escaped through the bottom.  */
@@ -1602,6 +1606,20 @@ lower_try_finally (struct leh_state *state, gimple tp)
   if (this_tf.goto_queue_map)
     pointer_map_destroy (this_tf.goto_queue_map);
 
+  /* If there was an old (aka outer) eh_seq, append the current eh_seq.
+     If there was no old eh_seq, then the append is trivially already done.  */
+  if (old_eh_seq)
+    {
+      if (eh_seq == NULL)
+       eh_seq = old_eh_seq;
+      else
+       {
+         gimple_seq new_eh_seq = eh_seq;
+         eh_seq = old_eh_seq;
+         gimple_seq_add_seq(&eh_seq, new_eh_seq);
+       }
+    }
+
   return this_tf.top_p_seq;
 }