This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC 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: Recent libstdc++ regression on i686-linux: abi/cxx_runtime_only_linkage.cc


... OK, this is the version which I added back again (hopefully for the last time ;) For consistency with the rest of the library the reference count is an _Atomic_word.

I tested the patch on x86_64-linux, and also by changing the _GLIBCXX_ATOMIC_BUILTINS_4 name everywhere in the new code to something non existing together with similarly changing to non-existing names the __sync_* calls. Committed to mainline.

Paolo.

/////////////////
2008-08-23  Paolo Carlini  <paolo.carlini@oracle.com>

	* testsuite/lib/libstdc++.exp (check_v3_target_atomic_builtins): Add.
	* testsuite/lib/dg-options.exp (dg-require-atomic-builtins): Likewise.
	* testsuite/18_support/exception_ptr/current_exception.cc: Use it.
        * testsuite/18_support/exception_ptr/rethrow_exception.cc: Likewise.
        * testsuite/18_support/exception_ptr/lifespan.cc: Likewise.

2008-08-23  Sebastian Redl <sebastian.redl@getdesigned.at>

	Add (again) exception propagation support as per N2179.  Feature is
	available only when _GLIBCXX_ATOMIC_BUILTINS_4 is defined.
	* libsupc++/exception_ptr.h (exception_ptr, current_exception,
        copy_exception, rethrow_exception): New file, implement exception
	propagation.
        * libsupc++/eh_ptr.cc (exception_ptr, current_exception,
        rethrow_exception, __gxx_dependent_exception_cleanup): Likewise.
        * libsupc++/unwind-cxx.h (__cxa_exception): Add reference count.
	(__cxa_dependent_exception, __cxa_allocate_dependent_exception,
        __cxa_free_dependent_exception, __get_dependent_exception_from_ue,
        __GXX_INIT_DEPENDENT_EXCEPTION_CLASS, __is_dependent_exception,
        __gxx_dependent_exception_class, __get_object_from_ue,
        __get_object_from_ambiguous_exception): Add.
        (__GXX_INIT_EXCEPTION_CLASS, __gxx_exception_class): Rename.
        (__is_gxx_exception_class): Handle dependent exceptions.
        * libsupc++/eh_arm.cc (__cxa_type_match): Likewise.
        * libsupc++/eh_call.cc (__cxa_call_unexpected): Likewise.
        * libsupc++/eh_personality.cc (__gxx_personality_*): Likewise.
        * libsupc++/eh_type.cc (__cxa_current_exception_type): Likewise.
        * libsupc++/eh_alloc.cc (__cxa_allocate_dependent_exception,
        __cxa_free_dependent_exception): Add.
        * libsupc++/eh_throw.cc (__gxx_exception_cleanup): Handle reference
        counting.
        * libsupc++/exception: Conditionally include exception_ptr.h.
        * libsupc++/Makefile.am: Register new files.
        * libsupc++/Makefile.in: Regenerate.
        * config/abi/pre/gnu.ver: Add new symbols.
        * testsuite/18_support/exception_ptr/current_exception.cc: Test the
        core functionality of current_exception().
        * testsuite/18_support/exception_ptr/rethrow_exception.cc: Test the
        core functionality of rethrow_exception().
        * testsuite/18_support/exception_ptr/lifespan.cc: Test the life span of
        exception objects during exception propagation.
Index: libsupc++/eh_arm.cc
===================================================================
*** libsupc++/eh_arm.cc	(revision 139507)
--- libsupc++/eh_arm.cc	(working copy)
***************
*** 1,5 ****
  // -*- C++ -*- ARM specific Exception handling support routines.
! // Copyright (C) 2004, 2005 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
--- 1,5 ----
  // -*- C++ -*- ARM specific Exception handling support routines.
! // Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
*************** __cxa_type_match(_Unwind_Exception* ue_h
*** 48,60 ****
--- 48,66 ----
  {
    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: libsupc++/eh_type.cc
===================================================================
*** libsupc++/eh_type.cc	(revision 139507)
--- libsupc++/eh_type.cc	(working copy)
***************
*** 1,5 ****
  // -*- C++ -*- Exception handling routines for catching.
! // Copyright (C) 2001 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
--- 1,5 ----
  // -*- C++ -*- Exception handling routines for catching.
! // Copyright (C) 2001, 2008 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
*************** std::type_info *__cxa_current_exception_
*** 43,49 ****
    __cxa_eh_globals *globals = __cxa_get_globals ();
    __cxa_exception *header = globals->caughtExceptions;
    if (header)
!     return header->exceptionType;
    else
      return 0;
  }
--- 43,57 ----
    __cxa_eh_globals *globals = __cxa_get_globals ();
    __cxa_exception *header = globals->caughtExceptions;
    if (header)
!     {
!       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: libsupc++/Makefile.in
===================================================================
*** libsupc++/Makefile.in	(revision 139507)
--- libsupc++/Makefile.in	(working copy)
*************** am__libsupc___la_SOURCES_DIST = array_ty
*** 79,85 ****
  	bad_cast.cc bad_typeid.cc class_type_info.cc del_op.cc \
  	del_opnt.cc del_opv.cc del_opvnt.cc dyncast.cc eh_alloc.cc \
  	eh_arm.cc eh_aux_runtime.cc eh_call.cc eh_catch.cc \
! 	eh_exception.cc eh_globals.cc eh_personality.cc \
  	eh_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
  	eh_unex_handler.cc enum_type_info.cc function_type_info.cc \
  	fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
--- 79,85 ----
  	bad_cast.cc bad_typeid.cc class_type_info.cc del_op.cc \
  	del_opnt.cc del_opv.cc del_opvnt.cc dyncast.cc eh_alloc.cc \
  	eh_arm.cc eh_aux_runtime.cc eh_call.cc eh_catch.cc \
! 	eh_exception.cc eh_globals.cc eh_personality.cc eh_ptr.cc \
  	eh_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
  	eh_unex_handler.cc enum_type_info.cc function_type_info.cc \
  	fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
*************** am__objects_1 = array_type_info.lo atexi
*** 91,97 ****
  	bad_typeid.lo class_type_info.lo del_op.lo del_opnt.lo \
  	del_opv.lo del_opvnt.lo dyncast.lo eh_alloc.lo eh_arm.lo \
  	eh_aux_runtime.lo eh_call.lo eh_catch.lo eh_exception.lo \
! 	eh_globals.lo eh_personality.lo eh_term_handler.lo \
  	eh_terminate.lo eh_throw.lo eh_type.lo eh_unex_handler.lo \
  	enum_type_info.lo function_type_info.lo \
  	fundamental_type_info.lo guard.lo new_handler.lo new_op.lo \
--- 91,97 ----
  	bad_typeid.lo class_type_info.lo del_op.lo del_opnt.lo \
  	del_opv.lo del_opvnt.lo dyncast.lo eh_alloc.lo eh_arm.lo \
  	eh_aux_runtime.lo eh_call.lo eh_catch.lo eh_exception.lo \
! 	eh_globals.lo eh_personality.lo eh_ptr.lo eh_term_handler.lo \
  	eh_terminate.lo eh_throw.lo eh_type.lo eh_unex_handler.lo \
  	enum_type_info.lo function_type_info.lo \
  	fundamental_type_info.lo guard.lo new_handler.lo new_op.lo \
*************** am__libsupc__convenience_la_SOURCES_DIST
*** 107,113 ****
  	atexit_arm.cc bad_cast.cc bad_typeid.cc class_type_info.cc \
  	del_op.cc del_opnt.cc del_opv.cc del_opvnt.cc dyncast.cc \
  	eh_alloc.cc eh_arm.cc eh_aux_runtime.cc eh_call.cc eh_catch.cc \
! 	eh_exception.cc eh_globals.cc eh_personality.cc \
  	eh_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
  	eh_unex_handler.cc enum_type_info.cc function_type_info.cc \
  	fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
--- 107,113 ----
  	atexit_arm.cc bad_cast.cc bad_typeid.cc class_type_info.cc \
  	del_op.cc del_opnt.cc del_opv.cc del_opvnt.cc dyncast.cc \
  	eh_alloc.cc eh_arm.cc eh_aux_runtime.cc eh_call.cc eh_catch.cc \
! 	eh_exception.cc eh_globals.cc eh_personality.cc eh_ptr.cc \
  	eh_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
  	eh_unex_handler.cc enum_type_info.cc function_type_info.cc \
  	fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
*************** toolexeclib_LTLIBRARIES = libsupc++.la
*** 356,362 ****
  noinst_LTLIBRARIES = libsupc++convenience.la
  headers = \
  	exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
! 	initializer_list
  
  @GLIBCXX_HOSTED_TRUE@c_sources = \
  @GLIBCXX_HOSTED_TRUE@	cp-demangle.c 
--- 356,362 ----
  noinst_LTLIBRARIES = libsupc++convenience.la
  headers = \
  	exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
! 	initializer_list exception_ptr.h
  
  @GLIBCXX_HOSTED_TRUE@c_sources = \
  @GLIBCXX_HOSTED_TRUE@	cp-demangle.c 
*************** sources = \
*** 380,385 ****
--- 380,386 ----
  	eh_exception.cc \
  	eh_globals.cc \
  	eh_personality.cc \
+ 	eh_ptr.cc \
  	eh_term_handler.cc \
  	eh_terminate.cc \
  	eh_throw.cc \
Index: libsupc++/eh_alloc.cc
===================================================================
*** libsupc++/eh_alloc.cc	(revision 139507)
--- libsupc++/eh_alloc.cc	(working copy)
***************
*** 1,5 ****
  // -*- C++ -*- Allocate exception objects.
! // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
  // Free Software Foundation, Inc.
  //
  // This file is part of GCC.
--- 1,5 ----
  // -*- C++ -*- Allocate exception objects.
! // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008
  // Free Software Foundation, Inc.
  //
  // This file is part of GCC.
*************** typedef char one_buffer[EMERGENCY_OBJ_SI
*** 89,94 ****
--- 89,97 ----
  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.
*************** __cxxabiv1::__cxa_free_exception(void *v
*** 157,159 ****
--- 160,225 ----
    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: libsupc++/unwind-cxx.h
===================================================================
*** libsupc++/unwind-cxx.h	(revision 139507)
--- libsupc++/unwind-cxx.h	(working copy)
***************
*** 1,5 ****
  // -*- C++ -*- Exception handling and frame unwind runtime interface routines.
! // Copyright (C) 2001 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
--- 1,6 ----
  // -*- C++ -*- Exception handling and frame unwind runtime interface routines.
! // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
! // Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
***************
*** 39,56 ****
  #include <exception>
  #include <cstddef>
  #include "unwind.h"
  
  #pragma GCC visibility push(default)
  
  namespace __cxxabiv1
  {
  
! // A 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 the exception object itself.
    std::type_info *exceptionType;
    void (*exceptionDestructor)(void *); 
--- 40,61 ----
  #include <exception>
  #include <cstddef>
  #include "unwind.h"
+ #include <bits/atomic_word.h>
  
  #pragma GCC visibility push(default)
  
  namespace __cxxabiv1
  {
  
! // 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.
!   _Atomic_word referenceCount;
! 
    // Manage the exception object itself.
    std::type_info *exceptionType;
    void (*exceptionDestructor)(void *); 
*************** struct __cxa_exception
*** 87,92 ****
--- 92,138 ----
    _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
  {
*************** struct __cxa_eh_globals
*** 105,116 ****
  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.
  extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw();
  
! // Free the space allocated for the exception.
  extern "C" void __cxa_free_exception(void *thrown_exception) throw();
  
  // Throw the exception.
  extern "C" void __cxa_throw (void *thrown_exception,
  			     std::type_info *tinfo,
--- 151,170 ----
  extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
  extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw();
  
! // 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 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,
*************** __get_exception_header_from_ue (_Unwind_
*** 173,178 ****
--- 227,238 ----
    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)
*************** __is_gxx_exception_class(_Unwind_Excepti
*** 185,195 ****
  	 && c[4] == 'C'
  	 && c[5] == '+'
  	 && c[6] == '+'
! 	 && c[7] == '\0';
  }
  
  static inline void
! __GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
  {
    c[0] = 'G';
    c[1] = 'N';
--- 245,263 ----
  	 && c[4] == 'C'
  	 && c[5] == '+'
  	 && c[6] == '+'
! 	 && (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_PRIMARY_EXCEPTION_CLASS(_Unwind_Exception_Class c)
  {
    c[0] = 'G';
    c[1] = 'N';
*************** __GXX_INIT_EXCEPTION_CLASS(_Unwind_Excep
*** 201,206 ****
--- 269,287 ----
    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)
  {
*************** __gxx_caught_object(_Unwind_Exception* e
*** 233,240 ****
    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
  = ((((((((_Unwind_Exception_Class) 'G' 
  	 << 8 | (_Unwind_Exception_Class) 'N')
  	<< 8 | (_Unwind_Exception_Class) 'U')
--- 314,321 ----
    return (void*)eo->barrier_cache.bitpattern[0];
  }
  #else // !__ARM_EABI_UNWINDER__
! // 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')
*************** const _Unwind_Exception_Class __gxx_exce
*** 244,256 ****
      << 8 | (_Unwind_Exception_Class) '+')
     << 8 | (_Unwind_Exception_Class) '\0');
  
  static inline bool
  __is_gxx_exception_class(_Unwind_Exception_Class c)
  {
!   return c == __gxx_exception_class;
  }
  
! #define __GXX_INIT_EXCEPTION_CLASS(c) c = __gxx_exception_class
  
  // GNU C++ personality routine, Version 0.
  extern "C" _Unwind_Reason_Code __gxx_personality_v0
--- 325,360 ----
      << 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_primary_exception_class
!       || c == __gxx_dependent_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
*************** extern "C" _Unwind_Reason_Code __gxx_per
*** 265,275 ****
--- 369,395 ----
  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: libsupc++/exception
===================================================================
*** libsupc++/exception	(revision 139507)
--- libsupc++/exception	(working copy)
***************
*** 1,7 ****
  // Exception Handling support header for -*- C++ -*-
  
  // Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
! // 2004, 2005, 2006, 2007
  // Free Software Foundation
  //
  // This file is part of GCC.
--- 1,7 ----
  // Exception Handling support header for -*- C++ -*-
  
  // Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
! // 2004, 2005, 2006, 2007, 2008
  // Free Software Foundation
  //
  // This file is part of GCC.
*************** namespace std
*** 110,115 ****
--- 110,116 ----
     *  result in a call of @c terminate() (15.5.1)."
     */
    bool uncaught_exception() throw();
+ 
  } // namespace std
  
  _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
*************** _GLIBCXX_END_NAMESPACE
*** 132,135 ****
--- 133,141 ----
  
  #pragma GCC visibility pop
  
+ #if (defined(__GXX_EXPERIMENTAL_CXX0X__) \
+      && defined(_GLIBCXX_ATOMIC_BUILTINS_4))
+ #include <exception_ptr.h>
+ #endif
+ 
  #endif
Index: libsupc++/eh_throw.cc
===================================================================
*** libsupc++/eh_throw.cc	(revision 139507)
--- libsupc++/eh_throw.cc	(working copy)
***************
*** 1,5 ****
  // -*- C++ -*- Exception handling routines for throwing.
! // Copyright (C) 2001, 2003 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
--- 1,6 ----
  // -*- C++ -*- Exception handling routines for throwing.
! // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
! // Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
*************** using namespace __cxxabiv1;
*** 36,55 ****
  static void
  __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
  {
    __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.
    // _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 (header->exceptionDestructor)
!     header->exceptionDestructor (header + 1);
! 
!   __cxa_free_exception (header + 1);
  }
  
  
--- 37,63 ----
  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);
  
!   // 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);
  
! #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);
! #ifdef _GLIBCXX_ATOMIC_BUILTINS_4
!     }
! #endif
  }
  
  
*************** extern "C" void
*** 57,68 ****
  __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo, 
  			 void (*dest) (void *))
  {
    __cxa_exception *header = __get_exception_header_from_obj (obj);
    header->exceptionType = tinfo;
    header->exceptionDestructor = dest;
    header->unexpectedHandler = __unexpected_handler;
    header->terminateHandler = __terminate_handler;
!   __GXX_INIT_EXCEPTION_CLASS(header->unwindHeader.exception_class);
    header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
  
  #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
--- 65,78 ----
  __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_PRIMARY_EXCEPTION_CLASS(header->unwindHeader.exception_class);
    header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
  
  #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
Index: libsupc++/eh_ptr.cc
===================================================================
*** libsupc++/eh_ptr.cc	(revision 0)
--- libsupc++/eh_ptr.cc	(revision 0)
***************
*** 0 ****
--- 1,242 ----
+ // -*- 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>
+ 
+ #ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+ 
+ #include <exception>
+ #include <exception_ptr.h>
+ #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
+ std::current_exception() throw()
+ {
+   __cxa_eh_globals *globals = __cxa_get_globals ();
+   __cxa_exception *header = globals->caughtExceptions;
+ 
+   if (!header)
+     return std::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();
+ 
+   return std::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);
+ 
+   __cxa_free_dependent_exception (dep);
+ 
+   if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
+     {
+       if (header->exceptionDestructor)
+         header->exceptionDestructor (header + 1);
+ 
+       __cxa_free_exception (header + 1);
+     }
+ }
+ 
+ 
+ void
+ std::rethrow_exception(std::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 ();
+ }
+ 
+ #endif
Index: libsupc++/eh_personality.cc
===================================================================
*** libsupc++/eh_personality.cc	(revision 139507)
--- libsupc++/eh_personality.cc	(working copy)
*************** PERSONALITY_FUNCTION (int version,
*** 377,383 ****
    const unsigned char *p;
    _Unwind_Ptr landing_pad, ip;
    int handler_switch_value;
!   void* thrown_ptr = ue_header + 1;
    bool foreign_exception;
    int ip_before_insn = 0;
  
--- 377,383 ----
    const unsigned char *p;
    _Unwind_Ptr landing_pad, ip;
    int handler_switch_value;
!   void* thrown_ptr = 0;
    bool foreign_exception;
    int ip_before_insn = 0;
  
*************** PERSONALITY_FUNCTION (int version,
*** 543,572 ****
        bool saw_handler = false;
  
  #ifdef __ARM_EABI_UNWINDER__
        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
        // 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;
  #endif
  
        while (1)
--- 543,575 ----
        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);
  	}
!       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);
  	}
        // 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);
  	}
        else
!         {
!           thrown_ptr = __get_object_from_ue (ue_header);
!           throw_type = __get_exception_header_from_obj
!             (thrown_ptr)->exceptionType;
!         }
  #endif
  
        while (1)
*************** __cxa_call_unexpected (void *exc_obj_in)
*** 758,770 ****
  
        __cxa_eh_globals *globals = __cxa_get_globals_fast ();
        __cxa_exception *new_xh = globals->caughtExceptions;
!       void *new_ptr = new_xh + 1;
  
        // 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,
  				new_ptr, xh_switch_value))
  	__throw_exception_again;
  
--- 761,774 ----
  
        __cxa_eh_globals *globals = __cxa_get_globals_fast ();
        __cxa_exception *new_xh = globals->caughtExceptions;
!       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, __get_exception_header_from_obj
!                                   (new_ptr)->exceptionType,
  				new_ptr, xh_switch_value))
  	__throw_exception_again;
  
Index: libsupc++/Makefile.am
===================================================================
*** libsupc++/Makefile.am	(revision 139507)
--- libsupc++/Makefile.am	(working copy)
*************** noinst_LTLIBRARIES = libsupc++convenienc
*** 34,40 ****
  
  headers = \
  	exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
! 	initializer_list
  
  if GLIBCXX_HOSTED
    c_sources = \
--- 34,40 ----
  
  headers = \
  	exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
! 	initializer_list exception_ptr.h
  
  if GLIBCXX_HOSTED
    c_sources = \
*************** sources = \
*** 60,65 ****
--- 60,66 ----
  	eh_exception.cc \
  	eh_globals.cc \
  	eh_personality.cc \
+ 	eh_ptr.cc \
  	eh_term_handler.cc \
  	eh_terminate.cc \
  	eh_throw.cc \
Index: libsupc++/exception_ptr.h
===================================================================
*** libsupc++/exception_ptr.h	(revision 0)
--- libsupc++/exception_ptr.h	(revision 0)
***************
*** 0 ****
--- 1,171 ----
+ // Exception Handling support header (exception_ptr class) for -*- C++ -*-
+ 
+ // Copyright (C) 2008 Free Software Foundation
+ //
+ // 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.
+ 
+ /** @file exception_ptr.h
+  *  This is an internal header file, included by other headers and the
+  *  implementation. You should not attempt to use it directly.
+  */
+ 
+ #ifndef _EXCEPTION_PTR_H
+ #define _EXCEPTION_PTR_H
+ 
+ #pragma GCC visibility push(default)
+ 
+ #include <bits/c++config.h>
+ 
+ #if !defined(_GLIBCXX_ATOMIC_BUILTINS_4)
+ #  error This platform does not support exception propagation.
+ #endif
+ 
+ extern "C++" {
+ 
+ namespace std 
+ {
+   // Hide the free operators from other types
+   namespace __exception_ptr
+   {
+     /**
+      * @brief An opaque pointer to an arbitrary exception.
+      */
+     class exception_ptr;
+   }
+ 
+   using __exception_ptr::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();
+ 
+ 
+   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::current_exception() throw();
+       friend void std::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();
+ 
+ #ifdef __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();
+     };
+ 
+   } // namespace __exception_ptr
+ 
+ 
+   template <class _Ex>
+   exception_ptr copy_exception(_Ex __ex) throw()
+   {
+     try
+       {
+         throw __ex;
+       }
+     catch(...)
+       {
+         return current_exception ();
+       }
+   }
+ 
+ } // namespace std
+ 
+ } // extern "C++"
+ 
+ #pragma GCC visibility pop
+ 
+ #endif
Index: libsupc++/eh_call.cc
===================================================================
*** libsupc++/eh_call.cc	(revision 139507)
--- libsupc++/eh_call.cc	(working copy)
***************
*** 1,5 ****
  // -*- C++ -*- Helpers for calling unextected and terminate
! // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
--- 1,5 ----
  // -*- C++ -*- Helpers for calling unextected and terminate
! // Copyright (C) 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
  //
  // This file is part of GCC.
  //
*************** __cxa_call_unexpected(void* exc_obj_in)
*** 125,131 ****
  
        __cxa_eh_globals* globals = __cxa_get_globals_fast();
        __cxa_exception* new_xh = globals->caughtExceptions;
!       void* new_ptr = new_xh + 1;
        const std::type_info* catch_type;
        int n;
        bool bad_exception_allowed = false;
--- 125,131 ----
  
        __cxa_eh_globals* globals = __cxa_get_globals_fast();
        __cxa_exception* new_xh = globals->caughtExceptions;
!       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: testsuite/18_support/exception_ptr/current_exception.cc
===================================================================
*** testsuite/18_support/exception_ptr/current_exception.cc	(revision 0)
--- testsuite/18_support/exception_ptr/current_exception.cc	(revision 0)
***************
*** 0 ****
--- 1,92 ----
+ // { dg-options "-std=gnu++0x" }
+ // { dg-require-atomic-builtins "" }
+ 
+ // 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: testsuite/18_support/exception_ptr/lifespan.cc
===================================================================
*** testsuite/18_support/exception_ptr/lifespan.cc	(revision 0)
--- testsuite/18_support/exception_ptr/lifespan.cc	(revision 0)
***************
*** 0 ****
--- 1,190 ----
+ // { dg-options "-std=gnu++0x" }
+ // { dg-require-atomic-builtins "" }
+ 
+ // 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: testsuite/18_support/exception_ptr/rethrow_exception.cc
===================================================================
*** testsuite/18_support/exception_ptr/rethrow_exception.cc	(revision 0)
--- testsuite/18_support/exception_ptr/rethrow_exception.cc	(revision 0)
***************
*** 0 ****
--- 1,115 ----
+ // { dg-options "-std=gnu++0x" }
+ // { dg-require-atomic-builtins "" }
+ 
+ // 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: testsuite/lib/libstdc++.exp
===================================================================
*** testsuite/lib/libstdc++.exp	(revision 139507)
--- testsuite/lib/libstdc++.exp	(working copy)
*************** proc check_v3_target_cstdint { } {
*** 1062,1064 ****
--- 1062,1122 ----
      verbose "check_v3_target_cstdint: $et_cstdint" 2
      return $et_cstdint
  }
