OSDN Git Service

Correct many new ABI issues regarding vbase and vcall offset
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Apr 2000 18:13:22 +0000 (18:13 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Apr 2000 18:13:22 +0000 (18:13 +0000)
layout.
* cp-tree.h (BINFO_VTABLE): Document.
(struct lang_type): Tweak formatting.
(BINFO_PRIMARY_BINFO): Add to documentation.
(CLASSTYPE_VSIZE): Fix typo in comment.
(CLASSTYPE_VBASECLASSES): Update documentation.
(BINFO_VBASE_MARKED): Remove.
(SET_BINFO_VBASE_MARKED): Likewise.
(CLEAR_BINFO_VBASE_MARKED): Likewise.
(BINFO_FIELDS_MARKED): Remove.
(SET_BINFO_FIELDS_MARKED): Likewise.
(CLEAR_BINFO_FIELDS_MARKED): Likewise.
(enum access_kind): New enumeration.
(num_extra_vtbl_entries): Remove declaration.
(size_extra_vtbl_entries): Likewise.
(get_vtbl_decl_for_binfo): New function.
(dfs_vbase_unmark): Remove declaration.
(mark_primary_bases): Likewise.
* class.c (SAME_FN): Remove.
(struct vcall_offset_data_s): Move definition.
(build_vbase_pointer): Use `build', not `build_binary_op', to
access the vbase pointer under the new ABI.
(build_vtable_entry_ref): Use get_vtbl_decl_for_binfo.
(build_primary_vtable): Likewise.
(dfs_mark_primary_bases): Move here from search.c.
(mark_primary_bases): Likewise.
(determine_primary_bases): Under the new ABI, don't make a base
class a primary base just because we don't yet have any virtual
functions.
(layout_vtable_decl): Use get_vtbl_decl_for_binfo.
(num_vfun_entries): Remove.
(dfs_count_virtuals): Likewise.
(num_extra_vtbl_entries): Likewise.
(size_extra_vtbl_entries): Likewise.
(layout_virtual_bases): Iterate in inheritance graph order under
the new ABI.
(finish_struct_1): Use TYPE_VFIELD, not CLASSTYPE_VSIZE, to
indicate that a vfield is present.
(init_class_processing): Initialize access_public_node, etc., from
ak_public, etc.
(get_vtbl_decl_for_binfo): New function.
(dump_class_hierarchy_r): Likewise.
(dump_class_hierarchy): Use it.
(finish_vtbls): Build the vtbls in inheritance graph order.
(dfs_finish_vtbls): Adjust call to build_vtbl_initializer.
(initialize_vtable): Use get_vtbl_decl_for_binfo.
(accumulate_vtbl_inits): Add comments explaining why a pre-order
walk is required.
(dfs_accumulate_vtbl_inits): Set BINFO_VTABLE to the location
where the vptr points, even for primary vtables.
(build_vtbl_initializer): Adjust handling of vbase and vcall
offsets.
(build_vcall_and_vbase_vtable_entries): New function.
(dfs_build_vbase_offset_vtbl_entries): Remove.
(build_vbase_offset_vtbl_entries): Reimplement.
(dfs_build_vcall_offset_vtbl_entries): Don't include virtuals that
were already handled in a primary base class vtable.
(build_vcall_offset_vtbl_entries): Adjust.
(build_rtti_vtbl_entries): Adjust.
* decl2.c (output_vtable_inherit): Use get_vtbl_decl_for_binfo.
* init.c (expand_virtual_init): Simplify.
* repo.c (repo_get_id): Use get_vtbl_decl_for_binfo.
* rtti.c (create_pseudo_type_info): Adjust calculation of vptr.
* search.c (BINFO_ACCESS): New macro.
(SET_BINFO_ACCESS): Likewise.
(dfs_access_in_type): Manipulate access_kinds, not access nodes.
(access_in_type): Likewise.
(dfs_accessible_p): Likewise.
(protected_accessible_p): Likewise.
(lookup_fnfields_1): Adjust documentation.
(dfs_mark_primary_bases): Move to class.c
(mark_primary_bases): Likewise.
(dfs_vbase_unmark): Remove.
(virtual_context): Use BINFO_FOR_VBASE.
(dfs_get_vbase_types): Simplify.
(dfs_build_inheritance_graph_order): New function.
(get_vbase_types): Use it.
* tree.c (debug_binfo): Use get_vtbl_decl_for_binfo.

* tinfo.cc (get_vbase_offset): New function.
(__vmi_class_type_info::do_find_public_src): Use it.
(__vmi_class_type_info::do_dyncast): Likewise.
(__vmi_class_type_info::do_upcast): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32905 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/repo.c
gcc/cp/rtti.c
gcc/cp/search.c
gcc/cp/tinfo.cc
gcc/cp/tree.c
gcc/testsuite/g++.old-deja/g++.abi/layout1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.abi/vtable.C
gcc/testsuite/g++.old-deja/g++.abi/vtable2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.jason/dcast3.C

index 1a74fea..8fcacd2 100644 (file)
@@ -1,3 +1,90 @@
+2000-04-04  Mark Mitchell  <mark@codesourcery.com>
+
+       Correct many new ABI issues regarding vbase and vcall offset
+       layout.
+       * cp-tree.h (BINFO_VTABLE): Document.
+       (struct lang_type): Tweak formatting.
+       (BINFO_PRIMARY_BINFO): Add to documentation.
+       (CLASSTYPE_VSIZE): Fix typo in comment.
+       (CLASSTYPE_VBASECLASSES): Update documentation.
+       (BINFO_VBASE_MARKED): Remove.
+       (SET_BINFO_VBASE_MARKED): Likewise.
+       (CLEAR_BINFO_VBASE_MARKED): Likewise.
+       (BINFO_FIELDS_MARKED): Remove.
+       (SET_BINFO_FIELDS_MARKED): Likewise.
+       (CLEAR_BINFO_FIELDS_MARKED): Likewise.
+       (enum access_kind): New enumeration.
+       (num_extra_vtbl_entries): Remove declaration.
+       (size_extra_vtbl_entries): Likewise.
+       (get_vtbl_decl_for_binfo): New function.
+       (dfs_vbase_unmark): Remove declaration.
+       (mark_primary_bases): Likewise.
+       * class.c (SAME_FN): Remove.
+       (struct vcall_offset_data_s): Move definition.
+       (build_vbase_pointer): Use `build', not `build_binary_op', to
+       access the vbase pointer under the new ABI.
+       (build_vtable_entry_ref): Use get_vtbl_decl_for_binfo.
+       (build_primary_vtable): Likewise.
+       (dfs_mark_primary_bases): Move here from search.c.
+       (mark_primary_bases): Likewise.
+       (determine_primary_bases): Under the new ABI, don't make a base
+       class a primary base just because we don't yet have any virtual
+       functions.
+       (layout_vtable_decl): Use get_vtbl_decl_for_binfo.
+       (num_vfun_entries): Remove.
+       (dfs_count_virtuals): Likewise.
+       (num_extra_vtbl_entries): Likewise.
+       (size_extra_vtbl_entries): Likewise.
+       (layout_virtual_bases): Iterate in inheritance graph order under
+       the new ABI.
+       (finish_struct_1): Use TYPE_VFIELD, not CLASSTYPE_VSIZE, to
+       indicate that a vfield is present.
+       (init_class_processing): Initialize access_public_node, etc., from
+       ak_public, etc.
+       (get_vtbl_decl_for_binfo): New function.
+       (dump_class_hierarchy_r): Likewise.
+       (dump_class_hierarchy): Use it.
+       (finish_vtbls): Build the vtbls in inheritance graph order.
+       (dfs_finish_vtbls): Adjust call to build_vtbl_initializer.
+       (initialize_vtable): Use get_vtbl_decl_for_binfo.
+       (accumulate_vtbl_inits): Add comments explaining why a pre-order
+       walk is required.
+       (dfs_accumulate_vtbl_inits): Set BINFO_VTABLE to the location
+       where the vptr points, even for primary vtables.
+       (build_vtbl_initializer): Adjust handling of vbase and vcall
+       offsets.
+       (build_vcall_and_vbase_vtable_entries): New function.
+       (dfs_build_vbase_offset_vtbl_entries): Remove.
+       (build_vbase_offset_vtbl_entries): Reimplement.
+       (dfs_build_vcall_offset_vtbl_entries): Don't include virtuals that
+       were already handled in a primary base class vtable.
+       (build_vcall_offset_vtbl_entries): Adjust.
+       (build_rtti_vtbl_entries): Adjust.
+       * decl2.c (output_vtable_inherit): Use get_vtbl_decl_for_binfo.
+       * init.c (expand_virtual_init): Simplify.
+       * repo.c (repo_get_id): Use get_vtbl_decl_for_binfo.
+       * rtti.c (create_pseudo_type_info): Adjust calculation of vptr.
+       * search.c (BINFO_ACCESS): New macro.
+       (SET_BINFO_ACCESS): Likewise.
+       (dfs_access_in_type): Manipulate access_kinds, not access nodes.
+       (access_in_type): Likewise.
+       (dfs_accessible_p): Likewise.
+       (protected_accessible_p): Likewise.
+       (lookup_fnfields_1): Adjust documentation.
+       (dfs_mark_primary_bases): Move to class.c
+       (mark_primary_bases): Likewise.
+       (dfs_vbase_unmark): Remove.
+       (virtual_context): Use BINFO_FOR_VBASE.
+       (dfs_get_vbase_types): Simplify.
+       (dfs_build_inheritance_graph_order): New function.
+       (get_vbase_types): Use it.
+       * tree.c (debug_binfo): Use get_vtbl_decl_for_binfo.
+
+       * tinfo.cc (get_vbase_offset): New function.
+       (__vmi_class_type_info::do_find_public_src): Use it.
+       (__vmi_class_type_info::do_dyncast): Likewise.
+       (__vmi_class_type_info::do_upcast): Likewise.
+       
 2000-04-03  Zack Weinberg  <zack@wolery.cumb.org>
 
        * lang-specs.h: Pass -fno-show-column to the preprocessor.
index f3a94dc..a9f3595 100644 (file)
@@ -38,12 +38,6 @@ Boston, MA 02111-1307, USA.  */
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-/* This is how we tell when two virtual member functions are really the
-   same.  */
-#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
-
-extern void set_class_shadows PARAMS ((tree));
-
 /* The number of nested classes being processed.  If we are not in the
    scope of any class, this is zero.  */
 
@@ -68,6 +62,22 @@ typedef struct class_stack_node {
   splay_tree names_used;
 }* class_stack_node_t;
 
+typedef struct vcall_offset_data_s
+{
+  /* The binfo for the most-derived type.  */
+  tree derived;
+  /* The binfo for the virtual base for which we're building
+     initializers.  */
+  tree vbase;
+  /* The vcall offset initializers built up so far.  */
+  tree inits;
+  /* The vtable index of the next vcall or vbase offset.  */
+  tree index;
+  /* Nonzero if we are building the initializer for the primary
+     vtable.  */
+  int primary_p;
+} vcall_offset_data;
+
 /* 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;
@@ -108,7 +118,7 @@ static tree fixed_type_or_null PARAMS ((tree, int *));
 static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
                                                          int, tree));
 static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
-static tree build_vtbl_initializer PARAMS ((tree, tree));
+static tree build_vtbl_initializer PARAMS ((tree, tree, int *));
 static int count_fields PARAMS ((tree));
 static int add_fields_to_vec PARAMS ((tree, tree, int));
 static void check_bitfield_decl PARAMS ((tree));
@@ -135,19 +145,17 @@ static void propagate_binfo_offsets PARAMS ((tree, tree));
 static void layout_virtual_bases PARAMS ((tree, varray_type *));
 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 *));
-static tree build_vbase_offset_vtbl_entries PARAMS ((tree, tree));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
 static tree dfs_vcall_offset_queue_p PARAMS ((tree, void *));
 static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
-static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree));
-static tree dfs_count_virtuals PARAMS ((tree, void *));
+static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
 static void layout_vtable_decl PARAMS ((tree, int));
-static int num_vfun_entries PARAMS ((tree));
 static tree dfs_find_final_overrider PARAMS ((tree, void *));
 static tree find_final_overrider PARAMS ((tree, tree, tree));
 static tree dfs_find_base PARAMS ((tree, void *));
 static int make_new_vtable PARAMS ((tree, tree));
-extern void dump_class_hierarchy PARAMS ((tree, int));
+static void dump_class_hierarchy_r PARAMS ((tree, tree, int));
+extern void dump_class_hierarchy PARAMS ((tree));
 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,
@@ -162,6 +170,10 @@ static void layout_empty_base PARAMS ((tree, tree, varray_type));
 static void accumulate_vtbl_inits PARAMS ((tree, tree));
 static void set_vindex PARAMS ((tree, tree, int *));
 static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
+static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, 
+                                                       vcall_offset_data *));
+static tree dfs_mark_primary_bases PARAMS ((tree, void *));
+static void mark_primary_bases PARAMS ((tree));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -274,9 +286,10 @@ build_vbase_pointer (exp, type)
       /* 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 = build (PLUS_EXPR, 
+                        TREE_TYPE (vbase_ptr),
+                        vbase_ptr,
+                        BINFO_VPTR_FIELD (vbase));
       vbase_ptr = build1 (NOP_EXPR, 
                          build_pointer_type (ptrdiff_type_node),
                          vbase_ptr);
@@ -462,7 +475,7 @@ build_vtable_entry_ref (basetype, vtbl, idx)
   static char asm_stmt[] = ".vtable_entry %c0, %c1";
   tree s, i, i2;
 
-  s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
+  s = build_unary_op (ADDR_EXPR, get_vtbl_decl_for_binfo (basetype), 0);
   s = build_tree_list (build_string (1, "s"), s);
 
   i = build_array_ref (vtbl, idx);
@@ -533,7 +546,23 @@ build_vtbl_ref (instance, idx)
          && (TREE_CODE (instance) == RESULT_DECL
              || TREE_CODE (instance) == PARM_DECL
              || TREE_CODE (instance) == VAR_DECL))
-       vtbl = TYPE_BINFO_VTABLE (basetype);
+       {
+         vtbl = TYPE_BINFO_VTABLE (basetype);
+         /* Knowing the dynamic type of INSTANCE we can easily obtain
+            the correct vtable entry.  In the new ABI, we resolve
+            this back to be in terms of the primary vtable.  */
+         if (TREE_CODE (vtbl) == PLUS_EXPR)
+           {
+             idx = fold (build (PLUS_EXPR,
+                                TREE_TYPE (idx),
+                                idx,
+                                build (EXACT_DIV_EXPR,
+                                       TREE_TYPE (idx),
+                                       TREE_OPERAND (vtbl, 1),
+                                       TYPE_SIZE_UNIT (vtable_entry_type))));
+             vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
+           }
+       }
       else
        vtbl = build_vfield_ref (instance, basetype);
     }
@@ -733,10 +762,9 @@ build_primary_vtable (binfo, type)
        return 0;
       
       virtuals = copy_list (BINFO_VIRTUALS (binfo));
-      TREE_TYPE (decl) = TREE_TYPE (BINFO_VTABLE (binfo));
-      DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
-      DECL_SIZE_UNIT (decl)
-       = TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo)));
+      TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo));
+      DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl));
+      DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
     }
   else
     {
@@ -1623,6 +1651,97 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
     }
 }
 
+/* Called via dfs_walk from mark_primary_bases.  Sets
+   BINFO_PRIMARY_MARKED_P for BINFO, if appropriate.  */
+
+static tree
+dfs_mark_primary_bases (binfo, data)
+     tree binfo;
+     void *data;
+{
+  int i;
+  tree base_binfo;
+
+  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+    return NULL_TREE;
+
+  i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+  base_binfo = BINFO_BASETYPE (binfo, i);
+
+  if (!TREE_VIA_VIRTUAL (base_binfo))
+    /* Non-virtual base classes are easy.  */
+    BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+  else
+    {
+      tree shared_binfo;
+
+      shared_binfo 
+       = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
+
+      /* If this virtual base is not already primary somewhere else in
+        the hiearchy, then we'll be using this copy.  */
+      if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
+       {
+         BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
+         BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+       }
+    }
+
+  return NULL_TREE;
+}
+
+/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
+   dominated by BINFO that are primary bases.  */
+
+static void
+mark_primary_bases (type)
+     tree type;
+{
+  tree vbases;
+
+  /* Mark the TYPE_BINFO hierarchy.  We need to mark primary bases in
+     pre-order to deal with primary virtual bases.  (The virtual base
+     would be skipped if it were not marked as primary, and that
+     requires getting to dfs_mark_primary_bases before
+     dfs_skip_nonprimary_vbases_unmarkedp has a chance to skip the
+     virtual base.)  */
+  dfs_walk_real (TYPE_BINFO (type), dfs_mark_primary_bases, NULL,
+                dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+  /* Now go through the virtual base classes in inheritance graph
+     order.  Any that are not already primary will need to be
+     allocated in TYPE, and so we need to mark their primary bases.  */
+  for (vbases = TYPE_BINFO (type); vbases; vbases = TREE_CHAIN (vbases))
+    {
+      tree vbase;
+
+      /* Make sure that only BINFOs appear on this list.
+        Historically, the TREE_CHAIN was used for other purposes, and
+        we want to make sure that none of those uses remain.  */
+      my_friendly_assert (TREE_CODE (vbases) == TREE_VEC, 20000402);
+
+      if (!TREE_VIA_VIRTUAL (vbases))
+       continue;
+
+      vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), type);
+      if (BINFO_VBASE_PRIMARY_P (vbase))
+       /* This virtual base was already included in the hierarchy, so
+          there's nothing to do here.  */
+       continue;
+
+      /* Temporarily pretend that VBASE is primary so that its bases
+        will be walked; this is the real copy of VBASE.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 1;
+
+      /* Now, walk its bases.  */
+      dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
+                    dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+      /* VBASE wasn't really primary.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 0;
+    }
+}
+
 /* Make the Ith baseclass of T its primary base.  */
 
 static void
@@ -1696,7 +1815,7 @@ determine_primary_base (t, vfuns_p)
                                 VF_BASETYPE_VALUE (vfields),
                                 CLASSTYPE_VFIELDS (t));
 
-             if (*vfuns_p == 0)
+             if (!flag_new_abi && *vfuns_p == 0)
                set_primary_base (t, i, vfuns_p);
            }
        }
