OSDN Git Service

Allow indirect primary bases.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Jul 2000 00:24:44 +0000 (00:24 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Jul 2000 00:24:44 +0000 (00:24 +0000)
* cp-tree.h (struct lang_type): Remove vfield_parent.  Add
primary_base.
(CLASSTYPE_VFIELD_PARENT): Remove.
(CLASSTYPE_PRIMARY_BINFO): Reimplement.
(BINFO_PRIMARY_BINFO): Remove.
(CLASSTYPE_HAS_PRIMARY_BASE_P): Reimplement.
(BINFO_VBASE_PRIMARY_P): Likewise.
(BINFO_PRIMARY_BASE_OF): New macro.
(BINFO_INDIRECT_PRIMARY_P): Likewise.
(get_primary_binfo): New function.
* decl.c (lang_mark_tree): Make lang_type::primary_base.
* class.c (vcall_offset_data_s): Rename to ...
(vtbl_init_data_s): ... this.  Rename primary_p to primary_vtbl_p,
and add ctor_vtbl_p.
(get_derived_offset): Use get_primary_binfo.
(dfs_mark_primary_bases): Adjust handling of virtual primary
bases.
(mark_primary_bases): Likewise.
(set_primary_base): Take a binfo, not an integer, as a
representation of the primary base.
(indirect_primary_base_p): Remove.
(determine_primary_base): Adjust for indirect primary bases.
(dfs_find_final_overrider): Fix typo in coment.
(update_vtable_entry_for_fn): Use get_primary_binfo.
(layout_nonempty_base_or_field): Tweak.
(build_base_fields): Adjust for new primary base semantics.
(dfs_propagate_binfo_offsets): Remove.
(propagate_binfo_offsets): Rewrite.
(dfs_set_offset_for_shared_vbases): Remove.
(layout_virtual_bases): Don't use it.
(layout_class_type): Set CLASSTYPE_SIZE correctly under the new
ABI.
(finish_struct_1): Set CLASSTYPE_PRIMARY_BINFO, not
CLASSTYPE_VFIELD_PARENT.
(dfs_get_primary_binfo): New function.
(get_primary_binfo): Likewise.
(dump_class_hierarchy_r): Tweak printing of primary bases.
(build_vtbl_initializer): Fix typo in comments.  Use
vtbl_init_data.
(build_vcall_and_vbase_vtbl_entries): Likewise.
(build_vbaes_offset_vtbl_entries): Likewise.
(dfs_build_vcall_offset_vtbl_entries): Adjust setting of
BV_VCALL_INDEX to handle indirect primary bases.
(build_vcall_offset_vtbl_entries): Use vtbl_init_data.
(build_rtti_vtbl_entries): Likewise.
* search.c (get_shared_vbase_if_not_primary): Tweak.
(find_vbase_instance): Likewise.
(binfo_for_vtable): Simplify.
* tree.c (unshare_base_binfos): Clear BINFO_PRIMARY_BASE_OF.
(make_binfo): Make it have 11 entries.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/search.c
gcc/cp/tree.c

index ad35dd8..3a2fdd4 100644 (file)
@@ -1,3 +1,57 @@
+2000-07-30  Mark Mitchell  <mark@codesourcery.com>
+
+       Allow indirect primary bases.
+       * cp-tree.h (struct lang_type): Remove vfield_parent.  Add
+       primary_base.
+       (CLASSTYPE_VFIELD_PARENT): Remove.
+       (CLASSTYPE_PRIMARY_BINFO): Reimplement.
+       (BINFO_PRIMARY_BINFO): Remove.
+       (CLASSTYPE_HAS_PRIMARY_BASE_P): Reimplement.
+       (BINFO_VBASE_PRIMARY_P): Likewise.
+       (BINFO_PRIMARY_BASE_OF): New macro.
+       (BINFO_INDIRECT_PRIMARY_P): Likewise.
+       (get_primary_binfo): New function.
+       * decl.c (lang_mark_tree): Make lang_type::primary_base.
+       * class.c (vcall_offset_data_s): Rename to ...
+       (vtbl_init_data_s): ... this.  Rename primary_p to primary_vtbl_p,
+       and add ctor_vtbl_p.
+       (get_derived_offset): Use get_primary_binfo.
+       (dfs_mark_primary_bases): Adjust handling of virtual primary
+       bases.
+       (mark_primary_bases): Likewise.
+       (set_primary_base): Take a binfo, not an integer, as a
+       representation of the primary base.
+       (indirect_primary_base_p): Remove.
+       (determine_primary_base): Adjust for indirect primary bases.
+       (dfs_find_final_overrider): Fix typo in coment.
+       (update_vtable_entry_for_fn): Use get_primary_binfo.
+       (layout_nonempty_base_or_field): Tweak.
+       (build_base_fields): Adjust for new primary base semantics.
+       (dfs_propagate_binfo_offsets): Remove.
+       (propagate_binfo_offsets): Rewrite.
+       (dfs_set_offset_for_shared_vbases): Remove.
+       (layout_virtual_bases): Don't use it.
+       (layout_class_type): Set CLASSTYPE_SIZE correctly under the new
+       ABI.
+       (finish_struct_1): Set CLASSTYPE_PRIMARY_BINFO, not
+       CLASSTYPE_VFIELD_PARENT.
+       (dfs_get_primary_binfo): New function.
+       (get_primary_binfo): Likewise.
+       (dump_class_hierarchy_r): Tweak printing of primary bases.
+       (build_vtbl_initializer): Fix typo in comments.  Use
+       vtbl_init_data.
+       (build_vcall_and_vbase_vtbl_entries): Likewise.
+       (build_vbaes_offset_vtbl_entries): Likewise.
+       (dfs_build_vcall_offset_vtbl_entries): Adjust setting of
+       BV_VCALL_INDEX to handle indirect primary bases.
+       (build_vcall_offset_vtbl_entries): Use vtbl_init_data.
+       (build_rtti_vtbl_entries): Likewise.
+       * search.c (get_shared_vbase_if_not_primary): Tweak.
+       (find_vbase_instance): Likewise.
+       (binfo_for_vtable): Simplify.
+       * tree.c (unshare_base_binfos): Clear BINFO_PRIMARY_BASE_OF.
+       (make_binfo): Make it have 11 entries.
+       
 2000-07-30  Alex Samuel  <samuel@codesourcery.com>
 
        * mangle.c (DECL_TEMPLATE_ID_P): Remove.
index f9c2c9e..cf62937 100644 (file)
@@ -62,8 +62,10 @@ typedef struct class_stack_node {
   splay_tree names_used;
 }* class_stack_node_t;
 
-typedef struct vcall_offset_data_s
+typedef struct vtbl_init_data_s
 {
+  /* The base for which we're building initializers.  */
+  tree binfo;
   /* The binfo for the most-derived type.  */
   tree derived;
   /* The negative-index vtable initializers built up so far.  These
@@ -72,7 +74,7 @@ typedef struct vcall_offset_data_s
   /* The last (i.e., most negative entry in INITS.  */
   tree* last_init;
   /* The binfo for the virtual base for which we're building
-     initializers.  */
+     vcall offset initializers.  */
   tree vbase;
   /* The functions in vbase for which we have already provided vcall
      offsets.  */
@@ -81,8 +83,11 @@ typedef struct vcall_offset_data_s
   tree index;
   /* Nonzero if we are building the initializer for the primary
      vtable.  */
-  int primary_p;
-} vcall_offset_data;
+  int primary_vtbl_p;
+  /* Nonzero if we are building the initializer for a construction
+     vtable.  */
+  int ctor_vtbl_p;
+} vtbl_init_data;
 
 /* The stack itself.  This is an dynamically resized array.  The
    number of elements allocated is CURRENT_CLASS_STACK_SIZE.  */
