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: use vbase offsets in vtables



This patch completes the support for using vbase offsets in vtables,
rather than storing virtual base pointer fields in the objects
themselves.  That makes objects that use lots of virtual bases a good
bit smaller, and makes their initialization faster.

This patch actually exacerbates the infamous vtable-thunks bug --
althoug the new ABI will contain a fix that handles this correctly.
But, for now, it's now the case that a derived class trying to access
a virtual base during construction may not really be accessing the
right storage.  (Before, virtual function calls didn't work; now, even
getting a data member out of the class may not work.)

This patch also includes a minor tweak to our RTTI implementation to
deal with the new handling of virtual bases -- but not in an ABI
compliant way.  Nathan Sidwell will be contributing a complete
implementation of the new ABI RTTI handling code in the near future.

Of course, all of this affects only the new ABI; the default ABI is
unaffected.

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

2000-01-16  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (flag_new_abi): Move.
	(flag_use_cxa_atexit): Likewise.
	(flag_honor_std): Likewise.
	(flag_rtti): Likewise.
	(vbase_offsets_in_vtable_p): Define.
	(vptrs_present_everywhere_p): Likewise.
	(TYPE_CONTAINS_VPTR_P): Likewise.
	(dfs_walk_real): Declare.
	* class.c (build_vbase_pointer_fields): Check
	vbase_offsets_in_vtable_p.
	(dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in
	BINFO_VPTR_FIELD.
	(build_vbase_offset_vtbl_entries): Simplify.
	(build_vbase_offset_vtbl_entries): Adjust.
	(build_vbase_pointer): Add ability to look up vbase offsets in
	vtable. 
	(start_vtable): New function.
	(add_virtual_function): Use it.
	(determine_primary_base): Use TYPE_CONTAINS_VPTR_P.
	(num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p.
	(build_vtbl_initializer): Take the type of the complete object as
	input.  Use it to correctly calculate vbase offsets.
	(dfs_finish_vtbls): Pass the complete type to
	build_vtbl_initializer.
	(check_bases_and_members): Use TYPE_CONTAINS_VPTR_P.
	(create_vtable_ptr): Create a vtable even if there are no
	new virtual functions, under the new ABI.
	(finish_struct_1): Likewise.
	(get_vfield_name): Use TYPE_CONTAINS_VPTR_P.
	* decl.c (exapnd_static_init): Remove call to
	preserve_initializer.
	* decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in
	vtables.
	* init.c (initialize_vtbl_ptrs): Initialize them in pre-order.
	(expand_virtual_init): Use vbase_offsets_in_vtable_p.
	(construct_virtual_bases): Don't initialize virtual base pointers
	under the new ABI.
	(build_aggr_init): Clean up comment.
	(expand_aggr_init_1): Likewise.
	* rtti.c (expand_class_desc): Store the virtual function table
	index where the vbase offset lives in the offset field.
	* search.c (dfs_walk_real): Make it global.
	(dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P.
	* tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD.
	
	* tinfo.h (USItype): Make it signed under the new ABI.
	* tinfo.cc (convert_to_base): New function.  Encapsulate base
	conversion logic here.
	(__class_type_info::do_upcast): Use it.
	(__class_type_info::do_dyncast): Likewise.
	(__class_type_info::do_find_public_subobj): Likewise.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.234
diff -c -p -r1.234 class.c
*** class.c	2000/01/16 17:38:06	1.234
--- class.c	2000/01/17 03:40:15
*************** static tree resolve_address_of_overloade
*** 115,121 ****
  							  int, tree));
  static void build_vtable_entry_ref PROTO((tree, tree, tree));
  static tree build_vtable_entry_for_fn PROTO((tree, tree));
! static tree build_vtbl_initializer PROTO((tree));
  static int count_fields PROTO((tree));
  static int add_fields_to_vec PROTO((tree, tree, int));
  static void check_bitfield_decl PROTO((tree));
--- 115,121 ----
  							  int, tree));
  static void build_vtable_entry_ref PROTO((tree, tree, tree));
  static tree build_vtable_entry_for_fn PROTO((tree, tree));
! static tree build_vtbl_initializer PROTO((tree, tree));
  static int count_fields PROTO((tree));
  static int add_fields_to_vec PROTO((tree, tree, int));
  static void check_bitfield_decl PROTO((tree));