@@ -2184,6 +2303,7 @@ layout_vtable_decl (binfo, n)
 {
   tree itype;
   tree atype;
+  tree vtable;
 
   itype = size_int (n);
   atype = build_cplus_array_type (vtable_entry_type, 
@@ -2191,12 +2311,11 @@ layout_vtable_decl (binfo, n)
   layout_type (atype);
 
   /* We may have to grow the vtable.  */
-  if (!same_type_p (TREE_TYPE (BINFO_VTABLE (binfo)), atype))
+  vtable = get_vtbl_decl_for_binfo (binfo);
+  if (!same_type_p (TREE_TYPE (vtable), atype))
     {
-      tree vtable = BINFO_VTABLE (binfo);
-
       TREE_TYPE (vtable) = atype;
-      DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = 0;
+      DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = NULL_TREE;
       layout_decl (vtable, 0);
 
       /* At one time the vtable info was grabbed 2 words at a time.  This
@@ -2206,104 +2325,6 @@ layout_vtable_decl (binfo, n)
     }
 }
 
-/* Returns the number of virtual function table entries (excluding
-   RTTI information, vbase and vcall offests, etc.) in the vtable for
-   BINFO.  */
-
-static int
-num_vfun_entries (binfo)
-     tree binfo;
-{
-  return list_length (BINFO_VIRTUALS (binfo));
-}
-
-typedef struct vcall_offset_data_s
-{
-  /* The binfo for the most-derived type.  */
-  tree derived;
-  /* The binfo for the virtual base for which we're building
-     initializers.  */
-  tree vbase;
-  /* The vcall offset initializers built up so far.  */
-  tree inits;
-  /* The number of vcall offsets accumulated.  */
-  int offsets;
-} vcall_offset_data;
-
-/* Called from num_extra_vtbl_entries via dfs_walk.  */
-
-static tree
-dfs_count_virtuals (binfo, data)
-     tree binfo;
-     void *data;
-{
-  /* Non-primary bases are not interesting; all of the virtual
-     function table entries have been overridden.  */
-  if (!BINFO_PRIMARY_MARKED_P (binfo))
-    ((vcall_offset_data *) data)->offsets += num_vfun_entries (binfo);
-  
-  return NULL_TREE;
-}
-
-/* Returns the number of extra entries (at negative indices) required
-   for BINFO's vtable.  */
-
-tree
-num_extra_vtbl_entries (binfo)
-     tree binfo;
-{
-  tree type;
-  int entries;
-
-  type = BINFO_TYPE (binfo);
-  entries = 0;
-
-  /* There is an entry for the offset to each virtual base.  */
-  if (vbase_offsets_in_vtable_p ())
-    entries += list_length (CLASSTYPE_VBASECLASSES (type));
-
-  /* If this is a virtual base, there are entries for each virtual
-     function defined in this class or its bases.  */
-  if (vcall_offsets_in_vtable_p () && TREE_VIA_VIRTUAL (binfo))
-    {
-      vcall_offset_data vod;
-
-      vod.vbase = binfo;
-      vod.offsets = 0;
-      dfs_walk (binfo,
-               dfs_count_virtuals,
-               dfs_vcall_offset_queue_p,
-               &vod);
-      entries += vod.offsets;
-    }
-      
-  /* When laying out COM-compatible classes, there are no RTTI
-     entries.  */
-  if (CLASSTYPE_COM_INTERFACE (type))
-    ;
-  /* When using vtable thunks, there are two RTTI entries: the "offset
-     to top" value and the RTTI entry itself.  */
-  else if (flag_vtable_thunks)
-    entries += 2;
-  /* When not using vtable thunks there is only a single entry.  */
-  else
-    entries += 1;
-
-  return size_int (entries);
-}
-
-/* Returns the offset (in bytes) from the beginning of BINFO's vtable
-   where the vptr should actually point.  */
-
-tree
-size_extra_vtbl_entries (binfo)
-     tree binfo;
-{
-  tree offset = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type),
-                           num_extra_vtbl_entries (binfo));
-  return fold (offset);
-}
-
 /* True if we should override the given BASE_FNDECL with the given
    FNDECL.  */
 
@@ -3989,7 +4010,7 @@ check_bases_and_members (t, empty_p)
 /* 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
+   is not added to the TYPE_FIELDS list; it is the caller's
    responsibility to do that.  */
 
 static tree
@@ -4205,7 +4226,7 @@ layout_virtual_bases (t, base_offsets)
      tree t;
      varray_type *base_offsets;
 {
-  tree vbase;
+  tree vbases;
   unsigned HOST_WIDE_INT dsize;
   unsigned HOST_WIDE_INT eoc;
 
@@ -4225,53 +4246,70 @@ layout_virtual_bases (t, base_offsets)
   TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
 
   /* Go through the virtual bases, allocating space for each virtual
-     base that is not already a primary base class.  */
-  for (vbase = CLASSTYPE_VBASECLASSES (t); 
-       vbase; 
-       vbase = TREE_CHAIN (vbase))
-    if (!BINFO_VBASE_PRIMARY_P (vbase))
-      {
-       /* This virtual base is not a primary base of any class in the
-          hierarchy, so we have to add space for it.  */
-       tree basetype;
-       unsigned int desired_align;
+     base that is not already a primary base class.  Under the new
+     ABI, these are allocated according to a depth-first left-to-right
+     postorder traversal; in the new ABI, inheritance graph order is
+     used instead.  */
+  for (vbases = (flag_new_abi 
+                ? TYPE_BINFO (t) 
+                : CLASSTYPE_VBASECLASSES (t));
+       vbases; 
+       vbases = TREE_CHAIN (vbases))
+    {
+      tree vbase;
+
+      if (!TREE_VIA_VIRTUAL (vbases))
+       continue;
+
+      if (flag_new_abi)
+       vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), t);
+      else
+       vbase = vbases;
+
+      if (!BINFO_VBASE_PRIMARY_P (vbase))
+       {
+         /* This virtual base is not a primary base of any class in the
+            hierarchy, so we have to add space for it.  */
+         tree basetype;
+         unsigned int desired_align;
 
-       basetype = BINFO_TYPE (vbase);
+         basetype = BINFO_TYPE (vbase);
 
-       if (flag_new_abi)
-         desired_align = CLASSTYPE_ALIGN (basetype);
-       else
-         /* Under the old ABI, virtual bases were aligned as for the
+         if (flag_new_abi)
+           desired_align = CLASSTYPE_ALIGN (basetype);
+         else
+           /* Under the old ABI, virtual bases were aligned as for the
             entire base object (including its virtual bases).  That's
             wasteful, in general.  */
-         desired_align = TYPE_ALIGN (basetype);
-       TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
-
-       /* Add padding so that we can put the virtual base class at an
-          appropriately aligned offset.  */
-       dsize = CEIL (dsize, desired_align) * desired_align;
-
-       /* Under the new ABI, we try to squish empty virtual bases in
-          just like ordinary empty bases.  */
-       if (flag_new_abi && is_empty_class (basetype))
-         layout_empty_base (vbase,
-                            size_int (CEIL (dsize, BITS_PER_UNIT)),
-                            *base_offsets);
-       else
-         {
-           /* And compute the offset of the virtual base.  */
-           propagate_binfo_offsets (vbase, 
-                                    ssize_int (CEIL (dsize, BITS_PER_UNIT)));
-           /* Every virtual baseclass takes a least a UNIT, so that
-              we can take it's address and get something different
-              for each base.  */
-           dsize += MAX (BITS_PER_UNIT,
-                         tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
-         }
+           desired_align = TYPE_ALIGN (basetype);
+         TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
+
+         /* Add padding so that we can put the virtual base class at an
+            appropriately aligned offset.  */
+         dsize = CEIL (dsize, desired_align) * desired_align;
+
+         /* Under the new ABI, we try to squish empty virtual bases in
+            just like ordinary empty bases.  */
+         if (flag_new_abi && is_empty_class (basetype))
+           layout_empty_base (vbase,
+                              size_int (CEIL (dsize, BITS_PER_UNIT)),
+                              *base_offsets);
+         else
+           {
+             /* And compute the offset of the virtual base.  */
+             propagate_binfo_offsets (vbase, 
+                                      ssize_int (CEIL (dsize, BITS_PER_UNIT)));
+             /* Every virtual baseclass takes a least a UNIT, so that
+                we can take it's address and get something different
+                for each base.  */
+             dsize += MAX (BITS_PER_UNIT,
+                           tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
+           }
 
-       /* Keep track of the offsets assigned to this virtual base.  */
-       record_base_offsets (vbase, base_offsets);
-      }
+         /* Keep track of the offsets assigned to this virtual base.  */
+         record_base_offsets (vbase, base_offsets);
+       }
+    }
 
   /* Make sure that all of the CLASSTYPE_VBASECLASSES have their
      BINFO_OFFSET set correctly.  Those we just allocated certainly
@@ -4288,10 +4326,10 @@ layout_virtual_bases (t, base_offsets)
      in get_base_distance depend on the BINFO_OFFSETs being set
      correctly.  */
   dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
-  for (vbase = CLASSTYPE_VBASECLASSES (t);
-       vbase;
-       vbase = TREE_CHAIN (vbase))
-    dfs_walk (vbase, dfs_set_offset_for_unshared_vbases, NULL, t);
+  for (vbases = CLASSTYPE_VBASECLASSES (t);
+       vbases;
+       vbases = TREE_CHAIN (vbases))
+    dfs_walk (vbases, dfs_set_offset_for_unshared_vbases, NULL, t);
 
   /* If we had empty base classes that protruded beyond the end of the
      class, we didn't update DSIZE above; we were hoping to overlay
@@ -4310,11 +4348,11 @@ layout_virtual_bases (t, base_offsets)
 
   /* Check for ambiguous virtual bases.  */
   if (extra_warnings)
-    for (vbase = CLASSTYPE_VBASECLASSES (t); 
-        vbase; 
-        vbase = TREE_CHAIN (vbase))
+    for (vbases = CLASSTYPE_VBASECLASSES (t); 
+        vbases
+        vbases = TREE_CHAIN (vbases))
       {
-       tree basetype = BINFO_TYPE (vbase);
+       tree basetype = BINFO_TYPE (vbases);
        if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
          cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
                      basetype, t);
@@ -4572,7 +4610,7 @@ layout_class_type (t, empty_p, vfuns_p,
   /* Clean up.  */
   VARRAY_FREE (v);
 }
-     
+
 /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
    (or C++ class declaration).
 
@@ -4791,7 +4829,7 @@ finish_struct_1 (t)
      the base types we marked.  */
   finish_vtbls (t);
 
-  if (CLASSTYPE_VSIZE (t) != 0)
+  if (TYPE_VFIELD (t))
     {
       /* In addition to this one, all the other vfields should be listed.  */
       /* Before that can be done, we have to have FIELD_DECLs for them, and
@@ -5030,13 +5068,13 @@ init_class_processing ()
                                    * sizeof (struct class_stack_node));
 
   access_default_node = build_int_2 (0, 0);
-  access_public_node = build_int_2 (1, 0);
-  access_protected_node = build_int_2 (2, 0);
-  access_private_node = build_int_2 (3, 0);
+  access_public_node = build_int_2 (ak_public, 0);
+  access_protected_node = build_int_2 (ak_protected, 0);
+  access_private_node = build_int_2 (ak_private, 0);
   access_default_virtual_node = build_int_2 (4, 0);
-  access_public_virtual_node = build_int_2 (5, 0);
-  access_protected_virtual_node = build_int_2 (6, 0);
-  access_private_virtual_node = build_int_2 (7, 0);
+  access_public_virtual_node = build_int_2 (4 | ak_public, 0);
+  access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
+  access_private_virtual_node = build_int_2 (4 | ak_private, 0);
 }
 
 /* Set current scope to NAME. CODE tells us if this is a
@@ -6047,12 +6085,36 @@ note_name_declared_in_class (name, decl)
     }
 }
 
-/* Dump the offsets of all the bases rooted at BINFO to stderr.
-   INDENT should be zero when called from the top level; it is
-   incremented recursively.  */
+/* Returns the VAR_DECL for the complete vtable associated with
+   BINFO.  (Under the new ABI, secondary vtables are merged with
+   primary vtables; this function will return the VAR_DECL for the
+   primary vtable.)  */
 
-void
-dump_class_hierarchy (binfo, indent)
+tree
+get_vtbl_decl_for_binfo (binfo)
+     tree binfo;
+{
+  tree decl;
+
+  decl = BINFO_VTABLE (binfo);
+  if (decl && TREE_CODE (decl) == PLUS_EXPR)
+    {
+      my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
+                         2000403);
+      decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
+    }
+  if (decl)
+    my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
+  return decl;
+}
+
+/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
+   dominated by T) to stderr.  INDENT should be zero when called from
+   the top level; it is incremented recursively.  */
+
+static void
+dump_class_hierarchy_r (t, binfo, indent)
+     tree t;
      tree binfo;
      int indent;
 {
@@ -6063,11 +6125,31 @@ dump_class_hierarchy (binfo, indent)
           type_as_string (binfo, TS_PLAIN));
   fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
           tree_low_cst (BINFO_OFFSET (binfo), 0));