@@ -150,15 +155,13 @@ static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
 static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
 static void fixup_pending_inline PARAMS ((struct pending_inline *));
 static void fixup_inline_methods PARAMS ((tree));
-static void set_primary_base PARAMS ((tree, int, int *));
-static tree dfs_propagate_binfo_offsets PARAMS ((tree, void *));
+static void set_primary_base PARAMS ((tree, tree, int *));
 static void propagate_binfo_offsets PARAMS ((tree, tree));
 static void layout_virtual_bases PARAMS ((tree, varray_type *));
-static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
 static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
-static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
 static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
-static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
+static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
 static void layout_vtable_decl PARAMS ((tree, int));
 static tree dfs_find_final_overrider PARAMS ((tree, void *));
 static tree find_final_overrider PARAMS ((tree, tree, tree));
@@ -179,9 +182,9 @@ static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
 static void layout_empty_base PARAMS ((tree, tree, varray_type));
 static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
 static void set_vindex PARAMS ((tree, tree, int *));
-static void build_rtti_vtbl_entries PARAMS ((tree, tree, vcall_offset_data *));
+static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
 static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, 
-                                                       vcall_offset_data *));
+                                                       vtbl_init_data *));
 static tree dfs_mark_primary_bases PARAMS ((tree, void *));
 static void mark_primary_bases PARAMS ((tree));
 static void clone_constructors_and_destructors PARAMS ((tree));
@@ -193,8 +196,8 @@ static void build_vtt PARAMS ((tree));
 static tree *build_vtt_inits PARAMS ((tree, tree, int, tree *, tree *));
 static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
 static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
-static int indirect_primary_base_p PARAMS ((tree, tree));
 static tree get_matching_base PARAMS ((tree, tree));
+static tree dfs_get_primary_binfo PARAMS ((tree, void*));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -687,7 +690,7 @@ get_derived_offset (binfo, type)
   tree offset2;
 
   while (!same_type_p (BINFO_TYPE (binfo), type))
-    binfo = BINFO_PRIMARY_BINFO (binfo);
+    binfo = get_primary_binfo (binfo);
 
   offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
   return size_binop (MINUS_EXPR, offset1, offset2);
@@ -1701,19 +1704,14 @@ 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);
+  base_binfo = get_primary_binfo (binfo);
 
-  if (!TREE_VIA_VIRTUAL (base_binfo))
-    /* Non-virtual base classes are easy.  */
-    BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
-  else
+  if (TREE_VIA_VIRTUAL (base_binfo))
     {
       tree shared_binfo;
       tree type;
@@ -1723,7 +1721,7 @@ dfs_mark_primary_bases (binfo, 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))
+      if (!BINFO_PRIMARY_MARKED_P (shared_binfo))
        {
          /* Make sure the CLASSTYPE_VBASECLASSES list contains the
             primary copy; it's the one that really exists.  */
@@ -1731,12 +1729,14 @@ dfs_mark_primary_bases (binfo, data)
            TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
                                        CLASSTYPE_VBASECLASSES (type)))
              = base_binfo;
-
-         BINFO_VBASE_PRIMARY_P (base_binfo) = 1;
-         BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
        }
+      else
+       base_binfo = NULL_TREE;
     }
 
+  if (base_binfo)
+    BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
+
   return NULL_TREE;
 }
 
@@ -1774,36 +1774,29 @@ mark_primary_bases (type)
        continue;
 
       vbase = binfo_for_vbase (BINFO_TYPE (vbases), type);
