--- /dev/null
+diff -urN gcc-3.3.4.orig/gcc/except.c gcc-3.3.4/gcc/except.c
+--- gcc-3.3.4.orig/gcc/except.c 2004-03-17 18:07:30.000000000 +0000
++++ gcc-3.3.4/gcc/except.c 2004-08-31 14:01:32.000000000 +0000
+@@ -186,6 +186,7 @@
+ 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;
+
+@@ -912,29 +913,48 @@
+ }
+
+ 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 ()
+ {
+- 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->type == ERT_CLEANUP
+- && cleanup->u.cleanup.exp == fixup->u.fixup.cleanup_exp)
+- break;
+- }
+- if (j > n)
+- abort ();
+-
+- fixup->u.fixup.real_region = cleanup->outer;
++
+ }
+ }
+
+diff -urN gcc-3.3.4.orig/gcc/testsuite/g++.dg/eh/cleanup2.C gcc-3.3.4/gcc/testsuite/g++.dg/eh/cleanup2.C
+--- gcc-3.3.4.orig/gcc/testsuite/g++.dg/eh/cleanup2.C 1970-01-01 00:00:00.000000000 +0000
++++ gcc-3.3.4/gcc/testsuite/g++.dg/eh/cleanup2.C 2004-08-31 14:03:41.000000000 +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;
++}