C++ PATCH: Fix ctor vtables for extreme virtual inheritance

Jason Merrill jason_merrill@redhat.com
Fri Jun 8 04:07:00 GMT 2001


The old code in dfs_accumulate_vtbl_inits failed to consider the
possibility that a lost virtual base could still share its vptr with
another lost virtual base within the sub-hierarchy of the base under
construction.  This patch fixes that.

Tested i686-pc-linux-gnu, applied to trunk and branch.

2001-06-06  Nathan Sidwell  <nathan@codesourcery.com>
	    Jason Merrill <jason_merrill@redhat.com>

	PR c++/3061
	* class.c (build_secondary_vtable): Use assert, rather than an error
	message.
	(dfs_fixup_binfo_vtbls): BINFO_VTABLE might be NULL.
	(dfs_accumulate_vtbl_inits): A lost primary virtual base may
	be between ORIG_BINFO and RTTI_BINFO, but neither of them.
	Don't set BINFO_VTABLE for a primary virtual base.

*** class.c.~1~	Fri Jun  8 11:15:29 2001
--- class.c	Fri Jun  8 11:03:18 2001
*************** build_secondary_vtable (binfo, for_type)
*** 868,887 ****
    /* Make fresh virtual list, so we can smash it later.  */
    BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
  
!   if (TREE_VIA_VIRTUAL (binfo))
!     {
!       tree binfo1 = binfo_for_vbase (BINFO_TYPE (binfo), for_type);
! 
!       /* XXX - This should never happen, if it does, the caller should
! 	 ensure that the binfo is from for_type's binfos, not from any
! 	 base type's.  We can remove all this code after a while.  */
!       if (binfo1 != binfo)
! 	warning ("internal inconsistency: binfo offset error for rtti");
! 
!       offset = BINFO_OFFSET (binfo1);
!     }
!   else
!     offset = BINFO_OFFSET (binfo);
  
    /* In the new ABI, secondary vtables are laid out as part of the
       same structure as the primary vtable.  */
--- 868,875 ----
    /* Make fresh virtual list, so we can smash it later.  */
    BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
  
!   my_friendly_assert (binfo == CANONICAL_BINFO (binfo, for_type), 20010605);
!   offset = BINFO_OFFSET (binfo);
  
    /* In the new ABI, secondary vtables are laid out as part of the
       same structure as the primary vtable.  */
*************** dfs_get_primary_binfo (binfo, data)
*** 6761,6772 ****
    return NULL_TREE;
  }
  
! /* Returns the binfo for the primary base of BINFO.  Note that in a
!    complex hierarchy the resulting BINFO may not actually *be*
!    primary.  In particular if the resulting BINFO is a virtual base,
!    and it occurs elsewhere in the hierarchy, then this occurrence may
!    not actually be a primary base in the complete object.  Check
!    BINFO_PRIMARY_P to be sure.  */
  
  tree
  get_primary_binfo (binfo)
--- 6749,6760 ----
    return NULL_TREE;
  }
  
! /* Returns the unshared binfo for the primary base of BINFO.  Note
!    that in a complex hierarchy the resulting BINFO may not actually
!    *be* primary.  In particular if the resulting BINFO is a virtual
!    base, and it occurs elsewhere in the hierarchy, then this
!    occurrence may not actually be a primary base in the complete
!    object.  Check BINFO_PRIMARY_P to be sure.  */
  
  tree
  get_primary_binfo (binfo)
*************** dfs_fixup_binfo_vtbls (binfo, data)
*** 7413,7419 ****
  
    /* If we scribbled the construction vtable vptr into BINFO, clear it
       out now.  */
!   if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
        && (TREE_PURPOSE (BINFO_VTABLE (binfo)) 
  	  == TREE_VALUE ((tree) data)))
      BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
--- 7401,7408 ----
  
    /* If we scribbled the construction vtable vptr into BINFO, clear it
       out now.  */
!   if (BINFO_VTABLE (binfo)
!       && TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
        && (TREE_PURPOSE (BINFO_VTABLE (binfo)) 
  	  == TREE_VALUE ((tree) data)))
      BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 7559,7599 ****
           virtual base.  If it is not the same primary in the hierarchy of T,
           we'll need to generate a ctor vtable for it, to place at its
           location in T.  If it is the same primary, we still need a VTT
!          entry for the vtable, but that must be the base it is a
!          primary for within the sub-hierarchy of RTTI_BINFO.  */
!       tree parent;
!       tree best_primary = NULL;
!       tree primary_for;
!       
!       my_friendly_assert (BINFO_PRIMARY_P (binfo), 20010131);
  
!       for (primary_for = BINFO_PRIMARY_BASE_OF (binfo);
!            primary_for;
!            primary_for = BINFO_PRIMARY_BASE_OF (primary_for))
!         {
!           for (parent = primary_for;
!                parent;
!                parent = BINFO_INHERITANCE_CHAIN (parent))
!              {
!                if (parent == rtti_binfo)
!                  {
!                    best_primary = primary_for;
!                    break;
!                  }
!              }
!            if (!parent)
!              break;
!         }
!       if (best_primary)
!         {
!           vtbl = BINFO_VTABLE (best_primary);
!           if (TREE_CODE (vtbl) == TREE_LIST)
!             {
!               my_friendly_assert (TREE_PURPOSE (vtbl) == rtti_binfo,
!                                   20010126);
!               vtbl = TREE_VALUE (vtbl);
!             }
          }
      }
    else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
      return inits;
--- 7548,7627 ----
           virtual base.  If it is not the same primary in the hierarchy of T,
           we'll need to generate a ctor vtable for it, to place at its
           location in T.  If it is the same primary, we still need a VTT
!          entry for the vtable, but it should point to the ctor vtable for the
! 	 base it is a primary for within the sub-hierarchy of RTTI_BINFO.
  
! 	 There are three possible cases:
! 
!          1) We are in the same place.
! 	 2) We are a primary base within a lost primary virtual base of
! 	    RTTI_BINFO.
! 	 3) We are not primary to anything else in RTTI_BINFO.  */
! 
!       tree primary = NULL_TREE;
!       if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo),
! 			      size_diffop (BINFO_OFFSET (binfo),
! 					   BINFO_OFFSET (rtti_binfo))))
! 	{
! 	  /* Case 1: We're in the same place relative to RTTI_BINFO as we
! 	     were in the complete type, so we are primary either to
! 	     RTTI_BINFO or one of its secondary bases.  */
! 
! 	  tree b = BINFO_PRIMARY_BASE_OF (binfo);
! 
! 	  /* Walk down our until we either find the last primary base or
! 	     rtti_binfo.  */
! 	  for (; b; b = BINFO_PRIMARY_BASE_OF (b))
! 	    {
! 	      primary = b;
! 	      if (b == rtti_binfo)
! 		break;
! 	    }
          }
+       else
+ 	{
+ 	  /* Case 2 or 3: We're not in the same place.  We might still be
+ 	     primary to something within a lost primary virtual base of
+ 	     RTTI_BINFO.  */
+ 
+ 	  tree b = BINFO_PRIMARY_BASE_OF (binfo);
+ 	  tree last;
+ 
+ 	  /* First, look through the bases we are primary to for a virtual
+ 	     base.  */
+ 	  for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+ 	    {
+ 	      last = b;
+ 	      if (TREE_VIA_VIRTUAL (b))
+ 		break;
+ 	    }
+ 	  /* If we run out of primary links, keep looking down our
+ 	     inheritance chain; we might be an indirect primary of a
+ 	     virtual base.  */
+ 	  if (b == NULL_TREE)
+ 	    for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
+ 	      if (TREE_VIA_VIRTUAL (b))
+ 		break;
+ 
+ 	  /* If we found a virtual base B and it is a base of RTTI_BINFO, we
+ 	     share our vtable with LAST, i.e. the derived-most base within
+ 	     B of which we are a primary.  Otherwise, we get our own.  */
+ 	  if (b && binfo_for_vbase (BINFO_TYPE (b),
+ 				    BINFO_TYPE (rtti_binfo)))
+ 	    primary = last;
+ 	}
+ 
+       if (primary)
+ 	{
+           vtbl = BINFO_VTABLE (primary);
+ 	  /* If we haven't already been here for our primary derivation,
+ 	     all bets are off.  Especially for case 2 above, we need
+ 	     the derived vtable to have been generated.  */
+ 	  my_friendly_assert (TREE_CODE (vtbl) == TREE_LIST
+ 			      && TREE_PURPOSE (vtbl) == rtti_binfo,
+ 			      20010126);
+ 	  vtbl = TREE_VALUE (vtbl);
+ 	}
      }
    else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
      return inits;
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 7625,7633 ****
    if (!ctor_vtbl_p)
      {
        /* For an ordinary vtable, set BINFO_VTABLE.  */
-       BINFO_VTABLE (binfo) = vtbl;
        if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
!         inits = NULL_TREE;
      }
    else
      /* For a construction vtable, we can't overwrite BINFO_VTABLE.
--- 7653,7662 ----
    if (!ctor_vtbl_p)
      {
        /* For an ordinary vtable, set BINFO_VTABLE.  */
        if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
! 	inits = NULL_TREE;
!       else
! 	BINFO_VTABLE (binfo) = vtbl;
      }
    else
      /* For a construction vtable, we can't overwrite BINFO_VTABLE.



More information about the Gcc-patches mailing list