This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch-rfc] N2179: Exception Propagation in C++


Peter Dimov wrote:
4)

Define __exception_ptr. Add

#ifdef __GXX_EXPERIMENTAL_CXX0X__
typedef __exception_ptr exception_ptr;
#endif

?

I went with a variant of this. I define everything (including the free functions) in the namespace __exception_ptr and import it into std if 0x mode is enabled.


Modified patch attached.

Sebastian
Index: libstdc++-v3/libsupc++/eh_arm.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_arm.cc	(revision 137946)
+++ libstdc++-v3/libsupc++/eh_arm.cc	(working copy)
@@ -1,5 +1,5 @@
 // -*- C++ -*- ARM specific Exception handling support routines.
-// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -48,13 +48,19 @@
 {
   bool forced_unwind = __is_gxx_forced_unwind_class(ue_header->exception_class);
   bool foreign_exception = !forced_unwind && !__is_gxx_exception_class(ue_header->exception_class);
+  bool dependent_exception =
+    __is_dependent_exception(ue_header->exception_class);
   __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
+  __cxa_dependent_exception *dx = __get_dependent_exception_from_ue(ue_header);
   const std::type_info* throw_type;
 
   if (forced_unwind)
     throw_type = &typeid(abi::__forced_unwind);
   else if (foreign_exception)
     throw_type = &typeid(abi::__foreign_exception);
+  else if (dependent_exception)
+    throw_type = __get_exception_header_from_obj
+      (dx->primaryException)->exceptionType;
   else
     throw_type = xh->exceptionType;
 
Index: libstdc++-v3/libsupc++/eh_type.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_type.cc	(revision 137946)
+++ libstdc++-v3/libsupc++/eh_type.cc	(working copy)
@@ -1,5 +1,5 @@
 // -*- C++ -*- Exception handling routines for catching.
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2008 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -43,7 +43,15 @@
   __cxa_eh_globals *globals = __cxa_get_globals ();
   __cxa_exception *header = globals->caughtExceptions;
   if (header)
-    return header->exceptionType;
+    {
+      if (__is_dependent_exception (header->unwindHeader.exception_class))
+        {
+          __cxa_dependent_exception *de =
+            __get_dependent_exception_from_ue (&header->unwindHeader);
+          header = __get_exception_header_from_obj (de->primaryException);
+        }
+      return header->exceptionType;
+    }
   else
     return 0;
 }
Index: libstdc++-v3/libsupc++/eh_alloc.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_alloc.cc	(revision 137946)
+++ libstdc++-v3/libsupc++/eh_alloc.cc	(working copy)
@@ -1,5 +1,5 @@
 // -*- C++ -*- Allocate exception objects.
-// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008
 // Free Software Foundation, Inc.
 //
 // This file is part of GCC.
@@ -89,6 +89,9 @@
 static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
 static bitmask_type emergency_used;
 
+static __cxa_dependent_exception dependents_buffer[EMERGENCY_OBJ_COUNT];
+static bitmask_type dependents_used;
+
 namespace
 {
   // A single mutex controlling emergency allocations.
@@ -157,3 +160,66 @@
   else
     free (ptr - sizeof (__cxa_exception));
 }
