This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix c++/12491
- From: Richard Henderson <rth at twiddle dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 14 Jan 2004 13:04:10 -0800
- Subject: fix c++/12491
Eric's analysis in the PR is correct, but his patch adjusts only
one user, rather than the producer of this information.
Fixed thus.
r~
PR c++/12491
* except.c (struct eh_region): Add u.fixup.resolved.
(resolve_one_fixup_region): Split out from ...
(resolve_fixup_regions): ... here.
Index: except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.255
diff -u -p -r1.255 except.c
--- except.c 9 Jan 2004 20:03:53 -0000 1.255
+++ except.c 14 Jan 2004 20:58:27 -0000
@@ -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);
}
}
Index: testsuite/g++.dg/eh/cleanup2.C
===================================================================
RCS file: testsuite/g++.dg/eh/cleanup2.C
diff -N testsuite/g++.dg/eh/cleanup2.C
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/g++.dg/eh/cleanup2.C 14 Jan 2004 20:58:37 -0000
@@ -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;
+}