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]

C++ PATCH: Fix empty base class optimization bugs



The new ABI allows empty base classes to be overlayed with other
objects.  For example:

  struct A {};
  struct B {};
  struct C : A, B {};

In this example, both `A' and `B' will be at offset zero in `C'.

However, the C++ standard doesn't allow you to put two objects of the
same type at the same offset.  This patch fixes our handling of that
restriction; for example, we used to get wrong:

  struct A {};
  struct B : A {
    A a[3];
  };

we put the array at offset zero, along with the base class.

Fixed with this patch.  Tested on i686-pc-linux-gnu.

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

2000-10-19  Mark Mitchell  <mark@codesourcery.com>

	* class.c (subobject_offset_fn): New type.
	(dfs_record_base_offsets): Remove.
	(record_base_offsets): Likewise.
	(dfs_search_base_offsets): Likewise.
	(record_subobject_offset): New function.
	(check_subobject_offset): Likewise.
	(walk_subobject_offsets): Likewise.
	(record_subobject_offsets): Likewise.
	(layout_conflict_p): Reimplement.
	(layout_nonempty_base_or_field): Correct handling of type
	conflicts during layout.
	(layout_empty_base): Likewise.
	(build_base_field): Adjust to handle new representation of empty
	base offset table.
	(build_base_fields): Likewise.
	(layout_virtual_bases): Likewise.
	(splay_tree_compare_integer_csts): New function.
	(layout_class_type): Use a splay_tree, rather than a varray, to
	represent the offsets of empty bases.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.339
diff -c -p -r1.339 class.c
*** class.c	2000/10/13 06:26:42	1.339
--- class.c	2000/10/20 05:59:33
*************** typedef struct vtbl_init_data_s
*** 89,94 ****
--- 89,97 ----
    int ctor_vtbl_p;
  } vtbl_init_data;
  
+ /* The type of a function passed to walk_subobject_offsets.  */
+ typedef int (*subobject_offset_fn) PARAMS ((tree, tree, splay_tree));
+ 
  /* The stack itself.  This is an dynamically resized array.  The
     number of elements allocated is CURRENT_CLASS_STACK_SIZE.  */
  static int current_class_stack_size;
*************** static void check_field_decl PARAMS ((tr
*** 142,149 ****
  static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
  				     int *));
  static void build_base_field PARAMS ((record_layout_info, tree, int *,
! 				      unsigned int *, varray_type *));
! static varray_type build_base_fields PARAMS ((record_layout_info, int *));
  static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
  static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
  					       int *));
--- 145,153 ----
  static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
  				     int *));
  static void build_base_field PARAMS ((record_layout_info, tree, int *,
! 				      unsigned int *, splay_tree));
! static void build_base_fields PARAMS ((record_layout_info, int *,
! 				       splay_tree));
  static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
  static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
  					       int *));
*************** static void fixup_pending_inline PARAMS 
*** 157,163 ****
  static void fixup_inline_methods PARAMS ((tree));
  static void set_primary_base PARAMS ((tree, tree, int *));
  static void propagate_binfo_offsets PARAMS ((tree, tree));
! static void layout_virtual_bases PARAMS ((tree, varray_type *));
  static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
  static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
  static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
--- 161,167 ----
  static void fixup_inline_methods PARAMS ((tree));
  static void set_primary_base PARAMS ((tree, tree, int *));
  static void propagate_binfo_offsets PARAMS ((tree, tree));
! static void layout_virtual_bases PARAMS ((tree, splay_tree));
  static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
  static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
  static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
*************** static void initialize_vtable PARAMS ((t
*** 174,186 ****
  static void initialize_array PARAMS ((tree, tree));
  static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
  						   tree, tree,
! 						   varray_type));
! static tree dfs_record_base_offsets PARAMS ((tree, void *));
! static void record_base_offsets PARAMS ((tree, varray_type *));
! static tree dfs_search_base_offsets PARAMS ((tree, void *));
! static int layout_conflict_p PARAMS ((tree, varray_type));
  static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