*************** static void remove_base_fields PROTO((tr
*** 145,151 ****
  static tree dfs_set_offset_for_shared_vbases PROTO((tree, void *));
  static tree dfs_set_offset_for_unshared_vbases PROTO((tree, void *));
  static tree dfs_build_vbase_offset_vtbl_entries PROTO((tree, void *));
! static tree build_vbase_offset_vtbl_entries PROTO((tree));
  
  /* Variables shared between class.c and call.c.  */
  
--- 145,152 ----
  static tree dfs_set_offset_for_shared_vbases PROTO((tree, void *));
  static tree dfs_set_offset_for_unshared_vbases PROTO((tree, void *));
  static tree dfs_build_vbase_offset_vtbl_entries PROTO((tree, void *));
! static tree build_vbase_offset_vtbl_entries PROTO((tree, tree));
! static void start_vtable PROTO((tree, int *));
  
  /* Variables shared between class.c and call.c.  */
  
*************** build_vbase_pointer_fields (rec, empty_p
*** 178,186 ****
    tree decl;
    int i;
  
!   /* Handle basetypes almost like fields, but record their
!      offsets differently.  */
  
    for (i = 0; i < n_baseclasses; i++)
      {
        register tree base_binfo = TREE_VEC_ELT (binfos, i);
--- 179,190 ----
    tree decl;
    int i;
  
!   /* Under the new ABI, there are no vbase pointers in the object.
!      Instead, the offsets are stored in the vtable.  */
!   if (vbase_offsets_in_vtable_p ())
!     return NULL_TREE;
  
+   /* Loop over the baseclasses, adding vbase pointers as needed.  */
    for (i = 0; i < n_baseclasses; i++)
      {
        register tree base_binfo = TREE_VEC_ELT (binfos, i);
*************** dfs_build_vbase_offset_vtbl_entries (bin
*** 251,260 ****
    else if (TREE_VIA_VIRTUAL (binfo))
      {
        tree init;
  
        init = BINFO_OFFSET (binfo);
!       init = build1 (NOP_EXPR, vtable_entry_type, init);
!       TREE_VALUE (list) = tree_cons (NULL_TREE, init, TREE_VALUE (list));
      }
  
    SET_BINFO_VTABLE_PATH_MARKED (binfo);
--- 255,281 ----
    else if (TREE_VIA_VIRTUAL (binfo))
      {
        tree init;
+       tree vbase;
+ 
+       /* Remember the index to the vbase offset for this virtual
+ 	 base.  */
+       vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list));
+       if (!TREE_VALUE (list))
+ 	BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
+       else
+ 	{
+ 	  BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
+ 	  BINFO_VPTR_FIELD (vbase) = ssize_binop (MINUS_EXPR,
+ 						  BINFO_VPTR_FIELD (vbase),
+ 						  integer_one_node);
+ 	}
  
+       /* And record the offset at which this virtual base lies in the
+ 	 vtable.  */
        init = BINFO_OFFSET (binfo);
!       TREE_VALUE (list) = tree_cons (BINFO_VPTR_FIELD (vbase),
! 				     init, 
! 				     TREE_VALUE (list));
      }
  
    SET_BINFO_VTABLE_PATH_MARKED (binfo);
*************** dfs_build_vbase_offset_vtbl_entries (bin
*** 262,330 ****
    return NULL_TREE;
  }
  
! /* Returns the initializers for the vbase offset entries in the
!    vtable, in reverse order.  */
  
  static tree
! build_vbase_offset_vtbl_entries (binfo)
       tree binfo;
  {
-   tree type;
    tree inits;
    tree init;
  
    /* Under the old ABI, pointers to virtual bases are stored in each
       object.  */
!   if (!flag_new_abi)
      return NULL_TREE;
  
    /* If there are no virtual baseclasses, then there is nothing to
       do.  */
!   type = BINFO_TYPE (binfo);
!   if (!TYPE_USES_VIRTUAL_BASECLASSES (type))
      return NULL_TREE;
  
    inits = NULL_TREE;
  
!   /* Under the new ABI, the vtable contains offsets to all virtual
!      bases.  The ABI specifies different layouts depending on whether
!      or not *all* of the bases of this type are virtual.  */
!   if (CLASSTYPE_N_BASECLASSES (type) 
!       == list_length (CLASSTYPE_VBASECLASSES (type)))
!     {
!       /* In this case, the offsets are allocated from right to left of
! 	 the declaration order in which the virtual bases appear.  */
!       int i;
! 
!       for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
! 	{
! 	  tree vbase = BINFO_BASETYPE (binfo, i);
! 	  init = BINFO_OFFSET (vbase);
! 	  init = build1 (NOP_EXPR, vtable_entry_type, init);
! 	  inits = tree_cons (NULL_TREE, init, inits);
! 	}
!     }
!   else
!     {
!       tree list;
! 
!       /* While in this case, the offsets are allocated in the reverse
! 	 order of a depth-first left-to-right traversal of the
! 	 hierarchy.  We use BINFO_VTABLE_PATH_MARKED because we are
! 	 ourselves during a dfs_walk, and so BINFO_MARKED is already
! 	 in use.  */
!       list = build_tree_list (type, NULL_TREE);
!       TREE_TYPE (list) = binfo;
!       dfs_walk (binfo,
! 		dfs_build_vbase_offset_vtbl_entries,
! 		dfs_vtable_path_unmarked_real_bases_queue_p,
! 		list);
!       dfs_walk (binfo,
! 		dfs_vtable_path_unmark,
! 		dfs_vtable_path_marked_real_bases_queue_p,
! 		list);
!       inits = nreverse (TREE_VALUE (list));
!     }
  
    /* We've now got offsets in the right oder.  However, the offsets
       we've stored are offsets from the beginning of the complete
--- 283,328 ----
    return NULL_TREE;
  }
  
! /* Returns the initializers for the vbase offset entries in the vtable
!    for BINFO (which is part of the class hierarchy dominated by T), in
!    reverse order.  */
  
  static tree
! build_vbase_offset_vtbl_entries (binfo, t)
       tree binfo;
+      tree t;
  {
    tree inits;
    tree init;
+   tree list;
  
    /* Under the old ABI, pointers to virtual bases are stored in each
       object.  */
!   if (!vbase_offsets_in_vtable_p ())
      return NULL_TREE;
  
    /* If there are no virtual baseclasses, then there is nothing to
       do.  */
!   if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
      return NULL_TREE;
  
    inits = NULL_TREE;
  
!   /* The offsets are allocated in the reverse order of a
!      depth-first left-to-right traversal of the hierarchy.  We use
!      BINFO_VTABLE_PATH_MARKED because we are ourselves during a
!      dfs_walk, and so BINFO_MARKED is already in use.  */
!   list = build_tree_list (t, NULL_TREE);
!   TREE_TYPE (list) = binfo;
!   dfs_walk (binfo,
! 	    dfs_build_vbase_offset_vtbl_entries,
! 	    dfs_vtable_path_unmarked_real_bases_queue_p,
! 	    list);
!   dfs_walk (binfo,
! 	    dfs_vtable_path_unmark,
! 	    dfs_vtable_path_marked_real_bases_queue_p,
! 	    list);
!   inits = nreverse (TREE_VALUE (list));
  
    /* We've now got offsets in the right oder.  However, the offsets
       we've stored are offsets from the beginning of the complete
*************** build_vbase_offset_vtbl_entries (binfo)
*** 334,342 ****
        tree exp = TREE_VALUE (init);
  
        exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo));
!       exp = build1 (NOP_EXPR, vtable_entry_type, TREE_VALUE (init));
        exp = fold (exp);
        TREE_CONSTANT (exp) = 1;
        TREE_VALUE (init) = exp;
      }
  
--- 332,344 ----
        tree exp = TREE_VALUE (init);
  
        exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo));
!       exp = build1 (NOP_EXPR, vtable_entry_type, exp);
        exp = fold (exp);
        TREE_CONSTANT (exp) = 1;
+       /* The dfs_build_vbase_offset_vtbl_entries routine uses the
+ 	 TREE_PURPOSE to scribble in.  But, we need to clear it now so
+ 	 that the values are not perceived as labeled initializers.  */
+       TREE_PURPOSE (init) = NULL_TREE;
        TREE_VALUE (init) = exp;
      }
  
*************** build_vbase_offset_vtbl_entries (binfo)
*** 344,359 ****
  }
  
  /* Returns a pointer to the virtual base class of EXP that has the
!    indicated TYPE.  */
  
  static tree
  build_vbase_pointer (exp, type)
       tree exp, type;
  {
!   char *name;
!   FORMAT_VBASE_NAME (name, type);
  
!   return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
  }
  
  /* Build multi-level access to EXPR using hierarchy path PATH.
--- 346,386 ----
  }
  
  /* Returns a pointer to the virtual base class of EXP that has the
!    indicated TYPE.  EXP is of class type, not a pointer type.  */
  
  static tree
  build_vbase_pointer (exp, type)
       tree exp, type;
  {
!   if (vbase_offsets_in_vtable_p ())
!     {
!       tree vbase;
!       tree vbase_ptr;
  
!       /* Find the shared copy of TYPE; that's where the vtable offset
! 	 is recorded.  */
!       vbase = BINFO_FOR_VBASE (type, TREE_TYPE (exp));
!       /* Find the virtual function table pointer.  */
!       vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp));
!       /* Compute the location where the offset will lie.  */
!       vbase_ptr = build_binary_op (PLUS_EXPR, 
! 				   vbase_ptr,
! 				   BINFO_VPTR_FIELD (vbase));
!       vbase_ptr = build1 (NOP_EXPR, 
! 			  build_pointer_type (ptrdiff_type_node),
! 			  vbase_ptr);
!       /* Add the contents of this location to EXP.  */
!       return build (PLUS_EXPR,
! 		    build_pointer_type (type),
! 		    build_unary_op (ADDR_EXPR, exp, /*noconvert=*/0),
! 		    build1 (INDIRECT_REF, ptrdiff_type_node, vbase_ptr));
!     }
!   else
!     {
!       char *name;
!       FORMAT_VBASE_NAME (name, type);
!       return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
!     }
  }
  
  /* Build multi-level access to EXPR using hierarchy path PATH.
*************** get_vtable_entry_n (virtuals, n)
*** 1100,1105 ****
--- 1127,1151 ----
    return virtuals;
  }
  
+ /* Call this function whenever its known that a vtable for T is going
+    to be needed.  It's safe to call it more than once.  *HAS_VIRTUAL_P
+    is initialized to the number of slots that are reserved at the
+    beginning of the vtable for RTTI information.  */
+ 
+ static void
+ start_vtable (t, has_virtual_p)
+      tree t;
+      int *has_virtual_p;
+ {
+   if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t))
+     {
+       if (flag_vtable_thunks)
+ 	*has_virtual_p = 2;
+       else
+ 	*has_virtual_p = 1;
+     }
+ }
+ 
  /* Add a virtual function to all the appropriate vtables for the class
     T.  DECL_VINDEX(X) should be error_mark_node, if we want to
     allocate a new slot in our table.  If it is error_mark_node, we
*************** add_virtual_function (pv, phv, has_virtu
*** 1139,1151 ****
        /* If we are using thunks, use two slots at the front, one
  	 for the offset pointer, one for the tdesc pointer.
           For ARM-style vtables, use the same slot for both.  */