+
+
+extern "C" __cxa_dependent_exception*
+__cxxabiv1::__cxa_allocate_dependent_exception() throw()
+{
+  __cxa_dependent_exception *ret;
+
+  ret = static_cast<__cxa_dependent_exception*>
+    (malloc (sizeof (__cxa_dependent_exception)));
+
+  if (!ret)
+    {
+      __gnu_cxx::__scoped_lock sentry(emergency_mutex);
+
+      bitmask_type used = dependents_used;
+      unsigned int which = 0;
+
+      while (used & 1)
+	{
+	  used >>= 1;
+	  if (++which >= EMERGENCY_OBJ_COUNT)
+	    goto failed;
+	}
+
+      dependents_used |= (bitmask_type)1 << which;
+      ret = &dependents_buffer[which];
+
+    failed:;
+
+      if (!ret)
+	std::terminate ();
+    }
+
+  // We have an uncaught exception as soon as we allocate memory.  This
+  // yields uncaught_exception() true during the copy-constructor that
+  // initializes the exception object.  See Issue 475.
+  __cxa_eh_globals *globals = __cxa_get_globals ();
+  globals->uncaughtExceptions += 1;
+
+  memset (ret, 0, sizeof (__cxa_dependent_exception));
+
+  return ret;
+}
+
+
+extern "C" void
+__cxxabiv1::__cxa_free_dependent_exception
+  (__cxa_dependent_exception *vptr) throw()
+{
+  char *base = (char *) dependents_buffer;
+  char *ptr = (char *) vptr;
+  if (ptr >= base
+      && ptr < base + sizeof (dependents_buffer))
+    {
+      const unsigned int which
+	= (unsigned) (ptr - base) / sizeof (__cxa_dependent_exception);
+
+      __gnu_cxx::__scoped_lock sentry(emergency_mutex);
+      dependents_used &= ~((bitmask_type)1 << which);
+    }
+  else
+    free (vptr);
+}
Index: libstdc++-v3/libsupc++/unwind-cxx.h
===================================================================
--- libstdc++-v3/libsupc++/unwind-cxx.h	(revision 137946)
+++ libstdc++-v3/libsupc++/unwind-cxx.h	(working copy)
@@ -1,5 +1,5 @@
 // -*- C++ -*- Exception handling and frame unwind runtime interface routines.
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2008 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -45,12 +45,15 @@
 namespace __cxxabiv1
 {
 
-// A C++ exception object consists of a header, which is a wrapper around
-// an unwind object header with additional C++ specific information,
+// A primary C++ exception object consists of a header, which is a wrapper
+// around an unwind object header with additional C++ specific information,
 // followed by the exception object itself.
 
 struct __cxa_exception
-{ 
+{
+  // Manage this header.
+  std::size_t referenceCount;
+
   // Manage the exception object itself.
   std::type_info *exceptionType;
   void (*exceptionDestructor)(void *); 
@@ -87,6 +90,47 @@
   _Unwind_Exception unwindHeader;
 };
 
+// A dependent C++ exception object consists of a wrapper around an unwind
+// object header with additional C++ specific information, containing a pointer
+// to a primary exception object.
+
+struct __cxa_dependent_exception
+{
+  // The primary exception this thing depends on.
+  void *primaryException;
+
+  // The C++ standard has entertaining rules wrt calling set_terminate
+  // and set_unexpected in the middle of the exception cleanup process.
+  std::unexpected_handler unexpectedHandler;
+  std::terminate_handler terminateHandler;
+
+  // The caught exception stack threads through here.
+  __cxa_exception *nextException;
+
+  // How many nested handlers have caught this exception.  A negated
+  // value is a signal that this object has been rethrown.
+  int handlerCount;
+
+#ifdef __ARM_EABI_UNWINDER__
+  // Stack of exceptions in cleanups.
+  __cxa_exception* nextPropagatingException;
+
+  // The nuber of active cleanup handlers for this exception.
+  int propagationCount;
+#else
+  // Cache parsed handler data from the personality routine Phase 1
+  // for Phase 2 and __cxa_call_unexpected.
+  int handlerSwitchValue;
+  const unsigned char *actionRecord;
+  const unsigned char *languageSpecificData;
+  _Unwind_Ptr catchTemp;
+  void *adjustedPtr;
+#endif
+
+  // The generic exception header.  Must be last.
+  _Unwind_Exception unwindHeader;
+};
+
 // Each thread in a C++ program has access to a __cxa_eh_globals object.
 struct __cxa_eh_globals
 {
@@ -105,12 +149,20 @@
 extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
 extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw();
 
-// Allocate memory for the exception plus the thown object.
+// Allocate memory for the primary exception plus the thrown object.
 extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw();
 
-// Free the space allocated for the exception.
+// Free the space allocated for the primary exception.
 extern "C" void __cxa_free_exception(void *thrown_exception) throw();
 
+// Allocate memory for a dependent exception.
+extern "C" __cxa_dependent_exception*
+__cxa_allocate_dependent_exception() throw();
+
+// Free the space allocated for the dependent exception.
+extern "C" void
+__cxa_free_dependent_exception(__cxa_dependent_exception *ex) throw();
+
 // Throw the exception.
 extern "C" void __cxa_throw (void *thrown_exception,
 			     std::type_info *tinfo,
@@ -173,6 +225,12 @@
   return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
 }
 
+static inline __cxa_dependent_exception *
+__get_dependent_exception_from_ue (_Unwind_Exception *exc)
+{
+  return reinterpret_cast<__cxa_dependent_exception *>(exc + 1) - 1;
+}
+
 #ifdef __ARM_EABI_UNWINDER__
 static inline bool
 __is_gxx_exception_class(_Unwind_Exception_Class c)
@@ -185,11 +243,19 @@
 	 && c[4] == 'C'
 	 && c[5] == '+'
 	 && c[6] == '+'
-	 && c[7] == '\0';
+	 && (c[7] == '\0' || c[7] == '\x01');
 }
 
+// Only checks for primary or dependent, but not that it is a C++ exception at
+// all.
+static inline bool
+__is_dependent_exception(_Unwind_Exception_Class c)
+{
+  return c[7] == '\x01';
+}
+
 static inline void
-__GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
+__GXX_INIT_PRIMARY_EXCEPTION_CLASS(_Unwind_Exception_Class c)
 {
   c[0] = 'G';
   c[1] = 'N';
@@ -201,6 +267,19 @@
   c[7] = '\0';
 }
 
+static inline void
+__GXX_INIT_DEPENDENT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
+{
+  c[0] = 'G';
+  c[1] = 'N';
+  c[2] = 'U';
+  c[3] = 'C';
+  c[4] = 'C';
+  c[5] = '+';
+  c[6] = '+';
+  c[7] = '\x01';
+}
+
 static inline bool
 __is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
 {
@@ -233,8 +312,8 @@
   return (void*)eo->barrier_cache.bitpattern[0];
 }
 #else // !__ARM_EABI_UNWINDER__
-// This is the exception class we report -- "GNUCC++\0".
-const _Unwind_Exception_Class __gxx_exception_class
+// This is the primary exception class we report -- "GNUCC++\0".
+const _Unwind_Exception_Class __gxx_primary_exception_class
 = ((((((((_Unwind_Exception_Class) 'G' 
 	 << 8 | (_Unwind_Exception_Class) 'N')
 	<< 8 | (_Unwind_Exception_Class) 'U')
@@ -244,14 +323,37 @@
     << 8 | (_Unwind_Exception_Class) '+')
    << 8 | (_Unwind_Exception_Class) '\0');
 
+// This is the dependent (from std::rethrow_exception) exception class we report
+// "GNUCC++\x01"
+const _Unwind_Exception_Class __gxx_dependent_exception_class
+= ((((((((_Unwind_Exception_Class) 'G' 
+	 << 8 | (_Unwind_Exception_Class) 'N')
+	<< 8 | (_Unwind_Exception_Class) 'U')
+       << 8 | (_Unwind_Exception_Class) 'C')
+      << 8 | (_Unwind_Exception_Class) 'C')
+     << 8 | (_Unwind_Exception_Class) '+')
+    << 8 | (_Unwind_Exception_Class) '+')
+   << 8 | (_Unwind_Exception_Class) '\x01');
+
 static inline bool
 __is_gxx_exception_class(_Unwind_Exception_Class c)
 {
-  return c == __gxx_exception_class;
+  return c == __gxx_primary_exception_class
+      || c == __gxx_dependent_exception_class;
 }
 
-#define __GXX_INIT_EXCEPTION_CLASS(c) c = __gxx_exception_class
+// Only checks for primary or dependent, but not that it is a C++ exception at
+// all.
+static inline bool
+__is_dependent_exception(_Unwind_Exception_Class c)
+{
+  return (c & 1);
+}
 
+#define __GXX_INIT_PRIMARY_EXCEPTION_CLASS(c) c = __gxx_primary_exception_class
+#define __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(c) \
+  c = __gxx_dependent_exception_class
+
 // GNU C++ personality routine, Version 0.
 extern "C" _Unwind_Reason_Code __gxx_personality_v0
      (int, _Unwind_Action, _Unwind_Exception_Class,
@@ -265,11 +367,27 @@
 static inline void*
 __gxx_caught_object(_Unwind_Exception* eo)
 {
+  // Bad as it looks, this actually works for dependent exceptions too.
   __cxa_exception* header = __get_exception_header_from_ue (eo);
   return header->adjustedPtr;
 }
 #endif // !__ARM_EABI_UNWINDER__
 
+static inline void*
+__get_object_from_ue(_Unwind_Exception* eo) throw()
+{
+  return __is_dependent_exception (eo->exception_class) ?
+    __get_dependent_exception_from_ue (eo)->primaryException :
+    eo + 1;
+}
+
+static inline void *
+__get_object_from_ambiguous_exception(__cxa_exception *p_or_d) throw()
+{
+	return __get_object_from_ue (&p_or_d->unwindHeader);
+}
+
+
 } /* namespace __cxxabiv1 */
 
 #pragma GCC visibility pop
Index: libstdc++-v3/libsupc++/exception
===================================================================
--- libstdc++-v3/libsupc++/exception	(revision 137946)
+++ libstdc++-v3/libsupc++/exception	(working copy)
@@ -1,7 +1,7 @@
 // Exception Handling support header for -*- C++ -*-
 
 // Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-// 2004, 2005, 2006, 2007
+// 2004, 2005, 2006, 2007, 2008
 // Free Software Foundation
 //
 // This file is part of GCC.
@@ -110,6 +110,128 @@
    *  result in a call of @c terminate() (15.5.1)."
    */
   bool uncaught_exception() throw();
+
+  // Hide the free operators from other types, and the whole class from C++98
+  namespace __exception_ptr
+  {
+    /**
+     * @brief An opaque pointer to an arbitrary exception.
+     */
+    class exception_ptr;
+
+    /** Obtain an %exception_ptr to the currently handled exception. If there
+     *  is none, or the currently handled exception is foreign, return the null
+     *  value.
+     */
+    exception_ptr current_exception() throw();
+
+    /// Throw the object pointed to by the %exception_ptr.
+    void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
+
+    /// Obtain an %exception_ptr pointing to a copy of the supplied object.
+    template <class _Ex>
+    exception_ptr copy_exception(_Ex __ex) throw();
+  }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+  using __exception_ptr::exception_ptr;
+
+  using __exception_ptr::current_exception;
+  using __exception_ptr::rethrow_exception;
+  using __exception_ptr::copy_exception;
+#endif
+
+  namespace __exception_ptr
+  {
+    bool operator==(const exception_ptr&,
+                    const exception_ptr&) throw();
+    bool operator!=(const exception_ptr&,
+                    const exception_ptr&) throw();
+
+    class exception_ptr
+    {
+      void* _M_exception_object;
+
+      explicit exception_ptr(void* __e) throw();
+
+      void _M_addref() throw();
+      void _M_release() throw();
+
+      void *_M_get() const throw();
+
+      void _M_safe_bool_dummy();
+
+      friend exception_ptr std::__exception_ptr::current_exception() throw();
+      friend void std::__exception_ptr::rethrow_exception(exception_ptr);
+
+    public:
+      exception_ptr() throw();
+
+      typedef void (exception_ptr::*__safe_bool)();
+
+      // For construction from nullptr or 0.
+      exception_ptr(__safe_bool) throw();
+
+      exception_ptr(const exception_ptr&) throw();
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      exception_ptr(exception_ptr&& __o) throw()
+        : _M_exception_object(__o._M_exception_object)
+      {
+        __o._M_exception_object = 0;
+      }
+#endif
+
+      exception_ptr& operator=(const exception_ptr&) throw();
+
+#if __GXX_EXPERIMENTAL_CXX0X__
+      exception_ptr& operator=(exception_ptr&& __o) throw()
+      {
+        exception_ptr(__o).swap(*this);
+        return *this;
+      }
+#endif
+
+      ~exception_ptr() throw();
+
+      void swap(exception_ptr&) throw();
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      void swap(exception_ptr &&__o) throw()
+      {
+        void *__tmp = _M_exception_object;
+        _M_exception_object = __o._M_exception_object;
+        __o._M_exception_object = __tmp;
+      }
+#endif
+
+      bool operator!() const throw();
+      operator __safe_bool() const throw();
+
+      friend bool operator==(const exception_ptr&,
+                             const exception_ptr&) throw();
+
+      const type_info *__cxa_exception_type() const throw();
+    };
+
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+    template <class _Ex>
+    exception_ptr copy_exception(_Ex __ex) throw()
+    {
+      try
+        {
+          throw __ex;
+        }
+      catch(...)
+        {
+          return current_exception ();
+        }
+    }
+#endif
+
+  } // namespace __exception_ptr
+
 } // namespace std
 
 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
Index: libstdc++-v3/libsupc++/eh_throw.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_throw.cc	(revision 137946)
+++ libstdc++-v3/libsupc++/eh_throw.cc	(working copy)
@@ -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 @@
 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 (__sync_sub_and_fetch (&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 @@
 __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
Index: libstdc++-v3/libsupc++/eh_ptr.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_ptr.cc	(revision 0)
+++ libstdc++-v3/libsupc++/eh_ptr.cc	(revision 0)
@@ -0,0 +1,235 @@
+// -*- C++ -*- Implement the members of exception_ptr.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// GCC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING.  If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <bits/c++config.h>
+#include <exception>
+#include "unwind-cxx.h"
+
+using namespace __cxxabiv1;
+
+
+std::__exception_ptr::exception_ptr::exception_ptr() throw()
+  : _M_exception_object(0)
+{
+}
+
+
+std::__exception_ptr::exception_ptr::exception_ptr(void* obj) throw()
+  : _M_exception_object(obj)
+{
+  _M_addref();
+}
+
+
+std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool) throw()
+  : _M_exception_object(0)
+{
+}
+
+
+std::__exception_ptr::exception_ptr::exception_ptr(
+                        const exception_ptr& other) throw()
+  : _M_exception_object(other._M_exception_object)
+{
+  _M_addref();
+}
+
+
+std::__exception_ptr::exception_ptr::~exception_ptr() throw()
+{
+  _M_release();
+}
+
+
+std::__exception_ptr::exception_ptr&
+std::__exception_ptr::exception_ptr::operator=(
+                    const exception_ptr& other) throw()
+{
+  exception_ptr(other).swap(*this);
+  return *this;
+}
+
+
+void
+std::__exception_ptr::exception_ptr::_M_addref() throw()
+{
+  if (_M_exception_object)
+    {
+      __cxa_exception *eh =
+        __get_exception_header_from_obj (_M_exception_object);
+      __sync_add_and_fetch (&eh->referenceCount, 1);
+    }
+}
+
+
+void
+std::__exception_ptr::exception_ptr::_M_release() throw()
+{
+  if (_M_exception_object)
+    {
+      __cxa_exception *eh =
+        __get_exception_header_from_obj (_M_exception_object);
+      if (__sync_sub_and_fetch (&eh->referenceCount, 1) == 0)
+        {
+          if (eh->exceptionDestructor)
+            eh->exceptionDestructor (_M_exception_object);
+
+          __cxa_free_exception (_M_exception_object);
+          _M_exception_object = 0;
+        }
+    }
+}
+
+
+void*
+std::__exception_ptr::exception_ptr::_M_get() const throw()
+{
+  return _M_exception_object;
+}
+
+
+void
+std::__exception_ptr::exception_ptr::_M_safe_bool_dummy()
+{
+}
+
+
+void
+std::__exception_ptr::exception_ptr::swap(exception_ptr &other) throw()
+{
+  void *tmp = _M_exception_object;
+  _M_exception_object = other._M_exception_object;
+  other._M_exception_object = tmp;
+}
+
+
+bool
+std::__exception_ptr::exception_ptr::operator!() const throw()
+{
+  return _M_exception_object == 0;
+}
+
+
+std::__exception_ptr::exception_ptr::operator __safe_bool() const throw()
+{
+  return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0;
+}
+
+
+const std::type_info*
+std::__exception_ptr::exception_ptr::__cxa_exception_type() const throw()
+{
+  __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object);
+  return eh->exceptionType;
+}
+
+
+bool std::__exception_ptr::operator==(const exception_ptr& lhs,
+                                      const exception_ptr& rhs) throw()
+{
+  return lhs._M_exception_object == rhs._M_exception_object;
+}
+
+
+bool std::__exception_ptr::operator!=(const exception_ptr& lhs,
+                                      const exception_ptr& rhs) throw()
+{
+  return !(lhs == rhs);
+}
+
+
+std::__exception_ptr::exception_ptr
+std::__exception_ptr::current_exception() throw()
+{
+  __cxa_eh_globals *globals = __cxa_get_globals ();
+  __cxa_exception *header = globals->caughtExceptions;
+
+  if (!header)
+    return std::__exception_ptr::exception_ptr();
+
+  // Since foreign exceptions can't be counted, we can't return them.
+  if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
+    return std::__exception_ptr::exception_ptr();
+
+  return std::__exception_ptr::exception_ptr(
+    __get_object_from_ambiguous_exception (header));
+}
+
+
+static void
+__gxx_dependent_exception_cleanup (_Unwind_Reason_Code code,
+                                   _Unwind_Exception *exc)
+{
+  // This cleanup is set only for dependents.
+  __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc);
+  __cxa_exception *header =
+    __get_exception_header_from_obj (dep->primaryException);
+
+  // 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
+  // like the GCC _Unwind_DeleteException function does.
+  if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
+    __terminate (header->terminateHandler);
+
+  if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
+    {
+      if (header->exceptionDestructor)
+        header->exceptionDestructor (header + 1);
+
+      __cxa_free_exception (header + 1);
+    }
+}
+
+
+void
+std::__exception_ptr::rethrow_exception(std::__exception_ptr::exception_ptr ep)
+{
+  void *obj = ep._M_get();
+  __cxa_exception *eh = __get_exception_header_from_obj (obj);
+
+  __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
+  dep->primaryException = obj;
+  __sync_add_and_fetch (&eh->referenceCount, 1);
+
+  dep->unexpectedHandler = __unexpected_handler;
+  dep->terminateHandler = __terminate_handler;
+  __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class);
+  dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup;
+
+#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
+  _Unwind_SjLj_RaiseException (&dep->unwindHeader);
+#else
+  _Unwind_RaiseException (&dep->unwindHeader);
+#endif
+
+  // Some sort of unwinding error.  Note that terminate is a handler.
+  __cxa_begin_catch (&dep->unwindHeader);
+  std::terminate ();
+}
Index: libstdc++-v3/libsupc++/eh_personality.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_personality.cc	(revision 137946)
+++ libstdc++-v3/libsupc++/eh_personality.cc	(working copy)
@@ -377,7 +377,7 @@
   const unsigned char *p;
   _Unwind_Ptr landing_pad, ip;
   int handler_switch_value;
-  void* thrown_ptr = ue_header + 1;
+  void* thrown_ptr = 0;
   bool foreign_exception;
   int ip_before_insn = 0;
 
@@ -543,30 +543,33 @@
       bool saw_handler = false;
 
 #ifdef __ARM_EABI_UNWINDER__
+      // ??? How does this work - more importantly, how does it interact with
+      // dependent exceptions?
       throw_type = ue_header;
       if (actions & _UA_FORCE_UNWIND)
 	{
 	  __GXX_INIT_FORCED_UNWIND_CLASS(ue_header->exception_class);
-	  thrown_ptr = 0;
 	}
-      else if (foreign_exception)
-	thrown_ptr = 0;
+      else if (!foreign_exception)
+	thrown_ptr = __get_object_from_ue (ue_header);
 #else
       // During forced unwinding, match a magic exception type.
       if (actions & _UA_FORCE_UNWIND)
 	{
 	  throw_type = &typeid(abi::__forced_unwind);
-	  thrown_ptr = 0;
 	}
       // With a foreign exception class, there's no exception type.
       // ??? What to do about GNU Java and GNU Ada exceptions?
       else if (foreign_exception)
 	{
 	  throw_type = &typeid(abi::__foreign_exception);
-	  thrown_ptr = 0;
 	}
       else
-	throw_type = xh->exceptionType;
+        {
+          thrown_ptr = __get_object_from_ue (ue_header);
+          throw_type = __get_exception_header_from_obj
+            (thrown_ptr)->exceptionType;
+        }
 #endif
 
       while (1)
@@ -758,13 +761,14 @@
 
       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
       __cxa_exception *new_xh = globals->caughtExceptions;
-      void *new_ptr = new_xh + 1;
+      void *new_ptr = __get_object_from_ambiguous_exception (new_xh);
 
       // We don't quite have enough stuff cached; re-parse the LSDA.
       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,
+      if (check_exception_spec (&info, __get_exception_header_from_obj
+                                  (new_ptr)->exceptionType,
 				new_ptr, xh_switch_value))
 	__throw_exception_again;
 
Index: libstdc++-v3/libsupc++/Makefile.am
===================================================================
--- libstdc++-v3/libsupc++/Makefile.am	(revision 137946)
+++ libstdc++-v3/libsupc++/Makefile.am	(working copy)
@@ -60,6 +60,7 @@
 	eh_exception.cc \
 	eh_globals.cc \
 	eh_personality.cc \
+	eh_ptr.cc \
 	eh_term_handler.cc \
 	eh_terminate.cc \
 	eh_throw.cc \
Index: libstdc++-v3/libsupc++/eh_call.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_call.cc	(revision 137946)
+++ libstdc++-v3/libsupc++/eh_call.cc	(working copy)
@@ -1,5 +1,5 @@
 // -*- C++ -*- Helpers for calling unextected and terminate
-// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -125,7 +125,7 @@
 
       __cxa_eh_globals* globals = __cxa_get_globals_fast();
       __cxa_exception* new_xh = globals->caughtExceptions;
-      void* new_ptr = new_xh + 1;
+      void* new_ptr = __gxx_get_object_from_ambiguous_exception (new_xh);
       const std::type_info* catch_type;
       int n;
       bool bad_exception_allowed = false;
Index: libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
===================================================================
--- libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc	(revision 0)
+++ libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc	(revision 0)
@@ -0,0 +1,90 @@
+// { dg-options "-std=gnu++0x" }
+// 2008-05-25  Sebastian Redl  <sebastian.redl@getdesigned.at>
+
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// current_exception() under various conditions.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  exception_ptr ep = current_exception();
+  VERIFY( !ep );
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  try {
+    throw 0;
+  } catch(...) {
+    exception_ptr ep = current_exception();
+    VERIFY( ep );
+  }
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  try {
+    throw exception();
+  } catch(std::exception&) {
+    exception_ptr ep = current_exception();
+    VERIFY( ep );
+  }
+}
+
+void test04()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  try {
+    throw 0;
+  } catch(...) {
+    exception_ptr ep1 = current_exception();
+    try {
+      throw 0;
+    } catch(...) {
+      exception_ptr ep2 = current_exception();
+      VERIFY( ep1 != ep2 );
+    }
+    exception_ptr ep3 = current_exception();
+    // Not guaranteed by standard, but by this implementation.
+    VERIFY( ep1 == ep3 );
+  }
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  return 0;
+}
Index: libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
===================================================================
--- libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc	(revision 0)
+++ libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc	(revision 0)
@@ -0,0 +1,188 @@
+// { dg-options "-std=gnu++0x" }
+// 2008-05-25  Sebastian Redl  <sebastian.redl@getdesigned.at>
+
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// Tests the life span of the exception object.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+bool may_destruct = false;
+
+class destructing
+{
+  mutable bool copied;
+
+public:
+  destructing() : copied(false) { }
+  destructing(const destructing &o) : copied(false) { o.copied = true; }
+  ~destructing() { VERIFY( copied || may_destruct ); }
+};
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  may_destruct = false;
+
+  // Test the destructing class.
+  {
+    destructing *d = new destructing;
+    destructing d2(*d);
+    delete d;
+    may_destruct = true;
+  }
+  may_destruct = false;
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  may_destruct = false;
+
+  try {
+    throw destructing();
+  } catch(...) {
+    may_destruct = true;
+  }
+  may_destruct = false;
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  may_destruct = false;
+
+  try {
+    throw destructing();
+  } catch(...) {
+    {
+      exception_ptr ep = current_exception();
+    }
+    may_destruct = true;
+  }
+  may_destruct = false;
+}
+
+void test04()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  may_destruct = false;
+
+  {
+    exception_ptr ep;
+    try {
+      throw destructing();
+    } catch(...) {
+      ep = current_exception();
+    }
+    may_destruct = true;
+  }
+  may_destruct = false;
+}
+
+void test05_helper()
+{
+  using namespace std;
+  try {
+    throw destructing();
+  } catch(...) {
+    exception_ptr ep = current_exception();
+    rethrow_exception(ep);
+  }
+}
+
+void test05()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  may_destruct = false;
+
+  try {
+    test05_helper();
+  } catch(...) {
+    may_destruct = true;
+  }
+  may_destruct = false;
+}
+
+void test06_helper()
+{
+  using namespace std;
+  try {
+    throw destructing();
+  } catch(...) {
+    exception_ptr ep = current_exception();
+    throw;
+  }
+}
+
+void test06()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  may_destruct = false;
+
+  try {
+    test06_helper();
+  } catch(...) {
+    may_destruct = true;
+  }
+  may_destruct = false;
+}
+
+std::exception_ptr gep;
+
+void test99()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  may_destruct = false;
+
+  try {
+    throw destructing();
+  } catch(...) {
+    gep = current_exception();
+  }
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  test06();
+
+  test99();
+  may_destruct = true;
+  return 0;
+}
Index: libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc
===================================================================
--- libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc	(revision 0)
+++ libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc	(revision 0)
@@ -0,0 +1,113 @@
+// { dg-options "-std=gnu++0x" }
+// 2008-05-25  Sebastian Redl  <sebastian.redl@getdesigned.at>
+
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// rethrow_exception() and preservation of data
+
+#include <exception>
+#include <typeinfo>
+#include <cstring>
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  try {
+    rethrow_exception(copy_exception(0));
+  } catch(...) {
+  }
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  try {
+    rethrow_exception(copy_exception(runtime_error("test")));
+  } catch(exception &e) {
+    VERIFY( typeid(e) == typeid(runtime_error) );
+    VERIFY( strcmp(e.what(), "test") == 0 );
+  }
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  exception_ptr ep;
+  try {
+    throw 0;
+  } catch(...) {
+    ep = current_exception();
+  }
+  try {
+    rethrow_exception(ep);
+  } catch(...) {
+  }
+}
+
+void test04()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std;
+
+  // Weave the exceptions in an attempt to confuse the machinery.
+  try {
+    throw 0;
+  } catch(...) {
+    exception_ptr ep1 = current_exception();
+    try {
+      throw 1;
+    } catch(...) {
+      exception_ptr ep2 = current_exception();
+      try {
+        rethrow_exception(ep1);
+      } catch(...) {
+        try {
+          rethrow_exception(ep2);
+        } catch(...) {
+          try {
+            rethrow_exception(ep1);
+          } catch(...) {
+          }
+          try {
+            rethrow_exception(ep2);
+          } catch(...) {
+          }
+        }
+      }
+    }
+  }
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+
+  return 0;
+}
Index: libstdc++-v3/config/abi/pre/gnu.ver
===================================================================
--- libstdc++-v3/config/abi/pre/gnu.ver	(revision 137946)
+++ libstdc++-v3/config/abi/pre/gnu.ver	(working copy)
@@ -112,10 +112,11 @@
       std::n[^au]*;
       std::nu[^m]*;
       std::num[^e]*;