! static void layout_empty_base PARAMS ((tree, tree, varray_type));
  static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
  static void set_vindex PARAMS ((tree, tree, int *));
  static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
--- 178,186 ----
  static void initialize_array PARAMS ((tree, tree));
  static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
  						   tree, tree,
! 						   splay_tree));
  static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
! static void layout_empty_base PARAMS ((tree, tree, splay_tree));
  static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
  static void set_vindex PARAMS ((tree, tree, int *));
  static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
*************** static tree dfs_build_secondary_vptr_vtt
*** 199,204 ****
--- 199,212 ----
  static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
  static tree get_matching_base PARAMS ((tree, tree));
  static tree dfs_get_primary_binfo PARAMS ((tree, void*));
+ static int record_subobject_offset PARAMS ((tree, tree, splay_tree));
+ static int check_subobject_offset PARAMS ((tree, tree, splay_tree));
+ static int walk_subobject_offsets PARAMS ((tree, subobject_offset_fn,
+ 					   tree, splay_tree, int));
+ static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
+ static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
+ static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
+ 						    splay_tree_key k2));
  
  /* Variables shared between class.c and call.c.  */
  
*************** build_vtbl_or_vbase_field (name, assembl
*** 3694,3809 ****
    return field;
  }
  
! /* Record the type of BINFO in the slot in DATA (which is really a
!    `varray_type *') corresponding to the BINFO_OFFSET.  */
  
! static tree
! dfs_record_base_offsets (binfo, data)
!      tree binfo;
!      void *data;
  {
!   varray_type *v;
!   unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
  
!   v = (varray_type *) data;
!   while (VARRAY_SIZE (*v) <= offset)
!     VARRAY_GROW (*v, 2 * VARRAY_SIZE (*v));
!   VARRAY_TREE (*v, offset) = tree_cons (NULL_TREE,
! 					BINFO_TYPE (binfo),
! 					VARRAY_TREE (*v, offset));
  
!   return NULL_TREE;
  }
  
! /* Add the offset of BINFO and its bases to BASE_OFFSETS.  */
  
! static void
! record_base_offsets (binfo, base_offsets)
!      tree binfo;
!      varray_type *base_offsets;
  {
!   dfs_walk (binfo,
! 	    dfs_record_base_offsets,
! 	    dfs_skip_vbases,
! 	    base_offsets);
  }
  
! /* Returns non-NULL if there is already an entry in DATA (which is
!    really a `varray_type') indicating that an object with the same
!    type of BINFO is already at the BINFO_OFFSET for BINFO.  */
  
! static tree
! dfs_search_base_offsets (binfo, data)
!      tree binfo;
!      void *data;
  {
!   if (is_empty_class (BINFO_TYPE (binfo)))
      {
!       varray_type v = (varray_type) data;
!       /* Find the offset for this BINFO.  */
!       unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
!       tree t;
  
!       /* If we haven't yet encountered any objects at offsets that
! 	 big, then there's no conflict.  */
!       if (VARRAY_SIZE (v) <= offset)
! 	return NULL_TREE;
!       /* Otherwise, go through the objects already allocated at this
! 	 offset.  */
!       for (t = VARRAY_TREE (v, offset); t; t = TREE_CHAIN (t))
! 	if (same_type_p (TREE_VALUE (t), BINFO_TYPE (binfo)))
! 	  return binfo;
      }
  
!   return NULL_TREE;
  }
  
! /* Returns non-zero if there's a conflict between BINFO and a base
!    already mentioned in BASE_OFFSETS if BINFO is placed at its current
!    BINFO_OFFSET.  */
  
  static int
