except.c (collect_one_action_chain): Add an explicit cleanup action if regions surrou...
authorRichard Henderson <rth@redhat.com>
Fri, 3 Aug 2001 23:15:51 +0000 (16:15 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 3 Aug 2001 23:15:51 +0000 (16:15 -0700)
        * 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

gcc/ChangeLog
gcc/except.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/filter1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/eh/filter2.C [new file with mode: 0644]

index b2eb17f34aaf6db77cd9c10a2c7a616c6551504a..65f73d0e91d35fc2d840d67d2f3d3f73ce240f0e 100644 (file)
@@ -1,3 +1,9 @@
+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;
index e24a901c3c4c0e2ff1e051fd487870ee53463ae3..4397cfc963dc4f1da1b4e7bb68326fe72ec13aed 100644 (file)
@@ -3020,6 +3020,17 @@ expand_eh_return ()
   emit_label (around_label);
 }
 \f
+/* 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);
            }
index c03e7e3948e1942e24aa2406d6a3d796f2a945fc..2424e7451f3499c12b2d6163f289f246ba567122 100644 (file)
@@ -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 (file)
index 0000000..6ff0574
--- /dev/null
@@ -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 (file)
index 0000000..fe87cc9
--- /dev/null
@@ -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 ();
+}