-  fprintf (stderr, " %s\n",
-          BINFO_PRIMARY_MARKED_P (binfo) ? "primary" : "");
+  if (TREE_VIA_VIRTUAL (binfo))
+    fprintf (stderr, " virtual");
+  if (BINFO_PRIMARY_MARKED_P (binfo)
+      || (TREE_VIA_VIRTUAL (binfo) 
+         && BINFO_VBASE_PRIMARY_P (BINFO_FOR_VBASE (BINFO_TYPE (binfo), 
+                                                    t))))
+    fprintf (stderr, " primary");
+  fprintf (stderr, "\n");
 
   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
-    dump_class_hierarchy (BINFO_BASETYPE (binfo, i), indent + 2);
+    dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
+}
+
+/* Dump the BINFO hierarchy for T.  */
+
+void
+dump_class_hierarchy (t)
+     tree t;
+{
+  tree vbase;
+
+  dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
+  fprintf (stderr, "virtual bases\n");
+  for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; vbase = TREE_CHAIN (vbase))
+    dump_class_hierarchy_r (t, vbase, 0);
 }
 
 /* Virtual function table initialization.  */
@@ -6087,14 +6169,18 @@ finish_vtbls (t)
         vtables in one contiguous vtable.  The primary vtable is
         first, followed by the non-virtual secondary vtables in
         inheritance graph order.  */
-      list = build_tree_list (t, NULL_TREE);
+      list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
+      TREE_TYPE (list) = t;
       accumulate_vtbl_inits (TYPE_BINFO (t), list);
       /* Then come the virtual bases, also in inheritance graph
         order.  */
-      for (vbase = CLASSTYPE_VBASECLASSES (t);
-          vbase;
-          vbase = TREE_CHAIN (vbase))
-       accumulate_vtbl_inits (vbase, list);
+      for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
+       {
+         if (!TREE_VIA_VIRTUAL (vbase))
+           continue;
+         accumulate_vtbl_inits (BINFO_FOR_VBASE (BINFO_TYPE (vbase), t),
+                                list);
+       }
 
       if (TYPE_BINFO_VTABLE (t))
        initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
@@ -6121,7 +6207,7 @@ dfs_finish_vtbls (binfo, data)
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
       && BINFO_NEW_VTABLE_MARKED (binfo, t))
     initialize_vtable (binfo, 
-                      build_vtbl_initializer (binfo, t));
+                      build_vtbl_initializer (binfo, t, NULL));
 
   CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
   SET_BINFO_MARKED (binfo);
@@ -6140,7 +6226,7 @@ initialize_vtable (binfo, inits)
   tree decl;
 
   layout_vtable_decl (binfo, list_length (inits));
-  decl = BINFO_VTABLE (binfo);
+  decl = get_vtbl_decl_for_binfo (binfo);
   context = DECL_CONTEXT (decl);
   DECL_CONTEXT (decl) = 0;
   DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
@@ -6156,10 +6242,12 @@ accumulate_vtbl_inits (binfo, inits)
      tree binfo;
      tree inits;
 {
-  /* Walk the BINFO and its bases.  */
+  /* Walk the BINFO and its bases.  We walk in preorder so that as we
+     initialize each vtable we can figure out at what offset the
+     secondary vtable lies from the primary vtable.  */
   dfs_walk_real (binfo,
                 dfs_accumulate_vtbl_inits,
-                NULL, 
+                NULL,
                 dfs_skip_vbases,
                 inits);
 }
@@ -6177,33 +6265,37 @@ dfs_accumulate_vtbl_inits (binfo, data)
   tree t;
 
   l = (tree) data;
-  t = TREE_PURPOSE (l);
+  t = TREE_TYPE (l);
 
   if (!BINFO_PRIMARY_MARKED_P (binfo)
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
       && BINFO_NEW_VTABLE_MARKED (binfo, t))
     {
-      /* If this is a secondary vtable, record its location.  */
-      if (binfo != TYPE_BINFO (t))
-       {
-         tree vtbl;
-
-         vtbl = TYPE_BINFO_VTABLE (t);
-         vtbl = build1 (ADDR_EXPR, 
-                        build_pointer_type (TREE_TYPE (vtbl)),
-                        vtbl);
-         BINFO_VTABLE (binfo)
-           = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
-                    size_binop (MULT_EXPR,
-                                TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
-                                size_int (list_length (TREE_VALUE (l)))));
-       }
+      tree inits;
+      tree vtbl;
+      tree index;
+      int non_fn_entries;
+
+      /* Compute the initializer for this vtable.  */
+      inits = build_vtbl_initializer (binfo, t, &non_fn_entries);
+
+      /* Set BINFO_VTABLE to the address where the VPTR should point.  */
+      vtbl = TREE_PURPOSE (l);
+      vtbl = build1 (ADDR_EXPR, 
+                    build_pointer_type (TREE_TYPE (vtbl)),
+                    vtbl);
+      index = size_binop (PLUS_EXPR,
+                         size_int (non_fn_entries),
+                         size_int (list_length (TREE_VALUE (l))));
+      BINFO_VTABLE (binfo)
+       = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
+                size_binop (MULT_EXPR,
+                            TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
+                            index));
 
       /* Add the initializers for this vtable to the initializers for
         the other vtables we've already got.  */
-      TREE_VALUE (l) 
-       = chainon (TREE_VALUE (l),
-                  build_vtbl_initializer (binfo, t));
+      TREE_VALUE (l) = chainon (TREE_VALUE (l), inits);
     }
 
   CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
@@ -6214,29 +6306,48 @@ dfs_accumulate_vtbl_inits (binfo, data)
 /* Construct the initializer for BINFOs virtual function table.  BINFO
    is part of the hierarchy dominated by T.  The value returned is a
    TREE_LIST suitable for wrapping in a CONSTRUCTOR to use as the
-   DECL_INITIAL for a vtable.  */
+   DECL_INITIAL for a vtable.  If NON_FN_ENTRIES_P is not NULL,
+   *NON_FN_ENTRIES_P is set to the number of non-function entries in
+   the vtable.  */
 
 static tree
-build_vtbl_initializer (binfo, t)
+build_vtbl_initializer (binfo, t, non_fn_entries_p)
      tree binfo;
      tree t;
+     int *non_fn_entries_p;
 {
   tree v = BINFO_VIRTUALS (binfo);
   tree inits = NULL_TREE;
+  tree vfun_inits;
+  tree vbase;
+  vcall_offset_data vod;
 
-  /* Add entries to the vtable that indicate how to adjust the this
-     pointer when calling a virtual function in this class.  */
-  inits = build_vcall_offset_vtbl_entries (binfo, t);
-
-  /* Add entries to the vtable for offsets to our virtual bases.  */
-  inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
-                  inits);
+  /* Initialize those parts of VOD that matter.  */
+  vod.derived = t;
+  vod.inits = NULL_TREE;
+  vod.primary_p = (binfo == TYPE_BINFO (t));
+  /* The first vbase or vcall offset is at index -3 in the vtable.  */
+  vod.index = build_int_2 (-3, -1);
+
+  /* Add the vcall and vbase offset entries.  */
+  build_vcall_and_vbase_vtbl_entries (binfo, &vod);
+  inits = vod.inits;
+  /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+     build_vbase_offset_vtbl_entries.  */
+  for (vbase = CLASSTYPE_VBASECLASSES (t); 
+       vbase; 
+       vbase = TREE_CHAIN (vbase))
+    CLEAR_BINFO_VTABLE_PATH_MARKED (vbase);
 
   /* Add entries to the vtable for RTTI.  */
-  inits = chainon (build_rtti_vtbl_entries (binfo, t), inits);
+  inits = chainon (inits, build_rtti_vtbl_entries (binfo, t));
+
+  if (non_fn_entries_p)
+    *non_fn_entries_p = list_length (inits);
 
   /* Go through all the ordinary virtual functions, building up
      initializers.  */
+  vfun_inits = NULL_TREE;
   while (v)
     {
       tree delta;
@@ -6266,118 +6377,133 @@ build_vtbl_initializer (binfo, t)
       /* Enter it in the vtable.  */
       init = build_vtable_entry (delta, vcall_index, pfn);
       /* And add it to the chain of initializers.  */
-      inits = tree_cons (NULL_TREE, init, inits);
+      vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
 
       /* Keep going.  */
       v = TREE_CHAIN (v);
     }
 
-  /* The initializers were built up in reverse order; straighten them
-     out now.  */
-  return nreverse (inits);
+  /* The initializers for virtual functions were built up in reverse
+     order; straighten them out now.  */
+  vfun_inits = nreverse (vfun_inits);
+  
+  /* The complete initializer is the INITS, followed by the
+     VFUN_INITS.  */
+  return chainon (inits, vfun_inits);
 }
 
-/* Called from build_vbase_offset_vtbl_entries via dfs_walk.  */
+/* Sets vod->inits to be the initializers for the vbase and vcall
+   offsets in BINFO, which is in the hierarchy dominated by T.  */
 
-static tree
-dfs_build_vbase_offset_vtbl_entries (binfo, data)
+static void
+build_vcall_and_vbase_vtbl_entries (binfo, vod)
      tree binfo;
-     void *data;
+     vcall_offset_data *vod;
 {
-  tree list = (tree) data;
-
-  if (TREE_TYPE (list) == binfo)
-    /* The TREE_TYPE of LIST is the base class from which we started
-       walking.  If that BINFO is virtual it's not a virtual baseclass
-       of itself.  */
-    ;
-  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 (BINFO_TYPE (binfo), TREE_PURPOSE (list));
-      if (!TREE_VALUE (list))
-       BINFO_VPTR_FIELD (vbase) = build_int_2 (-3, 0);
-      else
-       {
-         BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
-         BINFO_VPTR_FIELD (vbase)
-           = fold (build (MINUS_EXPR, integer_type_node,
-                          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));
-    }
+  tree b;
+  tree inits;
 
-  SET_BINFO_VTABLE_PATH_MARKED (binfo);
-  
-  return NULL_TREE;
+  /* If this is a derived class, we must first create entries
+     corresponding to the base class.  These entries must go closer to
+     the vptr, so we save them up and add them to the end of the list
+     later.  */
+  inits = vod->inits;
+  vod->inits = NULL_TREE;
+  b = BINFO_PRIMARY_BINFO (binfo);
+  if (b)
+    build_vcall_and_vbase_vtbl_entries (b, vod);
+
+  /* Add the vbase entries for this base.  */
+  build_vbase_offset_vtbl_entries (binfo, vod);
+  /* Add the vcall entries for this base.  */
+  build_vcall_offset_vtbl_entries (binfo, vod);
+
+  vod->inits = chainon (vod->inits, inits);
 }
 
 /* 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.  */
+   reverse order.  VBASE_OFFSET_INDEX gives the vtable index
+   where the next vbase offset will go.  */
 
