[multiple changes]
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. From-SVN: r139509
This commit is contained in:
parent
f5d3c7e14e
commit
30a333ceeb
|
@ -1,3 +1,47 @@
|
||||||
|
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.
|
||||||
|
|
||||||
2008-08-22 Paolo Carlini <paolo.carlini@oracle.com>
|
2008-08-22 Paolo Carlini <paolo.carlini@oracle.com>
|
||||||
|
|
||||||
Revert again the N2179 patch.
|
Revert again the N2179 patch.
|
||||||
|
|
|
@ -66,7 +66,9 @@ GLIBCXX_3.4 {
|
||||||
# std::condition_variable;
|
# std::condition_variable;
|
||||||
std::co[^n]*;
|
std::co[^n]*;
|
||||||
std::c[p-s]*;
|
std::c[p-s]*;
|
||||||
std::c[u-z]*;
|
std::cu[^r]*;
|
||||||
|
# std::current_exception
|
||||||
|
std::c[v-z]*;
|
||||||
# std::[d-g]*;
|
# std::[d-g]*;
|
||||||
std::d[a-d]*;
|
std::d[a-d]*;
|
||||||
std::d[f-z]*;
|
std::d[f-z]*;
|
||||||
|
@ -112,10 +114,13 @@ GLIBCXX_3.4 {
|
||||||
std::n[^au]*;
|
std::n[^au]*;
|
||||||
std::nu[^m]*;
|
std::nu[^m]*;
|
||||||
std::num[^e]*;
|
std::num[^e]*;
|
||||||
std::[p-r]*;
|
|
||||||
std::ostrstream*;
|
std::ostrstream*;
|
||||||
std::out_of_range*;
|
std::out_of_range*;
|
||||||
std::overflow_error*;
|
std::overflow_error*;
|
||||||
|
std::[p-q]*;
|
||||||
|
std::r[^e]*;
|
||||||
|
std::re[^t]*;
|
||||||
|
# std::rethrow_exception
|
||||||
std::set_new_handler*;
|
std::set_new_handler*;
|
||||||
std::set_terminate*;
|
std::set_terminate*;
|
||||||
std::set_unexpected*;
|
std::set_unexpected*;
|
||||||
|
@ -1047,4 +1052,24 @@ CXXABI_1.3.3 {
|
||||||
_ZTIPu8char32_t;
|
_ZTIPu8char32_t;
|
||||||
_ZTIPKu8char32_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;
|
} CXXABI_1.3.2;
|
||||||
|
|
|
@ -34,7 +34,7 @@ noinst_LTLIBRARIES = libsupc++convenience.la
|
||||||
|
|
||||||
headers = \
|
headers = \
|
||||||
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
|
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
|
||||||
initializer_list
|
initializer_list exception_ptr.h
|
||||||
|
|
||||||
if GLIBCXX_HOSTED
|
if GLIBCXX_HOSTED
|
||||||
c_sources = \
|
c_sources = \
|
||||||
|
@ -60,6 +60,7 @@ sources = \
|
||||||
eh_exception.cc \
|
eh_exception.cc \
|
||||||
eh_globals.cc \
|
eh_globals.cc \
|
||||||
eh_personality.cc \
|
eh_personality.cc \
|
||||||
|
eh_ptr.cc \
|
||||||
eh_term_handler.cc \
|
eh_term_handler.cc \
|
||||||
eh_terminate.cc \
|
eh_terminate.cc \
|
||||||
eh_throw.cc \
|
eh_throw.cc \
|
||||||
|
|
|
@ -79,7 +79,7 @@ am__libsupc___la_SOURCES_DIST = array_type_info.cc atexit_arm.cc \
|
||||||
bad_cast.cc bad_typeid.cc class_type_info.cc del_op.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 \
|
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_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_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
|
||||||
eh_unex_handler.cc enum_type_info.cc function_type_info.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 \
|
fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
|
||||||
|
@ -91,7 +91,7 @@ am__objects_1 = array_type_info.lo atexit_arm.lo bad_cast.lo \
|
||||||
bad_typeid.lo class_type_info.lo del_op.lo del_opnt.lo \
|
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 \
|
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_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 \
|
eh_terminate.lo eh_throw.lo eh_type.lo eh_unex_handler.lo \
|
||||||
enum_type_info.lo function_type_info.lo \
|
enum_type_info.lo function_type_info.lo \
|
||||||
fundamental_type_info.lo guard.lo new_handler.lo new_op.lo \
|
fundamental_type_info.lo guard.lo new_handler.lo new_op.lo \
|
||||||
|
@ -107,7 +107,7 @@ am__libsupc__convenience_la_SOURCES_DIST = array_type_info.cc \
|
||||||
atexit_arm.cc bad_cast.cc bad_typeid.cc class_type_info.cc \
|
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 \
|
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_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_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
|
||||||
eh_unex_handler.cc enum_type_info.cc function_type_info.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 \
|
fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
|
||||||
|
@ -356,7 +356,7 @@ toolexeclib_LTLIBRARIES = libsupc++.la
|
||||||
noinst_LTLIBRARIES = libsupc++convenience.la
|
noinst_LTLIBRARIES = libsupc++convenience.la
|
||||||
headers = \
|
headers = \
|
||||||
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
|
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@c_sources = \
|
||||||
@GLIBCXX_HOSTED_TRUE@ cp-demangle.c
|
@GLIBCXX_HOSTED_TRUE@ cp-demangle.c
|
||||||
|
@ -380,6 +380,7 @@ sources = \
|
||||||
eh_exception.cc \
|
eh_exception.cc \
|
||||||
eh_globals.cc \
|
eh_globals.cc \
|
||||||
eh_personality.cc \
|
eh_personality.cc \
|
||||||
|
eh_ptr.cc \
|
||||||
eh_term_handler.cc \
|
eh_term_handler.cc \
|
||||||
eh_terminate.cc \
|
eh_terminate.cc \
|
||||||
eh_throw.cc \
|
eh_throw.cc \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- C++ -*- Allocate exception objects.
|
// -*- 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.
|
// Free Software Foundation, Inc.
|
||||||
//
|
//
|
||||||
// This file is part of GCC.
|
// This file is part of GCC.
|
||||||
|
@ -89,6 +89,9 @@ typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
|
||||||
static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
|
static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
|
||||||
static bitmask_type emergency_used;
|
static bitmask_type emergency_used;
|
||||||
|
|
||||||
|
static __cxa_dependent_exception dependents_buffer[EMERGENCY_OBJ_COUNT];
|
||||||
|
static bitmask_type dependents_used;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// A single mutex controlling emergency allocations.
|
// A single mutex controlling emergency allocations.
|
||||||
|
@ -157,3 +160,66 @@ __cxxabiv1::__cxa_free_exception(void *vptr) throw()
|
||||||
else
|
else
|
||||||
free (ptr - sizeof (__cxa_exception));
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- C++ -*- ARM specific Exception handling support routines.
|
// -*- 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.
|
// This file is part of GCC.
|
||||||
//
|
//
|
||||||
|
@ -48,13 +48,19 @@ __cxa_type_match(_Unwind_Exception* ue_header,
|
||||||
{
|
{
|
||||||
bool forced_unwind = __is_gxx_forced_unwind_class(ue_header->exception_class);
|
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 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_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;
|
const std::type_info* throw_type;
|
||||||
|
|
||||||
if (forced_unwind)
|
if (forced_unwind)
|
||||||
throw_type = &typeid(abi::__forced_unwind);
|
throw_type = &typeid(abi::__forced_unwind);
|
||||||
else if (foreign_exception)
|
else if (foreign_exception)
|
||||||
throw_type = &typeid(abi::__foreign_exception);
|
throw_type = &typeid(abi::__foreign_exception);
|
||||||
|
else if (dependent_exception)
|
||||||
|
throw_type = __get_exception_header_from_obj
|
||||||
|
(dx->primaryException)->exceptionType;
|
||||||
else
|
else
|
||||||
throw_type = xh->exceptionType;
|
throw_type = xh->exceptionType;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- C++ -*- Helpers for calling unextected and terminate
|
// -*- 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.
|
// This file is part of GCC.
|
||||||
//
|
//
|
||||||
|
@ -125,7 +125,7 @@ __cxa_call_unexpected(void* exc_obj_in)
|
||||||
|
|
||||||
__cxa_eh_globals* globals = __cxa_get_globals_fast();
|
__cxa_eh_globals* globals = __cxa_get_globals_fast();
|
||||||
__cxa_exception* new_xh = globals->caughtExceptions;
|
__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;
|
const std::type_info* catch_type;
|
||||||
int n;
|
int n;
|
||||||
bool bad_exception_allowed = false;
|
bool bad_exception_allowed = false;
|
||||||
|
|
|
@ -377,7 +377,7 @@ PERSONALITY_FUNCTION (int version,
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
_Unwind_Ptr landing_pad, ip;
|
_Unwind_Ptr landing_pad, ip;
|
||||||
int handler_switch_value;
|
int handler_switch_value;
|
||||||
void* thrown_ptr = ue_header + 1;
|
void* thrown_ptr = 0;
|
||||||
bool foreign_exception;
|
bool foreign_exception;
|
||||||
int ip_before_insn = 0;
|
int ip_before_insn = 0;
|
||||||
|
|
||||||
|
@ -543,30 +543,33 @@ PERSONALITY_FUNCTION (int version,
|
||||||
bool saw_handler = false;
|
bool saw_handler = false;
|
||||||
|
|
||||||
#ifdef __ARM_EABI_UNWINDER__
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
// ??? How does this work - more importantly, how does it interact with
|
||||||
|
// dependent exceptions?
|
||||||
throw_type = ue_header;
|
throw_type = ue_header;
|
||||||
if (actions & _UA_FORCE_UNWIND)
|
if (actions & _UA_FORCE_UNWIND)
|
||||||
{
|
{
|
||||||
__GXX_INIT_FORCED_UNWIND_CLASS(ue_header->exception_class);
|
__GXX_INIT_FORCED_UNWIND_CLASS(ue_header->exception_class);
|
||||||
thrown_ptr = 0;
|
|
||||||
}
|
}
|
||||||
else if (foreign_exception)
|
else if (!foreign_exception)
|
||||||
thrown_ptr = 0;
|
thrown_ptr = __get_object_from_ue (ue_header);
|
||||||
#else
|
#else
|
||||||
// During forced unwinding, match a magic exception type.
|
// During forced unwinding, match a magic exception type.
|
||||||
if (actions & _UA_FORCE_UNWIND)
|
if (actions & _UA_FORCE_UNWIND)
|
||||||
{
|
{
|
||||||
throw_type = &typeid(abi::__forced_unwind);
|
throw_type = &typeid(abi::__forced_unwind);
|
||||||
thrown_ptr = 0;
|
|
||||||
}
|
}
|
||||||
// With a foreign exception class, there's no exception type.
|
// With a foreign exception class, there's no exception type.
|
||||||
// ??? What to do about GNU Java and GNU Ada exceptions?
|
// ??? What to do about GNU Java and GNU Ada exceptions?
|
||||||
else if (foreign_exception)
|
else if (foreign_exception)
|
||||||
{
|
{
|
||||||
throw_type = &typeid(abi::__foreign_exception);
|
throw_type = &typeid(abi::__foreign_exception);
|
||||||
thrown_ptr = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw_type = xh->exceptionType;
|
{
|
||||||
|
thrown_ptr = __get_object_from_ue (ue_header);
|
||||||
|
throw_type = __get_exception_header_from_obj
|
||||||
|
(thrown_ptr)->exceptionType;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -758,13 +761,14 @@ __cxa_call_unexpected (void *exc_obj_in)
|
||||||
|
|
||||||
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
|
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
|
||||||
__cxa_exception *new_xh = globals->caughtExceptions;
|
__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.
|
// We don't quite have enough stuff cached; re-parse the LSDA.
|
||||||
parse_lsda_header (0, xh_lsda, &info);
|
parse_lsda_header (0, xh_lsda, &info);
|
||||||
|
|
||||||
// If this new exception meets the exception spec, allow it.
|
// 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))
|
new_ptr, xh_switch_value))
|
||||||
__throw_exception_again;
|
__throw_exception_again;
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -1,5 +1,6 @@
|
||||||
// -*- C++ -*- Exception handling routines for throwing.
|
// -*- C++ -*- Exception handling routines for throwing.
|
||||||
// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||||
|
// Free Software Foundation, Inc.
|
||||||
//
|
//
|
||||||
// This file is part of GCC.
|
// This file is part of GCC.
|
||||||
//
|
//
|
||||||
|
@ -36,20 +37,27 @@ using namespace __cxxabiv1;
|
||||||
static void
|
static void
|
||||||
__gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
|
__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);
|
__cxa_exception *header = __get_exception_header_from_ue (exc);
|
||||||
|
|
||||||
// If we haven't been caught by a foreign handler, then this is
|
// We only want to be called through _Unwind_DeleteException.
|
||||||
// some sort of unwind error. In that case just die immediately.
|
|
||||||
// _Unwind_DeleteException in the HP-UX IA64 libunwind library
|
// _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.
|
// like the GCC _Unwind_DeleteException function does.
|
||||||
if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
|
if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
|
||||||
__terminate (header->terminateHandler);
|
__terminate (header->terminateHandler);
|
||||||
|
|
||||||
|
#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
|
||||||
|
if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
if (header->exceptionDestructor)
|
if (header->exceptionDestructor)
|
||||||
header->exceptionDestructor (header + 1);
|
header->exceptionDestructor (header + 1);
|
||||||
|
|
||||||
__cxa_free_exception (header + 1);
|
__cxa_free_exception (header + 1);
|
||||||
|
#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,12 +65,14 @@ extern "C" void
|
||||||
__cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
|
__cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
|
||||||
void (*dest) (void *))
|
void (*dest) (void *))
|
||||||
{
|
{
|
||||||
|
// Definitely a primary.
|
||||||
__cxa_exception *header = __get_exception_header_from_obj (obj);
|
__cxa_exception *header = __get_exception_header_from_obj (obj);
|
||||||
|
header->referenceCount = 1;
|
||||||
header->exceptionType = tinfo;
|
header->exceptionType = tinfo;
|
||||||
header->exceptionDestructor = dest;
|
header->exceptionDestructor = dest;
|
||||||
header->unexpectedHandler = __unexpected_handler;
|
header->unexpectedHandler = __unexpected_handler;
|
||||||
header->terminateHandler = __terminate_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;
|
header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
|
||||||
|
|
||||||
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
|
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- C++ -*- Exception handling routines for catching.
|
// -*- 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.
|
// This file is part of GCC.
|
||||||
//
|
//
|
||||||
|
@ -43,7 +43,15 @@ std::type_info *__cxa_current_exception_type ()
|
||||||
__cxa_eh_globals *globals = __cxa_get_globals ();
|
__cxa_eh_globals *globals = __cxa_get_globals ();
|
||||||
__cxa_exception *header = globals->caughtExceptions;
|
__cxa_exception *header = globals->caughtExceptions;
|
||||||
if (header)
|
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;
|
return header->exceptionType;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Exception Handling support header for -*- C++ -*-
|
// Exception Handling support header for -*- C++ -*-
|
||||||
|
|
||||||
// Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
// Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||||
// 2004, 2005, 2006, 2007
|
// 2004, 2005, 2006, 2007, 2008
|
||||||
// Free Software Foundation
|
// Free Software Foundation
|
||||||
//
|
//
|
||||||
// This file is part of GCC.
|
// This file is part of GCC.
|
||||||
|
@ -110,6 +110,7 @@ namespace std
|
||||||
* result in a call of @c terminate() (15.5.1)."
|
* result in a call of @c terminate() (15.5.1)."
|
||||||
*/
|
*/
|
||||||
bool uncaught_exception() throw();
|
bool uncaught_exception() throw();
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
|
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
|
||||||
|
@ -132,4 +133,9 @@ _GLIBCXX_END_NAMESPACE
|
||||||
|
|
||||||
#pragma GCC visibility pop
|
#pragma GCC visibility pop
|
||||||
|
|
||||||
|
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) \
|
||||||
|
&& defined(_GLIBCXX_ATOMIC_BUILTINS_4))
|
||||||
|
#include <exception_ptr.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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
|
|
@ -1,5 +1,6 @@
|
||||||
// -*- C++ -*- Exception handling and frame unwind runtime interface routines.
|
// -*- C++ -*- Exception handling and frame unwind runtime interface routines.
|
||||||
// Copyright (C) 2001 Free Software Foundation, Inc.
|
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||||
|
// Free Software Foundation, Inc.
|
||||||
//
|
//
|
||||||
// This file is part of GCC.
|
// This file is part of GCC.
|
||||||
//
|
//
|
||||||
|
@ -39,18 +40,22 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include "unwind.h"
|
#include "unwind.h"
|
||||||
|
#include <bits/atomic_word.h>
|
||||||
|
|
||||||
#pragma GCC visibility push(default)
|
#pragma GCC visibility push(default)
|
||||||
|
|
||||||
namespace __cxxabiv1
|
namespace __cxxabiv1
|
||||||
{
|
{
|
||||||
|
|
||||||
// A C++ exception object consists of a header, which is a wrapper around
|
// A primary C++ exception object consists of a header, which is a wrapper
|
||||||
// an unwind object header with additional C++ specific information,
|
// around an unwind object header with additional C++ specific information,
|
||||||
// followed by the exception object itself.
|
// followed by the exception object itself.
|
||||||
|
|
||||||
struct __cxa_exception
|
struct __cxa_exception
|
||||||
{
|
{
|
||||||
|
// Manage this header.
|
||||||
|
_Atomic_word referenceCount;
|
||||||
|
|
||||||
// Manage the exception object itself.
|
// Manage the exception object itself.
|
||||||
std::type_info *exceptionType;
|
std::type_info *exceptionType;
|
||||||
void (*exceptionDestructor)(void *);
|
void (*exceptionDestructor)(void *);
|
||||||
|
@ -87,6 +92,47 @@ struct __cxa_exception
|
||||||
_Unwind_Exception unwindHeader;
|
_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.
|
// Each thread in a C++ program has access to a __cxa_eh_globals object.
|
||||||
struct __cxa_eh_globals
|
struct __cxa_eh_globals
|
||||||
{
|
{
|
||||||
|
@ -105,12 +151,20 @@ struct __cxa_eh_globals
|
||||||
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
|
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
|
||||||
extern "C" __cxa_eh_globals *__cxa_get_globals_fast () 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();
|
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();
|
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.
|
// Throw the exception.
|
||||||
extern "C" void __cxa_throw (void *thrown_exception,
|
extern "C" void __cxa_throw (void *thrown_exception,
|
||||||
std::type_info *tinfo,
|
std::type_info *tinfo,
|
||||||
|
@ -173,6 +227,12 @@ __get_exception_header_from_ue (_Unwind_Exception *exc)
|
||||||
return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
|
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__
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
static inline bool
|
static inline bool
|
||||||
__is_gxx_exception_class(_Unwind_Exception_Class c)
|
__is_gxx_exception_class(_Unwind_Exception_Class c)
|
||||||
|
@ -185,11 +245,19 @@ __is_gxx_exception_class(_Unwind_Exception_Class c)
|
||||||
&& c[4] == 'C'
|
&& c[4] == 'C'
|
||||||
&& c[5] == '+'
|
&& c[5] == '+'
|
||||||
&& c[6] == '+'
|
&& 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
|
static inline void
|
||||||
__GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
|
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(_Unwind_Exception_Class c)
|
||||||
{
|
{
|
||||||
c[0] = 'G';
|
c[0] = 'G';
|
||||||
c[1] = 'N';
|
c[1] = 'N';
|
||||||
|
@ -201,6 +269,19 @@ __GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
|
||||||
c[7] = '\0';
|
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
|
static inline bool
|
||||||
__is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
|
__is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
|
||||||
{
|
{
|
||||||
|
@ -233,8 +314,8 @@ __gxx_caught_object(_Unwind_Exception* eo)
|
||||||
return (void*)eo->barrier_cache.bitpattern[0];
|
return (void*)eo->barrier_cache.bitpattern[0];
|
||||||
}
|
}
|
||||||
#else // !__ARM_EABI_UNWINDER__
|
#else // !__ARM_EABI_UNWINDER__
|
||||||
// This is the exception class we report -- "GNUCC++\0".
|
// This is the primary exception class we report -- "GNUCC++\0".
|
||||||
const _Unwind_Exception_Class __gxx_exception_class
|
const _Unwind_Exception_Class __gxx_primary_exception_class
|
||||||
= ((((((((_Unwind_Exception_Class) 'G'
|
= ((((((((_Unwind_Exception_Class) 'G'
|
||||||
<< 8 | (_Unwind_Exception_Class) 'N')
|
<< 8 | (_Unwind_Exception_Class) 'N')
|
||||||
<< 8 | (_Unwind_Exception_Class) 'U')
|
<< 8 | (_Unwind_Exception_Class) 'U')
|
||||||
|
@ -244,13 +325,36 @@ const _Unwind_Exception_Class __gxx_exception_class
|
||||||
<< 8 | (_Unwind_Exception_Class) '+')
|
<< 8 | (_Unwind_Exception_Class) '+')
|
||||||
<< 8 | (_Unwind_Exception_Class) '\0');
|
<< 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
|
static inline bool
|
||||||
__is_gxx_exception_class(_Unwind_Exception_Class c)
|
__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.
|
// GNU C++ personality routine, Version 0.
|
||||||
extern "C" _Unwind_Reason_Code __gxx_personality_v0
|
extern "C" _Unwind_Reason_Code __gxx_personality_v0
|
||||||
|
@ -265,11 +369,27 @@ extern "C" _Unwind_Reason_Code __gxx_personality_sj0
|
||||||
static inline void*
|
static inline void*
|
||||||
__gxx_caught_object(_Unwind_Exception* eo)
|
__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);
|
__cxa_exception* header = __get_exception_header_from_ue (eo);
|
||||||
return header->adjustedPtr;
|
return header->adjustedPtr;
|
||||||
}
|
}
|
||||||
#endif // !__ARM_EABI_UNWINDER__
|
#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 */
|
} /* namespace __cxxabiv1 */
|
||||||
|
|
||||||
#pragma GCC visibility pop
|
#pragma GCC visibility pop
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -97,3 +97,12 @@ proc dg-require-cstdint { args } {
|
||||||
}
|
}
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1062,3 +1062,61 @@ proc check_v3_target_cstdint { } {
|
||||||
verbose "check_v3_target_cstdint: $et_cstdint" 2
|
verbose "check_v3_target_cstdint: $et_cstdint" 2
|
||||||
return $et_cstdint
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue