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] Yet more covariant ICEing


Hi
I've installed this patch which fixes more covariant problems. When figuring
a covariant thunk, we might have been overriding something which was already
a thunk. We need to combine the base adjustments into a single one. This
is trickier than one might like, because we've lost the direct information
about the final base to be converted to.

built & tested on i686-pc-linux-gnu.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
         The voices in my head said this was stupid too
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org

2002-12-31  Nathan Sidwell  <nathan@codesourcery.com>

	* class.c (modify_vtable_entry): Remove unused variable.
	(get_vcall_index): Always expect a non-thunk.
	(update_vtable_entry_for_fn): Combine covariant adjustments, when
	overriding a thunk. Pass get_vcall_index a non-thunk.

2002-12-31  Nathan Sidwell  <nathan@codesourcery.com>

	* g++.dg/inherit/covariant8.C: New test.

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.505
diff -c -3 -p -r1.505 class.c
*** cp/class.c	30 Dec 2002 13:39:41 -0000	1.505
--- cp/class.c	31 Dec 2002 19:34:29 -0000
*************** modify_vtable_entry (t, binfo, fndecl, d
*** 716,723 ****
    if (fndecl != BV_FN (v)
        || !tree_int_cst_equal (delta, BV_DELTA (v)))
      {
-       tree base_fndecl;
- 
        /* We need a new vtable for BINFO.  */
        if (make_new_vtable (t, binfo))
  	{
--- 716,721 ----
*************** modify_vtable_entry (t, binfo, fndecl, d
*** 730,736 ****
  	  v = *virtuals;
  	}
  
-       base_fndecl = BV_FN (v);
        BV_DELTA (v) = delta;
        BV_VCALL_INDEX (v) = NULL_TREE;
        BV_FN (v) = fndecl;
--- 728,733 ----
*************** get_vcall_index (tree fn, tree type)
*** 2331,2339 ****
  {
    tree v;
  
-   if (DECL_THUNK_P (fn))
-     fn = THUNK_TARGET (fn);
- 
    for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
      if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
  	|| same_signature_p (fn, TREE_PURPOSE (v)))
--- 2328,2333 ----
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2361,2378 ****
    tree delta;
    tree virtual_base;
    tree first_defn;
    bool lost = false;
  
-   if (DECL_THUNK_P (fn))
-     fn = THUNK_TARGET (fn);
-   
    /* Find the nearest primary base (possibly binfo itself) which defines
       this function; this is the class the caller will convert to when
       calling FN through BINFO.  */
    for (b = binfo; ; b = get_primary_binfo (b))
      {
        my_friendly_assert (b, 20021227);
!       if (look_for_overrides_here (BINFO_TYPE (b), fn))
  	break;
  
        /* The nearest definition is from a lost primary.  */
--- 2355,2372 ----
    tree delta;
    tree virtual_base;
    tree first_defn;
+   tree overrider_fn, overrider_target;
+   tree target_fn = DECL_THUNK_P (fn) ? THUNK_TARGET (fn) : fn;
+   tree over_return, base_return;
    bool lost = false;
  
    /* Find the nearest primary base (possibly binfo itself) which defines
       this function; this is the class the caller will convert to when
       calling FN through BINFO.  */
    for (b = binfo; ; b = get_primary_binfo (b))
      {
        my_friendly_assert (b, 20021227);
!       if (look_for_overrides_here (BINFO_TYPE (b), target_fn))
  	break;
  
        /* The nearest definition is from a lost primary.  */
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2382,2439 ****
    first_defn = b;
  
    /* Find the final overrider.  */
!   overrider = find_final_overrider (TYPE_BINFO (t), b, fn);
    if (overrider == error_mark_node)
      return;
!   {
!     /* Check for adjusting covariant return types. */
!     tree over_return = TREE_TYPE (TREE_TYPE (TREE_PURPOSE (overrider)));
!     tree base_return = TREE_TYPE (TREE_TYPE (fn));
! 
!     if (POINTER_TYPE_P (over_return)
! 	&& TREE_CODE (over_return) == TREE_CODE (base_return)
! 	&& CLASS_TYPE_P (TREE_TYPE (over_return))
! 	&& CLASS_TYPE_P (TREE_TYPE (base_return)))
!       {
! 	tree binfo;
! 	base_kind kind;
  
! 	binfo = lookup_base (TREE_TYPE (over_return), TREE_TYPE (base_return),
! 			     ba_check | ba_quiet, &kind);
  
! 	if (binfo && (kind == bk_via_virtual || !BINFO_OFFSET_ZEROP (binfo)))
! 	  {
! 	    tree fixed_offset = BINFO_OFFSET (binfo);
! 	    tree virtual_offset = NULL_TREE;
! 	    tree thunk;
! 	    
! 	    if (kind == bk_via_virtual)
! 	      {
! 		while (!TREE_VIA_VIRTUAL (binfo))
! 		  binfo = BINFO_INHERITANCE_CHAIN (binfo);
! 		
! 		/* If the covariant type is within the class hierarchy
! 		   we are currently laying out, the vbase index is not
! 		   yet known, so we have to remember the virtual base
! 		   binfo. */
! 		virtual_offset = binfo_for_vbase (BINFO_TYPE (binfo),
! 						  TREE_TYPE (over_return));
! 		fixed_offset = size_diffop (fixed_offset,
! 					    BINFO_OFFSET (virtual_offset));
! 	      }
! 	    
! 	    /* Replace the overriding function with a covariant thunk.
! 	       We will emit the overriding function in its own slot
! 	       as well. */
! 	    thunk = make_thunk (TREE_PURPOSE (overrider), /*this_adjusting=*/0,
! 				fixed_offset, virtual_offset);
! 	    TREE_PURPOSE (overrider) = thunk;
! 	    if (!virtual_offset && !DECL_NAME (thunk))
! 	      finish_thunk (thunk);
! 	  }
!       }
!   }
  
    /* Assume that we will produce a thunk that convert all the way to
       the final overrider, and not to an intermediate virtual base.  */
    virtual_base = NULL_TREE;
--- 2376,2460 ----
    first_defn = b;
  
    /* Find the final overrider.  */
!   overrider = find_final_overrider (TYPE_BINFO (t), b, target_fn);
    if (overrider == error_mark_node)
      return;
!   overrider_target = overrider_fn = TREE_PURPOSE (overrider);
!   
!   /* Check for adjusting covariant return types. */
!   over_return = TREE_TYPE (TREE_TYPE (overrider_target));
!   base_return = TREE_TYPE (TREE_TYPE (target_fn));
!   
!   if (POINTER_TYPE_P (over_return)
!       && TREE_CODE (over_return) == TREE_CODE (base_return)
!       && CLASS_TYPE_P (TREE_TYPE (over_return))
!       && CLASS_TYPE_P (TREE_TYPE (base_return)))
!     {
!       /* If FN is a covariant thunk, we must figure out the adjustment
!          to the final base FN was converting to. As OVERRIDER_TARGET might
!          also be converting to the return type of FN, we have to
!          combine the two conversions here.  */
!       tree fixed_offset, virtual_offset;
!       
!       if (DECL_THUNK_P (fn))
! 	{
! 	  fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn));
! 	  virtual_offset = THUNK_VIRTUAL_OFFSET (fn);
! 	  if (virtual_offset)
! 	    virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset),
! 					      TREE_TYPE (over_return));
! 	}
!       else
! 	fixed_offset = virtual_offset = NULL_TREE;
  
!       if (!virtual_offset)
! 	{
! 	  /* There was no existing virtual thunk (which takes
! 	     precidence). */
! 	  tree thunk_binfo;
! 	  base_kind kind;
! 	  
! 	  thunk_binfo = lookup_base (TREE_TYPE (over_return),
! 				     TREE_TYPE (base_return),
! 				     ba_check | ba_quiet, &kind);
  
! 	  if (thunk_binfo && (kind == bk_via_virtual
! 			      || !BINFO_OFFSET_ZEROP (thunk_binfo)))
! 	    {
! 	      tree offset = BINFO_OFFSET (thunk_binfo);
  
+ 	      if (kind == bk_via_virtual)
+ 		{
+ 		  /* We convert via virtual base. Find the virtual
+ 		     base and adjust the fixed offset to be from there.  */
+ 		  while (!TREE_VIA_VIRTUAL (thunk_binfo))
+ 		    thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
+ 	      
+ 		  virtual_offset = binfo_for_vbase (BINFO_TYPE (thunk_binfo),
+ 						    TREE_TYPE (over_return));
+ 		  offset = size_diffop (offset,
+ 					BINFO_OFFSET (virtual_offset));
+ 		}
+ 	      if (fixed_offset)
+ 		/* There was an existing fixed offset, this must be
+ 		   from the base just converted to, and the base the
+ 		   FN was thunking to.  */
+ 		fixed_offset = size_binop (PLUS_EXPR, fixed_offset, offset);
+ 	      else
+ 		fixed_offset = offset;
+ 	    }
+ 	}
+       
+       if (fixed_offset || virtual_offset)
+ 	/* Replace the overriding function with a covariant thunk.  We
+ 	   will emit the overriding function in its own slot as
+ 	   well. */
+ 	overrider_fn = make_thunk (overrider_target, /*this_adjusting=*/0,
+ 				   fixed_offset, virtual_offset);
+     }
+   else
+     my_friendly_assert (!DECL_THUNK_P (fn), 20021231);
+   
    /* Assume that we will produce a thunk that convert all the way to
       the final overrider, and not to an intermediate virtual base.  */
    virtual_base = NULL_TREE;
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2476,2491 ****
      delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
  			 BINFO_OFFSET (binfo));
  