-      std::[p-r]*;
       std::ostrstream*;
       std::out_of_range*;
       std::overflow_error*;
+      std::[p-q]*;
+      std::r*;
       std::set_new_handler*;
       std::set_terminate*;
       std::set_unexpected*;
@@ -885,6 +886,26 @@
     # char16_t and char32_t
     _ZNSt14numeric_limitsIu8char*;
 
+    # exception_ptr (or should they go into the libsupc++ area?)
+    _ZNSt15__exception_ptr13exception_ptrC1Ev;
+    _ZNSt15__exception_ptr13exception_ptrC2Ev;
+    _ZNSt15__exception_ptr13exception_ptrC1ERKS0_;
+    _ZNSt15__exception_ptr13exception_ptrC2ERKS0_;
+    _ZNSt15__exception_ptr13exception_ptrC1EMS0_FvvE;
+    _ZNSt15__exception_ptr13exception_ptrC2EMS0_FvvE;
+    _ZNSt15__exception_ptr13exception_ptrD1Ev;
+    _ZNSt15__exception_ptr13exception_ptrD2Ev;
+    _ZNSt15__exception_ptr13exception_ptraSERKS0_;
+    _ZNKSt15__exception_ptr13exception_ptrcvMS0_FvvEEv;
+    _ZNKSt15__exception_ptr13exception_ptrntEv;
+    _ZNKSt15__exception_ptr13exception_ptr20__cxa_exception_typeEv;
+    _ZNSt15__exception_ptr13exception_ptr4swapERS0_;
+    _ZNSt15__exception_ptreqERKNS_13exception_ptrES2_;
+    _ZNSt15__exception_ptrneERKNS_13exception_ptrES2_;
+
+    _ZNSt15__exception_ptr17current_exceptionEv;
+    _ZNSt15__exception_ptr17rethrow_exceptionENS_13exception_ptrE;
+
     # chrono
     _ZNSt6chrono12system_clock12is_monotonicE;
     _ZNSt6chrono12system_clock3nowEv;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]