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; +}