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]

-fabi-version=0 layout tweak


I'm pulling my hair out trying to make sure this empty base layout
code is correct, and this version gives me more confidence.  I'm
afraid the last version could cause us to get burned due to the fact
that BINFO_OFFSET contains an incorrect value for a while.  (No, that
is not a good thing, but not something we can fix too easily.)

Applied to mainline, tested on i686-pc-linux-gnu.

-- 
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2002-11-29  Mark Mitchell  <mark@codesourcery.com>

	* class.c (walk_subobject_offsets): Recur on binfos as well as on
	types.
	(layout_nonempty_base_or_field): Pass it a binfo when processing a
	base class.
	(layout_empty_base): Likewise.
	(build_base_field): Likewise.
	
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.497
diff -c -p -r1.497 class.c
*** class.c	27 Nov 2002 20:44:16 -0000	1.497
--- class.c	29 Nov 2002 21:13:03 -0000
*************** walk_subobject_offsets (type, f, offset,
*** 3410,3421 ****
--- 3410,3429 ----
       int vbases_p;
  {
    int r = 0;
+   tree type_binfo = NULL_TREE;
  
    /* If this OFFSET is bigger than the MAX_OFFSET, then we should
       stop.  */
    if (max_offset && INT_CST_LT (max_offset, offset))
      return 0;
  
+   if (!TYPE_P (type)) 
+     {
+       if (abi_version_at_least (2))
+ 	type_binfo = type;
+       type = BINFO_TYPE (type);
+     }
+ 
    if (CLASS_TYPE_P (type))
      {
        tree field;
*************** walk_subobject_offsets (type, f, offset,
*** 3432,3440 ****
  	return r;
  
        /* Iterate through the direct base classes of TYPE.  */
!       for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
  	{
! 	  binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
  
  	  if (abi_version_at_least (2) 
  	      && TREE_VIA_VIRTUAL (binfo))
--- 3440,3452 ----
  	return r;
  
        /* Iterate through the direct base classes of TYPE.  */
!       if (!type_binfo)
! 	type_binfo = TYPE_BINFO (type);
!       for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++i)
  	{
! 	  tree binfo_offset;
! 
! 	  binfo = BINFO_BASETYPE (type_binfo, i);
  
  	  if (abi_version_at_least (2) 
  	      && TREE_VIA_VIRTUAL (binfo))
*************** walk_subobject_offsets (type, f, offset,
*** 3445,3455 ****
  	      && !BINFO_PRIMARY_P (binfo))
  	    continue;
  
! 	  r = walk_subobject_offsets (BINFO_TYPE (binfo),
  				      f,
! 				      size_binop (PLUS_EXPR,
! 						  offset,
! 						  BINFO_OFFSET (binfo)),
  				      offsets,
  				      max_offset,
  				      (abi_version_at_least (2) 
--- 3457,3481 ----
  	      && !BINFO_PRIMARY_P (binfo))
  	    continue;
  
! 	  if (!abi_version_at_least (2))
! 	    binfo_offset = size_binop (PLUS_EXPR,
! 				       offset,
! 				       BINFO_OFFSET (binfo));
! 	  else
! 	    {
! 	      tree orig_binfo;
! 	      /* We cannot rely on BINFO_OFFSET being set for the base
! 		 class yet, but the offsets for direct non-virtual
! 		 bases can be calculated by going back to the TYPE.  */
! 	      orig_binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
! 	      binfo_offset = size_binop (PLUS_EXPR,	      
! 					 offset,
! 					 BINFO_OFFSET (orig_binfo));
! 	    }
! 
! 	  r = walk_subobject_offsets (binfo,
  				      f,
! 				      binfo_offset,
  				      offsets,
  				      max_offset,
  				      (abi_version_at_least (2) 
*************** walk_subobject_offsets (type, f, offset,
*** 3458,3487 ****
  	    return r;
  	}
  
!       /* Iterate through the virtual base classes of TYPE.  In G++
! 	 3.2, we included virtual bases in the direct base class loop
! 	 above, which results in incorrect results; the correct
! 	 offsets for virtual bases are only known when working with
! 	 the most derived type.  */
!       if (abi_version_at_least (2) && vbases_p)
  	{
  	  tree vbase;
  
! 	  for (vbase = CLASSTYPE_VBASECLASSES (type);
! 	       vbase;
! 	       vbase = TREE_CHAIN (vbase))
  	    {
! 	      binfo = TREE_VALUE (vbase);
! 	      r = walk_subobject_offsets (BINFO_TYPE (binfo),
! 					  f,
! 					  size_binop (PLUS_EXPR,
! 						      offset,
! 						      BINFO_OFFSET (binfo)),
! 					  offsets,
! 					  max_offset,
! 					  /*vbases_p=*/0);
! 	      if (r)
! 		return r;
  	    }
  	}
  
--- 3484,3538 ----
  	    return r;
  	}
  
!       if (abi_version_at_least (2))
  	{
  	  tree vbase;
  
! 	  /* Iterate through the virtual base classes of TYPE.  In G++
! 	     3.2, we included virtual bases in the direct base class
! 	     loop above, which results in incorrect results; the
! 	     correct offsets for virtual bases are only known when
! 	     working with the most derived type.  */
! 	  if (vbases_p)
! 	    for (vbase = CLASSTYPE_VBASECLASSES (type);
! 		 vbase;
! 		 vbase = TREE_CHAIN (vbase))
! 	      {
! 		binfo = TREE_VALUE (vbase);
! 		r = walk_subobject_offsets (binfo,
! 					    f,
! 					    size_binop (PLUS_EXPR,
! 							offset,
! 							BINFO_OFFSET (binfo)),
! 					    offsets,
! 					    max_offset,
! 					    /*vbases_p=*/0);
! 		if (r)
! 		  return r;
! 	      }
! 	  else
  	    {
! 	      /* We still have to walk the primary base, if it is
! 		 virtual.  (If it is non-virtual, then it was walked
! 		 above.)  */
! 	      vbase = get_primary_binfo (type_binfo);
! 	      if (vbase && TREE_VIA_VIRTUAL (vbase))
! 		{
! 		  tree derived = type_binfo;
! 		  while (BINFO_INHERITANCE_CHAIN (derived))
! 		    derived = BINFO_INHERITANCE_CHAIN (derived);
! 		  derived = TREE_TYPE (derived);
! 		  vbase = binfo_for_vbase (TREE_TYPE (vbase), derived);
! 
! 		  if (BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
! 		    {
! 		      r = (walk_subobject_offsets 
! 			   (vbase, f, offset,
! 			    offsets, max_offset, /*vbases_p=*/0));
! 		      if (r)
! 			return r;
! 		    }
! 		}
  	    }
  	}
  
*************** layout_nonempty_base_or_field (record_la
*** 3652,3658 ****
  	 virtual base.  */
        if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
  	break;
!       if (layout_conflict_p (type, offset, offsets, field_p))
  	{
  	  /* Strip off the size allocated to this field.  That puts us
  	     at the first place we could have put the field with
--- 3703,3710 ----
  	 virtual base.  */
        if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
  	break;
!       if (layout_conflict_p (field_p ? type : binfo, offset, 
! 			     offsets, field_p))
  	{
  	  /* Strip off the size allocated to this field.  That puts us
  	     at the first place we could have put the field with
*************** layout_empty_base (binfo, eoc, offsets, 
*** 3726,3732 ****
  
    /* This is an empty base class.  We first try to put it at offset
       zero.  */
!   if (layout_conflict_p (BINFO_TYPE (binfo),
  			 BINFO_OFFSET (binfo),
  			 offsets, 
  			 /*vbases_p=*/0))
--- 3778,3784 ----
  
    /* This is an empty base class.  We first try to put it at offset
       zero.  */
!   if (layout_conflict_p (binfo,
  			 BINFO_OFFSET (binfo),
  			 offsets, 
  			 /*vbases_p=*/0))
*************** layout_empty_base (binfo, eoc, offsets, 
*** 3737,3743 ****
        propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
        while (1) 
  	{
! 	  if (!layout_conflict_p (BINFO_TYPE (binfo),
  				  BINFO_OFFSET (binfo), 
  				  offsets,
  				  /*vbases_p=*/0))
--- 3789,3795 ----
        propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
        while (1) 
  	{
! 	  if (!layout_conflict_p (binfo,
  				  BINFO_OFFSET (binfo), 
  				  offsets,
  				  /*vbases_p=*/0))
*************** build_base_field (record_layout_info rli
*** 3848,3881 ****
      }
  
    /* Record the offsets of BINFO and its base subobjects.  */
!   record_subobject_offsets (BINFO_TYPE (binfo), 
  			    BINFO_OFFSET (binfo),
  			    offsets, 
  			    /*vbases_p=*/0);
- 
-   if (abi_version_at_least (2))
-     {
-       /* If BINFO has a primary virtual base that is really going to
- 	 be located at the same offset as binfo, it will have been
- 	 skipped -- but we should record empty bases from there too.  */
-       while (true) 
- 	{
- 	  tree b;
- 
- 	  b = get_primary_binfo (binfo);
- 	  if (!b)
- 	    break;
- 	  b = CANONICAL_BINFO (b, rli->t);
- 	  if (BINFO_PRIMARY_BASE_OF (b) != binfo)
- 	    break;
- 	  if (TREE_VIA_VIRTUAL (b))
- 	    record_subobject_offsets (BINFO_TYPE (b),
- 				      BINFO_OFFSET (b),
- 				      offsets,
- 				      /*vbases_p=*/0);
- 	  binfo = b;
- 	}
-     }
  
    return next_field;
  }
--- 3900,3909 ----
      }
  
    /* Record the offsets of BINFO and its base subobjects.  */
!   record_subobject_offsets (binfo,
  			    BINFO_OFFSET (binfo),
  			    offsets, 
  			    /*vbases_p=*/0);
  
    return next_field;
  }


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