without g++ FE inlining, ct.C (attached in the following)correctly called
my_terminate when an exception was thrown in a destructor called in a clean-up
exception handler. However, after FE inlining, this exception was propagate out
of the clean-up exception handler and reached the catch(...) block in the outer
caller function.
This bug seems to exist in g++ versions 3.4.3 up to 4.2.

-bash-3.00$ /import/dr3/s10/gcc-4.2/bin/g++ ct.C
-bash-3.00$ ./a.out
throw 1
throw 2
ABC::~ABC()
PASS: my_terminate
-bash-3.00$ /import/dr3/s10/gcc-4.2/bin/g++ ct.C  -O
-bash-3.00$ ./a.out
throw 1
throw 2
ABC::~ABC()
ERROR: should not catch ...
-bash-3.00$ /import/dr3/s10/gcc-4.2/bin/g++ ct.C  -O -DNO_FE_INLINE
-bash-3.00$ ./a.out
throw 1
throw 2
ABC::~ABC()
PASS: my_terminate
-bash-3.00$ /import/dr3/s10/gcc-4.2/bin/g++ -v
Using built-in specs.
Target: sparc-sun-solaris2.10
Configured with: /import/dr2/starlex/1/gcc-4.2-20070228/configure
--prefix=/import/dr3/s10/gcc-4.2 --enable-languages=c,c++,fortran
--enable-rpath --with-mpfr=/import/dr3/s10/gcc-4.2
--with-gmp=/import/dr3/s10/gcc-4.2
Thread model: posix
gcc version 4.2.0 20070228 (prerelease)
-bash-3.00$ cat ct.C
// mimic ctype.C
// a constructor calls other functions
// its base class constructor can throw exception
// handler of that case should be allowed to unwind_resume?

#include <stdlib.h>
#include <stdio.h>
#include <exception>

struct ABC
{
   // ABC();
   ~ABC();
};
extern "C" void f2();
struct BASE
{
   ABC tmp;
   // BASE();
#if !defined(NO_FE_INLINE)
   inline ~BASE() { f2(); }
#else
   ~BASE();
#endif
};

#if defined(NO_FE_INLINE)
BASE::~BASE() { f2(); }
#endif

struct CHILD: public BASE
{
#if defined(__GNUC__) && !defined(NO_FE_INLINE)
   CHILD() __attribute__((noinline));
#else
   CHILD();
#endif
   // ~CHILD();
};

extern "C" void f1();
CHILD::CHILD()
{
   f1();
}

extern "C" void f1()
{
    printf("throw 1\n"); fflush(stdout);
    throw 1;
}
extern "C" void f2()
{
    printf("throw 2\n"); fflush(stdout);
    throw 2;
}
void my_terminate()
{
    printf("PASS: my_terminate\n");
    exit(0);
}
int main()
{
  std::set_terminate(my_terminate);
  try {
    CHILD tmp;
    printf("ERROR: should not be here ...\n");
    fflush(stdout);
  } catch (...) {
    printf("ERROR: should not catch ...\n");
    fflush(stdout);
  }
  return 0;
}
ABC::~ABC()
{
    printf("ABC::~ABC()\n");
    fflush(stdout);
}


-- 
           Summary: g++ inlined destructors incorrectly throw exception out
                    of clean-up handler
           Product: gcc
           Version: 4.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: hailijuan at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34258

Reply via email to