!   modify_vtable_entry (t, 
! 		       binfo, 
! 		       TREE_PURPOSE (overrider),
! 		       delta,
! 		       virtuals);
  
    if (virtual_base)
      BV_VCALL_INDEX (*virtuals) 
!       = get_vcall_index (TREE_PURPOSE (overrider),
! 			 BINFO_TYPE (virtual_base));
  }
  
  /* Called from modify_all_vtables via dfs_walk.  */
--- 2497,2507 ----
      delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
  			 BINFO_OFFSET (binfo));
  
!   modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
  
    if (virtual_base)
      BV_VCALL_INDEX (*virtuals) 
!       = get_vcall_index (overrider_target, BINFO_TYPE (virtual_base));
  }
  
  /* Called from modify_all_vtables via dfs_walk.  */
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.790
diff -c -3 -p -r1.790 cp-tree.h
*** cp/cp-tree.h	31 Dec 2002 18:58:04 -0000	1.790
--- cp/cp-tree.h	31 Dec 2002 19:35:05 -0000
*************** struct lang_decl GTY(())
*** 2977,2985 ****
  /* A tree indicating how to perform the virtual adjustment. For a this
     adjusting thunk it is the number of bytes to be added to the vtable
     to find the vcall offset. For a result adjusting thunk, it is the
!    binfo of the relevant virtual base.  The vptr is always located at
!    offset zero from the this or result pointer.  If NULL, then there
!    is no virtual adjust.  */
  #define THUNK_VIRTUAL_OFFSET(DECL) \
    (LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset)
  