-static tree
-build_vbase_offset_vtbl_entries (binfo, t)
+static void
+build_vbase_offset_vtbl_entries (binfo, vod)
      tree binfo;
-     tree t;
+     vcall_offset_data *vod;
 {
-  tree inits;
-  tree init;
-  tree list;
+  tree vbase;
+  tree t;
 
   /* Under the old ABI, pointers to virtual bases are stored in each
      object.  */
   if (!vbase_offsets_in_vtable_p ())
-    return NULL_TREE;
+    return;
 
   /* If there are no virtual baseclasses, then there is nothing to
      do.  */
   if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
-    return NULL_TREE;
+    return;
 
-  inits = NULL_TREE;
+  t = vod->derived;
 
-  /* 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,
-           unmarked_vtable_pathp,
-           list);
-  dfs_walk (binfo,
-           dfs_vtable_path_unmark,
-           marked_vtable_pathp,
-           list);
-  inits = nreverse (TREE_VALUE (list));
-
-  /* We've now got offsets in the right order.  However, the offsets
-     we've stored are offsets from the beginning of the complete
-     object, and we need offsets from this BINFO.  */
-  for (init = inits; init; init = TREE_CHAIN (init))
-    {
-      /* 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)
-       = fold (build1 (NOP_EXPR, vtable_entry_type,
-                       size_diffop (TREE_VALUE (init),
-                                    BINFO_OFFSET (binfo))));
-    }
+  /* Go through the virtual bases, adding the offsets.  */
+  for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
+       vbase;
+       vbase = TREE_CHAIN (vbase))
+    {
+      tree b;
+      tree delta;
+      
+      if (!TREE_VIA_VIRTUAL (vbase))
+       continue;
 
-  return inits;
+      /* Find the instance of this virtual base in the complete
+        object.  */
+      b = BINFO_FOR_VBASE (BINFO_TYPE (vbase), t);
+
+      /* If we've already got an offset for this virtual base, we
+        don't need another one.  */
+      if (BINFO_VTABLE_PATH_MARKED (b))
+       continue;
+      SET_BINFO_VTABLE_PATH_MARKED (b);
+
+      /* Figure out where we can find this vbase offset.  */
+      delta = size_binop (MULT_EXPR, 
+                         convert (ssizetype, vod->index),
+                         convert (ssizetype,
+                                  TYPE_SIZE_UNIT (vtable_entry_type)));
+      if (vod->primary_p)
+       BINFO_VPTR_FIELD (b) = delta;
+
+      if (binfo != TYPE_BINFO (t))
+       {
+         tree orig_vbase;
+
+         /* Find the instance of this virtual base in the type of BINFO.  */
+         orig_vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbase),
+                                       BINFO_TYPE (binfo));
+
+         /* The vbase offset had better be the same.  */
+         if (!tree_int_cst_equal (delta,
+                                  BINFO_VPTR_FIELD (orig_vbase)))
+           my_friendly_abort (20000403);
+       }
+
+      /* The next vbase will come at a more negative offset.  */
+      vod->index = fold (build (MINUS_EXPR, integer_type_node,
+                               vod->index, integer_one_node));
+
+      /* The initializer is the delta from BINFO to this virtual base.
+          The vbase offsets go in reverse inheritance-graph order, and
+          we are walking in inheritance graph order so these end up in
+          the right order.  */
+      delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
+      vod->inits = tree_cons (NULL_TREE, 
+                             fold (build1 (NOP_EXPR, 
+                                           vtable_entry_type,
+                                           delta)),
+                             vod->inits);
+    }
 }
 
 /* Called from build_vcall_offset_vtbl_entries via dfs_walk.  */
@@ -6402,20 +6528,22 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
   vcall_offset_data* vod;
   tree virtuals;
   tree binfo_inits;
-
-  /* Primary bases are not interesting; all of the virtual
-     function table entries have been overridden.  */
-  if (BINFO_PRIMARY_MARKED_P (binfo))
-     return NULL_TREE;
+  tree b;
+  int i;
 
   vod = (vcall_offset_data *) data;
   binfo_inits = NULL_TREE;
+  
+  /* Skip virtuals that we have already handled in a primary base
+     class.  */
+  virtuals = BINFO_VIRTUALS (binfo);
+  b = BINFO_PRIMARY_BINFO (binfo);
+  if (b)
+    for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (b)); ++i)
+      virtuals = TREE_CHAIN (virtuals);
 
-  /* We chain the offsets on in reverse order.  That's correct --
-     build_vtbl_initializer will straighten them out.  */
-  for (virtuals = BINFO_VIRTUALS (binfo);
-       virtuals;
-       virtuals = TREE_CHAIN (virtuals))
+  /* Make entries for the rest of the virtuals.  */
+  while (virtuals)
     {
       /* Figure out what function we're looking at.  */
       tree fn = TREE_VALUE (virtuals);
@@ -6430,34 +6558,48 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
                                   size_diffop (BINFO_OFFSET (base_binfo),
                                                BINFO_OFFSET (vod->vbase)))),
                     binfo_inits);
+      vod->index = fold (build (MINUS_EXPR, integer_type_node,
+                               vod->index, integer_one_node));
+      virtuals = TREE_CHAIN (virtuals);
     }
 
-  /* Now add the initializers we've just created to the list that will
-     be returned to our caller.  */
-  vod->inits = chainon (vod->inits, binfo_inits);
+  /* The offests are built up in reverse order, so we straighten them
+     here.  We simultaneously add them to VOD->INITS; we're walking
+     the bases in inheritance graph order, and the initializers are
+     supposed to appear in reverse inheritance order, so that's
+     correct.  */
+  while (binfo_inits)
+    {
+      tree next;
+
+      next = TREE_CHAIN (binfo_inits);
+      TREE_CHAIN (binfo_inits) = vod->inits;
+      vod->inits = binfo_inits;
+      binfo_inits = next;
+    }
 
   return NULL_TREE;
 }
 
-/* Returns the initializers for the vcall offset entries in the vtable
-   for BINFO (which is part of the class hierarchy dominated by T), in
-   reverse order.  */
+/* Adds the initializers for the vcall offset entries in the vtable
+   for BINFO (which is part of the class hierarchy dominated by T) to
+   VOD->INITS.  */
 
-static tree
-build_vcall_offset_vtbl_entries (binfo, t)
+static void
+build_vcall_offset_vtbl_entries (binfo, vod)
      tree binfo;
-     tree t;
+     vcall_offset_data *vod;
 {
-  vcall_offset_data vod;
+  tree inits;
 
   /* Under the old ABI, the adjustments to the `this' pointer were made
      elsewhere.  */
   if (!vcall_offsets_in_vtable_p ())
-    return NULL_TREE;
+    return;
 
   /* We only need these entries if this base is a virtual base.  */
   if (!TREE_VIA_VIRTUAL (binfo))
-    return NULL_TREE;
+    return;
 
   /* We need a vcall offset for each of the virtual functions in this
      vtable.  For example:
@@ -6481,15 +6623,15 @@ build_vcall_offset_vtbl_entries (binfo, t)
      in our non-virtual bases vtables.  For each base, the entries
      appear in the same order as in the base; but the bases themselves
      appear in reverse depth-first, left-to-right order.  */
-  vod.derived = t;
-  vod.vbase = binfo;
-  vod.inits = NULL_TREE;
-  dfs_walk (binfo,
-           dfs_build_vcall_offset_vtbl_entries,
-           dfs_vcall_offset_queue_p,
-           &vod);
-
-  return vod.inits;
+  vod->vbase = binfo;
+  inits = vod->inits;
+  vod->inits = NULL_TREE;
+  dfs_walk_real (binfo,
+                dfs_build_vcall_offset_vtbl_entries,
+                NULL,
+                dfs_vcall_offset_queue_p,
+                vod);
+  vod->inits = chainon (vod->inits, inits);
 }
 
 /* Return vtbl initializers for the RTTI entries coresponding to the
@@ -6503,10 +6645,10 @@ build_rtti_vtbl_entries (binfo, t)
 {
   tree b;
   tree basetype;
-  tree inits;
   tree offset;
   tree decl;
   tree init;
+  tree inits;
 
   basetype = BINFO_TYPE (binfo);
   inits = NULL_TREE;
@@ -6519,19 +6661,15 @@ build_rtti_vtbl_entries (binfo, t)
      primary base, and then add the offset in the vtbl to that value.  */
   b = binfo;
   while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)))
-    b = BINFO_BASETYPE (b, 
-                       CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (b)));
-  offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
-
-  /* Add the offset-to-top entry.  */
-  if (flag_vtable_thunks)
     {
-      /* Convert the offset to look like a function pointer, so that
-        we can put it in the vtable.  */
-      init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
-      TREE_CONSTANT (init) = 1;
-      inits = tree_cons (NULL_TREE, init, inits);
+      tree primary_base;
+
+      primary_base = BINFO_PRIMARY_BINFO (b);
+      if (!BINFO_PRIMARY_MARKED_P (primary_base))
+       break;
+      b = primary_base;
     }
+  offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
 
   /* The second entry is, in the case of the new ABI, the address of
      the typeinfo object, or, in the case of the old ABI, a function
@@ -6561,10 +6699,19 @@ build_rtti_vtbl_entries (binfo, t)
       TREE_CONSTANT (init) = 1;
       init = build_vtable_entry (offset, integer_zero_node, init);
     }
-
-  /* Hook the RTTI declaration onto the list.  */
   inits = tree_cons (NULL_TREE, init, inits);
 
+  /* Add the offset-to-top entry.  It comes earlier in the vtable that
+     the the typeinfo entry.  */
+  if (flag_vtable_thunks)
+    {
+      /* Convert the offset to look like a function pointer, so that
+        we can put it in the vtable.  */
+      init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+      TREE_CONSTANT (init) = 1;
+      inits = tree_cons (NULL_TREE, init, inits);
+    }
+
   return inits;
 }
 
index 0433135..07b8675 100644 (file)
@@ -55,8 +55,6 @@ Boston, MA 02111-1307, USA.  */
       ICS_ELLIPSIS_FLAG (in _CONV)
       STMT_IS_FULL_EXPR_P (in _STMT)
    2: IDENTIFIER_OPNAME_P.
-      BINFO_VBASE_MARKED.
-      BINFO_FIELDS_MARKED.
       TYPE_POLYMORHPIC_P (in _TYPE)
       ICS_THIS_FLAG (in _CONV)
       STMT_LINENO_FOR_FN_P (in _STMT)
@@ -130,6 +128,13 @@ Boston, MA 02111-1307, USA.  */
      this function.  (This binfo's BINFO_TYPE will always be the same
      as the DECL_CLASS_CONTEXT for the function.)
 
