]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/3719 (Unable to retrow exception in unexpected exception handler.)
authorRichard Henderson <rth@redhat.com>
Sun, 31 Mar 2002 02:56:34 +0000 (18:56 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 31 Mar 2002 02:56:34 +0000 (18:56 -0800)
        PR c++/3719
        * libsupc++/eh_personality.cc (__cxa_call_unexpected): Copy handler
        data out of the exception struct before calling unexpectedHandler.

* g++.dg/eh/unexpected1.C: New.

From-SVN: r51623

gcc/testsuite/g++.dg/eh/unexpected1.C [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/eh_personality.cc

diff --git a/gcc/testsuite/g++.dg/eh/unexpected1.C b/gcc/testsuite/g++.dg/eh/unexpected1.C
new file mode 100644 (file)
index 0000000..26a5848
--- /dev/null
@@ -0,0 +1,46 @@
+// PR 3719
+// Test that an unexpected handler can rethrow to categorize.
+// { dg-do run }
+
+#include <exception>
+
+extern "C" void abort ();
+
+struct One { };
+struct Two { };
+
+static void
+handle_unexpected ()
+{
+  try
+  {
+    throw;
+  }
+  catch (One &)
+  {
+    throw Two ();
+  }
+}
+
+static void
+doit () throw (Two)
+{
+  throw One ();
+}
+
+main ()
+{
+  std::set_unexpected (handle_unexpected);
+
+  try
+  {
+    doit ();
+  }
+  catch (Two &)
+  {
+  }
+  catch (...)
+  {
+    abort ();
+  }
+}
index f280238833fcd57bf8cf874eb2983b8d42d3188f..948d4d5e29984651a0bff34a9f8de037ee0704b7 100644 (file)
@@ -1,3 +1,9 @@
+2002-03-30  Richard Henderson  <rth@redhat.com>
+
+       PR c++/3719
+       * libsupc++/eh_personality.cc (__cxa_call_unexpected): Copy handler
+       data out of the exception struct before calling unexpectedHandler.
+
 2002-03-27  Roger Sayle  <roger@eyesopen.com>
 
        * include/c_std/std_cmath.h:  To prevent problems overloading
index 802b9e2ca3062753c56c191c50ca0b2a18a969e5..35e93a3c473ee163806fac2dc0b0e6076d8c8ad9 100644 (file)
@@ -439,7 +439,18 @@ __cxa_call_unexpected (void *exc_obj_in)
     ~end_catch_protect() { __cxa_end_catch(); }
   } end_catch_protect_obj;
 
+  lsda_header_info info;
   __cxa_exception *xh = __get_exception_header_from_ue (exc_obj);
+  const unsigned char *xh_lsda;
+  _Unwind_Sword xh_switch_value;
+  std::terminate_handler xh_terminate_handler;
+
+  // If the unexpectedHandler rethrows the exception (e.g. to categorize it),
+  // it will clobber data about the current handler.  So copy the data out now.
+  xh_lsda = xh->languageSpecificData;
+  xh_switch_value = xh->handlerSwitchValue;
+  xh_terminate_handler = xh->terminateHandler;
+  info.ttype_base = (_Unwind_Ptr) xh->catchTemp;
 
   try 
     { __unexpected (xh->unexpectedHandler); } 
@@ -453,13 +464,11 @@ __cxa_call_unexpected (void *exc_obj_in)
       void *new_ptr = new_xh + 1;
       
       // We don't quite have enough stuff cached; re-parse the LSDA.
-      lsda_header_info info;
-      parse_lsda_header (0, xh->languageSpecificData, &info);
-      info.ttype_base = (_Unwind_Ptr) xh->catchTemp;
+      parse_lsda_header (0, xh_lsda, &info);
       
       // If this new exception meets the exception spec, allow it.
       if (check_exception_spec (&info, new_xh->exceptionType,
-                               new_ptr, xh->handlerSwitchValue))
+                               new_ptr, xh_switch_value))
        __throw_exception_again;
       
       // If the exception spec allows std::bad_exception, throw that.
@@ -467,10 +476,10 @@ __cxa_call_unexpected (void *exc_obj_in)
       // bad_exception doesn't have virtual bases, that's OK; just pass 0.
 #ifdef __EXCEPTIONS  
       const std::type_info &bad_exc = typeid (std::bad_exception);
-      if (check_exception_spec (&info, &bad_exc, 0, xh->handlerSwitchValue))
+      if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value))
        throw std::bad_exception();
 #endif   
       // Otherwise, die.
-      __terminate(xh->terminateHandler);
+      __terminate (xh_terminate_handler);
     }
 }