--- 2977,2989 ----
  /* A tree indicating how to perform the virtual adjustment. For a this
     adjusting thunk it is the number of bytes to be added to the vtable
     to find the vcall offset. For a result adjusting thunk, it is the
!    binfo of the relevant virtual base.  If NULL, then there is no
!    virtual adjust.  (The vptr is always located at offset zero from
!    the this or result pointer.)  (If the covariant type is within the
!    class hierarchy being layed out, the vbase index is not yet known
!    at the point we need to create the thunks, hence the need to use
!    binfos.)  */
! 
  #define THUNK_VIRTUAL_OFFSET(DECL) \
    (LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset)
  
Index: testsuite/g++.dg/inherit/covariant8.C
===================================================================
RCS file: testsuite/g++.dg/inherit/covariant8.C
diff -N testsuite/g++.dg/inherit/covariant8.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/inherit/covariant8.C	31 Dec 2002 19:35:44 -0000
***************
*** 0 ****
--- 1,34 ----
+ // { dg-do compile }
+ 
+ // Copyright (C) 2002 Free Software Foundation, Inc.
+ // Contributed by Nathan Sidwell 31 Dec 2002 <nathan@codesourcery.com>
+ 
+ // ICE with covariant thunks.
+ 
+ struct c0 {};
+ 
+ struct c1 : virtual c0
+ {
+   virtual c0 &f2 ();
+ };
+ 
+ struct c2 
+ {
+   int m;
+ };
+ 
+ struct c3 : virtual c0, virtual c1, c2
+ {
+   virtual c1 &f2 ();
+ };
+ 
+ c1 &c3::f2 ()
+ {
+   throw 0;
+ }
+ 
+ struct c4 : virtual c3, virtual c0, virtual c1 {};
+ 
+ struct c8 : virtual c2, virtual c0 {};
+ 
+ struct c12 : virtual c4, virtual c3, virtual c8 {};

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