!       if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
! 	{
! 	  if (flag_vtable_thunks)
! 	    *has_virtual = 2;
! 	  else
! 	    *has_virtual = 1;
! 	}
  
        /* Build a new INT_CST for this DECL_VINDEX.  */
        {
--- 1185,1191 ----
        /* If we are using thunks, use two slots at the front, one
  	 for the offset pointer, one for the tdesc pointer.
           For ARM-style vtables, use the same slot for both.  */
!       start_vtable (t, has_virtual);
  
        /* Build a new INT_CST for this DECL_VINDEX.  */
        {
*************** determine_primary_base (t, has_virtual_p
*** 1767,1773 ****
        tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
        tree basetype = BINFO_TYPE (base_binfo);
  
!       if (TYPE_POLYMORPHIC_P (basetype))
  	{
  	  /* Even a virtual baseclass can contain our RTTI
  	     information.  But, we prefer a non-virtual polymorphic
--- 1807,1813 ----
        tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
        tree basetype = BINFO_TYPE (base_binfo);
  
!       if (TYPE_CONTAINS_VPTR_P (basetype))
  	{
  	  /* Even a virtual baseclass can contain our RTTI
  	     information.  But, we prefer a non-virtual polymorphic
*************** num_extra_vtbl_entries (binfo)
*** 2287,2295 ****
    tree type;
    int entries;
  
- 
    /* Under the old ABI, there are no entries at negative offsets.  */
!   if (!flag_new_abi)
      return size_zero_node;
  
    type = BINFO_TYPE (binfo);
--- 2327,2334 ----
    tree type;
    int entries;
  
    /* Under the old ABI, there are no entries at negative offsets.  */
!   if (!vbase_offsets_in_vtable_p ())
      return size_zero_node;
  
    type = BINFO_TYPE (binfo);
*************** size_extra_vtbl_entries (binfo)
*** 2317,2334 ****
    return fold (offset);
  }
  
! /* Construct the initializer for BINFOs virtual function table.  */
  
  static tree
! build_vtbl_initializer (binfo)
       tree binfo;
  {
    tree v = BINFO_VIRTUALS (binfo);
    tree inits = NULL_TREE;
    tree type = BINFO_TYPE (binfo);
  
    /* Add entries to the vtable for offsets to our virtual bases.  */
!   inits = build_vbase_offset_vtbl_entries (binfo);
  
    /* Process the RTTI stuff at the head of the list.  If we're not
       using vtable thunks, then the RTTI entry is just an ordinary
--- 2356,2375 ----
    return fold (offset);
  }
  
! /* Construct the initializer for BINFOs virtual function table.  BINFO
!    is part of the hierarchy dominated by T.  */
  
  static tree
! build_vtbl_initializer (binfo, t)
       tree binfo;
+      tree t;
  {
    tree v = BINFO_VIRTUALS (binfo);
    tree inits = NULL_TREE;
    tree type = BINFO_TYPE (binfo);
  
    /* Add entries to the vtable for offsets to our virtual bases.  */
!   inits = build_vbase_offset_vtbl_entries (binfo, t);
  
    /* Process the RTTI stuff at the head of the list.  If we're not
       using vtable thunks, then the RTTI entry is just an ordinary
*************** build_vtbl_initializer (binfo)
*** 2397,2403 ****
  static tree
  dfs_finish_vtbls (binfo, data)
       tree binfo;
!      void *data ATTRIBUTE_UNUSED;
  {
    if (!BINFO_PRIMARY_MARKED_P (binfo)
        && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
--- 2438,2444 ----
  static tree
  dfs_finish_vtbls (binfo, data)
       tree binfo;
!      void *data;
  {
    if (!BINFO_PRIMARY_MARKED_P (binfo)
        && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
*************** dfs_finish_vtbls (binfo, data)
*** 2409,2415 ****
        decl = BINFO_VTABLE (binfo);
        context = DECL_CONTEXT (decl);
        DECL_CONTEXT (decl) = 0;
!       DECL_INITIAL (decl) = build_vtbl_initializer (binfo);
        cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
        DECL_CONTEXT (decl) = context;
      }
--- 2450,2456 ----
        decl = BINFO_VTABLE (binfo);
        context = DECL_CONTEXT (decl);
        DECL_CONTEXT (decl) = 0;
!       DECL_INITIAL (decl) = build_vtbl_initializer (binfo, (tree) data);
        cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
        DECL_CONTEXT (decl) = context;
      }
*************** check_bases_and_members (t, empty_p)
*** 4112,4120 ****
    /* Check all the method declarations.  */
    check_methods (t);
  
!   /* A nearly-empty class has to be polymorphic; a nearly empty class
!      contains a vptr.  */
!   if (!TYPE_POLYMORPHIC_P (t))
      CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
  
    /* Do some bookkeeping that will guide the generation of implicitly
--- 4153,4161 ----
    /* Check all the method declarations.  */
    check_methods (t);
  
!   /* A nearly-empty class has to be vptr-containing; a nearly empty
!      class contains just a vptr.  */
!   if (!TYPE_CONTAINS_VPTR_P (t))
      CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
  
    /* Do some bookkeeping that will guide the generation of implicitly
*************** create_vtable_ptr (t, empty_p, has_virtu
*** 4177,4182 ****
--- 4218,4229 ----
        add_virtual_function (pending_virtuals_p, pending_hard_virtuals_p,
  			    has_virtual_p, fn, t);
  
+   /* Even if there weren't any new virtual functions, we might need a
+      new virtual function table if we're supposed to include vptrs in
+      all classes that need them.  */
+   if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())
+     start_vtable (t, has_virtual_p);
+     
    /* If we couldn't find an appropriate base class, create a new field
       here.  */
    if (*has_virtual_p && !TYPE_VFIELD (t))
*************** finish_struct_1 (t)
*** 4771,4777 ****
        TYPE_VFIELD (t) = vfield;
      }
  
!   if (flag_rtti && TYPE_POLYMORPHIC_P (t) && !pending_hard_virtuals)
      modify_all_vtables (t, NULL_TREE);
  
    for (pending_hard_virtuals = nreverse (pending_hard_virtuals);
--- 4818,4824 ----
        TYPE_VFIELD (t) = vfield;
      }
  
!   if (flag_rtti && TYPE_CONTAINS_VPTR_P (t) && !pending_hard_virtuals)
      modify_all_vtables (t, NULL_TREE);
  
    for (pending_hard_virtuals = nreverse (pending_hard_virtuals);
*************** finish_struct_1 (t)
*** 4802,4810 ****
  	}
      }
  
!   /* Under our model of GC, every C++ class gets its own virtual
!      function table, at least virtually.  */
!   if (pending_virtuals)
      {
        pending_virtuals = nreverse (pending_virtuals);
        /* We must enter these virtuals into the table.  */
--- 4849,4857 ----
  	}
      }
  
!   /* If necessary, create the vtable for this class.  */
!   if (pending_virtuals
!       || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))
      {
        pending_virtuals = nreverse (pending_virtuals);
        /* We must enter these virtuals into the table.  */
*************** finish_struct_1 (t)
*** 4836,4841 ****
--- 4883,4890 ----
  
        CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
      }
