re PR c++/4381 (Exceptions virtually inherited from a class cause segmentation fault at run time)

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.

From-SVN: r50936
This commit is contained in:
Jason Merrill 2002-03-17 19:09:37 -05:00 committed by Jason Merrill
parent 155038f242
commit 6afcef6bd2
3 changed files with 77 additions and 17 deletions

View File

@ -0,0 +1,24 @@
// PR c++/4381
// Test that exception-specs work properly for classes with virtual bases.
// { dg-do run }
class Base {};
struct A : virtual public Base
{
A() {}
};
struct B {};
void func() throw (B,A)
{
throw A();
}
int main(void)
{
try { func(); }
catch (A& a) { }
}

View File

@ -1,3 +1,11 @@
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.
Fri Mar 15 09:55:49 2002 Anthony Green <green@redhat.com>
* configure.in: Remove useless is_mingw32.

View File

@ -96,9 +96,37 @@ get_ttype_entry (lsda_header_info *info, _Unwind_Word i)
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,
_Unwind_Sword filter_value)
void *thrown_ptr, _Unwind_Sword filter_value)
{
const unsigned char *e = info->TType - filter_value - 1;
@ -106,7 +134,6 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
{
const std::type_info *catch_type;
_Unwind_Word tmp;
void *dummy;
e = read_uleb128 (e, &tmp);
@ -117,7 +144,12 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
// Match a ttype entry.
catch_type = get_ttype_entry (info, tmp);
if (catch_type->__do_catch (throw_type, &dummy, 1))
// ??? 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;
}
}
@ -154,7 +186,7 @@ PERSONALITY_FUNCTION (int version,
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
void *adjusted_ptr = xh + 1;
void *thrown_ptr = xh + 1;
// Interface version check.
if (version != 1)
@ -294,7 +326,6 @@ PERSONALITY_FUNCTION (int version,
{
// 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.
@ -308,14 +339,7 @@ PERSONALITY_FUNCTION (int version,
}
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))
if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
{
saw_handler = true;
break;
@ -329,7 +353,8 @@ PERSONALITY_FUNCTION (int version,
// 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))
&& ! check_exception_spec (&info, throw_type, thrown_ptr,
ar_filter))
{
saw_handler = true;
break;
@ -365,7 +390,7 @@ PERSONALITY_FUNCTION (int version,
xh->handlerSwitchValue = handler_switch_value;
xh->actionRecord = action_record;
xh->languageSpecificData = language_specific_data;
xh->adjustedPtr = adjusted_ptr;
xh->adjustedPtr = thrown_ptr;
// ??? Completely unknown what this field is supposed to be for.
// ??? Need to cache TType encoding base for call_unexpected.
@ -425,6 +450,7 @@ __cxa_call_unexpected (void *exc_obj_in)
__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;
@ -433,13 +459,15 @@ __cxa_call_unexpected (void *exc_obj_in)
// If this new exception meets the exception spec, allow it.
if (check_exception_spec (&info, new_xh->exceptionType,
xh->handlerSwitchValue))
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, xh->handlerSwitchValue))
if (check_exception_spec (&info, &bad_exc, 0, xh->handlerSwitchValue))
throw std::bad_exception();
#endif
// Otherwise, die.