-      if (BINFO_VBASE_PRIMARY_P (vbase))
+      if (BINFO_PRIMARY_MARKED_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.  */
+/* Make the BINFO the primary base of T.  */
 
 static void
-set_primary_base (t, i, vfuns_p)
+set_primary_base (t, binfo, vfuns_p)
      tree t;
-     int i;
+     tree binfo;
      int *vfuns_p;
 {
   tree basetype;
 
-  CLASSTYPE_VFIELD_PARENT (t) = i;
-  basetype = BINFO_TYPE (CLASSTYPE_PRIMARY_BINFO (t));
+  CLASSTYPE_PRIMARY_BINFO (t) = binfo;
+  basetype = BINFO_TYPE (binfo);
   TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
   TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
   TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
@@ -1811,35 +1804,6 @@ set_primary_base (t, i, vfuns_p)
   *vfuns_p = CLASSTYPE_VSIZE (basetype);
 }
 
-/* Returns true iff BINFO (a direct virtual base of T) is an indirect
-   primary base.  */
-
-static int
-indirect_primary_base_p (t, binfo)
-     tree t;
-     tree binfo;
-{
-  int i;
-
-  for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
-    {
-      tree type;
-      tree b;
-
-      /* Figure out to which type the Ith base corresponds.  */
-      type = TYPE_BINFO_BASETYPE (t, i);
-      /* See if any of the primary bases have the same type as BINFO.  */
-      for (b = TYPE_BINFO (type); b; b = TREE_CHAIN (b))
-       /* If this base is primary, and has the same type as BINFO,
-          then BINFO is an indirect primary base.  */
-       if (BINFO_PRIMARY_MARKED_P (b)
-           && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
-         return 1;
-    }
-
-  return 0;
-}
-
 /* Determine the primary class for T.  */
 
 static void
@@ -1848,16 +1812,18 @@ determine_primary_base (t, vfuns_p)
      int *vfuns_p;
 {
   int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+  tree vbases;
+  tree type_binfo;
 
   /* If there are no baseclasses, there is certainly no primary base.  */
   if (n_baseclasses == 0)
     return;
 
-  *vfuns_p = 0;
+  type_binfo = TYPE_BINFO (t);
 
   for (i = 0; i < n_baseclasses; i++)
     {
-      tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
+      tree base_binfo = BINFO_BASETYPE (type_binfo, i);
       tree basetype = BINFO_TYPE (base_binfo);
 
       if (TYPE_CONTAINS_VPTR_P (basetype))
@@ -1876,7 +1842,7 @@ determine_primary_base (t, vfuns_p)
 
          if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
            {
-             set_primary_base (t, i, vfuns_p);
+             set_primary_base (t, base_binfo, vfuns_p);
              CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
            }
          else
@@ -1895,60 +1861,93 @@ determine_primary_base (t, vfuns_p)
                                 CLASSTYPE_VFIELDS (t));
 
              if (!flag_new_abi && *vfuns_p == 0)
-               set_primary_base (t, i, vfuns_p);
+               set_primary_base (t, base_binfo, vfuns_p);
            }
        }
     }
 
   if (!TYPE_VFIELD (t))
