This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH to libsupc++/eh_personality.cc for c++/4381
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 18 Mar 2002 00:08:32 +0000
- Subject: C++ PATCH to libsupc++/eh_personality.cc for c++/4381
The RTTI code wants a pointer to the thrown object for checking whether
throw and catch types match, so that it can return the adjusted pointer.
When checking an exception-specifier, we aren't interested in the adjusted
pointer, but we still need to pass in the thrown pointer, because otherwise
the RTTI code will crash if it tries to look up a virtual base through a
garbage vtable pointer. It would be nice to have a separate routine that
just checked for a relationship between two types, but we don't, so we need
to pass in the pointer.
Tested i686-pc-linux-gnu. Applied to trunk and 3.1 branch.
Test in g++.dg/eh/spec3.C.
2002-03-17 Jason Merrill <jason@redhat.com>
PR c++/4381
* libsupc++/eh_personality.cc (get_adjusted_ptr): New static fn.
(check_exception_spec): Call it. Take the thrown pointer.
(__cxa_call_unexpected): Pass it.
(PERSONALITY_FUNCTION): Likewise. Use get_adjusted_ptr.
*** libsupc++/eh_personality.cc.~1~ Sat Nov 17 11:53:03 2001
--- libsupc++/eh_personality.cc Sun Mar 17 23:48:54 2002
*************** get_ttype_entry (lsda_header_info *info,
*** 96,104 ****
return reinterpret_cast<const std::type_info *>(ptr);
}
static bool
check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
! _Unwind_Sword filter_value)
{
const unsigned char *e = info->TType - filter_value - 1;
--- 96,132 ----
return reinterpret_cast<const std::type_info *>(ptr);
}
+ // Given the thrown type THROW_TYPE, pointer to a variable containing a
+ // pointer to the exception object THROWN_PTR_P and a type CATCH_TYPE to
+ // compare against, return whether or not there is a match and if so,
+ // update *THROWN_PTR_P.
+
+ static bool
+ get_adjusted_ptr (const std::type_info *catch_type,
+ const std::type_info *throw_type,
+ void **thrown_ptr_p)
+ {
+ void *thrown_ptr = *thrown_ptr_p;
+
+ // Pointer types need to adjust the actual pointer, not
+ // the pointer to pointer that is the exception object.
+ // This also has the effect of passing pointer types
+ // "by value" through the __cxa_begin_catch return value.
+ if (throw_type->__is_pointer_p ())
+ thrown_ptr = *(void **) thrown_ptr;
+
+ if (catch_type->__do_catch (throw_type, &thrown_ptr, 1))
+ {
+ *thrown_ptr_p = thrown_ptr;
+ return true;
+ }
+
+ return false;
+ }
+
static bool
check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
! void *thrown_ptr, _Unwind_Sword filter_value)
{
const unsigned char *e = info->TType - filter_value - 1;
*************** check_exception_spec (lsda_header_info *
*** 106,112 ****
{
const std::type_info *catch_type;
_Unwind_Word tmp;
- void *dummy;
e = read_uleb128 (e, &tmp);
--- 134,139 ----
*************** check_exception_spec (lsda_header_info *
*** 117,123 ****
// Match a ttype entry.
catch_type = get_ttype_entry (info, tmp);
! if (catch_type->__do_catch (throw_type, &dummy, 1))
return true;
}
}
--- 144,155 ----
// Match a ttype entry.
catch_type = get_ttype_entry (info, tmp);
!
! // ??? There is currently no way to ask the RTTI code about the
! // relationship between two types without reference to a specific
! // object. There should be; then we wouldn't need to mess with
! // thrown_ptr here.
! if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
return true;
}
}
*************** PERSONALITY_FUNCTION (int version,
*** 154,160 ****
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
! void *adjusted_ptr = xh + 1;
// Interface version check.
if (version != 1)
--- 186,192 ----
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
! void *thrown_ptr = xh + 1;
// Interface version check.
if (version != 1)
*************** PERSONALITY_FUNCTION (int version,
*** 294,300 ****
{
// Positive filter values are handlers.
catch_type = get_ttype_entry (&info, ar_filter);
- adjusted_ptr = xh + 1;
// Null catch type is a catch-all handler. We can catch
// foreign exceptions with this.
--- 326,331 ----
*************** PERSONALITY_FUNCTION (int version,
*** 308,321 ****
}
else if (throw_type)
{
! // Pointer types need to adjust the actual pointer, not
! // the pointer to pointer that is the exception object.
! // This also has the effect of passing pointer types
! // "by value" through the __cxa_begin_catch return value.
! if (throw_type->__is_pointer_p ())
! adjusted_ptr = *(void **) adjusted_ptr;
!
! if (catch_type->__do_catch (throw_type, &adjusted_ptr, 1))
{
saw_handler = true;
break;
--- 339,345 ----
}
else if (throw_type)
{
! if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
{
saw_handler = true;
break;
*************** PERSONALITY_FUNCTION (int version,
*** 329,335 ****
// see we can't match because there's no __cxa_exception
// object to stuff bits in for __cxa_call_unexpected to use.
if (throw_type
! && ! check_exception_spec (&info, throw_type, ar_filter))
{
saw_handler = true;
break;
--- 353,360 ----
// see we can't match because there's no __cxa_exception
// object to stuff bits in for __cxa_call_unexpected to use.
if (throw_type
! && ! check_exception_spec (&info, throw_type, thrown_ptr,
! ar_filter))
{
saw_handler = true;
break;
*************** PERSONALITY_FUNCTION (int version,
*** 365,371 ****
xh->handlerSwitchValue = handler_switch_value;
xh->actionRecord = action_record;
xh->languageSpecificData = language_specific_data;
! xh->adjustedPtr = adjusted_ptr;
// ??? Completely unknown what this field is supposed to be for.
// ??? Need to cache TType encoding base for call_unexpected.
--- 390,396 ----
xh->handlerSwitchValue = handler_switch_value;
xh->actionRecord = action_record;
xh->languageSpecificData = language_specific_data;
! xh->adjustedPtr = thrown_ptr;
// ??? Completely unknown what this field is supposed to be for.
// ??? Need to cache TType encoding base for call_unexpected.
*************** __cxa_call_unexpected (void *exc_obj_in)
*** 425,430 ****
--- 450,456 ----
__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.
lsda_header_info info;
*************** __cxa_call_unexpected (void *exc_obj_in)
*** 433,445 ****
// If this new exception meets the exception spec, allow it.
if (check_exception_spec (&info, new_xh->exceptionType,
! xh->handlerSwitchValue))
__throw_exception_again;
// If the exception spec allows std::bad_exception, throw that.
#ifdef __EXCEPTIONS
const std::type_info &bad_exc = typeid (std::bad_exception);
! if (check_exception_spec (&info, &bad_exc, xh->handlerSwitchValue))
throw std::bad_exception();
#endif
// Otherwise, die.
--- 459,473 ----
// If this new exception meets the exception spec, allow it.
if (check_exception_spec (&info, new_xh->exceptionType,
! new_ptr, xh->handlerSwitchValue))
__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.
#ifdef __EXCEPTIONS
const std::type_info &bad_exc = typeid (std::bad_exception);
! if (check_exception_spec (&info, &bad_exc, 0, xh->handlerSwitchValue))
throw std::bad_exception();
#endif
// Otherwise, die.