! layout_conflict_p (binfo, base_offsets)
!      tree binfo;
!      varray_type base_offsets;
  {
!   return dfs_walk (binfo, dfs_search_base_offsets, dfs_skip_vbases,
! 		   base_offsets) != NULL_TREE;
  }
  
  /* DECL is a FIELD_DECL corresponding either to a base subobject of a
     non-static data member of the type indicated by RLI.  BINFO is the
!    binfo corresponding to the base subobject, or, if this is a
!    non-static data-member, a dummy BINFO for the type of the data
!    member.  BINFO may be NULL if checks to see if the field overlaps
!    an existing field with the same type are not required.  V maps
!    offsets to types already located at those offsets.  This function
!    determines the position of the DECL.  */
  
  static void
! layout_nonempty_base_or_field (rli, decl, binfo, v)
       record_layout_info rli;
       tree decl;
       tree binfo;
!      varray_type v;
  {
    /* Try to place the field.  It may take more than one try if we have
       a hard time placing the field without putting two objects of the
       same type at the same address.  */
    while (1)
      {
-       tree offset;
        struct record_layout_info_s old_rli = *rli;
  
        /* Place this field.  */
        place_field (rli, decl);
-       
-       /* Now that we know where it wil be placed, update its
- 	 BINFO_OFFSET.  */
        offset = byte_position (decl);
-       if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
- 	propagate_binfo_offsets (binfo, 
- 				 convert (ssizetype, offset));
   
        /* We have to check to see whether or not there is already
  	 something of the same type at the offset we're about to use.
--- 3702,3909 ----
    return field;
  }
  
! /* If TYPE is an empty class type, records its OFFSET in the table of
!    OFFSETS.  */
  
! static int
! record_subobject_offset (type, offset, offsets)
!      tree type;
!      tree offset;
!      splay_tree offsets;
  {
!   splay_tree_node n;
  
!   if (!is_empty_class (type))
!     return 0;
  
!   /* Record the location of this empty object in OFFSETS.  */
!   n = splay_tree_lookup (offsets, (splay_tree_key) offset);
!   if (!n)
!     n = splay_tree_insert (offsets, 
! 			   (splay_tree_key) offset,
! 			   (splay_tree_value) NULL_TREE);
!   n->value = ((splay_tree_value) 
! 	      tree_cons (NULL_TREE,
! 			 type,
! 			 (tree) n->value));
! 
!   return 0;
  }
  
! /* Returns non-zero if TYPE is an empty class type and there is
!    already an entry in OFFSETS for the same TYPE as the same OFFSET.  */
  
! static int
! check_subobject_offset (type, offset, offsets)
!      tree type;
!      tree offset;
!      splay_tree offsets;
  {
!   splay_tree_node n;
!   tree t;
! 
!   if (!is_empty_class (type))
!     return 0;
! 
!   /* Record the location of this empty object in OFFSETS.  */
!   n = splay_tree_lookup (offsets, (splay_tree_key) offset);
!   if (!n)
!     return 0;
! 
!   for (t = (tree) n->value; t; t = TREE_CHAIN (t))
!     if (same_type_p (TREE_VALUE (t), type))
!       return 1;
! 
!   return 0;
  }
  
! /* Walk through all the subobjects of TYPE (located at OFFSET).  Call
!    F for every subobject, passing it the type, offset, and table of
!    OFFSETS.  If VBASES_P is non-zero, then even non-virtual primary
!    bases should be traversed; otherwise, they are ignored.  If F
!    returns a non-zero value, the traversal ceases, and that value is
!    returned.  Otherwise, returns zero.  */
  
! static int
! walk_subobject_offsets (type, f, offset, offsets, vbases_p)
!      tree type;
!      subobject_offset_fn f;
!      tree offset;
!      splay_tree offsets;
!      int vbases_p;
  {
!   int r = 0;
! 
!   if (CLASS_TYPE_P (type))
      {
!       tree field;
!       int i;
  
!       /* Record the location of TYPE.  */
!       r = (*f) (type, offset, offsets);
!       if (r)
! 	return r;
! 
!       /* Iterate through the direct base classes of TYPE.  */
!       for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
! 	{
! 	  tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
! 
! 	  if (!vbases_p 
! 	      && TREE_VIA_VIRTUAL (binfo) 
! 	      && !BINFO_PRIMARY_MARKED_P (binfo))
! 	    continue;
! 
! 	  r = walk_subobject_offsets (BINFO_TYPE (binfo),
! 				      f,
! 				      size_binop (PLUS_EXPR,
! 						  offset,
! 						  BINFO_OFFSET (binfo)),
! 				      offsets,
! 				      vbases_p);
! 	  if (r)
! 	    return r;
! 	}
! 
!       /* Iterate through the fields of TYPE.  */
!       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	if (TREE_CODE (field) == FIELD_DECL)
! 	  {
! 	    r = walk_subobject_offsets (TREE_TYPE (field),
! 					f,
! 					size_binop (PLUS_EXPR,
! 						    offset,
! 						    DECL_FIELD_OFFSET (field)),
! 					offsets,
! 					/*vbases_p=*/1);
! 	    if (r)
! 	      return r;
! 	  }
      }
+   else if (TREE_CODE (type) == ARRAY_TYPE)
+     {
+       tree domain = TYPE_DOMAIN (type);
+       tree index;
  
!       /* Step through each of the elements in the array.  */
!       for (index = size_zero_node; 
! 	   INT_CST_LT (index, TYPE_MAX_VALUE (domain));
! 	   index = size_binop (PLUS_EXPR, index, size_one_node))
! 	{
! 	  r = walk_subobject_offsets (TREE_TYPE (type),
! 				      f,
! 				      offset,
! 				      offsets,
! 				      /*vbases_p=*/1);
! 	  if (r)
! 	    return r;
! 	  offset = size_binop (PLUS_EXPR, offset, 
! 			       TYPE_SIZE_UNIT (TREE_TYPE (type)));
! 	}
!     }
! 
!   return 0;
! }
! 
! /* Record all of the empty subobjects of TYPE (located at OFFSET) in
!    OFFSETS.  If VBASES_P is non-zero, virtual bases of TYPE are
!    examined.  */
! 
! static void
! record_subobject_offsets (type, offset, offsets, vbases_p)
!      tree type;
!      tree offset;
!      splay_tree offsets;
!      int vbases_p;
! {
!   walk_subobject_offsets (type, record_subobject_offset, offset,
! 			  offsets, vbases_p);
  }
  
! /* Returns non-zero if any of the empty subobjects of TYPE (located at
!    OFFSET) conflict with entries in OFFSETS.  If VBASES_P is non-zero,
!    virtual bases of TYPE are examined.  */
  
  static int
! layout_conflict_p (type, offset, offsets, vbases_p)
!      tree type;
!      tree offset;
!      splay_tree offsets;
!      int vbases_p;
  {
!   return walk_subobject_offsets (type, check_subobject_offset, offset,
! 				 offsets, vbases_p);
  }
  
  /* DECL is a FIELD_DECL corresponding either to a base subobject of a
     non-static data member of the type indicated by RLI.  BINFO is the
!    binfo corresponding to the base subobject, OFFSETS maps offsets to
!    types already located at those offsets.  This function determines
!    the position of the DECL.  */
  
  static void
! layout_nonempty_base_or_field (rli, decl, binfo, offsets)
       record_layout_info rli;
       tree decl;
       tree binfo;
!      splay_tree offsets;
  {
+   tree offset = NULL_TREE;
+   tree type = TREE_TYPE (decl);
+   /* If we are laying out a base class, rather than a field, then
+      DECL_ARTIFICIAL will be set on the FIELD_DECL.  */
+   int field_p = !DECL_ARTIFICIAL (decl);
+ 
    /* Try to place the field.  It may take more than one try if we have
       a hard time placing the field without putting two objects of the
       same type at the same address.  */
    while (1)
      {
        struct record_layout_info_s old_rli = *rli;
  
        /* Place this field.  */
        place_field (rli, decl);
        offset = byte_position (decl);
   
        /* We have to check to see whether or not there is already
  	 something of the same type at the offset we're about to use.
*************** layout_nonempty_base_or_field (rli, decl
*** 3820,3859 ****
  	 empty class, have non-zero size, any overlap can happen only
  	 with a direct or indirect base-class -- it can't happen with
  	 a data member.  */
!       if (binfo && flag_new_abi && layout_conflict_p (binfo, v))
  	{
- 	  /* Undo the propagate_binfo_offsets call.  */
- 	  offset = size_diffop (size_zero_node, offset);
- 	  propagate_binfo_offsets (binfo, convert (ssizetype, offset));
- 	 
  	  /* Strip off the size allocated to this field.  That puts us
  	     at the first place we could have put the field with
  	     proper alignment.  */
  	  *rli = old_rli;
  
! 	  /* Bump up by the alignment required for the type, without
! 	     virtual base classes.  */
  	  rli->bitpos
! 	    = size_binop (PLUS_EXPR, rli->bitpos,
! 			  bitsize_int (CLASSTYPE_ALIGN (BINFO_TYPE (binfo))));
  	  normalize_rli (rli);
  	}
        else
  	/* There was no conflict.  We're done laying out this field.  */
  	break;
      }
  }
  
  /* Layout the empty base BINFO.  EOC indicates the byte currently just
     past the end of the class, and should be correctly aligned for a
!    class of the type indicated by BINFO; BINFO_OFFSETS gives the
!    offsets of the other bases allocated so far.  */
  
  static void
! layout_empty_base (binfo, eoc, binfo_offsets)
       tree binfo;
       tree eoc;
!      varray_type binfo_offsets;
  {
    tree alignment;
    tree basetype = BINFO_TYPE (binfo);
--- 3920,3965 ----
  	 empty class, have non-zero size, any overlap can happen only
  	 with a direct or indirect base-class -- it can't happen with
  	 a data member.  */
!       if (flag_new_abi && layout_conflict_p (TREE_TYPE (decl),
! 					     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
  	     proper alignment.  */
  	  *rli = old_rli;
  
! 	  /* Bump up by the alignment required for the type.  */
  	  rli->bitpos
! 	    = size_binop (PLUS_EXPR, rli->bitpos, 
! 			  bitsize_int (binfo 
! 				       ? CLASSTYPE_ALIGN (type)
! 				       : TYPE_ALIGN (type)));
  	  normalize_rli (rli);
  	}
        else
  	/* There was no conflict.  We're done laying out this field.  */
  	break;
      }
+ 
+   /* Now that we know where it wil be placed, update its
+      BINFO_OFFSET.  */
+   if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+     propagate_binfo_offsets (binfo, 
+ 			     convert (ssizetype, offset));
  }
  
  /* Layout the empty base BINFO.  EOC indicates the byte currently just
     past the end of the class, and should be correctly aligned for a
!    class of the type indicated by BINFO; OFFSETS gives the offsets of
!    the empty bases allocated so far.  */
  
  static void
! layout_empty_base (binfo, eoc, offsets)
       tree binfo;
       tree eoc;
!      splay_tree offsets;
  {
    tree alignment;
    tree basetype = BINFO_TYPE (binfo);
*************** layout_empty_base (binfo, eoc, binfo_off
*** 3864,3877 ****
  
    /* This is an empty base class.  We first try to put it at offset
       zero.  */
!   if (layout_conflict_p (binfo, binfo_offsets))
      {
        /* That didn't work.  Now, we move forward from the next
  	 available spot in the class.  */
        propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
        while (1) 
  	{
! 	  if (!layout_conflict_p (binfo, binfo_offsets))
  	    /* We finally found a spot where there's no overlap.  */
  	    break;
  
--- 3970,3989 ----
  
    /* 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))
      {
        /* That didn't work.  Now, we move forward from the next
  	 available spot in the class.  */
        propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
        while (1) 
  	{
! 	  if (!layout_conflict_p (BINFO_TYPE (binfo),
! 				  BINFO_OFFSET (binfo), 
! 				  offsets,
! 				  /*vbases_p=*/0))
  	    /* We finally found a spot where there's no overlap.  */
  	    break;
  
*************** layout_empty_base (binfo, eoc, binfo_off
*** 3884,3898 ****
  /* Build a FIELD_DECL for the base given by BINFO in the class
     indicated by RLI.  If the new object is non-empty, clear *EMPTY_P.
     *BASE_ALIGN is a running maximum of the alignments of any base
!    class.  */
  
  static void
! build_base_field (rli, binfo, empty_p, base_align, v)
       record_layout_info rli;
       tree binfo;
       int *empty_p;
       unsigned int *base_align;
!      varray_type *v;
  {
    tree basetype = BINFO_TYPE (binfo);
    tree decl;
--- 3996,4010 ----
  /* Build a FIELD_DECL for the base given by BINFO in the class
     indicated by RLI.  If the new object is non-empty, clear *EMPTY_P.
     *BASE_ALIGN is a running maximum of the alignments of any base
!    class.  OFFSETS gives the location of empty base subobjects.  */
  
  static void
! build_base_field (rli, binfo, empty_p, base_align, offsets)
       record_layout_info rli;
       tree binfo;
       int *empty_p;
       unsigned int *base_align;
!      splay_tree offsets;
  {
    tree basetype = BINFO_TYPE (binfo);
    tree decl;
*************** build_base_field (rli, binfo, empty_p, b
*** 3933,3939 ****
        /* Try to place the field.  It may take more than one try if we
  	 have a hard time placing the field without putting two
  	 objects of the same type at the same address.  */
!       layout_nonempty_base_or_field (rli, decl, binfo, *v);
      }
    else
      {
--- 4045,4051 ----
        /* Try to place the field.  It may take more than one try if we
  	 have a hard time placing the field without putting two
  	 objects of the same type at the same address.  */
!       layout_nonempty_base_or_field (rli, decl, binfo, offsets);
      }
    else
      {
*************** build_base_field (rli, binfo, empty_p, b
*** 3942,3949 ****
        /* On some platforms (ARM), even empty classes will not be
  	 byte-aligned.  */
        eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
!       eoc = CEIL (eoc, DECL_ALIGN (decl)) * DECL_ALIGN (decl);
!       layout_empty_base (binfo, size_int (eoc), *v);
      }
  
    /* Check for inaccessible base classes.  If the same base class
--- 4054,4061 ----
        /* On some platforms (ARM), even empty classes will not be
  	 byte-aligned.  */
        eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
!       eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
!       layout_empty_base (binfo, size_int (eoc), offsets);
      }
  
    /* Check for inaccessible base classes.  If the same base class
*************** build_base_field (rli, binfo, empty_p, b
*** 3954,3986 ****
  		basetype, rli->t);
    
    /* Record the offsets of BINFO and its base subobjects.  */
!   record_base_offsets (binfo, v);
  }
  
! /* Layout all of the non-virtual base classes.  Returns a map from
!    offsets to types present at those offsets.  */
  
! static varray_type
! build_base_fields (rli, empty_p)
       record_layout_info rli;
       int *empty_p;
  {
    /* Chain to hold all the new FIELD_DECLs which stand in for base class
       subobjects.  */
    tree rec = rli->t;
    int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
    int i;
-   varray_type v;
    unsigned int base_align = 0;
  
-   /* Create the table mapping offsets to empty base classes.  */
-   VARRAY_TREE_INIT (v, 32, "v");
- 
    /* Under the new ABI, the primary base class is always allocated
       first.  */
    if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
      build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), 
! 		      empty_p, &base_align, &v);
  
    /* Now allocate the rest of the bases.  */
    for (i = 0; i < n_baseclasses; ++i)
--- 4066,4098 ----
  		basetype, rli->t);
    
    /* Record the offsets of BINFO and its base subobjects.  */
!   record_subobject_offsets (BINFO_TYPE (binfo), 
! 			    BINFO_OFFSET (binfo),
! 			    offsets, 
! 			    /*vbases_p=*/0);
  }
  
! /* Layout all of the non-virtual base classes.  Record empty
!    subobjects in OFFSETS.  */
  
! static void
! build_base_fields (rli, empty_p, offsets)
       record_layout_info rli;
       int *empty_p;
+      splay_tree offsets;
  {
    /* Chain to hold all the new FIELD_DECLs which stand in for base class
       subobjects.  */
    tree rec = rli->t;
    int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
    int i;
    unsigned int base_align = 0;
  
    /* Under the new ABI, the primary base class is always allocated
       first.  */
    if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
      build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), 
! 		      empty_p, &base_align, offsets);
  
    /* Now allocate the rest of the bases.  */
    for (i = 0; i < n_baseclasses; ++i)
*************** build_base_fields (rli, empty_p)
*** 4001,4010 ****
  	  && !BINFO_PRIMARY_MARKED_P (base_binfo))
  	continue;
  
!       build_base_field (rli, base_binfo, empty_p, &base_align, &v);
      }
- 
-   return v;
  }
  
  /* Go through the TYPE_METHODS of T issuing any appropriate
--- 4113,4120 ----
  	  && !BINFO_PRIMARY_MARKED_P (base_binfo))
  	continue;
  
!       build_base_field (rli, base_binfo, empty_p, &base_align, offsets);
      }
  }
  
  /* Go through the TYPE_METHODS of T issuing any appropriate
*************** dfs_set_offset_for_unshared_vbases (binf
*** 4573,4585 ****
  }
  
  /* Set BINFO_OFFSET for all of the virtual bases for T.  Update
!    TYPE_ALIGN and TYPE_SIZE for T.  BASE_OFFSETS is a varray mapping
!    offsets to the types at those offsets.  */
  
  static void
! layout_virtual_bases (t, base_offsets)
       tree t;
!      varray_type *base_offsets;
  {
    tree vbases;
    unsigned HOST_WIDE_INT dsize;
--- 4683,4695 ----
  }
  
  /* Set BINFO_OFFSET for all of the virtual bases for T.  Update
!    TYPE_ALIGN and TYPE_SIZE for T.  OFFSETS gives the location of
!    empty subobjects of T.  */
  
  static void
! layout_virtual_bases (t, offsets)
       tree t;
!      splay_tree offsets;
  {
    tree vbases;
    unsigned HOST_WIDE_INT dsize;
*************** layout_virtual_bases (t, base_offsets)
*** 4649,4655 ****
  	  if (flag_new_abi && is_empty_class (basetype))
  	    layout_empty_base (vbase,
  			       size_int (CEIL (dsize, BITS_PER_UNIT)),
! 			       *base_offsets);
  	  else
  	    {
  	      tree offset;
--- 4759,4765 ----
  	  if (flag_new_abi && is_empty_class (basetype))
  	    layout_empty_base (vbase,
  			       size_int (CEIL (dsize, BITS_PER_UNIT)),
! 			       offsets);
  	  else
  	    {
  	      tree offset;
*************** layout_virtual_bases (t, base_offsets)
*** 4669,4675 ****
  	    }
  
  	  /* Keep track of the offsets assigned to this virtual base.  */
! 	  record_base_offsets (vbase, base_offsets);
  	}
      }
  
--- 4779,4788 ----
  	    }
  
  	  /* Keep track of the offsets assigned to this virtual base.  */
! 	  record_subobject_offsets (BINFO_TYPE (vbase), 
! 				    BINFO_OFFSET (vbase),
! 				    offsets,
! 				    /*vbases_p=*/0);
  	}
      }
  