-    CLASSTYPE_VFIELD_PARENT (t) = -1;
+    CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
+
+  /* Mark the indirect primary bases.  */
+  for (vbases = CLASSTYPE_VBASECLASSES (t);
+       vbases;
+       vbases = TREE_CHAIN (vbases)) 
+    {
+      tree binfo = TREE_VALUE (vbases);
+
+      /* See if this virtual base is an indirect primary base.  If so,
+        it must be either a primary base or an indirect primary base
+        in one of the direct bases.  */
+      for (i = 0; i < n_baseclasses; ++i) 
+       {
+         tree basetype;
+         tree v;
+
+         basetype = TYPE_BINFO_BASETYPE (t, i);
+         for (v = CLASSTYPE_VBASECLASSES (basetype); 
+              v; 
+              v = TREE_CHAIN (v))
+           {
+             tree b = TREE_VALUE (v);
+             if ((BINFO_PRIMARY_MARKED_P (b)
+                  || BINFO_INDIRECT_PRIMARY_P (b))
+                 && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+               {
+                 BINFO_INDIRECT_PRIMARY_P (binfo) = 1;
+                 break;
+               }
+           }
+
+         /* If we've discovered that this virtual base is an indirect
+            primary base, then we can move on to the next virtual
+            base.  */
+         if (BINFO_INDIRECT_PRIMARY_P (binfo))
+           break;
+       }
+    }
 
   /* The new ABI allows for the use of a "nearly-empty" virtual base
      class as the primary base class if no non-virtual polymorphic
      base can be found.  */
   if (flag_new_abi && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
     {
-      /* If not -1, this is the index in TYPE_BINFO_BASETYPEs of the
-        best primary base candidate we have found so far.  */
-      int candidate = -1;
+      /* If not NULL, this is the best primary base candidate we have
+         found so far.  */
+      tree candidate = NULL_TREE;
+      tree base_binfo;
 
       /* Loop over the baseclasses.  */
-      for (i = 0; i < n_baseclasses; ++i)
+      for (base_binfo = TYPE_BINFO (t);
+          base_binfo;
+          base_binfo = TREE_CHAIN (base_binfo))
        {
-         tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
          tree basetype = BINFO_TYPE (base_binfo);
 
          if (TREE_VIA_VIRTUAL (base_binfo) 
              && CLASSTYPE_NEARLY_EMPTY_P (basetype))
            {
-             int indirect_primary_p;
-
-             /* Figure out whether or not this base is an indirect
-                primary base.  */
-             indirect_primary_p = indirect_primary_base_p (t, base_binfo);
-
              /* If this is not an indirect primary base, then it's
                 definitely our primary base.  */
-             if (!indirect_primary_p) 
+             if (!BINFO_INDIRECT_PRIMARY_P (base_binfo))
                {
-                 candidate = i;
+                 candidate = base_binfo;
                  break;
                }
              /* If this was an indirect primary base, it's still our
                 primary base -- unless there's another nearly-empty
                 virtual base that isn't an indirect primary base.  */
-             else if (candidate == -1)
-               candidate = i;
+             else if (!candidate)
+               candidate = base_binfo;
            }
        }
 
       /* If we've got a primary base, use it.  */
-      if (candidate != -1) 
+      if (candidate)
        {
          set_primary_base (t, candidate, vfuns_p);
          CLASSTYPE_VFIELDS (t) 
-           = copy_list (CLASSTYPE_VFIELDS (TYPE_BINFO_BASETYPE (t, 
-                                                                candidate)));
+           = copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
        }       
     }
 
@@ -2475,9 +2474,10 @@ dfs_find_final_overrider (binfo, data)
        {
          tree base;
 
-         /* Assume the path is non-virtual.  See if there are any base from
-            (but not including) the overrider up to and including the
-            base where the function is defined. */
+         /* Assume the path is non-virtual.  See if there are any
+            virtual bases from (but not including) the overrider up
+            to and including the base where the function is
+            defined. */
          for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
            if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
              {
@@ -2612,7 +2612,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
       tree primary_base;
       tree f;
 
-      primary_base = BINFO_PRIMARY_BINFO (b);
+      primary_base = get_primary_binfo (b);
       if (!primary_base)
        break;
 
@@ -3792,7 +3792,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
       /* Now that we know where it wil be placed, update its
         BINFO_OFFSET.  */
       offset = byte_position (decl);
-      if (binfo)
+      if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
        propagate_binfo_offsets (binfo, 
                                 convert (ssizetype, offset));
  
@@ -3978,13 +3978,13 @@ build_base_fields (rli, empty_p)
     {
       tree base_binfo;
 
+      base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
+
       /* Under the new ABI, the primary base was already allocated
         above, so we don't need to allocate it again here.  */
-      if (flag_new_abi && i == CLASSTYPE_VFIELD_PARENT (rec))
+      if (flag_new_abi && base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
        continue;
 
-      base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
-
       /* A primary virtual base class is allocated just like any other
         base class, but a non-primary virtual base is allocated
         later, in layout_virtual_bases.  */
@@ -4486,66 +4486,60 @@ fixup_inline_methods (type)
   CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
 }
 
-/* Called from propagate_binfo_offsets via dfs_walk.  */
-
-static tree
-dfs_propagate_binfo_offsets (binfo, data)
-     tree binfo; 
-     void *data;
-{
-  tree offset = (tree) data;
-
-  /* Update the BINFO_OFFSET for this base.  Allow for the case where it
-     might be negative.  */
-  BINFO_OFFSET (binfo)
-    = convert (sizetype, size_binop (PLUS_EXPR,
-                                    convert (ssizetype, BINFO_OFFSET (binfo)),
-                                             offset));
-  SET_BINFO_MARKED (binfo);
-
-  return NULL_TREE;
-}
-
 /* Add OFFSET to all base types of BINFO which is a base in the
    hierarchy dominated by T.
 
-   OFFSET, which is a type offset, is number of bytes.
-
-   Note that we don't have to worry about having two paths to the
-   same base type, since this type owns its association list.  */
+   OFFSET, which is a type offset, is number of bytes.  */
 
 static void
 propagate_binfo_offsets (binfo, offset)
      tree binfo;
      tree offset;
 {
-  dfs_walk (binfo, 
-           dfs_propagate_binfo_offsets, 
-           dfs_skip_nonprimary_vbases_unmarkedp,
-           offset);
-  dfs_walk (binfo,
-           dfs_unmark,
-           dfs_skip_nonprimary_vbases_markedp,
-           NULL);
-}
+  int i;
+  tree primary_binfo;
 
-/* Called via dfs_walk from layout_virtual bases.  */
+  /* Update BINFO's offset.  */
+  BINFO_OFFSET (binfo)
+    = convert (sizetype, 
+              size_binop (PLUS_EXPR,
+                          convert (ssizetype, BINFO_OFFSET (binfo)),
+                          offset));
 
-static tree
-dfs_set_offset_for_shared_vbases (binfo, data)
-     tree binfo;
-     void *data;
-{
-  if (TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
+  /* Find the primary base class.  */
+  primary_binfo = get_primary_binfo (binfo);
+
+  /* Scan all of the bases, pushing the BINFO_OFFSET adjust
+     downwards.  */
+  for (i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
     {
-      /* Update the shared copy.  */
-      tree shared_binfo;
+      tree base_binfo;
 
-      shared_binfo = binfo_for_vbase (BINFO_TYPE (binfo), (tree) data);
-      BINFO_OFFSET (shared_binfo) = BINFO_OFFSET (binfo);
-    }
+      /* On the first through the loop, do the primary base.  Because
+        the primary base need not be an immediate base, we must
+        handle the primary base specially.  */
+      if (i == -1) 
+       {
+         if (!primary_binfo) 
+           continue;
 
-  return NULL_TREE;
+         base_binfo = primary_binfo;
+       }
+      else
+       {
+         base_binfo = BINFO_BASETYPE (binfo, i);
+         /* Don't do the primary base twice.  */
+         if (base_binfo == primary_binfo)
+           continue;
+       }
+
+      /* Skip virtual bases that aren't our primary base.  */
+      if (TREE_VIA_VIRTUAL (base_binfo)
+         && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo)
+       continue;
+
+      propagate_binfo_offsets (base_binfo, offset);
+    }
 }
 
 /* Called via dfs_walk from layout_virtual bases.  */
@@ -4622,7 +4616,7 @@ layout_virtual_bases (t, base_offsets)
       else
        vbase = TREE_VALUE (vbases);
 
-      if (!BINFO_VBASE_PRIMARY_P (vbase))
+      if (!BINFO_PRIMARY_MARKED_P (vbase))
        {
          /* This virtual base is not a primary base of any class in the
             hierarchy, so we have to add space for it.  */
@@ -4673,16 +4667,7 @@ layout_virtual_bases (t, base_offsets)
        }
     }
 
-  /* Make sure that all of the CLASSTYPE_VBASECLASSES have their
-     BINFO_OFFSET set correctly.  Those we just allocated certainly
-     will.  The others are primary baseclasses; we walk the hierarchy
-     to find the primary copies and update the shared copy.  */
-  dfs_walk (TYPE_BINFO (t), 
-           dfs_set_offset_for_shared_vbases, 
-           dfs_unmarked_real_bases_queue_p,
-           t);
-
-  /* Now, go through the TYPE_BINFO hierarchy again, setting the
+  /* Now, go through the TYPE_BINFO hierarchy, setting the
      BINFO_OFFSETs correctly for all non-primary copies of the virtual
      bases and their direct and indirect bases.  The ambiguity checks
      in get_base_distance depend on the BINFO_OFFSETs being set
@@ -4942,8 +4927,7 @@ layout_class_type (t, empty_p, vfuns_p,
       CLASSTYPE_SIZE (t) = bitsize_zero_node;
       CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
     }
-  else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t)
-          && TYPE_HAS_COMPLEX_ASSIGN_REF (t))
+  else if (flag_new_abi)
     {
       CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
       CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
@@ -5034,7 +5018,7 @@ finish_struct_1 (t)
      make sure we lay it out again.  */
   TYPE_SIZE (t) = NULL_TREE;
   CLASSTYPE_GOT_SEMICOLON (t) = 0;
-  CLASSTYPE_VFIELD_PARENT (t) = -1;
+  CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
   vfuns = 0;
   CLASSTYPE_RTTI (t) = NULL_TREE;
 
@@ -6472,6 +6456,69 @@ get_vtbl_decl_for_binfo (binfo)
   return decl;
 }
 
+/* Called from get_primary_binfo via dfs_walk.  */
+
+static tree
+dfs_get_primary_binfo (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree primary_base = (tree) data;
+
+  if (TREE_VIA_VIRTUAL (binfo) 
+      && same_type_p (TREE_TYPE (binfo), TREE_TYPE (primary_base)))
+    return binfo;
+  
+  return NULL_TREE;
+}
+
+/* Returns 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.  */
+
+tree
+get_primary_binfo (binfo)
+     tree binfo;
+{
+  tree primary_base;
+  tree result;
+
+  primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
+  if (!primary_base)
+    return NULL_TREE;
+
+  /* A non-virtual primary base is always a direct base, and easy to
+     find.  */
+  if (!TREE_VIA_VIRTUAL (primary_base))
+    {
+      int i;
+
+      /* Scan the direct basetypes until we find a base with the same
+        type as the primary base.  */
+      for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+       {
+         tree base_binfo = BINFO_BASETYPE (binfo, i);
+         
+         if (same_type_p (BINFO_TYPE (base_binfo),
+                          BINFO_TYPE (primary_base)))
+           return base_binfo;
+       }
+
+      /* We should always find the primary base.  */
+      my_friendly_abort (20000729);
+    }
+
+  /* For a primary virtual base, we have to scan the entire hierarchy
+     rooted at BINFO; the virtual base could be an indirect virtual
+     base.  */
+  result = dfs_walk (binfo, dfs_get_primary_binfo, NULL, primary_base);
+  my_friendly_assert (result != NULL_TREE, 20000730);
+  return result;
+}
+
 /* 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.  */
@@ -6493,8 +6540,8 @@ dump_class_hierarchy_r (t, binfo, indent)
     fprintf (stderr, " virtual");
   if (BINFO_PRIMARY_MARKED_P (binfo)
       || (TREE_VIA_VIRTUAL (binfo) 
-         && BINFO_VBASE_PRIMARY_P (binfo_for_vbase (BINFO_TYPE (binfo), 
-                                                    t))))
+         && BINFO_PRIMARY_MARKED_P (binfo_for_vbase (BINFO_TYPE (binfo), 
+                                                     t))))
     fprintf (stderr, " primary");
   fprintf (stderr, "\n");
 
@@ -7021,7 +7068,7 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
    is part of the hierarchy dominated by T.  If we're building a
    construction vtable, the ORIG_BINFO is the binfo we should use to
    find the actual function pointers to put in the vtable.  Otherwise,
-   ORIG_BINFO should be the same as BINFO.  The RTTI_DOMINATOR is the
+   ORIG_BINFO should be the same as BINFO.  The RTTI_BINFO is the
    BINFO that should be indicated by the RTTI information in the
    vtable; it will be a base class of T, rather than T itself, if we
    are building a construction vtable.
@@ -7029,7 +7076,14 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
    The value returned is a TREE_LIST suitable for wrapping in a
    CONSTRUCTOR to use as the 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.  */
+   number of non-function entries in the vtable.  
+
+   It might seem that this function should never be called with a
+   BINFO for which BINFO_PRIMARY_MARKED_P holds, the vtable for such a
+   base is always subsumed by a derived class vtable.  However, when
+   we are building construction vtables we do build vtables for
+   primary bases; we need these while the primary base is being
+   constructed.  */
 
 static tree
 build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
@@ -7040,23 +7094,25 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
      int *non_fn_entries_p;
 {
   tree v;
-   tree vfun_inits;
+  tree vfun_inits;
   tree vbase;
-  vcall_offset_data vod;
-
-  /* Initialize those parts of VOD that matter.  */
-  vod.derived = t;
-  vod.inits = NULL_TREE;
-  vod.last_init = &vod.inits;
-  vod.primary_p = (binfo == TYPE_BINFO (t));
+  vtbl_init_data vid;
+
+  /* Initialize VID.  */
+  vid.binfo = binfo;
+  vid.derived = t;
+  vid.inits = NULL_TREE;
+  vid.last_init = &vid.inits;
+  vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
+  vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
   /* The first vbase or vcall offset is at index -3 in the vtable.  */
-  vod.index = ssize_int (-3);
+  vid.index = ssize_int (-3);
 
   /* Add entries to the vtable for RTTI.  */
-  build_rtti_vtbl_entries (binfo, rtti_binfo, &vod);
+  build_rtti_vtbl_entries (binfo, rtti_binfo, &vid);
 
   /* Add the vcall and vbase offset entries.  */
-  build_vcall_and_vbase_vtbl_entries (binfo, &vod);
+  build_vcall_and_vbase_vtbl_entries (binfo, &vid);
    /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
      build_vbase_offset_vtbl_entries.  */
   for (vbase = CLASSTYPE_VBASECLASSES (t); 
@@ -7065,7 +7121,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
     CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
 
   if (non_fn_entries_p)
-    *non_fn_entries_p = list_length (vod.inits);
+    *non_fn_entries_p = list_length (vid.inits);
 
   /* Go through all the ordinary virtual functions, building up
      initializers.  */
@@ -7116,32 +7172,32 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
   vfun_inits = nreverse (vfun_inits);
   
   /* The negative offset initializers are also in reverse order.  */
-  vod.inits = nreverse (vod.inits);
+  vid.inits = nreverse (vid.inits);
 
   /* Chain the two together.  */
-  return chainon (vod.inits, vfun_inits);
+  return chainon (vid.inits, vfun_inits);
 }
 
-/* Sets vod->inits to be the initializers for the vbase and vcall
+/* Sets vid->inits to be the initializers for the vbase and vcall
    offsets in BINFO, which is in the hierarchy dominated by T.  */
 
 static void
-build_vcall_and_vbase_vtbl_entries (binfo, vod)
+build_vcall_and_vbase_vtbl_entries (binfo, vid)
      tree binfo;
-     vcall_offset_data *vod;
+     vtbl_init_data *vid;
 {
   tree b;
 
   /* If this is a derived class, we must first create entries
      corresponding to the primary base class.  */
-  b = BINFO_PRIMARY_BINFO (binfo);
+  b = get_primary_binfo (binfo);
   if (b)
-    build_vcall_and_vbase_vtbl_entries (b, vod);
+    build_vcall_and_vbase_vtbl_entries (b, vid);
 
   /* Add the vbase entries for this base.  */
-  build_vbase_offset_vtbl_entries (binfo, vod);
+  build_vbase_offset_vtbl_entries (binfo, vid);
   /* Add the vcall entries for this base.  */
-  build_vcall_offset_vtbl_entries (binfo, vod);
+  build_vcall_offset_vtbl_entries (binfo, vid);
 }
 
 /* Returns the initializers for the vbase offset entries in the vtable
@@ -7150,9 +7206,9 @@ build_vcall_and_vbase_vtbl_entries (binfo, vod)
    where the next vbase offset will go.  */
 
 static void
-build_vbase_offset_vtbl_entries (binfo, vod)
+build_vbase_offset_vtbl_entries (binfo, vid)
      tree binfo;
-     vcall_offset_data *vod;
+     vtbl_init_data *vid;
 {
   tree vbase;
   tree t;
@@ -7167,7 +7223,7 @@ build_vbase_offset_vtbl_entries (binfo, vod)
   if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
     return;
 
-  t = vod->derived;
+  t = vid->derived;
 
   /* Go through the virtual bases, adding the offsets.  */
   for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
@@ -7192,10 +7248,10 @@ build_vbase_offset_vtbl_entries (binfo, vod)
 
       /* Figure out where we can find this vbase offset.  */
       delta = size_binop (MULT_EXPR, 
-                         vod->index,
+                         vid->index,
                          convert (ssizetype,
                                   TYPE_SIZE_UNIT (vtable_entry_type)));
-      if (vod->primary_p)
+      if (vid->primary_vtbl_p)
        BINFO_VPTR_FIELD (b) = delta;
 
       if (binfo != TYPE_BINFO (t))
@@ -7213,19 +7269,19 @@ build_vbase_offset_vtbl_entries (binfo, vod)
        }
 
       /* The next vbase will come at a more negative offset.  */
-      vod->index = size_binop (MINUS_EXPR, vod->index, ssize_int (1));
+      vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
 
       /* 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->last_init 
+      *vid->last_init 
        = build_tree_list (NULL_TREE,
                           fold (build1 (NOP_EXPR, 
                                         vtable_entry_type,
                                         delta)));
-      vod->last_init = &TREE_CHAIN (*vod->last_init);
+      vid->last_init = &TREE_CHAIN (*vid->last_init);
     }
 }
 
@@ -7236,7 +7292,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
      tree binfo;
      void *data;
 {
-  vcall_offset_data* vod;
+  vtbl_init_data* vid;
   tree derived_virtuals;
   tree base_virtuals;
   tree binfo_inits;
@@ -7247,7 +7303,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
   tree primary_binfo;
   int i;
 
-  vod = (vcall_offset_data *) data;
+  vid = (vtbl_init_data *) data;
   binfo_inits = NULL_TREE;
 
   /* We might be a primary base class.  Go up the inheritance
@@ -7256,8 +7312,21 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
   non_primary_binfo = binfo;
   while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
     {
-      tree b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
-      if (BINFO_PRIMARY_BINFO (b) != non_primary_binfo)
+      tree b;
+
+      /* If we have reached a virtual base, then it must be the
+        virtual base for which we are building vcall offsets.  In
+        turn, the virtual base must be a (possibly indirect) primary
+        base of the class that we are initializing, or we wouldn't
+        care about its vtable offsets.  */
+      if (TREE_VIA_VIRTUAL (non_primary_binfo))
+       {
+         non_primary_binfo = vid->binfo;
+         break;
+       }
+
+      b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+      if (get_primary_binfo (b) != non_primary_binfo)
        break;
       non_primary_binfo = b;
     }
@@ -7266,7 +7335,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
      class.  */
   base_virtuals = BINFO_VIRTUALS (binfo);
   derived_virtuals = BINFO_VIRTUALS (non_primary_binfo);
-  primary_binfo = BINFO_PRIMARY_BINFO (binfo);
+  primary_binfo = get_primary_binfo (binfo);
   if (primary_binfo)
     for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (primary_binfo)); ++i)
       {
@@ -7289,11 +7358,11 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
         signature as FN, then we do not need a second vcall offset.
         Check the list of functions already present in the derived
         class vtable.  */
-      for (i = 0; i < VARRAY_ACTIVE_SIZE (vod->fns); ++i) 
+      for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i) 
        {
          tree derived_entry;
 
-         derived_entry = VARRAY_TREE (vod->fns, i);
+         derived_entry = VARRAY_TREE (vid->fns, i);
          if (same_signature_p (BV_FN (derived_entry), fn))
            {
              BV_VCALL_INDEX (derived_virtuals) 
@@ -7301,42 +7370,35 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
              break;
            }
        }
