[multiple changes]
[gcc.git] / libstdc++-v3 / libsupc++ / eh_throw.cc
index b405f8f7c64188c167227bb85d8d7a7d1fc866a4..24b357772b4d45431ccc51109ca5bbc3c64542ff 100644 (file)
@@ -1,5 +1,6 @@
 // -*- C++ -*- Exception handling routines for throwing.
-// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+// Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -36,20 +37,27 @@ 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);
+#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+  if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
+    {
+#endif
+      if (header->exceptionDestructor)
+        header->exceptionDestructor (header + 1);
 
-  __cxa_free_exception (header + 1);
+      __cxa_free_exception (header + 1);
+#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+    }
+#endif
 }
 
 
@@ -57,12 +65,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 = 1;
   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