+   /* If we didn't need a new vtable, see if we should copy one from
+      the base.  */
    else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
      {
        tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
*************** finish_struct_1 (t)
*** 4855,4861 ****
  	CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
      }
  
!   if (TYPE_POLYMORPHIC_P (t))
      {
        CLASSTYPE_VSIZE (t) = has_virtual;
        if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
--- 4904,4910 ----
  	CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
      }
  
!   if (TYPE_CONTAINS_VPTR_P (t))
      {
        CLASSTYPE_VSIZE (t) = has_virtual;
        if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
*************** get_vfield_name (type)
*** 6004,6010 ****
    char *buf;
  
    while (BINFO_BASETYPES (binfo)
! 	 && TYPE_POLYMORPHIC_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
  	 && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
      binfo = BINFO_BASETYPE (binfo, 0);
  
--- 6053,6059 ----
    char *buf;
  
    while (BINFO_BASETYPES (binfo)
! 	 && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
  	 && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
      binfo = BINFO_BASETYPE (binfo, 0);
  
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.384
diff -c -p -r1.384 cp-tree.h
*** cp-tree.h	2000/01/16 16:59:43	1.384
--- cp-tree.h	2000/01/17 03:40:18
*************** Boston, MA 02111-1307, USA.  */
*** 177,183 ****
--- 177,220 ----
  #define RECORD_OR_UNION_TYPE_CHECK(NODE)	NODE
  
  #endif
+ 
+ /* ABI control.  */
+ 
+ /* Nonzero to enable experimental ABI changes.  */
+ 
+ extern int flag_new_abi;
+ 
+ /* Nonzero to use __cxa_atexit, rather than atexit, to register
+    destructors for local statics and global objects.  */
+ 
+ extern int flag_use_cxa_atexit;
  
+ /* Nonzero to not ignore namespace std. */
+ 
+ extern int flag_honor_std;
+ 
+ /* Nonzero means generate 'rtti' that give run-time type information.  */
+ 
+ extern int flag_rtti;
+ 
+ /* Nonzero if virtual base class offsets are stored in the virtual
+    function table.  Zero if, instead, a pointer to the virtual base is
+    stored in the object itself.  */
+ #define vbase_offsets_in_vtable_p() (flag_new_abi)
+ 
+ /* Nonzero if a derived class that needs a vptr should always get one,
+    even if a non-primary base class already has one.  For example,
+    given:
+ 
+      struct S { int i; virtual void f(); };
+      struct T : virtual public S {};
+ 
+    one could either reuse the vptr in `S' for `T', or create a new
+    vptr for `T'.  If this flag is nonzero we choose the latter
+    alternative; otherwise, we choose the former.  */
+ #define vptrs_present_everywhere_p() (flag_new_abi)
+ 
+ 
  /* Language-dependent contents of an identifier.  */
  
  struct lang_identifier
*************** struct lang_decl
*** 2156,2161 ****
--- 2193,2204 ----
     polymorphic class.  */
  #define TYPE_POLYMORPHIC_P(NODE) (TREE_LANG_FLAG_2 (NODE))
  
+ /* Nonzero if this class has a virtual function table pointer.  */
+ #define TYPE_CONTAINS_VPTR_P(NODE) 		\
+   (TYPE_POLYMORPHIC_P (NODE) 			\
+    || (vbase_offsets_in_vtable_p () 		\
+        && TYPE_USES_VIRTUAL_BASECLASSES (NODE)))
+ 
  extern int flag_new_for_scope;
  
  /* This flag is true of a local VAR_DECL if it was declared in a for
*************** extern struct pending_inline *pending_in
*** 3160,3169 ****
  
  extern int flag_this_is_variable;
  
- /* Nonzero means generate 'rtti' that give run-time type information.  */
- 
- extern int flag_rtti;
- 
  /* Nonzero means do emit exported implementations of functions even if
     they can be inlined.  */
  
--- 3203,3208 ----
*************** extern int flag_implicit_templates;
*** 3187,3205 ****
  
  extern int flag_weak;
  
- /* Nonzero to enable experimental ABI changes.  */
- 
- extern int flag_new_abi;
- 
- /* Nonzero to use __cxa_atexit, rather than atexit, to register
-    destructors for local statics and global objects.  */
- 
- extern int flag_use_cxa_atexit;
- 
- /* Nonzero to not ignore namespace std. */
- 
- extern int flag_honor_std;
- 
  /* Nonzero if we should expand functions calls inline at the tree
     level, rather than at the RTL level.  */
  
--- 3226,3231 ----
*************** extern tree binfo_for_vtable			PROTO((tr
*** 3959,3964 ****
--- 3985,3995 ----
  extern int  binfo_from_vbase			PROTO((tree));
  extern tree dfs_walk                            PROTO((tree, 
  						       tree (*)(tree, void *),
+ 						       tree (*) (tree, void *),
+ 						       void *));
+ extern tree dfs_walk_real                      PROTO ((tree, 
+ 						       tree (*) (tree, void *),
+ 						       tree (*) (tree, void *),
  						       tree (*) (tree, void *),
  						       void *));
  extern tree dfs_unmark                          PROTO((tree, void *));
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.532
diff -c -p -r1.532 decl.c
*** decl.c	2000/01/16 17:06:42	1.532
--- decl.c	2000/01/17 03:40:27
*************** expand_static_init (decl, init)
*** 8201,8215 ****
        finish_if_stmt ();
      }
    else
!     {
!       /* This code takes into account memory allocation policy of
! 	 `start_decl'.  Namely, if TYPE_NEEDS_CONSTRUCTING does not
! 	 hold for this object, then we must make permanent the storage
! 	 currently in the temporary obstack.  */
!       if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
! 	preserve_initializer ();
!       static_aggregates = tree_cons (init, decl, static_aggregates);
!     }
  }
  
  /* Finish the declaration of a catch-parameter.  */
--- 8201,8207 ----
        finish_if_stmt ();
      }
    else
!     static_aggregates = tree_cons (init, decl, static_aggregates);
  }
  
  /* Finish the declaration of a catch-parameter.  */
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.296
diff -c -p -r1.296 decl2.c
*** decl2.c	2000/01/16 17:03:49	1.296
--- decl2.c	2000/01/17 03:40:30
*************** mark_vtable_entries (decl)
*** 2296,2303 ****
        fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) 
  		: FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
  