+ 
+ proc check_v3_target_atomic_builtins { } {
+     global cxxflags
+     global DEFAULT_CXXFLAGS
+     global et_cstdint
+ 
+     global tool	
+ 
+     if { ![info exists et_atomic_builtins_target_name] } {
+ 	set et_atomic_builtins_target_name ""
+     }
+ 
+     # If the target has changed since we set the cached value, clear it.
+     set current_target [current_target_name]
+     if { $current_target != $et_atomic_builtins_target_name } {
+ 	verbose "check_v3_target_atomic_builtins: `$et_atomic_builtins_target_name'" 2
+ 	set et_atomic_builtins_target_name $current_target
+ 	if [info exists et_atomic_builtins] {
+ 	    verbose "check_v3_target_atomic_builtins: removing cached result" 2
+ 	    unset et_atomic_builtins
+ 	}
+     }
+ 
+     if [info exists et_atomic_builtins] {
+ 	verbose "check_v3_target_atomic_builtins: using cached result" 2
+     } else {
+ 	set et_atomic_builtins 0
+ 
+ 	# Set up and compile a C++0x test program that depends
+ 	# on the C99 stdint facilities to be available.
+ 	set src atomic_builtins[pid].cc
+ 	set exe atomic_builtins[pid].exe
+ 
+ 	set f [open $src "w"]
+ 	puts $f "#include <bits/c++config.h>"
+ 	puts $f "int main()"
+ 	puts $f "#ifdef _GLIBCXX_ATOMIC_BUILTINS_4"
+ 	puts $f "{ return 0; }"
+ 	puts $f "#endif"
+ 	close $f
+ 
+ 	set cxxflags_saved $cxxflags
+ 	set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -Werror"
+ 
+ 	set lines [v3_target_compile $src $exe executable ""]
+ 	set cxxflags $cxxflags_saved
+ 	file delete $src
+ 
+ 	if [string match "" $lines] {
+ 	    # No error message, compilation succeeded.
+ 	    set et_atomic_builtins 1
+ 	} else {
+ 	    verbose "check_v3_target_atomic_builtins: compilation failed" 2
+ 	}
+     }
+     verbose "check_v3_target_atomic_builtins: $et_atomic_builtins" 2
+     return $et_atomic_builtins
+ }
Index: testsuite/lib/dg-options.exp
===================================================================
*** testsuite/lib/dg-options.exp	(revision 139507)
--- testsuite/lib/dg-options.exp	(working copy)
*************** proc dg-require-cstdint { args } {
*** 97,99 ****
--- 97,108 ----
      }
      return
  }