+   BINFO_VTABLE
+     Sometimes this is a VAR_DECL.  Under the new ABI, it is instead
+     an expression with POINTER_TYPE pointing that gives the value
+     to which the vptr should be initialized.  Use get_vtbl_decl_for_binfo
+     to extract the VAR_DECL for the complete vtable; that macro works
+     in both ABIs.
+
    DECL_ARGUMENTS
      For a VAR_DECL this is DECL_ANON_UNION_ELEMS.  
 
@@ -1356,24 +1361,17 @@ struct lang_type
   int vsize;
   int vfield_parent;
 
-  union tree_node *vfields;
-  union tree_node *vbases;
-
-  union tree_node *tags;
-
-  union tree_node *search_slot;
-
-  union tree_node *size;
-  union tree_node *size_unit;
-
-  union tree_node *pure_virtuals;
-  union tree_node *friend_classes;
-
-  union tree_node *rtti;
-
-  union tree_node *methods;
-
-  union tree_node *template_info;
+  tree vfields;
+  tree vbases;
+  tree tags;
+  tree search_slot;
+  tree size;
+  tree size_unit;
+  tree pure_virtuals;
+  tree friend_classes;
+  tree rtti;
+  tree methods;
+  tree template_info;
   tree befriending_classes;
 };
 
@@ -1538,21 +1536,29 @@ struct lang_type
 #define CLASSTYPE_PRIMARY_BINFO(NODE) \
   (BINFO_PRIMARY_BINFO (TYPE_BINFO (NODE)))
 
-/* If non-NULL, this is the binfo for the primary base of BINFO.  */
+/* If non-NULL, this is the binfo for the primary base of BINFO.  Note
+   that in a complex hierarchy the resulting BINFO may not actually
+   *be* primary.  In particular if the resulting BINFO is a virtual
+   base, and it occurs elsewhere in the hierarchy, then this
+   occurrence may not actually be a primary base in the complete
+   object.  Check BINFO_PRIMARY_MARKED_P to be sure.  */
 #define BINFO_PRIMARY_BINFO(NODE)                                      \
   (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (NODE))                    \
    ? BINFO_BASETYPE (NODE,                                             \
                     CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE)))       \
    : NULL_TREE)
 
-/* The number of virtual functions present in this classes virtual
+/* The number of virtual functions present in this class' virtual
    function table.  */
 #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
 
 /* A chain of BINFOs for the direct and indirect virtual base classes
-   that this type uses in depth-first left-to-right order.  These
-   BINFOs are distinct from those in the TYPE_BINFO hierarchy.  So,
-   given: 
+   that this type uses in a post-order depth-first left-to-right
+   order.  (In other words, these bases appear in the order that they
+   should be initialized.)
+
+   These BINFOs are distinct from those in the TYPE_BINFO hierarchy.
+   So, given:
 
      struct A {};
      struct B : public A {};
@@ -1683,9 +1689,7 @@ struct lang_type
 
    We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private
    inheritance is indicated by the absence of the other two flags, not
-   by TREE_VIA_PRIVATE, which is unused.
-
-   The TREE_CHAIN is for scratch space in search.c.  */
+   by TREE_VIA_PRIVATE, which is unused.  */
 
 /* Nonzero means marked by DFS or BFS search, including searches
    by `get_binfo' and `get_base_distance'.  */
@@ -1695,18 +1699,6 @@ struct lang_type
 #define SET_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=1))
 #define CLEAR_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=0))
 
-/* Nonzero means marked in search through virtual inheritance hierarchy.  */
-#define BINFO_VBASE_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-/* Modifier macros */
-#define SET_BINFO_VBASE_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-#define CLEAR_BINFO_VBASE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-
-/* Nonzero means marked in search for members or member functions.  */
-#define BINFO_FIELDS_MARKED(NODE) \
-  (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)):TREE_LANG_FLAG_2(NODE))
-#define SET_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=1))
-#define CLEAR_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=0))
-
 /* Nonzero means that this class is on a path leading to a new vtable.  */
 #define BINFO_VTABLE_PATH_MARKED(NODE) \
   (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):TREE_LANG_FLAG_3(NODE))
@@ -3081,6 +3073,17 @@ typedef enum tmpl_spec_kind {
   tsk_expl_inst            /* An explicit instantiation.  */
 } tmpl_spec_kind;
 
+/* The various kinds of access.  BINFO_ACCESS depends on these being
+   two bit quantities.  The numerical values are important; they are
+   used to initialize RTTI data structures, so chaning them changes
+   the ABI.  */
+typedef enum access_kind {
+  ak_none = 0,             /* Inaccessible.  */
+  ak_public = 1,           /* Accessible, as a `public' thing.  */
+  ak_protected = 2,        /* Accessible, as a `protected' thing.  */
+  ak_private = 3           /* Accessible, as a `private' thing.  */
+} access_kind;
+
 /* Zero means prototype weakly, as in ANSI C (no args means nothing).
    Each language context defines how this variable should be set.  */
 extern int strict_prototype;
@@ -3694,8 +3697,7 @@ extern void unreverse_member_declarations       PARAMS ((tree));
 extern void invalidate_class_lookup_cache       PARAMS ((void));
 extern void maybe_note_name_used_in_class       PARAMS ((tree, tree));
 extern void note_name_declared_in_class         PARAMS ((tree, tree));
-extern tree num_extra_vtbl_entries              PARAMS ((tree));
-extern tree size_extra_vtbl_entries             PARAMS ((tree));
+extern tree get_vtbl_decl_for_binfo           PARAMS ((tree));
 
 /* in cvt.c */
 extern tree convert_to_reference               PARAMS ((tree, tree, int, int, tree));
@@ -4203,7 +4205,6 @@ extern tree dfs_walk_real                      PARAMS ((tree,
                                                       tree (*) (tree, void *),
                                                       void *));
 extern tree dfs_unmark                          PARAMS ((tree, void *));
-extern tree dfs_vbase_unmark                    PARAMS ((tree, void *));
 extern tree dfs_vtable_path_unmark              PARAMS ((tree, void *));
 extern tree markedp                             PARAMS ((tree, void *));
 extern tree unmarkedp                           PARAMS ((tree, void *));
@@ -4214,7 +4215,6 @@ extern tree dfs_marked_real_bases_queue_p       PARAMS ((tree, void *));
 extern tree dfs_skip_vbases                     PARAMS ((tree, void *));
 extern tree marked_vtable_pathp                 PARAMS ((tree, void *));
 extern tree unmarked_vtable_pathp               PARAMS ((tree, void *));
-extern void mark_primary_bases                  PARAMS ((tree));
 extern tree convert_pointer_to_vbase            PARAMS ((tree, tree));
 extern tree find_vbase_instance                 PARAMS ((tree, tree));
 
index 37a352e..be51512 100644 (file)
@@ -2544,7 +2544,7 @@ output_vtable_inherit (vars)
     op[1] = const0_rtx;
   else if (parent)
     {
-      parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent));
+      parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent)));
       op[1] = XEXP (DECL_RTL (parent), 0);  /* strip the mem ref  */
     }
   else
index ff8e058..4623abf 100644 (file)
@@ -653,31 +653,23 @@ expand_virtual_init (binfo, decl)
   tree type = BINFO_TYPE (binfo);
   tree vtbl, vtbl_ptr;
   tree vtype, vtype_binfo;
+  tree b;
 
   /* Compute the location of the vtable.  */
   vtype = DECL_CONTEXT (TYPE_VFIELD (type));
   vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
-  vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
+  b = binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo);
 
+  /* Figure out what vtable BINFO's vtable is based on, and mark it as
+     used.  */
+  vtbl = get_vtbl_decl_for_binfo (b);
+  assemble_external (vtbl);
+  TREE_USED (vtbl) = 1;
+
+  /* Now compute the address to use when initializing the vptr.  */
+  vtbl = BINFO_VTABLE (b);
   if (TREE_CODE (vtbl) == VAR_DECL)
-    {
-      assemble_external (vtbl);
-      TREE_USED (vtbl) = 1;
-      vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
-    }
-  else
-    /* Under the new ABI, secondary vtables are stored with the
-       primary vtable.  So, the BINFO_VTABLE may be an expression for
-       computing the secondary vtable, rather than the secondary
-       vtable itself.  */
-    my_friendly_assert (merge_primary_and_secondary_vtables_p (), 
-                       20000220);
-
-  /* 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));
+    vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
 
   /* Compute the location of the vtpr.  */
   decl = convert_pointer_to_real (vtype_binfo, decl);
index 99d53f0..0d3879e 100644 (file)
@@ -103,7 +103,7 @@ repo_get_id (t)
       if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t))
        my_friendly_abort (981113);
 
-      t = TYPE_BINFO_VTABLE (t);
+      t = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
       if (t == NULL_TREE)
        return t;
     }
index e9873ba..a5429ec 100644 (file)
@@ -1640,11 +1640,14 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
 
   /* Under the new ABI, we need to point into the middle of the
      vtable.  */
-  if (vbase_offsets_in_vtable_p ())
+  if (flag_new_abi)
     {
-      vtable_decl = build (PLUS_EXPR, TREE_TYPE (vtable_decl), 
+      vtable_decl = build (PLUS_EXPR,
+                          TREE_TYPE (vtable_decl),
                           vtable_decl,
-                          size_extra_vtbl_entries (TYPE_BINFO (real_type)));
+                          size_binop (MULT_EXPR,
+                                      size_int (2),
+                                      TYPE_SIZE_UNIT (vtable_entry_type)));
       TREE_CONSTANT (vtable_decl) = 1;
     }
 
index 14ceff2..4c4b600 100644 (file)
@@ -143,7 +143,7 @@ static int  dependent_base_p PARAMS ((tree));
 static tree dfs_accessible_queue_p PARAMS ((tree, void *));
 static tree dfs_accessible_p PARAMS ((tree, void *));
 static tree dfs_access_in_type PARAMS ((tree, void *));
-static tree access_in_type PARAMS ((tree, tree));
+static access_kind access_in_type PARAMS ((tree, tree));
 static tree dfs_canonical_queue PARAMS ((tree, void *));
 static tree dfs_assert_unmarked_p PARAMS ((tree, void *));
 static void assert_canonical_unmarked PARAMS ((tree));
@@ -152,7 +152,6 @@ static int friend_accessible_p PARAMS ((tree, tree, tree));
 static void setup_class_bindings PARAMS ((tree, int));
 static int template_self_reference_p PARAMS ((tree, tree));
 static void fixup_all_virtual_upcast_offsets PARAMS ((tree, tree));
-static tree dfs_mark_primary_bases PARAMS ((tree, void *));
 static tree get_shared_vbase_if_not_primary PARAMS ((tree, void *));
 static tree dfs_find_vbase_instance PARAMS ((tree, void *));
 static tree dfs_get_pure_virtuals PARAMS ((tree, void *));
@@ -811,6 +810,18 @@ shared_unmarked_p (binfo, data)
   return unmarkedp (binfo, data);
 }
 
+/* The accessibility routines use BINFO_ACCESS for scratch space
+   during the computation of the accssibility of some declaration.  */
+
+#define BINFO_ACCESS(NODE) \
+  ((access_kind) ((TREE_LANG_FLAG_1 (NODE) << 1) | TREE_LANG_FLAG_6 (NODE)))
+
+/* Set the access associated with NODE to ACCESS.  */
+
+#define SET_BINFO_ACCESS(NODE, ACCESS)                 \
+  ((TREE_LANG_FLAG_1 (NODE) = (ACCESS & 2) != 0),      \
+   (TREE_LANG_FLAG_6 (NODE) = (ACCESS & 1) != 0))
+
 /* Called from access_in_type via dfs_walk.  Calculate the access to
    DATA (which is really a DECL) in BINFO.  */
 
@@ -821,18 +832,18 @@ dfs_access_in_type (binfo, data)
 {
   tree decl = (tree) data;
   tree type = BINFO_TYPE (binfo);
-  tree access = NULL_TREE;
+  access_kind access = ak_none;
 
   if (context_for_name_lookup (decl) == type)
     {
       /* If we have desceneded to the scope of DECL, just note the
         appropriate access.  */
       if (TREE_PRIVATE (decl))
-       access = access_private_node;
+       access = ak_private;
       else if (TREE_PROTECTED (decl))
-       access = access_protected_node;
+       access = ak_protected;
       else
-       access = access_public_node;
+       access = ak_public;
     }
   else 
     {
@@ -842,9 +853,10 @@ dfs_access_in_type (binfo, data)
         DECL_ACCESS.  */
       if (DECL_LANG_SPECIFIC (decl))
        {
-         access = purpose_member (type, DECL_ACCESS (decl));
-         if (access)
-           access = TREE_VALUE (access);
+         tree decl_access = purpose_member (type, DECL_ACCESS (decl));
+         if (decl_access)
+           access = ((access_kind) 
+                     TREE_INT_CST_LOW (TREE_VALUE (decl_access)));
        }
 
       if (!access)
@@ -860,35 +872,36 @@ dfs_access_in_type (binfo, data)
          for (i = 0; i < n_baselinks; ++i)
            {
              tree base_binfo = TREE_VEC_ELT (binfos, i);
-             tree base_access = TREE_CHAIN (canonical_binfo (base_binfo));
+             access_kind base_access 
+               = BINFO_ACCESS (canonical_binfo (base_binfo));
 
-             if (!base_access || base_access == access_private_node)
+             if (base_access == ak_none || base_access == ak_private)
                /* If it was not accessible in the base, or only
                   accessible as a private member, we can't access it
                   all.  */
-               base_access = NULL_TREE;
+               base_access = ak_none;
              else if (TREE_VIA_PROTECTED (base_binfo))
                /* Public and protected members in the base are
                   protected here.  */
-               base_access = access_protected_node;
+               base_access = ak_protected;
              else if (!TREE_VIA_PUBLIC (base_binfo))
                /* Public and protected members in the base are
                   private here.  */
-               base_access = access_private_node;
+               base_access = ak_private;
 
              /* See if the new access, via this base, gives more
                 access than our previous best access.  */
-             if (base_access &&
-                 (base_access == access_public_node
-                  || (base_access == access_protected_node
-                      && access != access_public_node)
-                  || (base_access == access_private_node
-                      && !access)))
+             if (base_access != ak_none
+                 && (base_access == ak_public
+                     || (base_access == ak_protected
+                         && access != ak_public)
+                     || (base_access == ak_private 
+                         && access == ak_none)))
                {
                  access = base_access;
 
                  /* If the new access is public, we can't do better.  */
-                 if (access == access_public_node)
+                 if (access == ak_public)
                    break;
                }
            }
@@ -896,7 +909,7 @@ dfs_access_in_type (binfo, data)
     }
 
   /* Note the access to DECL in TYPE.  */
-  TREE_CHAIN (binfo) = access;
+  SET_BINFO_ACCESS (binfo, access);
 
   /* Mark TYPE as visited so that if we reach it again we do not
      duplicate our efforts here.  */
@@ -907,7 +920,7 @@ dfs_access_in_type (binfo, data)
 
 /* Return the access to DECL in TYPE.  */
 
-static tree 
+static access_kind
 access_in_type (type, decl)
      tree type;
      tree decl;
@@ -929,7 +942,7 @@ access_in_type (type, decl)
   dfs_walk (binfo, dfs_unmark, shared_marked_p,  0);
   assert_canonical_unmarked (binfo);
 
-  return TREE_CHAIN (binfo);
+  return BINFO_ACCESS (binfo);
 }
 
 /* Called from dfs_accessible_p via dfs_walk.  */
@@ -960,17 +973,14 @@ dfs_accessible_p (binfo, data)
      void *data;
 {
   int protected_ok = data != 0;
-  tree access;
+  access_kind access;
 
-  /* We marked the binfos while computing the access in each type.
-     So, we unmark as we go now.  */
   SET_BINFO_MARKED (binfo);
-
-  access = TREE_CHAIN (binfo);
-  if (access == access_public_node
-      || (access == access_protected_node && protected_ok))
+  access = BINFO_ACCESS (binfo);
+  if (access == ak_public || (access == ak_protected && protected_ok))
     return binfo;
-  else if (access && is_friend (BINFO_TYPE (binfo), current_scope ()))
+  else if (access != ak_none
+          && is_friend (BINFO_TYPE (binfo), current_scope ()))
     return binfo;
 
   return NULL_TREE;
@@ -985,7 +995,7 @@ protected_accessible_p (decl, derived, binfo)
      tree derived;
      tree binfo;
 {
-  tree access;
+  access_kind access;
 
   /* We're checking this clause from [class.access.base]
 
@@ -1010,7 +1020,7 @@ protected_accessible_p (decl, derived, binfo)
   access = access_in_type (derived, decl);
 
   /* If m is inaccessible in DERIVED, then it's not a P.  */
-  if (access == NULL_TREE)
+  if (access == ak_none)
     return 0;
   
   /* [class.protected]
@@ -1752,12 +1762,11 @@ lookup_fnfields_1 (type, name)
    If it ever returns a non-NULL value, that value is immediately
    returned and the walk is terminated.  At each node FN, is passed a
    BINFO indicating the path from the curently visited base-class to
-   TYPE.  The TREE_CHAINs of the BINFOs may be used for scratch space;
-   they are otherwise unused.  Before each base-class is walked QFN is
-   called.  If the value returned is non-zero, the base-class is
-   walked; otherwise it is not.  If QFN is NULL, it is treated as a
-   function which always returns 1.  Both FN and QFN are passed the
-   DATA whenever they are called.  */
+   TYPE.  Before each base-class is walked QFN is called.  If the
+   value returned is non-zero, the base-class is walked; otherwise it
+   is not.  If QFN is NULL, it is treated as a function which always
+   returns 1.  Both FN and QFN are passed the DATA whenever they are
+   called.  */
 
 static tree
 bfs_walk (binfo, fn, qfn, data)
@@ -2194,97 +2203,6 @@ dfs_skip_nonprimary_vbases_markedp (binfo, data)
   return markedp (binfo, NULL);
 }
 
-/* Called via dfs_walk from mark_primary_bases.  */
-
-static tree
-dfs_mark_primary_bases (binfo, data)
-     tree binfo;
-     void *data;
-{
-  int i;
-  tree base_binfo;
-
-  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
-    return NULL_TREE;
-
-  i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
-  base_binfo = BINFO_BASETYPE (binfo, i);
-
-  if (!TREE_VIA_VIRTUAL (base_binfo))
-    /* Non-virtual base classes are easy.  */
-    BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
-  else
-    {
-      tree shared_binfo;
-
-      shared_binfo 
-       = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
-
-      /* If this virtual base is not already primary somewhere else in
-        the hiearchy, then we'll be using this copy.  */
-      if (!BINFO_VBASE_PRIMARY_P (shared_binfo)
-         && !BINFO_VBASE_MARKED (shared_binfo))
-       {
-         BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
-         BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
-       }
-    }
-
-  return NULL_TREE;
-}
-
-/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
-   dominated by BINFO that are primary bases.  */
-
-void
-mark_primary_bases (type)
-     tree type;
-{
-  tree vbase;
-
-  /* Mark the TYPE_BINFO hierarchy.  We need to mark primary bases in
-     pre-order to deal with primary virtual bases.  (The virtual base
-     would be skipped if it were not marked as primary, and that
-     requires getting to dfs_mark_primary_bases before
-     dfs_skip_nonprimary_vbases_unmarkedp has a chance to skip the
-     virtual base.)  */
-  dfs_walk_real (TYPE_BINFO (type), dfs_mark_primary_bases, NULL,
-                dfs_skip_nonprimary_vbases_unmarkedp, type);
-
-  /* Now go through the virtual base classes.  Any that are not
-     already primary will need to be allocated in TYPE, and so we need
-     to mark their primary bases.  */
-  for (vbase = CLASSTYPE_VBASECLASSES (type); 
-       vbase; 
-       vbase = TREE_CHAIN (vbase))
-    {
-      if (BINFO_VBASE_PRIMARY_P (vbase))
-       /* This virtual base was already included in the hierarchy, so
-          there's nothing to do here.  */
-       continue;
-
-      /* Temporarily pretend that VBASE is primary so that its bases
-        will be walked; this is the real copy of VBASE.  */
-      BINFO_PRIMARY_MARKED_P (vbase) = 1;
-
-      /* Now, walk its bases.  */
-      dfs_walk (vbase, dfs_mark_primary_bases,
-               dfs_skip_nonprimary_vbases_unmarkedp, type);
-
-      /* VBASE wasn't really primary.  */
-      BINFO_PRIMARY_MARKED_P (vbase) = 0;
-      /* And we don't want to allow it to *become* primary if it is a
-        base of some subsequent base class.  */
-      SET_BINFO_VBASE_MARKED (vbase);
-    }
-
-  /* Clear the VBASE_MARKED bits we set above.  */
-  for (vbase = CLASSTYPE_VBASECLASSES (type); 
-       vbase; 
-       vbase = TREE_CHAIN (vbase))
-    CLEAR_BINFO_VBASE_MARKED (vbase);
-}
-
 /* If BINFO is a non-primary virtual baseclass (in the hierarchy
    dominated by TYPE), and no primary copy appears anywhere in the
    hierarchy, return the shared copy.  If a primary copy appears
@@ -2577,17 +2495,6 @@ dfs_unmark (binfo, data)
   return NULL_TREE;
 }
 
-/* Clear both BINFO_MARKED and BINFO_VBASE_MARKED.  */
-
-tree
-dfs_vbase_unmark (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{
-  CLEAR_BINFO_VBASE_MARKED (binfo);
-  return dfs_unmark (binfo, data);
-}
-
 /* Clear BINFO_VTABLE_PATH_MARKED.  */
 
 tree
@@ -2781,7 +2688,7 @@ virtual_context (fndecl, t, vbase)
   while (path)
     {
       if (TREE_VIA_VIRTUAL (path))
-       return binfo_member (BINFO_TYPE (path), CLASSTYPE_VBASECLASSES (t));
+       return BINFO_FOR_VBASE (BINFO_TYPE (path), t);
       path = BINFO_INHERITANCE_CHAIN (path);
     }
   return 0;
@@ -3072,7 +2979,7 @@ dfs_get_vbase_types (binfo, data)
 {
   tree type = (tree) data;
 
-  if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
+  if (TREE_VIA_VIRTUAL (binfo))
     {
       tree new_vbase = make_binfo (size_zero_node, 
                                   BINFO_TYPE (binfo),
@@ -3083,24 +2990,50 @@ dfs_get_vbase_types (binfo, data)
       BINFO_INHERITANCE_CHAIN (new_vbase) = TYPE_BINFO (type);
       TREE_CHAIN (new_vbase) = CLASSTYPE_VBASECLASSES (type);
       CLASSTYPE_VBASECLASSES (type) = new_vbase;
-      SET_BINFO_VBASE_MARKED (binfo);
     }
   SET_BINFO_MARKED (binfo);
   return NULL_TREE;
 }
 
+/* Called via dfs_walk from mark_primary_bases.  Builds the
+   inheritance graph order list of BINFOs.  */
+
+static tree
+dfs_build_inheritance_graph_order (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree *last_binfo = (tree *) data;
+
+  if (*last_binfo)
+    TREE_CHAIN (*last_binfo) = binfo;
+  *last_binfo = binfo;
+  SET_BINFO_MARKED (binfo);
+  return NULL_TREE;
+}
+
 /* Set CLASSTYPE_VBASECLASSES for TYPE.  */
 
 void
 get_vbase_types (type)
      tree type;
 {
+  tree last_binfo;
+
   CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
   dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
   /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
      reverse it so that we get normal dfs ordering.  */
   CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
-  dfs_walk (TYPE_BINFO (type), dfs_vbase_unmark, markedp, 0);
+  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
+  /* Thread the BINFOs in inheritance-graph order.  */
+  last_binfo = NULL;
+  dfs_walk_real (TYPE_BINFO (type),
+                dfs_build_inheritance_graph_order,
+                NULL,
+                unmarkedp,
+                &last_binfo);
+  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
 }
 
 /* Called from find_vbase_instance via dfs_walk.  */
index 71e5c28..fbc498b 100644 (file)
@@ -590,6 +590,14 @@ adjust_pointer (const void *base, ptrdiff_t offset)
     (reinterpret_cast <const char *> (base) + offset);
 }
 
+inline ptrdiff_t
+get_vbase_offset (const void *object, ptrdiff_t offset)
+{
+  const char *vtable = *reinterpret_cast <const char *const *> (object);
+  vtable += offset;
+  return *reinterpret_cast <const ptrdiff_t *> (vtable);
+}
+
 // some predicate functions for __class_type_info::sub_kind
 inline bool contained_p (__class_type_info::sub_kind access_path)
 {
@@ -718,9 +726,7 @@ do_find_public_src (ptrdiff_t src2dst,
         {
           if (src2dst == -3)
             continue; // Not a virtual base, so can't be here.
-         const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
-          
-         offset = vtable[offset];
+         offset = get_vbase_offset (base, offset);
         }
       base = adjust_pointer <void> (base, offset);
       
@@ -841,9 +847,7 @@ do_dyncast (ptrdiff_t src2dst,
       if (base_list[i].is_virtual_p ())
         {
           base_access = sub_kind (base_access | contained_virtual_mask);
-         const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
-          
-         offset = vtable[offset];
+         offset = get_vbase_offset (base, offset);
        }
       base = adjust_pointer <void> (base, offset);
 
@@ -1041,10 +1045,7 @@ do_upcast (sub_kind access_path,
          sub_access = sub_kind (sub_access | contained_virtual_mask);
           
           if (base)
-            {
-             const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
-             offset = vtable[offset];
-           }
+           offset = get_vbase_offset (base, offset);
         }
       if (base)
         base = adjust_pointer <void> (base, offset);
index e27ff7b..d5e0a5d 100644 (file)
@@ -921,7 +921,7 @@ debug_binfo (elem)
   debug_tree (BINFO_TYPE (elem));
   if (BINFO_VTABLE (elem))
     fprintf (stderr, "vtable decl \"%s\"\n",
-            IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem))));
+            IDENTIFIER_POINTER (DECL_NAME (get_vtbl_decl_for_binfo (elem))));
   else
     fprintf (stderr, "no vtable decl yet\n");
   fprintf (stderr, "virtuals:\n");
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/layout1.C b/gcc/testsuite/g++.old-deja/g++.abi/layout1.C
new file mode 100644 (file)
index 0000000..a37ef07
--- /dev/null
@@ -0,0 +1,51 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+struct R
+{
+  virtual void r ();
+};
+
+struct S 
+{
+  virtual void f ();
+};
+
+struct T : virtual public S
+{
+  virtual void g ();
+};
+
+struct U : public R, virtual public T
+{
+  virtual void h ();
+};
+
+struct V : public R, virtual public S, virtual public T
+{
+  virtual void v ();
+};
+
+struct U1
+{
+  R r;
+  T t;
+};
+
+int main ()
+{
+  if (sizeof (U) != sizeof (U1))
+    return 1;
+  if (sizeof (V) != sizeof (U1))
+    return 2;
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main ()
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
index aafcad8..4c811a8 100644 (file)
@@ -65,7 +65,7 @@ int main ()
   
   if (vtable (&s4) != vtable (s2))
     return 1;
-    if (vtable (s2) >= vtable (s3))
+  if (vtable (s2) >= vtable (s3))
     return 2;
   if (vtable (s3) >= vtable (s1))
     return 3;
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
new file mode 100644 (file)
index 0000000..5d8cf9d
--- /dev/null
@@ -0,0 +1,179 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+#include <stddef.h>
+
+struct S0
+{
+  virtual void s0 ();
+};
+
+struct S1 : virtual public S0
+{
+  virtual void s1 ();
+};
+
+struct S2 : virtual public S1
+{
+  virtual void s1 ();
+  virtual void s0 ();
+};
+
+struct S3
+{
+  virtual void s3 ();
+};
+
+struct S4 : public S3, virtual public S2
+{
+  virtual void s1 ();
+};
+
+void S0::s0 ()
+{
+}
+
+void S1::s1 ()
+{
+}
+
+void S2::s1 ()
+{
+}
+
+void S2::s0 ()
+{
+}
+
+void S3::s3 ()
+{
+}
+
+void S4::s1 ()
+{
+}
+
+/* The vtables should look like:
+
+   S0 primary vtable
+   
+     S0 offset to top
+     S0 RTTI
+     S0::s0
+
+   =================
+
+   S1 primary vtable
+
+     S0::s0 vcall offset
+     S0 vbase offset
+     S1 offset to top
+     S1 RTTI
+     S0::s0
+     S1::s1
+
+   =================
+
+   S2 primary vtable
+   
+     S2::s1 vcall offset
+     S1 vbase offset
+     S2::s0 vcall offset
+     S0 vbase offset
+     S2 offset to top
+     S2 RTTI
+     S2::s0
+     S2::s1
+
+   =================
+
+   S3 primary vtable
+
+     S3 offset to top
+     S3 RTTI
+     S3::s3
+
+   =================
+
+   S4 primary vtable
+
+     vbase offset for S0
+     vbase offset for S1
+     vbase offset for S2
+     S4 offset to top
+     S4 RTTI
+     S3::s3
+     S4::s1
+
+   S2-in-S4 secondary vtable
+
+     S4::s1 vcall offset
+     S1 vbase offset
+     S2:s0 vcall offset
+     S0 vbase offset
+     S2 offset to top
+     S4 RTTI
+     S2::s0
+     S4::s1
+
+*/
+
+// These are tricks to allow us to get raw function pointers for
+// member functions.
+extern "C" {
+void s3__2S3 ();
+void s1__2S4 ();
+}
+
+int main ()
+{
+  S4 s4;
+  ptrdiff_t **vptr;
+  ptrdiff_t *vtbl;
+
+  // Set vtbl to point at the beginning of S4's primary vtable.
+  vptr = (ptrdiff_t **) &s4;
+  vtbl = *vptr;
+  vtbl -= 5;
+
+  if (*vtbl++ != ((char*) (S0*) &s4) - (char*) &s4)
+    return 1;
+  if (*vtbl++ != ((char*) (S1*) &s4) - (char*) &s4)
+    return 2;
+  if (*vtbl++ != ((char*) (S2*) &s4) - (char*) &s4)
+    return 3;
+  if (*vtbl++ != 0)
+    return 4;
+  // Skip the RTTI entry.
+  vtbl++;
+  if (*vtbl++ != (ptrdiff_t) &s3__2S3)
+    return 5;
+  if (*vtbl++ != (ptrdiff_t) &s1__2S4)
+    return 6;
+  // All the vcall and vbase offsets should be zero.
+  if (*vtbl++ != 0)
+    return 7;
+  if (*vtbl++ != 0)
+    return 8;
+  if (*vtbl++ != 0)
+    return 9;
+  if (*vtbl++ != 0)
+    return 10;
+  // Now we're at the S2 offset to top entry.
+  if (*vtbl++ != ((char*) &s4 - (char*) (S2*) &s4))
+    return 11;
+  // Skip the RTTI entry.
+  vtbl++;
+  // Skip the remaining virtual functions -- they are thunks.
+  vtbl++;
+  vtbl++;
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main ()
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
index 6d333f0..a67a1dd 100644 (file)
@@ -28,5 +28,5 @@ int main ()
   ap = (C2*)&e2;
   // ap points to base subobject shared by two Bs; fails
   if (dynamic_cast <B2*> (ap) != 0)
-    return 1;
+    return 2;
 }