diff options
author | Richard Henderson <rth@redhat.com> | 2003-05-07 15:11:38 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2003-05-07 15:11:38 -0700 |
commit | a944ceb94a99f5a271e2bd84a5a922858e5f699f (patch) | |
tree | c4966921e4085694a93888d4028afb2a1818fda4 /libstdc++-v3 | |
parent | a21d83cd14f80ebd8b9ab6c4d87c42bf06bfec08 (diff) | |
download | gcc-a944ceb94a99f5a271e2bd84a5a922858e5f699f.zip gcc-a944ceb94a99f5a271e2bd84a5a922858e5f699f.tar.gz gcc-a944ceb94a99f5a271e2bd84a5a922858e5f699f.tar.bz2 |
except.c: Revert 04-01 and 04-02 forced-unwind changes.
gcc/
* except.c: Revert 04-01 and 04-02 forced-unwind changes.
* flags.h, toplev.c, doc/invoke.texi: Likewise.
* unwind-dw2.c (_Unwind_GetCFA): Fix ptr->int conversion warning.
* unwind.inc (_Unwind_DeleteException): Check for null
exception_cleanup.
* unwind-sjlj.c (_Unwind_SjLj_Resume_or_Rethrow): New.
* unwind.inc (_Unwind_Resume_or_Rethrow): New.
* unwind.h: Declare them.
* libgcc-std.ver (GCC_3.3): Export them.
gcc/cp/
* cfns.gperf: Comment out POSIX thread cancellation points,
plus abort and raise.
* cfns.h: Regenerate.
gcc/testsuite/
* g++.dg/eh/forced1.C: Expect catch-all handlers to run.
Verify exception_cleanup not called for rethrows.
* g++.dg/eh/forced2.C: Test that exception_cleanup is called
when exiting catch block without rethrowing.
* g++.dg/eh/forced3.C: New.
* g++.dg/eh/forced4.C: New.
libstdc++-v3/
* libsupc++/eh_catch.cc (__cxa_begin_catch): Handle foreign exceptions.
(__cxa_end_catch): Likewise.
* libsupc++/eh_throw.cc (__cxa_rethrow): Likewise. Use
_Unwind_Resume_or_Rethrow.
* libsupc++/eh_personality.cc (empty_exception_spec): New.
(PERSONALITY_FUNCTION): Don't ignore terminate or catch-all
for _UA_FORCE_UNWIND. Honor empty filter spec for foreign
exceptions. Don't push terminate/unexpected to cxa functions.
(__cxa_call_unexpected): Remove foreign exception fixmes.
From-SVN: r66583
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 13 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_catch.cc | 45 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_personality.cc | 98 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_throw.cc | 11 |
4 files changed, 119 insertions, 48 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b79cdf2..b9c7bcb 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2003-05-07 Richard Henderson <rth@redhat.com> + + PR c++/10570 + * libsupc++/eh_catch.cc (__cxa_begin_catch): Handle foreign exceptions. + (__cxa_end_catch): Likewise. + * libsupc++/eh_throw.cc (__cxa_rethrow): Likewise. Use + _Unwind_Resume_or_Rethrow. + * libsupc++/eh_personality.cc (empty_exception_spec): New. + (PERSONALITY_FUNCTION): Don't ignore terminate or catch-all + for _UA_FORCE_UNWIND. Honor empty filter spec for foreign + exceptions. Don't push terminate/unexpected to cxa functions. + (__cxa_call_unexpected): Remove foreign exception fixmes. + 2003-05-07 Benjamin Kosnik <bkoz@redhat.com> * testsuite/27_io/ios_base/cons: New. diff --git a/libstdc++-v3/libsupc++/eh_catch.cc b/libstdc++-v3/libsupc++/eh_catch.cc index ba49dfe..4a678eb 100644 --- a/libstdc++-v3/libsupc++/eh_catch.cc +++ b/libstdc++-v3/libsupc++/eh_catch.cc @@ -1,5 +1,5 @@ // -*- C++ -*- Exception handling routines for catching. -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2003 Free Software Foundation, Inc. // // This file is part of GNU CC. // @@ -39,15 +39,28 @@ __cxa_begin_catch (void *exc_obj_in) { _Unwind_Exception *exceptionObject = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); - - // ??? Foreign exceptions can't be stacked here, and there doesn't - // appear to be any place to store for __cxa_end_catch to destroy. - - __cxa_exception *header = __get_exception_header_from_ue (exceptionObject); __cxa_eh_globals *globals = __cxa_get_globals (); __cxa_exception *prev = globals->caughtExceptions; - int count = header->handlerCount; + __cxa_exception *header = __get_exception_header_from_ue (exceptionObject); + + // Foreign exceptions can't be stacked here. If the exception stack is + // empty, then fine. Otherwise we really have no choice but to terminate. + // Note that this use of "header" is a lie. It's fine so long as we only + // examine header->unwindHeader though. + if (header->unwindHeader.exception_class != __gxx_exception_class) + { + if (prev != 0) + std::terminate (); + + // Remember for end_catch and rethrow. + globals->caughtExceptions = header; + + // ??? No sensible value to return; we don't know what the + // object is, much less where it is in relation to the header. + return 0; + } + int count = header->handlerCount; if (count < 0) // This exception was rethrown from an immediately enclosing region. count = -count + 1; @@ -71,8 +84,22 @@ __cxa_end_catch () { __cxa_eh_globals *globals = __cxa_get_globals_fast (); __cxa_exception *header = globals->caughtExceptions; - int count = header->handlerCount; + // A rethrow of a foreign exception will be removed from the + // the exception stack immediately by __cxa_rethrow. + if (!header) + return; + + // A foreign exception couldn't have been stacked (see above), + // so by definition processing must be complete. + if (header->unwindHeader.exception_class != __gxx_exception_class) + { + globals->caughtExceptions = 0; + _Unwind_DeleteException (&header->unwindHeader); + return; + } + + int count = header->handlerCount; if (count < 0) { // This exception was rethrown. Decrement the (inverted) catch @@ -92,7 +119,7 @@ __cxa_end_catch () } else if (count < 0) // A bug in the exception handling library or compiler. - std::abort (); + std::terminate (); header->handlerCount = count; } diff --git a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc index acc9c2e..2b315c3 100644 --- a/libstdc++-v3/libsupc++/eh_personality.cc +++ b/libstdc++-v3/libsupc++/eh_personality.cc @@ -1,5 +1,5 @@ // -*- C++ -*- The GNU C++ exception personality routine. -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. // // This file is part of GNU CC. // @@ -124,6 +124,8 @@ get_adjusted_ptr (const std::type_info *catch_type, return false; } +// Return true if THROW_TYPE matches one if the filter types. + static bool check_exception_spec (lsda_header_info *info, const std::type_info *throw_type, void *thrown_ptr, _Unwind_Sword filter_value) @@ -154,6 +156,18 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type, } } +// Return true if the filter spec is empty, ie throw(). + +static bool +empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value) +{ + const unsigned char *e = info->TType - filter_value - 1; + _Unwind_Word tmp; + + e = read_uleb128 (e, &tmp); + return tmp == 0; +} + // Using a different personality function name causes link failures // when trying to mix code using different exception handling models. #ifdef _GLIBCPP_SJLJ_EXCEPTIONS @@ -197,6 +211,7 @@ PERSONALITY_FUNCTION (int version, && exception_class == __gxx_exception_class) { handler_switch_value = xh->handlerSwitchValue; + language_specific_data = xh->languageSpecificData; landing_pad = (_Unwind_Ptr) xh->catchTemp; found_type = (landing_pad == 0 ? found_terminate : found_handler); goto install_context; @@ -275,7 +290,7 @@ PERSONALITY_FUNCTION (int version, // If ip is not present in the table, call terminate. This is for // a destructor inside a cleanup, or a library routine the compiler // was not expecting to throw. - found_type = (actions & _UA_FORCE_UNWIND ? found_nothing : found_terminate); + found_type = found_terminate; goto do_something; found_something: @@ -327,23 +342,15 @@ PERSONALITY_FUNCTION (int version, // Positive filter values are handlers. catch_type = get_ttype_entry (&info, ar_filter); - // Null catch type is a catch-all handler. We can catch - // foreign exceptions with this. - if (! catch_type) - { - if (!(actions & _UA_FORCE_UNWIND)) - { - saw_handler = true; - break; - } - } - else if (throw_type) + // Null catch type is a catch-all handler; we can catch foreign + // exceptions with this. Otherwise we must match types. + if (! catch_type + || (throw_type + && get_adjusted_ptr (catch_type, throw_type, + &thrown_ptr))) { - if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr)) - { - saw_handler = true; - break; - } + saw_handler = true; + break; } } else @@ -352,9 +359,12 @@ PERSONALITY_FUNCTION (int version, // ??? How do foreign exceptions fit in? As far as I can // see we can't match because there's no __cxa_exception // object to stuff bits in for __cxa_call_unexpected to use. + // Allow them iff the exception spec is non-empty. I.e. + // a throw() specification results in __unexpected. if (throw_type - && ! check_exception_spec (&info, throw_type, thrown_ptr, - ar_filter)) + ? ! check_exception_spec (&info, throw_type, thrown_ptr, + ar_filter) + : empty_exception_spec (&info, ar_filter)) { saw_handler = true; break; @@ -400,19 +410,37 @@ PERSONALITY_FUNCTION (int version, } install_context: - if (found_type == found_terminate) + // We can't use any of the cxa routines with foreign exceptions, + // because they all expect ue_header to be a struct __cxa_exception. + // So in that case, call terminate or unexpected directly. + if ((actions & _UA_FORCE_UNWIND) + || exception_class != __gxx_exception_class) { - __cxa_begin_catch (&xh->unwindHeader); - __terminate (xh->terminateHandler); + if (found_type == found_terminate) + std::terminate (); + else if (handler_switch_value < 0) + { + try + { std::unexpected (); } + catch(...) + { std::terminate (); } + } } - - // Cache the TType base value for __cxa_call_unexpected, as we won't - // have an _Unwind_Context then. - if (handler_switch_value < 0) + else { - parse_lsda_header (context, xh->languageSpecificData, &info); - xh->catchTemp = base_of_encoded_value (info.ttype_encoding, - context); + if (found_type == found_terminate) + { + __cxa_begin_catch (&xh->unwindHeader); + __terminate (xh->terminateHandler); + } + + // Cache the TType base value for __cxa_call_unexpected, as we won't + // have an _Unwind_Context then. + if (handler_switch_value < 0) + { + parse_lsda_header (context, language_specific_data, &info); + xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context); + } } _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), @@ -457,20 +485,19 @@ __cxa_call_unexpected (void *exc_obj_in) catch(...) { // Get the exception thrown from unexpected. - // ??? Foreign exceptions can't be stacked this way. - + __cxa_eh_globals *globals = __cxa_get_globals_fast (); __cxa_exception *new_xh = globals->caughtExceptions; void *new_ptr = new_xh + 1; - + // We don't quite have enough stuff cached; re-parse the LSDA. parse_lsda_header (0, xh_lsda, &info); - + // If this new exception meets the exception spec, allow it. if (check_exception_spec (&info, new_xh->exceptionType, new_ptr, xh_switch_value)) __throw_exception_again; - + // If the exception spec allows std::bad_exception, throw that. // We don't have a thrown object to compare against, but since // bad_exception doesn't have virtual bases, that's OK; just pass 0. @@ -479,6 +506,7 @@ __cxa_call_unexpected (void *exc_obj_in) if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value)) throw std::bad_exception(); #endif + // Otherwise, die. __terminate (xh_terminate_handler); } diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc index f20368a1..4fe4cd3 100644 --- a/libstdc++-v3/libsupc++/eh_throw.cc +++ b/libstdc++-v3/libsupc++/eh_throw.cc @@ -1,5 +1,5 @@ // -*- C++ -*- Exception handling routines for throwing. -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2003 Free Software Foundation, Inc. // // This file is part of GNU CC. // @@ -90,12 +90,15 @@ __cxa_rethrow () if (header) { // Tell __cxa_end_catch this is a rethrow. - header->handlerCount = -header->handlerCount; + if (header->unwindHeader.exception_class != __gxx_exception_class) + globals->caughtExceptions = 0; + else + header->handlerCount = -header->handlerCount; #ifdef _GLIBCPP_SJLJ_EXCEPTIONS - _Unwind_SjLj_RaiseException (&header->unwindHeader); + _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader); #else - _Unwind_RaiseException (&header->unwindHeader); + _Unwind_Resume_or_Rethrow (&header->unwindHeader); #endif // Some sort of unwinding error. Note that terminate is a handler. |