*************** end_of_class (t, include_virtuals_p)
*** 4744,4749 ****
--- 4857,4872 ----
    return result;
  }
  
+ /* Compare two INTEGER_CSTs K1 and K2.  */
+ 
+ static int
+ splay_tree_compare_integer_csts (k1, k2)
+      splay_tree_key k1;
+      splay_tree_key k2;
+ {
+   return tree_int_cst_compare ((tree) k1, (tree) k2);
+ }
+ 
  /* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T.  Calculate
     BINFO_OFFSETs for all of the base-classes.  Position the vtable
     pointer.  */
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4761,4768 ****
    tree field;
    tree vptr;
    record_layout_info rli;
-   varray_type v;
    unsigned HOST_WIDE_INT eoc;
  
    /* Keep track of the first non-static data member.  */
    non_static_data_members = TYPE_FIELDS (t);
--- 4884,4893 ----
    tree field;
    tree vptr;
    record_layout_info rli;
    unsigned HOST_WIDE_INT eoc;
+   /* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
+      types that appear at that offset.  */
+   splay_tree empty_base_offsets;
  
    /* Keep track of the first non-static data member.  */
    non_static_data_members = TYPE_FIELDS (t);
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4787,4793 ****
      }
  
    /* Build FIELD_DECLs for all of the non-virtual base-types.  */
!   v = build_base_fields (rli, empty_p);
    /* Add pointers to all of our virtual base-classes.  */
    TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
  			     TYPE_FIELDS (t));
--- 4912,4920 ----
      }
  
    /* Build FIELD_DECLs for all of the non-virtual base-types.  */
!   empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, 
! 				       NULL, NULL);
!   build_base_fields (rli, empty_p, empty_base_offsets);
    /* Add pointers to all of our virtual base-classes.  */
    TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
  			     TYPE_FIELDS (t));
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4800,4806 ****
    /* Layout the non-static data members.  */
    for (field = non_static_data_members; field; field = TREE_CHAIN (field))
      {
-       tree binfo;
        tree type;
        tree padding;
  
--- 4927,4932 ----
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4852,4861 ****
        else
  	padding = NULL_TREE;
  
!       /* Create a dummy BINFO corresponding to this field.  */
!       binfo = make_binfo (size_zero_node, type, NULL_TREE, NULL_TREE);
!       unshare_base_binfos (binfo);
!       layout_nonempty_base_or_field (rli, field, binfo, v);
  
        /* If we needed additional padding after this field, add it
  	 now.  */
--- 4978,4985 ----
        else
  	padding = NULL_TREE;
  
!       layout_nonempty_base_or_field (rli, field, NULL_TREE,
! 				     empty_base_offsets);
  
        /* If we needed additional padding after this field, add it
  	 now.  */
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4870,4876 ****
  	  DECL_SIZE (padding_field) = padding;
  	  DECL_ALIGN (padding_field) = 1;
  	  DECL_USER_ALIGN (padding_field) = 0;
! 	  layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, v);
  	}
      }
  
--- 4994,5002 ----
  	  DECL_SIZE (padding_field) = padding;
  	  DECL_ALIGN (padding_field) = 1;
  	  DECL_USER_ALIGN (padding_field) = 0;
! 	  layout_nonempty_base_or_field (rli, padding_field,
! 					 NULL_TREE, 
! 					 empty_base_offsets);
  	}
      }
  
*************** layout_class_type (t, empty_p, vfuns_p, 
*** 4956,4965 ****
       around.  We must get these done before we try to lay out the
       virtual function table.  As a side-effect, this will remove the
       base subobject fields.  */
!   layout_virtual_bases (t, &v);
  
    /* Clean up.  */
!   VARRAY_FREE (v);
  }
  
  /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
--- 5082,5091 ----
       around.  We must get these done before we try to lay out the
       virtual function table.  As a side-effect, this will remove the
       base subobject fields.  */
!   layout_virtual_bases (t, empty_base_offsets);
  
    /* Clean up.  */
!   splay_tree_delete (empty_base_offsets);
  }
  
  /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration

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