+ 
+ proc dg-require-atomic-builtins { args } {
+     if { ![ check_v3_target_atomic_builtins ] } {
+ 	upvar dg-do-what dg-do-what
+ 	set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+ 	return
+     }
+     return
+ }
Index: config/abi/pre/gnu.ver
===================================================================
*** config/abi/pre/gnu.ver	(revision 139507)
--- config/abi/pre/gnu.ver	(working copy)
*************** GLIBCXX_3.4 {
*** 66,72 ****
  #     std::condition_variable;
        std::co[^n]*;
        std::c[p-s]*;
!       std::c[u-z]*;
  #     std::[d-g]*;
        std::d[a-d]*;
        std::d[f-z]*;
--- 66,74 ----
  #     std::condition_variable;
        std::co[^n]*;
        std::c[p-s]*;
!       std::cu[^r]*;
! #     std::current_exception
!       std::c[v-z]*;
  #     std::[d-g]*;
        std::d[a-d]*;
        std::d[f-z]*;
*************** GLIBCXX_3.4 {
*** 112,121 ****
        std::n[^au]*;
        std::nu[^m]*;
        std::num[^e]*;
-       std::[p-r]*;
        std::ostrstream*;
        std::out_of_range*;
        std::overflow_error*;
        std::set_new_handler*;
        std::set_terminate*;
        std::set_unexpected*;
--- 114,126 ----
        std::n[^au]*;
        std::nu[^m]*;
        std::num[^e]*;
        std::ostrstream*;
        std::out_of_range*;
        std::overflow_error*;
+       std::[p-q]*;
+       std::r[^e]*;
+       std::re[^t]*;
+ #     std::rethrow_exception
        std::set_new_handler*;
        std::set_terminate*;
        std::set_unexpected*;
*************** CXXABI_1.3.3 {
*** 1047,1050 ****
--- 1052,1075 ----
      _ZTIPu8char32_t;
      _ZTIPKu8char32_t;
  
+     # exception_ptr
+     _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_;
+ 
+     _ZSt17current_exceptionv;
+     _ZSt17rethrow_exceptionNSt15__exception_ptr13exception_ptrE;
+ 
  } CXXABI_1.3.2;

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