-      if (i != VARRAY_ACTIVE_SIZE (vod->fns))
+      if (i != VARRAY_ACTIVE_SIZE (vid->fns))
        continue;
 
       /* The FN comes from BASE.  So, we must caculate the adjustment
         from the virtual base that derived from BINFO to BASE.  */
       base = DECL_CONTEXT (fn);
-      base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
+      base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
 
       /* Compute the vcall offset.  */
-      *vod->last_init 
+      *vid->last_init 
        = (build_tree_list 
           (NULL_TREE,
            fold (build1 (NOP_EXPR, vtable_entry_type,
                          size_diffop (BINFO_OFFSET (base_binfo),
-                                      BINFO_OFFSET (vod->vbase))))));
-      vod->last_init = &TREE_CHAIN (*vod->last_init);
-
-      /* If there is already a vcall index, then we are processing a
-        construction vtable.  The index should be the same as it was
-        when we processed the vtable for the base class.  */
-      if (BV_VCALL_INDEX (derived_virtuals))
-       my_friendly_assert (tree_int_cst_equal (BV_VCALL_INDEX
-                                               (derived_virtuals),
-                                               vod->index),
-                           20000516);
+                                      BINFO_OFFSET (vid->vbase))))));
+      vid->last_init = &TREE_CHAIN (*vid->last_init);
+
       /* Keep track of the vtable index where this vcall offset can be
-        found.  */
-      else
-       BV_VCALL_INDEX (derived_virtuals) = vod->index;
+        found.  For a construction vtable, we already made this
+        annotation when we build the original vtable.  */
+      if (!vid->ctor_vtbl_p)
+       BV_VCALL_INDEX (derived_virtuals) = vid->index;
 
       /* The next vcall offset will be found at a more negative
         offset.  */