!       if (TREE_CODE (fnaddr) == NOP_EXPR)
! 	/* RTTI offset.  */
  	continue;
  
        fn = TREE_OPERAND (fnaddr, 0);
--- 2296,2304 ----
        fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) 
  		: FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
  
!       if (TREE_CODE (fnaddr) != ADDR_EXPR)
! 	/* This entry is an offset: a virtual base class offset, a
! 	   virtual call offset, and RTTI offset, etc.  */
  	continue;
  
        fn = TREE_OPERAND (fnaddr, 0);
Index: init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.161
diff -c -p -r1.161 init.c
*** init.c	2000/01/16 20:22:56	1.161
--- init.c	2000/01/17 03:40:32
*************** initialize_vtbl_ptrs (type, addr)
*** 119,126 ****
  {
    tree list = build_tree_list (type, addr);
  
!   dfs_walk (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
! 	    dfs_unmarked_real_bases_queue_p, list);
    dfs_walk (TYPE_BINFO (type), dfs_unmark,
  	    dfs_marked_real_bases_queue_p, type);
    if (TYPE_USES_VIRTUAL_BASECLASSES (type))
--- 119,130 ----
  {
    tree list = build_tree_list (type, addr);
  
!   /* Walk through the hierarchy, initializing the vptr in each base
!      class.  We do these in pre-order because under the new ABI we
!      can't find the virtual bases for a class until we've initialized
!      the vtbl for that class.  */
!   dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
! 		 NULL, dfs_unmarked_real_bases_queue_p, list);
    dfs_walk (TYPE_BINFO (type), dfs_unmark,
  	    dfs_marked_real_bases_queue_p, type);
    if (TYPE_USES_VIRTUAL_BASECLASSES (type))
*************** expand_virtual_init (binfo, decl)
*** 657,663 ****
    vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
    /* Under the new ABI, we need to point into the middle of the
       vtable.  */
!   if (flag_new_abi)
      vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, 
  		  size_extra_vtbl_entries (binfo));
  
