This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]