-      vod->index = size_binop (MINUS_EXPR, vod->index, ssize_int (1));
+      vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
 
       /* Keep track of this function.  */
-      VARRAY_PUSH_TREE (vod->fns, derived_virtuals);
+      VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
     }
 
   return NULL_TREE;
@@ -7344,12 +7406,12 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
 
 /* 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.  */
+   VID->INITS.  */
 
 static void
-build_vcall_offset_vtbl_entries (binfo, vod)
+build_vcall_offset_vtbl_entries (binfo, vid)
      tree binfo;
-     vcall_offset_data *vod;
+     vtbl_init_data *vid;
 {
   /* Under the old ABI, the adjustments to the `this' pointer were made
      elsewhere.  */
@@ -7382,14 +7444,14 @@ build_vcall_offset_vtbl_entries (binfo, vod)
      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->vbase = binfo;
-  VARRAY_TREE_INIT (vod->fns, 32, "fns");
+  vid->vbase = binfo;
+  VARRAY_TREE_INIT (vid->fns, 32, "fns");
   dfs_walk_real (binfo,
                 dfs_build_vcall_offset_vtbl_entries,
                 NULL,
                 dfs_skip_vbases,
-                vod);
-  VARRAY_FREE (vod->fns);
+                vid);
+  VARRAY_FREE (vid->fns);
 }
 
 /* Return vtbl initializers for the RTTI entries coresponding to the
@@ -7397,10 +7459,10 @@ build_vcall_offset_vtbl_entries (binfo, vod)
    by RTTI_BINFO.  */
 
 static void