--- 661,667 ----
    vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
    /* Under the new ABI, we need to point into the middle of the
       vtable.  */
!   if (vbase_offsets_in_vtable_p ())
      vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, 
  		  size_extra_vtbl_entries (binfo));
  
*************** expand_aggr_vbase_init_1 (binfo, exp, ad
*** 720,726 ****
  /* Construct the virtual base-classes of THIS_REF (whose address is
     THIS_PTR).  The object has the indicated TYPE.  The construction
     actually takes place only if FLAG is non-zero.  INIT_LIST is list
!    of initialization for constructor to perform.  */
  
  static void
  construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
--- 724,730 ----
  /* Construct the virtual base-classes of THIS_REF (whose address is
     THIS_PTR).  The object has the indicated TYPE.  The construction
     actually takes place only if FLAG is non-zero.  INIT_LIST is list
!    of initializations for constructors to perform.  */
  
  static void
  construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
*************** construct_virtual_bases (type, this_ref,
*** 731,751 ****
       tree flag;
  {
    tree vbases;
-   tree result;
-   tree if_stmt;
  
    /* If there are no virtual baseclasses, we shouldn't even be here.  */
    my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
  
    /* First set the pointers in our object that tell us where to find
       our virtual baseclasses.  */
!   if_stmt = begin_if_stmt ();
!   finish_if_stmt_cond (flag, if_stmt);
!   result = init_vbase_pointers (type, this_ptr);
!   if (result)
!     finish_expr_stmt (build_compound_expr (result));
!   finish_then_clause (if_stmt);
!   finish_if_stmt ();
  
    /* Now, run through the baseclasses, initializing each.  */ 
    for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
--- 735,759 ----
       tree flag;
  {
    tree vbases;
  
    /* If there are no virtual baseclasses, we shouldn't even be here.  */
    my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
  
    /* First set the pointers in our object that tell us where to find
       our virtual baseclasses.  */
!   if (!vbase_offsets_in_vtable_p ())
!     {
!       tree if_stmt;
!       tree result;
! 
!       if_stmt = begin_if_stmt ();
!       finish_if_stmt_cond (flag, if_stmt);
!       result = init_vbase_pointers (type, this_ptr);
!       if (result)
! 	finish_expr_stmt (build_compound_expr (result));
!       finish_then_clause (if_stmt);
!       finish_if_stmt ();
!     }
  
    /* Now, run through the baseclasses, initializing each.  */ 
    for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
*************** finish_init_stmts (stmt_expr, compound_s
*** 1019,1029 ****
     If `init' is a CONSTRUCTOR, then we emit a warning message,
     explaining that such initializations are invalid.
  
-    ALIAS_THIS is nonzero iff we are initializing something which is
-    essentially an alias for current_class_ref.  In this case, the base
-    constructor may move it on us, and we must keep track of such
-    deviations.
- 
     If INIT resolves to a CALL_EXPR which happens to return
     something of the type we are looking for, then we know
     that we can safely use that call to perform the
--- 1027,1032 ----
*************** expand_default_init (binfo, true_exp, ex
*** 1216,1223 ****
     baseclass fields should really be pointing.  But we do know
     from TRUE_EXP.  In constructors, we don't know anything about
     the value being initialized.
- 
-    ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
  
     FLAGS is just passes to `build_method_call'.  See that function for
     its description.  */
--- 1219,1224 ----
Index: rtti.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/rtti.c,v
retrieving revision 1.51
diff -c -p -r1.51 rtti.c
*** rtti.c	1999/12/21 00:19:01	1.51
--- rtti.c	2000/01/17 03:40:33
***************
*** 1,5 ****
  /* RunTime Type Identification
!    Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
     Mostly written by Jason Merrill (jason@cygnus.com).
  
  This file is part of GNU CC.
--- 1,5 ----
  /* RunTime Type Identification
!    Copyright (C) 1995, 96-97, 1998, 1999, 2000 Free Software Foundation, Inc.
     Mostly written by Jason Merrill (jason@cygnus.com).
  
  This file is part of GNU CC.
*************** expand_class_desc (tdecl, type)
*** 811,817 ****
  			     (type_info_type_node,
  			      TYPE_QUAL_CONST)));
        fields [1] = build_lang_decl
! 	(FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
        DECL_BIT_FIELD (fields[1]) = 1;
        DECL_FIELD_SIZE (fields[1]) = 29;
  
--- 811,818 ----
  			     (type_info_type_node,
  			      TYPE_QUAL_CONST)));
        fields [1] = build_lang_decl
! 	(FIELD_DECL, NULL_TREE, 
! 	 flag_new_abi ? intSI_type_node : unsigned_intSI_type_node);
        DECL_BIT_FIELD (fields[1]) = 1;
        DECL_FIELD_SIZE (fields[1]) = 29;
  
*************** expand_class_desc (tdecl, type)
*** 839,853 ****
  
        if (TREE_VIA_VIRTUAL (binfo))
  	{
! 	  tree t = BINFO_TYPE (binfo);
! 	  const char *name;
! 	  tree field;
! 
! 	  FORMAT_VBASE_NAME (name, t);
! 	  field = lookup_field (type, get_identifier (name), 0, 0);
! 	  offset = size_binop (FLOOR_DIV_EXPR, 
! 		DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
! 	  offset = convert (sizetype, offset);
  	}
        else
  	offset = BINFO_OFFSET (binfo);
--- 840,865 ----
  
        if (TREE_VIA_VIRTUAL (binfo))
  	{
! 	  if (!vbase_offsets_in_vtable_p ())
! 	    {
! 	      tree t = BINFO_TYPE (binfo);
! 	      const char *name;
! 	      tree field;
! 
! 	      FORMAT_VBASE_NAME (name, t);
! 	      field = lookup_field (type, get_identifier (name), 0, 0);
! 	      offset = size_binop (FLOOR_DIV_EXPR, 
! 				   DECL_FIELD_BITPOS (field), 
! 				   size_int (BITS_PER_UNIT));
! 	      offset = convert (sizetype, offset);
! 	    }
! 	  else
! 	    {
! 	      /* Under the new ABI, we store the vtable offset at which
! 		 the virtual base offset can be found.  */
! 	      tree vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
! 	      offset = convert (sizetype, BINFO_VPTR_FIELD (vbase));
! 	    }
  	}
        else
  	offset = BINFO_OFFSET (binfo);
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.147
diff -c -p -r1.147 search.c
*** search.c	2000/01/16 16:59:44	1.147
--- search.c	2000/01/17 03:40:35
*************** static tree bfs_walk
*** 126,136 ****
  	       void *));
  static tree lookup_field_queue_p PROTO((tree, void *));
  static tree lookup_field_r PROTO((tree, void *));
- static tree dfs_walk_real PROTO ((tree, 
- 				  tree (*) (tree, void *),
- 				  tree (*) (tree, void *),
- 				  tree (*) (tree, void *),
- 				  void *));
  static tree get_virtuals_named_this_r PROTO ((tree, void *));
  static tree context_for_name_lookup PROTO ((tree));
  static tree canonical_binfo PROTO ((tree));
--- 126,131 ----
*************** bfs_walk (binfo, fn, qfn, data)
*** 1773,1779 ****
     performed, and PREFN is called in preorder, while POSTFN is called
     in postorder.  */
  
! static tree
  dfs_walk_real (binfo, prefn, postfn, qfn, data)
       tree binfo;
       tree (*prefn) PROTO((tree, void *));
--- 1768,1774 ----
     performed, and PREFN is called in preorder, while POSTFN is called
     in postorder.  */
  
! tree
  dfs_walk_real (binfo, prefn, postfn, qfn, data)
       tree binfo;
       tree (*prefn) PROTO((tree, void *));
*************** maybe_suppress_debug_info (t)
*** 3200,3208 ****
      TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
    else if (CLASSTYPE_INTERFACE_KNOWN (t))
      /* Don't set it.  */;
!   /* If the class has virtual functions, write out the debug info
!      along with the vtable.  */
!   else if (TYPE_POLYMORPHIC_P (t))
      TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
  
    /* Otherwise, just emit the debug info normally.  */
--- 3195,3203 ----
      TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
    else if (CLASSTYPE_INTERFACE_KNOWN (t))
      /* Don't set it.  */;
!   /* If the class has a vtable, write out the debug info along with
!      the vtable.  */
!   else if (TYPE_CONTAINS_VPTR_P (t))
      TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
  
    /* Otherwise, just emit the debug info normally.  */
Index: tinfo.cc
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tinfo.cc,v
retrieving revision 1.12
diff -c -p -r1.12 tinfo.cc
*** tinfo.cc	1999/09/21 14:40:12	1.12
--- tinfo.cc	2000/01/17 03:40:35
***************
*** 1,5 ****
  // Methods for type_info for -*- C++ -*- Run Time Type Identification.
! // Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation
  
  // This file is part of GNU CC.
  
--- 1,5 ----
  // Methods for type_info for -*- C++ -*- Run Time Type Identification.
! // Copyright (C) 1994, 1996, 1998, 1999, 2000 Free Software Foundation
  
  // This file is part of GNU CC.
  
***************
*** 31,36 ****
--- 31,64 ----
  #include "tinfo.h"
  #include "new"			// for placement new
  
+ namespace
+ {
+ // ADDR is a pointer to an object.  Convert it to a pointer to a base,
+ // using OFFSET.
+ inline void*
+ convert_to_base (void *addr, bool is_virtual, USItype offset)
+ {
+   if (!addr)
+     return NULL;
+ 
+   if (!is_virtual)
+     return (char *) addr + offset;
+ 
+ #ifdef __GXX_ABI_VERSION
+   // Under the new ABI, the offset gives us an index into the vtable,
+   // which contains an offset to the virtual base.  The vptr is always
+   // the first thing in the object.
+   std::ptrdiff_t *vtable = *((std::ptrdiff_t **) addr);
+   return ((char *) addr) + vtable[offset];
+ #else
+   // Under the old ABI, the offset gives us the address of a pointer
+   // to the virtual base.
+   return *((void **) ((char *) addr + offset));
+ #endif
+ }
+ 
+ }
+ 
  // This file contains the minimal working set necessary to link with code
  // that uses virtual functions and -frtti but does not actually use RTTI
  // functionality.
*************** do_upcast (sub_kind access_path,
*** 254,267 ****
        upcast_result result2;
        void *p = objptr;
        sub_kind sub_access = access_path;
!       if (p)
!         p = (char *)p + base_list[i].offset;
        if (base_list[i].is_virtual)
!         {
!           if (p)
!             p = *(void **)p;
! 	  sub_access = sub_kind (sub_access | contained_virtual_mask);
!         }
        if (base_list[i].access != PUBLIC)
          sub_access = sub_kind (sub_access & ~contained_public_mask);
        if (base_list[i].base->do_upcast (sub_access, target, p, result2))
--- 282,292 ----
        upcast_result result2;
        void *p = objptr;
        sub_kind sub_access = access_path;
!       p = convert_to_base (p, 
! 			   base_list[i].is_virtual,
! 			   base_list[i].offset);
        if (base_list[i].is_virtual)
! 	sub_access = sub_kind (sub_access | contained_virtual_mask);
        if (base_list[i].access != PUBLIC)
          sub_access = sub_kind (sub_access & ~contained_public_mask);
        if (base_list[i].base->do_upcast (sub_access, target, p, result2))
*************** do_dyncast (int boff, sub_kind access_pa
*** 344,356 ****
    for (size_t i = n_bases; i--;)
      {
        dyncast_result result2;
!       void *p = (char *)objptr + base_list[i].offset;
        sub_kind sub_access = access_path;
        if (base_list[i].is_virtual)
!         {
! 	  p = *(void **)p;
! 	  sub_access = sub_kind (sub_access | contained_virtual_mask);
! 	}
        if (base_list[i].access != PUBLIC)
          sub_access = sub_kind (sub_access & ~contained_public_mask);
        
--- 369,381 ----
    for (size_t i = n_bases; i--;)
      {
        dyncast_result result2;
!       void *p;
        sub_kind sub_access = access_path;
+       p = convert_to_base (objptr, 
+ 			   base_list[i].is_virtual,
+ 			   base_list[i].offset);
        if (base_list[i].is_virtual)
! 	sub_access = sub_kind (sub_access | contained_virtual_mask);
        if (base_list[i].access != PUBLIC)
          sub_access = sub_kind (sub_access & ~contained_public_mask);
        
*************** do_find_public_subobj (int boff, const t
*** 492,504 ****
      {
        if (base_list[i].access != PUBLIC)
          continue; // Not public, can't be here.
!       void *p = (char *)objptr + base_list[i].offset;
!       if (base_list[i].is_virtual)
!         {
!           if (boff == -1)
!             continue; // Not a virtual base, so can't be here.
!           p = *(void **)p;
!         }
  
        sub_kind base_kind = base_list[i].base->do_find_public_subobj
                                (boff, subtype, p, subptr);
--- 517,531 ----
      {
        if (base_list[i].access != PUBLIC)
          continue; // Not public, can't be here.
!       void *p;
! 
!       if (base_list[i].is_virtual && boff == -1)
! 	// Not a virtual base, so can't be here.
! 	continue;
!       
!       p = convert_to_base (objptr, 
! 			   base_list[i].is_virtual,
! 			   base_list[i].offset);
  
        sub_kind base_kind = base_list[i].base->do_find_public_subobj
                                (boff, subtype, p, subptr);
Index: tinfo.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tinfo.h,v
retrieving revision 1.7
diff -c -p -r1.7 tinfo.h
*** tinfo.h	1999/09/21 14:40:12	1.7
--- tinfo.h	2000/01/17 03:40:36
***************
*** 1,5 ****
  // RTTI support internals for -*- C++ -*-
! // Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation
  
  #include "typeinfo"
  
--- 1,5 ----
  // RTTI support internals for -*- C++ -*-
! // Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000 Free Software Foundation
  
  #include "typeinfo"
  
*************** public:
*** 167,173 ****
--- 167,177 ----
  
  // type_info for a general class.
  
+ #ifdef __GXX_ABI_VERSION
+ typedef int USItype __attribute__ ((mode (SI)));
+ #else
  typedef unsigned int USItype	__attribute__ ((mode (SI)));
+ #endif
  
  struct __class_type_info : public __user_type_info {
    enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };
Index: tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tree.c,v
retrieving revision 1.175
diff -c -p -r1.175 tree.c
*** tree.c	2000/01/02 19:41:09	1.175
--- tree.c	2000/01/17 03:40:37
*************** make_binfo (offset, binfo, vtable, virtu
*** 860,866 ****
    BINFO_OFFSET (new_binfo) = offset;
    BINFO_VTABLE (new_binfo) = vtable;
    BINFO_VIRTUALS (new_binfo) = virtuals;
-   BINFO_VPTR_FIELD (new_binfo) = NULL_TREE;
  
    if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
      BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));      
--- 860,865 ----

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