This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [patch-rfc] N2179: Exception Propagation in C++
- From: Sebastian Redl <sebastian dot redl at getdesigned dot at>
- To: Paolo Carlini <paolo dot carlini at oracle dot com>
- Cc: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Date: Wed, 13 Aug 2008 15:42:17 +0200
- Subject: Re: [patch-rfc] N2179: Exception Propagation in C++
- References: <48809CE2.1030500@windmuehlgasse.getdesigned.at> <916852.1216396821012.JavaMail.oracle@acsmt304.oracle.com> <4880D637.3050702@windmuehlgasse.getdesigned.at> <15968502.1216403855404.JavaMail.oracle@acsmt303.oracle.com> <48848C5F.508@windmuehlgasse.getdesigned.at> <3563700.1216648012003.JavaMail.oracle@acsmt304.oracle.com> <488677FA.8000701@windmuehlgasse.getdesigned.at> <28873818.1216775411231.JavaMail.oracle@acsmt301.oracle.com> <48875A5C.6080903@windmuehlgasse.getdesigned.at> <21979991.1216833609323.JavaMail.oracle@acsmt305.oracle.com> <3825956.1217239012707.JavaMail.oracle@acsmt301.oracle.com> <27280529.1217501658903.JavaMail.oracle@acsmt305.oracle.com> <18968936.1218119581291.JavaMail.oracle@acsmt304.oracle.com> <48A1E2B1.1030505@getdesigned.at> <10084862.1218570265098.JavaMail.oracle@acsmt301.oracle.com>
Paolo Carlini wrote:
Hi,
Here's the changlog entry:
I'm sorry, but, if you look at any existing entry, you will notice that each specific affected function must be individually named, just as New, in case of a new function. This is important, for people greping the ChangeLog.
Done, but I've followed existing practice in saying "Add" for new
functions. Also, I've not mentioned individual member functions of
exception_ptr.
Also, while you are re-diffing, please implement also the change to the exports, which must go under CXXABI_1.3.3.
Done.
Finally, remember to keep us (the v3 maintainers) updated about your Copyright Assignment: the FSF clerk told me that the paperworks is going well, this specific contribution can be accepted immediately, if we agree to do that on a technical basis, but didn't tell me that everything is completely Ok and definite.
The assignment was countersigned on July 14th. I received the mail
saying so on August 4th. The assignment should thus be complete.
PS: a minor nit, just to make my life easier, send the CL entry too as attachment, like the patch. Thanks!
Done.
Updated, compiled, tested, rediffed.
Sebastian
Add exception propagation support as per N2179.
* libsupc++/exception_ptr.h (exception_ptr, current_exception,
copy_exception, rethrow_exception): 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: libstdc++-v3/libsupc++/eh_arm.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_arm.cc (revision 139053)
+++ 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 139053)
+++ 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++/Makefile.in
===================================================================
--- libstdc++-v3/libsupc++/Makefile.in (revision 139053)
+++ libstdc++-v3/libsupc++/Makefile.in (working copy)
@@ -79,7 +79,7 @@
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_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 \
@@ -91,7 +91,7 @@
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_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 \
@@ -107,7 +107,7 @@
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_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 \
@@ -356,7 +356,7 @@
noinst_LTLIBRARIES = libsupc++convenience.la
headers = \
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
- initializer_list
+ initializer_list exception_ptr.h
@GLIBCXX_HOSTED_TRUE@c_sources = \
@GLIBCXX_HOSTED_TRUE@ cp-demangle.c
@@ -380,6 +380,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_alloc.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_alloc.cc (revision 139053)
+++ 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 139053)
+++ 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 139053)
+++ 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,7 @@
* result in a call of @c terminate() (15.5.1)."
*/
bool uncaught_exception() throw();
+
} // namespace std
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
@@ -132,4 +133,8 @@
#pragma GCC visibility pop
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <exception_ptr.h>
#endif
+
+#endif
Index: libstdc++-v3/libsupc++/eh_throw.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_throw.cc (revision 139053)
+++ 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,236 @@
+// -*- 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 <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);
+
+ 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 ();
+}
Index: libstdc++-v3/libsupc++/eh_personality.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_personality.cc (revision 139053)
+++ 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 139053)
+++ libstdc++-v3/libsupc++/Makefile.am (working copy)
@@ -34,7 +34,7 @@
headers = \
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
- initializer_list
+ initializer_list exception_ptr.h
if GLIBCXX_HOSTED
c_sources = \
@@ -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++/exception_ptr.h
===================================================================
--- libstdc++-v3/libsupc++/exception_ptr.h (revision 0)
+++ libstdc++-v3/libsupc++/exception_ptr.h (revision 0)
@@ -0,0 +1,169 @@
+// Exception Handling support header (exception_ptr class) 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.
+//
+// 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>
+
+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: libstdc++-v3/libsupc++/eh_call.cc
===================================================================
--- libstdc++-v3/libsupc++/eh_call.cc (revision 139053)
+++ 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 139053)
+++ libstdc++-v3/config/abi/pre/gnu.ver (working copy)
@@ -66,7 +66,9 @@
# std::condition_variable;
std::co[^n]*;
std::c[p-s]*;
- std::c[u-z]*;
+ std::cu[^r]*;
+# std::current_exception
+ std::c[v-z]*;
# std::[d-g]*;
std::d[a-d]*;
std::d[f-z]*;
@@ -112,10 +114,13 @@
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[^e]*;
+ std::re[^t]*;
+# std::rethrow_exception
std::set_new_handler*;
std::set_terminate*;
std::set_unexpected*;
@@ -1047,4 +1052,24 @@
_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;