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