]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/libsupc++/eh_throw.cc
Re-instate last patch...
[thirdparty/gcc.git] / libstdc++-v3 / libsupc++ / eh_throw.cc
index b405f8f7c64188c167227bb85d8d7a7d1fc866a4..198ff181035bf103628c85f02e798e28b3797e60 100644 (file)
@@ -1,5 +1,5 @@
 // -*- C++ -*- Exception handling routines for throwing.
-// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2003, 2008 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -36,20 +36,23 @@ using namespace __cxxabiv1;
 static void
 __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
 {
+  // This cleanup is set only for primaries.
   __cxa_exception *header = __get_exception_header_from_ue (exc);
 
-  // If we haven't been caught by a foreign handler, then this is
-  // some sort of unwind error.  In that case just die immediately.
+  // We only want to be called through _Unwind_DeleteException.
   // _Unwind_DeleteException in the HP-UX IA64 libunwind library
-  //  returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
+  // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
   // like the GCC _Unwind_DeleteException function does.
   if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
     __terminate (header->terminateHandler);
 
-  if (header->exceptionDestructor)
-    header->exceptionDestructor (header + 1);
+  if (__gnu_cxx::__exchange_and_add_dispatch (&header->referenceCount, -1) == 0)
+    {
+      if (header->exceptionDestructor)
+        header->exceptionDestructor (header + 1);
 
-  __cxa_free_exception (header + 1);
+      __cxa_free_exception (header + 1);
+    }
 }
 
 
@@ -57,12 +60,14 @@ extern "C" void
 __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo, 
                         void (*dest) (void *))
 {
+  // Definitely a primary.
   __cxa_exception *header = __get_exception_header_from_obj (obj);
+  header->referenceCount = 0;
   header->exceptionType = tinfo;
   header->exceptionDestructor = dest;
   header->unexpectedHandler = __unexpected_handler;
   header->terminateHandler = __terminate_handler;
-  __GXX_INIT_EXCEPTION_CLASS(header->unwindHeader.exception_class);
+  __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->unwindHeader.exception_class);
   header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
 
 #ifdef _GLIBCXX_SJLJ_EXCEPTIONS