-build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
+build_rtti_vtbl_entries (binfo, rtti_binfo, vid)
      tree binfo;
      tree rtti_binfo;
-     vcall_offset_data *vod;
+     vtbl_init_data *vid;
 {
   tree b;
   tree t;
@@ -7423,7 +7485,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
     {
       tree primary_base;
 
-      primary_base = BINFO_PRIMARY_BINFO (b);
+      primary_base = get_primary_binfo (b);
       if (!BINFO_PRIMARY_MARKED_P (primary_base))
        break;
       b = primary_base;
@@ -7459,8 +7521,8 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
       init = build_vtable_entry (offset, NULL_TREE, init, 
                                 /*generate_with_vtable_p=*/0);
     }
-  *vod->last_init = build_tree_list (NULL_TREE, init);
-  vod->last_init = &TREE_CHAIN (*vod->last_init);
+  *vid->last_init = build_tree_list (NULL_TREE, init);
+  vid->last_init = &TREE_CHAIN (*vid->last_init);
 
   /* Add the offset-to-top entry.  It comes earlier in the vtable that
      the the typeinfo entry.  */
@@ -7470,8 +7532,8 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
         we can put it in the vtable.  */
       init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
       TREE_CONSTANT (init) = 1;
-      *vod->last_init = build_tree_list (NULL_TREE, init);
-      vod->last_init = &TREE_CHAIN (*vod->last_init);
+      *vid->last_init = build_tree_list (NULL_TREE, init);
+      vid->last_init = &TREE_CHAIN (*vid->last_init);
     }
 }
 
index 56ec82d..63c1e8e 100644 (file)
@@ -69,9 +69,8 @@ Boston, MA 02111-1307, USA.  */
           or FIELD_DECL).
       NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
       IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
-   5: BINFO_PRIMARY_MARKED_P (in BINFO)
-   6: BINFO_VBASE_PRIMARY_P (in BINFO)
-      BINFO_ACCESS (in BINFO)
+   5: Unused.
+   6: BINFO_ACCESS (in BINFO)
 
    Usage of TYPE_LANG_FLAG_?:
    0: C_TYPE_FIELDS_READONLY (in RECORD_TYPE or UNION_TYPE).
@@ -100,7 +99,10 @@ Boston, MA 02111-1307, USA.  */
       DECL_THUNK_P (in a member FUNCTION_DECL)
 
    Usage of language-independent fields in a language-dependent manner:
-   
+
+   TREE_USED
+     This field is BINFO_INDIRECT_PRIMARY_P in a BINFO.
+
    TYPE_ALIAS_SET
      This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so
      forth as a substitute for the mark bits provided in `lang_type'.
@@ -1391,8 +1393,8 @@ struct lang_type
   unsigned dummy : 8;
       
   int vsize;
-  int vfield_parent;
 
+  tree primary_base;
   tree vfields;
   tree vbases;
   tree tags;
@@ -1562,34 +1564,16 @@ struct lang_type
    nested member class templates.  */
 #define CLASSTYPE_TAGS(NODE)           (TYPE_LANG_SPECIFIC(NODE)->tags)
 
-/* If this value is non-negative, it is the index (in the
-   TYPE_BINFO_BASETYPES) for the base-class whose vtable pointer we
-   are reusing.  For example, in D : B1, B2, PARENT would be 0, if D's
-   vtable came from B1, 1, if D's vtable came from B2.  */
-#define CLASSTYPE_VFIELD_PARENT(NODE)  (TYPE_LANG_SPECIFIC(NODE)->vfield_parent)
-
 /* Nonzero if NODE has a primary base class, i.e., a base class with
    which it shares the virtual fucntion table pointer.  */
 #define CLASSTYPE_HAS_PRIMARY_BASE_P(NODE) \
-  (CLASSTYPE_VFIELD_PARENT (NODE) != -1)
+  (CLASSTYPE_PRIMARY_BINFO (NODE) != NULL_TREE)
 
 /* If non-NULL, this is the binfo for the primary base class, i.e.,
    the base class which contains the virtual function table pointer
    for this class.  */
 #define CLASSTYPE_PRIMARY_BINFO(NODE) \
-  (BINFO_PRIMARY_BINFO (TYPE_BINFO (NODE)))
-
-/* 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)
+  (TYPE_LANG_SPECIFIC (NODE)->primary_base)
 
 /* The number of virtual functions present in this class' virtual
    function table.  */
@@ -1752,11 +1736,8 @@ struct lang_type
    class of a non-primary virtual base.  This flag is only valid for
    paths (given by BINFO_INHERITANCE_CHAIN) that really exist in the
    final object.  */
-#define BINFO_PRIMARY_MARKED_P(NODE) TREE_LANG_FLAG_5 (NODE)
-
-/* Nonzero if the virtual baseclass with the type given by this BINFO
-   is primary *somewhere* in the hierarchy.  */
-#define BINFO_VBASE_PRIMARY_P(NODE) TREE_LANG_FLAG_6 (NODE)
+#define BINFO_PRIMARY_MARKED_P(NODE) \
+  (BINFO_PRIMARY_BASE_OF (NODE) != NULL_TREE)
 
 /* The index in the VTT where this subobject's sub-VTT can be found.
    NULL_TREE if there is no sub-VTT.  */
@@ -1766,10 +1747,21 @@ struct lang_type
    found.  NULL_TREE if there is no secondary vptr in the VTT.  */
 #define BINFO_VPTR_INDEX(NODE) TREE_VEC_ELT ((NODE), 9)
 
+/* The binfo of which NODE is a primary base.  (This is different from
+   BINFO_INHERITANCE_CHAIN for virtual base because a virtual base is
+   sometimes a primary base for a class for which it is not an
+   immediate base.)  */
+#define BINFO_PRIMARY_BASE_OF(NODE) TREE_VEC_ELT ((NODE), 10)
+
 /* Nonzero if this binfo declares a virtual function which is
    overridden along a virtual path.  */
 #define BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P(NODE) TREE_LANG_FLAG_2 (NODE)
 
+/* Nonzero if this binfo is an indirect primary base, i.e. a virtual
+   base that is a primary base of some of other class in the
+   hierarchy.  */
+#define BINFO_INDIRECT_PRIMARY_P(NODE) TREE_USED (NODE)
+
 /* Used by various search routines.  */
 #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
 \f
@@ -3844,6 +3836,7 @@ extern void note_name_declared_in_class         PARAMS ((tree, tree));
 extern tree get_vtbl_decl_for_binfo             PARAMS ((tree));
 extern tree in_charge_arg_for_name              PARAMS ((tree));
 extern tree get_vtt_name                        PARAMS ((tree));
+extern tree get_primary_binfo                   PARAMS ((tree));
 
 /* in cvt.c */
 extern tree convert_to_reference               PARAMS ((tree, tree, int, int, tree));
index 020dd30..8832dab 100644 (file)
@@ -15007,6 +15007,7 @@ lang_mark_tree (t)
                  && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
        {
          ggc_mark (lt);
+         ggc_mark_tree (lt->primary_base);
          ggc_mark_tree (lt->vfields);
          ggc_mark_tree (lt->vbases);
          ggc_mark_tree (lt->tags);
index e0a42a2..bf19ce8 100644 (file)
@@ -2199,7 +2199,7 @@ get_shared_vbase_if_not_primary (binfo, data)
       /* This is a non-primary virtual base.  If there is no primary
         version, get the shared version.  */
       binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
-      if (BINFO_VBASE_PRIMARY_P (binfo))
+      if (BINFO_PRIMARY_MARKED_P (binfo))
        return NULL_TREE;
     }
 
@@ -2883,7 +2883,7 @@ find_vbase_instance (base, type)
   tree instance;
 
   instance = binfo_for_vbase (base, type);
-  if (!BINFO_VBASE_PRIMARY_P (instance))
+  if (!BINFO_PRIMARY_MARKED_P (instance))
     return instance;
 
   return dfs_walk (TYPE_BINFO (type), 
@@ -3357,21 +3357,9 @@ binfo_for_vtable (var)
      tree var;
 {
   tree binfo = TYPE_BINFO (DECL_CONTEXT (var));
-  tree binfos;
-  int i;
 
-  while (1)
-    {
-      binfos = BINFO_BASETYPES (binfo);
-      if (binfos == NULL_TREE)
-       break;
-
-      i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
-      if (i == -1)
-       break;
-
-      binfo = TREE_VEC_ELT (binfos, i);
-    }
+  while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+    binfo = get_primary_binfo (binfo);
 
   return binfo;
 }
index bed0d49..01d2fd9 100644 (file)
@@ -687,6 +687,7 @@ unshare_base_binfos (binfo)
       TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
       TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
       BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
+      BINFO_PRIMARY_BASE_OF (new_binfo) = NULL_TREE;
       unshare_base_binfos (new_binfo);
     }
 }
@@ -851,7 +852,7 @@ make_binfo (offset, binfo, vtable, virtuals)
      tree offset, binfo;
      tree vtable, virtuals;
 {
-  tree new_binfo = make_tree_vec (10);
+  tree new_binfo = make_tree_vec (11);
   tree type;
 
   if (TREE_CODE (binfo) == TREE_VEC)