Commit 6afcef6b by Jason Merrill Committed by Jason Merrill

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
parent 155038f2
// 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) { }
}
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> Fri Mar 15 09:55:49 2002 Anthony Green <green@redhat.com>
* configure.in: Remove useless is_mingw32. * configure.in: Remove useless is_mingw32.
......
...@@ -96,9 +96,37 @@ get_ttype_entry (lsda_header_info *info, _Unwind_Word i) ...@@ -96,9 +96,37 @@ get_ttype_entry (lsda_header_info *info, _Unwind_Word i)
return reinterpret_cast<const std::type_info *>(ptr); 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 static bool
check_exception_spec (lsda_header_info *info, const std::type_info *throw_type, 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; 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, ...@@ -106,7 +134,6 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
{ {
const std::type_info *catch_type; const std::type_info *catch_type;
_Unwind_Word tmp; _Unwind_Word tmp;
void *dummy;
e = read_uleb128 (e, &tmp); e = read_uleb128 (e, &tmp);
...@@ -117,7 +144,12 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type, ...@@ -117,7 +144,12 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
// Match a ttype entry. // Match a ttype entry.
catch_type = get_ttype_entry (info, tmp); 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; return true;
} }
} }
...@@ -154,7 +186,7 @@ PERSONALITY_FUNCTION (int version, ...@@ -154,7 +186,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 *adjusted_ptr = xh + 1; void *thrown_ptr = xh + 1;
// Interface version check. // Interface version check.
if (version != 1) if (version != 1)
...@@ -294,7 +326,6 @@ PERSONALITY_FUNCTION (int version, ...@@ -294,7 +326,6 @@ PERSONALITY_FUNCTION (int version,
{ {
// Positive filter values are handlers. // Positive filter values are handlers.
catch_type = get_ttype_entry (&info, ar_filter); catch_type = get_ttype_entry (&info, ar_filter);
adjusted_ptr = xh + 1;
// Null catch type is a catch-all handler. We can catch // Null catch type is a catch-all handler. We can catch
// foreign exceptions with this. // foreign exceptions with this.
...@@ -308,14 +339,7 @@ PERSONALITY_FUNCTION (int version, ...@@ -308,14 +339,7 @@ PERSONALITY_FUNCTION (int version,
} }
else if (throw_type) else if (throw_type)
{ {
// Pointer types need to adjust the actual pointer, not if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
// 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; saw_handler = true;
break; break;
...@@ -329,7 +353,8 @@ PERSONALITY_FUNCTION (int version, ...@@ -329,7 +353,8 @@ PERSONALITY_FUNCTION (int version,
// see we can't match because there's no __cxa_exception // see we can't match because there's no __cxa_exception
// object to stuff bits in for __cxa_call_unexpected to use. // object to stuff bits in for __cxa_call_unexpected to use.
if (throw_type if (throw_type
&& ! check_exception_spec (&info, throw_type, ar_filter)) && ! check_exception_spec (&info, throw_type, thrown_ptr,
ar_filter))
{ {
saw_handler = true; saw_handler = true;
break; break;
...@@ -365,7 +390,7 @@ PERSONALITY_FUNCTION (int version, ...@@ -365,7 +390,7 @@ PERSONALITY_FUNCTION (int version,
xh->handlerSwitchValue = handler_switch_value; xh->handlerSwitchValue = handler_switch_value;
xh->actionRecord = action_record; xh->actionRecord = action_record;
xh->languageSpecificData = language_specific_data; xh->languageSpecificData = language_specific_data;
xh->adjustedPtr = adjusted_ptr; xh->adjustedPtr = thrown_ptr;
// ??? Completely unknown what this field is supposed to be for. // ??? Completely unknown what this field is supposed to be for.
// ??? Need to cache TType encoding base for call_unexpected. // ??? Need to cache TType encoding base for call_unexpected.
...@@ -425,6 +450,7 @@ __cxa_call_unexpected (void *exc_obj_in) ...@@ -425,6 +450,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;
// We don't quite have enough stuff cached; re-parse the LSDA. // We don't quite have enough stuff cached; re-parse the LSDA.
lsda_header_info info; lsda_header_info info;
...@@ -433,13 +459,15 @@ __cxa_call_unexpected (void *exc_obj_in) ...@@ -433,13 +459,15 @@ __cxa_call_unexpected (void *exc_obj_in)
// 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, new_xh->exceptionType,
xh->handlerSwitchValue)) new_ptr, xh->handlerSwitchValue))
__throw_exception_again; __throw_exception_again;
// If the exception spec allows std::bad_exception, throw that. // 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 #ifdef __EXCEPTIONS
const std::type_info &bad_exc = typeid (std::bad_exception); 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(); throw std::bad_exception();
#endif #endif
// Otherwise, die. // Otherwise, die.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment