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: New ABI class layout



This patch should be the last major class-layout bit for the new ABI.
There's one little bit regarding bit-fields remaining.  However, for
the most part, this should be it, modulo bugs.  We'll be writing
test-cases over the next couple of days to check some of the details
of the ABI layout -- this code is still largely untested and so
probably doesn't yet work correctly.  The infrastructure is now in
place.

Using the new stor-layout.c APIs allows this code to be simpler: we no
longer have to stuff in FIELD_DECLs we don't want and then rip them
out later, for example.

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

2000-03-14  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h: Tweak documentation.
	* class.c (build_vbase_pointer_fields): Layout the fields, too.
	(avoid_overlap): Remove.
	(get_binfo_offset_as_int): New function.
	(dfs_serach_base_offsets): Likewise.
	(layout_nonempty_base_or_field): Likewise.
	(build_base_field): Layout fields here.  Avoid placing two objects
	of the same type at the same address, under the new ABI.
	(build_base_fields): Adjust accordingly.
	(create_vtable_ptr): Return the new field, but don't attach it to
	TYPE_FIELDS.
	(remove_base_field): Remove.
	(remove_base_fields): Remove.
	(layout_basetypes): Adjust accordingly.
	(layout_class_type): Call layout_field for each field, rather than
	just making a wholesale call to layout_type.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.268
diff -c -p -r1.268 class.c
*** class.c	2000/03/07 11:41:21	1.268
--- class.c	2000/03/15 00:14:31
*************** static void check_bitfield_decl PARAMS (
*** 116,132 ****
  static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
  static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
  				     int *));
! static int avoid_overlap PARAMS ((tree, tree, int *));
! static tree build_base_field PARAMS ((tree, tree, int *, int *, unsigned int *));
! static tree build_base_fields PARAMS ((tree, int *));
! static tree build_vbase_pointer_fields PARAMS ((tree, int *));
  static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
  					       int *));
  static void check_methods PARAMS ((tree));
  static void remove_zero_width_bit_fields PARAMS ((tree));
  static void check_bases PARAMS ((tree, int *, int *, int *));
  static void check_bases_and_members PARAMS ((tree, int *));
! static void create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
  static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
  static void fixup_pending_inline PARAMS ((struct pending_inline *));
  static void fixup_inline_methods PARAMS ((tree));
--- 116,132 ----
  static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
  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 *));
  static void check_methods PARAMS ((tree));
  static void remove_zero_width_bit_fields PARAMS ((tree));
  static void check_bases PARAMS ((tree, int *, int *, int *));
  static void check_bases_and_members PARAMS ((tree, int *));
! static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
  static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
  static void fixup_pending_inline PARAMS ((struct pending_inline *));
  static void fixup_inline_methods PARAMS ((tree));
*************** static tree dfs_propagate_binfo_offsets 
*** 135,142 ****
  static void propagate_binfo_offsets PARAMS ((tree, tree));
  static void layout_basetypes PARAMS ((tree));
  static void layout_virtual_bases PARAMS ((tree));
- static void remove_base_field PARAMS ((tree, tree, tree *));
- static void remove_base_fields PARAMS ((tree));
  static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
  static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
  static tree dfs_build_vbase_offset_vtbl_entries PARAMS ((tree, void *));
--- 135,140 ----
*************** static int make_new_vtable PARAMS ((tree
*** 155,160 ****
--- 153,161 ----
  extern void dump_class_hierarchy PARAMS ((tree, int));
  static tree build_vtable PARAMS ((tree, tree, tree));
  static void initialize_vtable PARAMS ((tree, tree));
+ static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
+ 						   tree, tree,
+ 						   varray_type));
  
  /* Variables shared between class.c and call.c.  */
  
*************** int n_inner_fields_searched = 0;
*** 175,186 ****
     FIELD_DECLS.  */
  
  static tree
! build_vbase_pointer_fields (rec, empty_p)
!      tree rec;
       int *empty_p;
  {
    /* Chain to hold all the new FIELD_DECLs which point at virtual
       base classes.  */
    tree vbase_decls = NULL_TREE;
    tree binfos = TYPE_BINFO_BASETYPES (rec);
    int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
--- 176,188 ----
     FIELD_DECLS.  */
  
  static tree
! build_vbase_pointer_fields (rli, empty_p)
!      record_layout_info rli;
       int *empty_p;
  {
    /* Chain to hold all the new FIELD_DECLs which point at virtual
       base classes.  */
+   tree rec = rli->t;
    tree vbase_decls = NULL_TREE;
    tree binfos = TYPE_BINFO_BASETYPES (rec);
    int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
*************** build_vbase_pointer_fields (rec, empty_p
*** 235,240 ****
--- 237,243 ----
  					    empty_p);
  	  BINFO_VPTR_FIELD (base_binfo) = decl;
  	  TREE_CHAIN (decl) = vbase_decls;
+ 	  layout_field (rli, decl);
  	  vbase_decls = decl;
  	  *empty_p = 0;
  
*************** build_vtbl_or_vbase_field (name, assembl
*** 4091,4136 ****
    return field;
  }
  
! /* If the empty base field in DECL overlaps with a base of the same type in
!    NEWDECL, which is either another base field or the first data field of
!    the class, pad the base just before NEWDECL and return 1.  Otherwise,
!    return 0.  */
  
! static int
! avoid_overlap (decl, newdecl, empty_p)
!      tree decl, newdecl;
!      int *empty_p;
  {
!   tree field;
  
!   if (newdecl == NULL_TREE
!       || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
!     return 0;
  
!   for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
!        field = TREE_CHAIN (field))
!     ;
  
!   DECL_SIZE (field) = bitsize_int (1);
!   DECL_SIZE_UNIT (field) = 0;
!   /* The containing class cannot be empty; this field takes up space.  */
!   *empty_p = 0;
  
!   return 1;
  }
  
! /* Build a FIELD_DECL for the base given by BINFO in T.  If the new
!    object is non-empty, clear *EMPTY_P.  Otherwise, set *SAW_EMPTY_P.
!    *BASE_ALIGN is a running maximum of the alignments of any base
!    class.  */
  
  static tree
! build_base_field (t, binfo, empty_p, saw_empty_p, base_align)
!      tree t;
       tree binfo;
       int *empty_p;
-      int *saw_empty_p;
       unsigned int *base_align;
  {
    tree basetype = BINFO_TYPE (binfo);
    tree decl;
--- 4094,4248 ----
    return field;
  }
  
! /* Return the BINFO_OFFSET for BINFO as a native integer, not an
!    INTEGER_CST.  */
  
! static unsigned HOST_WIDE_INT
! get_binfo_offset_as_int (binfo)
!      tree binfo;
  {
!   tree offset;
  
!   offset = BINFO_OFFSET (binfo);
!   my_friendly_assert (TREE_CODE (offset) == INTEGER_CST, 20000313);
!   my_friendly_assert (TREE_INT_CST_HIGH (offset) == 0, 20000313);
  
!   return (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (offset);
! }
  
! /* 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 = get_binfo_offset_as_int (binfo);
! 
!   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;
  }
  
! /* 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;
+       unsigned HOST_WIDE_INT offset;
+       tree t;
+ 
+       /* Find the offset for this BINFO.  */
+       offset = get_binfo_offset_as_int (binfo);
+       /* 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;
+ }
+ 
+ /* 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.  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;
+ 
+       /* Layout this field.  */
+       layout_field (rli, decl);
+       
+       /* Now that we know where it wil be placed, update its
+ 	 BINFO_OFFSET.  */
+       offset = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (decl)),
+ 			       BITS_PER_UNIT));
+       propagate_binfo_offsets (binfo, 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.
+ 	 For example:
+ 	 
+ 	 struct S {};
+ 	 struct T : public S { int i; };
+ 	 struct U : public S, public T {};
+ 	 
+ 	 Here, we put S at offset zero in U.  Then, we can't put T at
+ 	 offset zero -- its S component would be at the same address
+ 	 as the S we already allocated.  So, we have to skip ahead.
+ 	 Since all data members, including those whose type is an
+ 	 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 && dfs_walk (binfo,
+ 				    dfs_search_base_offsets,
+ 				    dfs_skip_vbases,
+ 				    v))
+ 	{
+ 	  /* Undo the propogate_binfo_offsets call.  */
+ 	  offset = convert (sizetype,
+ 			    size_diffop (size_zero_node, offset));
+ 	  propagate_binfo_offsets (binfo, 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->const_size -= TREE_INT_CST_LOW (DECL_SIZE (decl));
+ 	  /* Bump up by th alignment required for the type, without
+ 	     virtual base classes.  */
+ 	  rli->const_size += CLASSTYPE_ALIGN (BINFO_TYPE (binfo));
+ 	}
+       else
+ 	/* There was no conflict.  We're done laying out this field.  */
+ 	break;
+     }
+ }
+ 
+ /* 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;
*************** build_base_field (t, binfo, empty_p, saw
*** 4138,4162 ****
    if (TYPE_SIZE (basetype) == 0)
      /* This error is now reported in xref_tag, thus giving better
         location information.  */
!     return NULL_TREE;
    
    decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
    DECL_ARTIFICIAL (decl) = 1;
!   DECL_FIELD_CONTEXT (decl) = t;
    DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
    DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
    DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
    
-   if (flag_new_abi && integer_zerop (DECL_SIZE (decl)))
-     {
-       *saw_empty_p = 1;
-       return decl;
-     }
- 
-   /* The containing class is non-empty because it has a non-empty base
-      class.  */
-   *empty_p = 0;
-       
    if (! flag_new_abi)
      {
        /* Brain damage for backwards compatibility.  For no good
--- 4250,4264 ----
    if (TYPE_SIZE (basetype) == 0)
      /* This error is now reported in xref_tag, thus giving better
         location information.  */
!     return;
    
    decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
    DECL_ARTIFICIAL (decl) = 1;
!   DECL_FIELD_CONTEXT (decl) = rli->t;
    DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
    DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
    DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
    
    if (! flag_new_abi)
      {
        /* Brain damage for backwards compatibility.  For no good
*************** build_base_field (t, binfo, empty_p, saw
*** 4174,4213 ****
  			 (int) *base_align / BITS_PER_UNIT));
      }
  
!   return decl;
  }
  
! /* Returns a list of fields to stand in for the base class subobjects
!    of REC.  These fields are later removed by layout_basetypes.  */
  
! static tree
! build_base_fields (rec, empty_p)
!      tree rec;
       int *empty_p;
  {
    /* Chain to hold all the new FIELD_DECLs which stand in for base class
       subobjects.  */
!   tree base_decls = NULL_TREE;
    int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
!   tree decl, nextdecl;
!   int i, saw_empty = 0;
    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))
!     {
!       tree primary_base;
  
-       primary_base = CLASSTYPE_PRIMARY_BINFO (rec);
-       base_decls = chainon (build_base_field (rec, 
- 					      primary_base,
- 					      empty_p,
- 					      &saw_empty,
- 					      &base_align),
- 			    base_decls);
-     }
- 
    /* Now allocate the rest of the bases.  */
    for (i = 0; i < n_baseclasses; ++i)
      {
--- 4276,4360 ----
  			 (int) *base_align / BITS_PER_UNIT));
      }
  
!   if (!integer_zerop (DECL_SIZE (decl)))
!     {
!       /* The containing class is non-empty because it has a non-empty
! 	 base class.  */
!       *empty_p = 0;
! 
!       /* 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
!     {
!       /* This code assumes that zero-sized classes have one-byte
! 	 alignment.  There might someday be a system where that's not
! 	 true.  */
!       my_friendly_assert (DECL_ALIGN (basetype) == BITS_PER_UNIT, 
! 			  20000314);
! 
!       /* This is an empty base class.  We first try to put it at
! 	 offset zero.  */
!       if (dfs_walk (binfo, dfs_search_base_offsets, dfs_skip_vbases, *v))
! 	{
! 	  /* That didn't work.  Now, we move forward from the next
! 	     available spot in the class.  */
! 	  propagate_binfo_offsets (binfo, size_int (rli->const_size));
! 	  while (1) 
! 	    {
! 	      if (!dfs_walk (binfo, dfs_search_base_offsets, 
! 			     dfs_skip_vbases, *v))
! 		/* We finally found a spot where there's no overlap.  */
! 		break;
! 
! 	      /* There's overlap here, too.  Bump along to the next
! 		 spot.  */
! 	      propagate_binfo_offsets (binfo, size_one_node);
! 	    }
! 	}
!     }
! 
!   /* Check for inaccessible base classes.  If the same base class
!      appears more than once in the hierarchy, but isn't virtual, then
!      it's ambiguous.  */
!   if (get_base_distance (basetype, rli->t, 0, NULL) == -2)
!     cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
! 		basetype, rli->t);
!   
!   /* Record the offsets of BINFO and its base subobjects.  */
!   dfs_walk (binfo,
! 	    dfs_record_base_offsets,
! 	    dfs_skip_vbases,
! 	    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)
      {
*************** build_base_fields (rec, empty_p)
*** 4227,4270 ****
  	  && !BINFO_PRIMARY_MARKED_P (base_binfo))
  	continue;
  
!       base_decls = chainon (build_base_field (rec, base_binfo,
! 					      empty_p,
! 					      &saw_empty,
! 					      &base_align),
! 			    base_decls);
      }
  
!   /* Reverse the list of fields so we allocate the bases in the proper
!      order.  */
!   base_decls = nreverse (base_decls);
! 
!   /* In the presence of empty base classes, we run the risk of allocating
!      two objects of the same class on top of one another.  Avoid that.  */
!   if (flag_new_abi && saw_empty)
!     for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
!       {
! 	if (integer_zerop (DECL_SIZE (decl)))
! 	  {
! 	    /* First step through the following bases until we find
! 	       an overlap or a non-empty base.  */
! 	    for (nextdecl = TREE_CHAIN (decl); nextdecl;
! 		 nextdecl = TREE_CHAIN (nextdecl))
! 	      if (avoid_overlap (decl, nextdecl, empty_p)
! 		  || ! integer_zerop (DECL_SIZE (nextdecl)))
! 		goto nextbase;
! 
! 	    /* If we're still looking, also check against the first
! 	       field.  */
! 	    for (nextdecl = TYPE_FIELDS (rec);
! 		 nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
! 		 nextdecl = TREE_CHAIN (nextdecl))
! 	      /* keep looking */;
! 	    avoid_overlap (decl, nextdecl, empty_p);
! 	  }
!       nextbase:;
!       }
! 
!   return base_decls;
  }
  
  /* Go through the TYPE_METHODS of T issuing any appropriate
--- 4374,4383 ----
  	  && !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
*************** check_bases_and_members (t, empty_p)
*** 4438,4447 ****
  }
  
  /* If T needs a pointer to its virtual function table, set TYPE_VFIELD
!    accordingly, and, if necessary, add the TYPE_VFIELD to the
!    TYPE_FIELDS list.  */
  
! static void
  create_vtable_ptr (t, empty_p, has_virtual_p, 
  		   new_virtuals_p, overridden_virtuals_p)
       tree t;
--- 4551,4562 ----
  }
  
  /* If T needs a pointer to its virtual function table, set TYPE_VFIELD
!    accordingly.  If a new vfield was created (because T doesn't have a
!    primary base class), then the newly created field is returned.  It
!    is not added to the TYPE_FIELDS list; it is the callers
!    responsibility to do that.  */
  
! static tree
  create_vtable_ptr (t, empty_p, has_virtual_p, 
  		   new_virtuals_p, overridden_virtuals_p)
       tree t;
*************** create_vtable_ptr (t, empty_p, has_virtu
*** 4496,4524 ****
  				     t,
  				     empty_p);
  
!       /* Add the new field to the list of fields in this class.  */
!       if (!flag_new_abi)
! 	/* In the old ABI, the vtable pointer goes at the end of the
! 	   class.  */
! 	TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t));
!       else
! 	{
! 	  /* But in the new ABI, the vtable pointer is the first thing
! 	     in the class.  */
! 	  TYPE_FIELDS (t) = chainon (TYPE_VFIELD (t), TYPE_FIELDS (t));
! 	  /* If there were any baseclasses, they can't possibly be at
! 	     offset zero any more, because that's where the vtable
! 	     pointer is.  So, converting to a base class is going to
! 	     take work.  */
! 	  if (CLASSTYPE_N_BASECLASSES (t))
! 	    TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
! 	}
  
!       /* We can't yet add this new field to the list of all virtual
! 	 function table pointers in this class.  The
! 	 modify_all_vtables function depends on this not being done.
! 	 So, it is done later, in finish_struct_1.  */
      }
  }
  
  /* Fixup the inline function given by INFO now that the class is
--- 4611,4627 ----
  				     t,
  				     empty_p);
  
!       if (flag_new_abi && CLASSTYPE_N_BASECLASSES (t))
! 	/* If there were any baseclasses, they can't possibly be at
! 	   offset zero any more, because that's where the vtable
! 	   pointer is.  So, converting to a base class is going to
! 	   take work.  */
! 	TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
  
!       return TYPE_VFIELD (t);
      }
+ 
+   return NULL_TREE;
  }
  
  /* Fixup the inline function given by INFO now that the class is
*************** propagate_binfo_offsets (binfo, offset)
*** 4613,4697 ****
  	    NULL);
  }
  
- /* Remove *FIELD (which corresponds to the base given by BINFO) from
-    the field list for T.  */
- 
- static void
- remove_base_field (t, binfo, field)
-      tree t;
-      tree binfo;
-      tree *field;
- {
-   tree basetype = BINFO_TYPE (binfo);
-   tree offset;
- 
-   my_friendly_assert (TREE_TYPE (*field) == basetype, 23897);
- 
-   if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
-     cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
- 		basetype, t);
- 
-   offset
-     = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (*field)),
- 		      BITS_PER_UNIT));
-   propagate_binfo_offsets (binfo, offset);
- 
-   /* Remove this field.  */
-   *field = TREE_CHAIN (*field);
- }
- 
- /* Remove the FIELD_DECLs created for T's base classes in
-    build_base_fields.  Simultaneously, update BINFO_OFFSET for all the
-    bases, except for non-primary virtual baseclasses.  */
- 
- static void
- remove_base_fields (t)
-      tree t;
- {
-   int i;
-   tree *field;
- 
-   /* Now propagate offset information throughout the lattice.
-      Simultaneously, remove the temporary FIELD_DECLS we created in
-      build_base_fields to refer to base types.  */
-   field = &TYPE_FIELDS (t);
-   if (TYPE_VFIELD (t) == *field)
-     {
-       /* If this class did not have a primary base, we create a
- 	 virtual function table pointer.  It will be the first thing
- 	 in the class, under the new ABI.  Skip it; the base fields
- 	 will follow it.  */
-       my_friendly_assert (flag_new_abi 
- 			  && !CLASSTYPE_HAS_PRIMARY_BASE_P (t),
- 			  19991218);
-       field = &TREE_CHAIN (*field);
-     }
- 
-   /* Under the new ABI, the primary base is always allocated first.  */
-   if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-     remove_base_field (t, CLASSTYPE_PRIMARY_BINFO (t), field);
- 
-   /* Now remove the rest of the bases.  */
-   for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
-     {
-       tree binfo;
- 
-       /* Under the new ABI, we've already removed the primary base
- 	 above.  */
-       if (flag_new_abi && i == CLASSTYPE_VFIELD_PARENT (t))
- 	continue;
- 
-       binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
- 
-       /* We treat a primary virtual base class just like an ordinary base
- 	 class.  But, non-primary virtual bases are laid out later.  */
-       if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
- 	continue;
- 
-       remove_base_field (t, binfo, field);
-     }
- }
- 
  /* Called via dfs_walk from layout_virtual bases.  */
  
  static tree
--- 4716,4721 ----
*************** layout_basetypes (rec)
*** 4819,4835 ****
  {
    tree vbase_types;
  
  #ifdef STRUCTURE_SIZE_BOUNDARY
    /* Packed structures don't need to have minimum size.  */
    if (! TYPE_PACKED (rec))
      TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), STRUCTURE_SIZE_BOUNDARY);
  #endif
  
-   /* Remove the FIELD_DECLs we created for baseclasses in
-      build_base_fields.  Simultaneously, update the BINFO_OFFSETs for
-      everything in the hierarcy except non-primary virtual bases.  */
-   remove_base_fields (rec);
- 
    /* Allocate the virtual base classes.  */
    layout_virtual_bases (rec);
  
--- 4843,4857 ----
  {
    tree vbase_types;
  
+   if (CLASSTYPE_N_BASECLASSES (rec) == 0)
+     return;
+ 
  #ifdef STRUCTURE_SIZE_BOUNDARY
    /* Packed structures don't need to have minimum size.  */
    if (! TYPE_PACKED (rec))
      TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), STRUCTURE_SIZE_BOUNDARY);
  #endif
  
    /* Allocate the virtual base classes.  */
    layout_virtual_bases (rec);
  
*************** layout_class_type (t, empty_p, has_virtu
*** 4861,4924 ****
       tree *new_virtuals_p;
       tree *overridden_virtuals_p;
  {
!   tree padding = NULL_TREE;
  
    /* If possible, we reuse the virtual function table pointer from one
       of our base classes.  */
    determine_primary_base (t, has_virtual_p);
  
    /* Add pointers to all of our virtual base-classes.  */
!   TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, empty_p),
  			     TYPE_FIELDS (t));
    /* Build FIELD_DECLs for all of the non-virtual base-types.  */
!   TYPE_FIELDS (t) = chainon (build_base_fields (t, empty_p), 
! 			     TYPE_FIELDS (t));
! 
!   /* Create a pointer to our virtual function table.  */
!   create_vtable_ptr (t, empty_p, has_virtual_p,
! 		     new_virtuals_p, overridden_virtuals_p);
  
    /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS.  Thus,
       we have to save this before we start modifying
       TYPE_NONCOPIED_PARTS.  */
    fixup_inline_methods (t);
  
    /* We make all structures have at least one element, so that they
!      have non-zero size.  The field that we add here is fake, in the
!      sense that, for example, we don't want people to be able to
!      initialize it later.  So, we add it just long enough to let the
!      back-end lay out the type, and then remove it.  In the new ABI,
!      the class may be empty even if it has basetypes.  Therefore, we
!      add the fake field at the end of the fields list; if there are
!      already FIELD_DECLs on the list, their offsets will not be
!      disturbed.  */
    if (*empty_p)
      {
        padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
!       TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), padding);
        TYPE_NONCOPIED_PARTS (t) 
  	= tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t));
        TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
      }
  
    /* Let the back-end lay out the type. Note that at this point we
       have only included non-virtual base-classes; we will lay out the
       virtual base classes later.  So, the TYPE_SIZE/TYPE_ALIGN after
       this call are not necessarily correct; they are just the size and
       alignment when no virtual base clases are used.  */
!   layout_type (t);
! 
!   /* If we added an extra field to make this class non-empty, remove
!      it now.  */
!   if (*empty_p)
!     {
!       tree *declp;
! 
!       declp = &TYPE_FIELDS (t);
!       while (*declp != padding)
! 	declp = &TREE_CHAIN (*declp);
!       *declp = TREE_CHAIN (*declp);
!     }
  
    /* Delete all zero-width bit-fields from the list of fields.  Now
       that the type is laid out they are no longer important.  */
--- 4883,4999 ----
       tree *new_virtuals_p;
       tree *overridden_virtuals_p;
  {
!   tree non_static_data_members;
!   tree field;
!   tree vptr;
!   record_layout_info rli;
!   varray_type v;
!   int i;
! 
!   /* Keep track of the first non-static data member.  */
!   non_static_data_members = TYPE_FIELDS (t);
  
+   /* Initialize the layout information.  */
+   rli = new_record_layout_info (t);
+ 
    /* If possible, we reuse the virtual function table pointer from one
       of our base classes.  */
    determine_primary_base (t, has_virtual_p);
  
+   /* Create a pointer to our virtual function table.  */
+   vptr = create_vtable_ptr (t, empty_p, has_virtual_p,
+ 			    new_virtuals_p, overridden_virtuals_p);
+ 
+   /* Under the new ABI, the vptr is always the first thing in the
+      class.  */
+   if (flag_new_abi && vptr)
+     {
+       TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+       layout_field (rli, vptr);
+     }
+ 
    /* Add pointers to all of our virtual base-classes.  */
!   TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
  			     TYPE_FIELDS (t));
    /* Build FIELD_DECLs for all of the non-virtual base-types.  */
!   v = build_base_fields (rli, empty_p);
  
    /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS.  Thus,
       we have to save this before we start modifying
       TYPE_NONCOPIED_PARTS.  */
    fixup_inline_methods (t);
  
+   /* Layout the non-static data members.  */
+   for (field = non_static_data_members; 
+        field; 
+        field = TREE_CHAIN (field))
+     {
+       tree binfo;
+ 
+       /* We still pass things that aren't non-static data members to
+ 	 the back-end, in case it wants to do something with them.  */
+       if (TREE_CODE (field) != FIELD_DECL)
+ 	{
+ 	  layout_field (rli, field);
+ 	  continue;
+ 	}
+ 
+       /* Create a dummy BINFO corresponding to this field.  */
+       binfo = make_binfo (size_zero_node, TREE_TYPE (field),
+ 			  NULL_TREE, NULL_TREE);
+       unshare_base_binfos (binfo);
+       layout_nonempty_base_or_field (rli, field, binfo, v);
+     }
+ 
+   /* Clean up.  */
+   VARRAY_FREE (v);
+   
+   /* It might be the case that we grew the class to allocate a
+      zero-sized base class.  That won't be reflected in RLI, yet,
+      because we are willing to overlay multiple bases at the same
+      offset.  However, now we need to make sure that RLI is big enough
+      to reflect the entire class.  */
+   for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+     {
+       tree base_binfo;
+       unsigned HOST_WIDE_INT offset;
+ 
+       base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
+       offset = get_binfo_offset_as_int (base_binfo);
+       if (offset * BITS_PER_UNIT > rli->const_size)
+ 	rli->const_size = (offset + 1) * BITS_PER_UNIT;
+     }
+ 
    /* We make all structures have at least one element, so that they
!      have non-zero size.  In the new ABI, the class may be empty even
!      if it has basetypes.  Therefore, we add the fake field after all
!      the other fields; if there are already FIELD_DECLs on the list,
!      their offsets will not be disturbed.  */
    if (*empty_p)
      {
+       tree padding;
+ 
        padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
!       layout_field (rli, padding);
        TYPE_NONCOPIED_PARTS (t) 
  	= tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t));
        TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
      }
  
+   /* Under the old ABI, the vptr comes at the very end of the 
+      class.   */
+   if (!flag_new_abi && vptr)
+     {
+       layout_field (rli, vptr);
+       TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vptr);
+     }
+   
    /* Let the back-end lay out the type. Note that at this point we
       have only included non-virtual base-classes; we will lay out the
       virtual base classes later.  So, the TYPE_SIZE/TYPE_ALIGN after
       this call are not necessarily correct; they are just the size and
       alignment when no virtual base clases are used.  */
!   finish_record_layout (rli);
  
    /* Delete all zero-width bit-fields from the list of fields.  Now
       that the type is laid out they are no longer important.  */
*************** layout_class_type (t, empty_p, has_virtu
*** 4952,4961 ****
  
    /* Now fix up any virtual base class types that we left lying
       around.  We must get these done before we try to lay out the
!      virtual function table.  */
!   if (CLASSTYPE_N_BASECLASSES (t))
!     /* layout_basetypes will remove the base subobject fields.  */
!     layout_basetypes (t);
  }
       
  /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
--- 5027,5035 ----
  
    /* Now fix up any virtual base class types that we left lying
       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_basetypes (t);
  }
       
  /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.417
diff -c -p -r1.417 cp-tree.h
*** cp-tree.h	2000/03/13 04:54:39	1.417
--- cp-tree.h	2000/03/15 00:14:35
*************** struct lang_type
*** 1578,1585 ****
     which uses this must define what exactly this slot is used for.  */
  #define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot)
  
! /* These are the size, mode and alignment of the type without its
!    virtual base classes, for when we use this type as a base itself.  */
  #define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
  #define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->size_unit)
  #define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)
--- 1578,1585 ----
     which uses this must define what exactly this slot is used for.  */
  #define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot)
  
! /* These are the size and alignment of the type without its virtual
!    base classes, for when we use this type as a base itself.  */
  #define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
  #define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->size_unit)
  #define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)

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