re PR c++/12491 (Destructor fails to compile when optimizations (inlining) are enabled)
authorRichard Henderson <rth@redhat.com>
Wed, 14 Jan 2004 21:01:18 +0000 (13:01 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 14 Jan 2004 21:01:18 +0000 (13:01 -0800)
        PR c++/12491
        * except.c (struct eh_region): Add u.fixup.resolved.
        (resolve_one_fixup_region): Split out from ...
        (resolve_fixup_regions): ... here.
* g++.dg/eh/cleanup2.C: New.

From-SVN: r75883

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

index c5c9507..be309dd 100644 (file)
@@ -1,3 +1,10 @@
+2004-01-14  Richard Henderson  <rth@redhat.com>
+
+       PR c++/12491
+       * except.c (struct eh_region): Add u.fixup.resolved.
+       (resolve_one_fixup_region): Split out from ...
+       (resolve_fixup_regions): ... here.
+
 2004-01-14  Kazu Hirata  <kazu@cs.umass.edu>
 
        * config/mn10300/mn10300.h (STRUCT_VALUE): Change to 0.
index 1468d3b..b735cc1 100644 (file)
@@ -189,6 +189,7 @@ struct eh_region GTY(())
     struct eh_region_u_fixup {
       tree cleanup_exp;
       struct eh_region *real_region;
+      bool resolved;
     } GTY ((tag ("ERT_FIXUP"))) fixup;
   } GTY ((desc ("%0.type"))) u;
 
@@ -890,29 +891,49 @@ collect_eh_region_array (void)
 }
 
 static void
+resolve_one_fixup_region (struct eh_region *fixup)
+{
+  struct eh_region *cleanup, *real;
+  int j, n;
+
+  n = cfun->eh->last_region_number;
+  cleanup = 0;
+
+  for (j = 1; j <= n; ++j)
+    {
+      cleanup = cfun->eh->region_array[j];
+      if (cleanup && cleanup->type == ERT_CLEANUP
+         && cleanup->u.cleanup.exp == fixup->u.fixup.cleanup_exp)
+       break;
+    }
+  if (j > n)
+    abort ();
+
+  real = cleanup->outer;
+  if (real && real->type == ERT_FIXUP)
+    {
+      if (!real->u.fixup.resolved)
+       resolve_one_fixup_region (real);
+      real = real->u.fixup.real_region;
+    }
+
+  fixup->u.fixup.real_region = real;
+  fixup->u.fixup.resolved = true;
+}
+
+static void
 resolve_fixup_regions (void)
 {
-  int i, j, n = cfun->eh->last_region_number;
+  int i, n = cfun->eh->last_region_number;
 
   for (i = 1; i <= n; ++i)
     {
       struct eh_region *fixup = cfun->eh->region_array[i];
-      struct eh_region *cleanup = 0;
 
-      if (! fixup || fixup->type != ERT_FIXUP)
+      if (!fixup || fixup->type != ERT_FIXUP || fixup->u.fixup.resolved)
        continue;
 
-      for (j = 1; j <= n; ++j)
-       {
-         cleanup = cfun->eh->region_array[j];
-         if (cleanup && cleanup->type == ERT_CLEANUP
-             && cleanup->u.cleanup.exp == fixup->u.fixup.cleanup_exp)
-           break;
-       }
-      if (j > n)
-       abort ();
-
-      fixup->u.fixup.real_region = cleanup->outer;
+      resolve_one_fixup_region (fixup);
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/eh/cleanup2.C b/gcc/testsuite/g++.dg/eh/cleanup2.C
new file mode 100644 (file)
index 0000000..9c9c5ad
--- /dev/null
@@ -0,0 +1,46 @@
+// PR c++/12491
+// { dg-do compile }
+// { dg-options "-O2" }
+
+// The return statements are necessary to trigger this bug.
+
+class Object
+{
+public:
+  virtual ~Object (void) { return; }
+};
+
+class AutoPtr
+{
+public:
+  ~AutoPtr (void) { delete m_rep; return; }
+private:
+  const Object *m_rep;
+};
+
+class Handle
+{
+public:
+  ~Handle (void) { return; }
+private:
+    AutoPtr m_rep;
+};
+
+class HandleOf:public Handle
+{
+public:
+  ~HandleOf (void) { return; }
+};
+
+class Error
+{
+public:
+  ~Error (void);
+private:
+  HandleOf m_hndl;
+};
+
+Error::~Error (void)
+{
+  return;
+}