OSDN Git Service

revert mangling patch
[pf3gnuchains/gcc-fork.git] / gcc / cp / class.c
index 7198e54..77a5b7e 100644 (file)
@@ -83,6 +83,10 @@ typedef struct vcall_offset_data_s
 static int current_class_stack_size;
 static class_stack_node_t current_class_stack;
 
+/* An array of all local classes present in this translation unit, in
+   declaration order.  */
+varray_type local_classes;
+
 static tree get_vfield_name PARAMS ((tree));
 static void finish_struct_anon PARAMS ((tree));
 static tree build_vbase_pointer PARAMS ((tree, tree));
@@ -93,7 +97,8 @@ static tree get_basefndecls PARAMS ((tree, tree));
 static int build_primary_vtable PARAMS ((tree, tree));
 static int build_secondary_vtable PARAMS ((tree, tree));
 static tree dfs_finish_vtbls PARAMS ((tree, void *));
-static tree dfs_accumulate_vtbl_inits PARAMS ((tree, void *));
+static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
+                                              tree));
 static void finish_vtbls PARAMS ((tree));
 static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
 static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
@@ -118,7 +123,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, int *));
+static tree build_vtbl_initializer PARAMS ((tree, tree, 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));
@@ -157,6 +162,7 @@ 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 initialize_array PARAMS ((tree, tree));
 static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
                                                   tree, tree,
                                                   varray_type));
@@ -166,7 +172,7 @@ static tree dfs_search_base_offsets PARAMS ((tree, void *));
 static int layout_conflict_p PARAMS ((tree, varray_type));
 static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
 static void layout_empty_base PARAMS ((tree, tree, varray_type));
-static void accumulate_vtbl_inits PARAMS ((tree, tree));
+static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, 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, 
@@ -175,6 +181,14 @@ static tree dfs_mark_primary_bases PARAMS ((tree, void *));
 static void mark_primary_bases PARAMS ((tree));
 static void clone_constructors_and_destructors PARAMS ((tree));
 static tree build_clone PARAMS ((tree, tree));
+static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
+static tree copy_virtuals PARAMS ((tree));
+static void build_ctor_vtbl_group PARAMS ((tree, tree));
+static void build_vtt PARAMS ((tree));
+static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
+static tree dfs_build_vtt_inits PARAMS ((tree, void *));
+static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
+static int indirect_primary_base_p PARAMS ((tree, tree));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -244,7 +258,7 @@ build_vbase_pointer_fields (rli, empty_p)
            {
              tree other_base_binfo = TREE_VEC_ELT (binfos, j);
              if (! TREE_VIA_VIRTUAL (other_base_binfo)
-                 && BINFO_FOR_VBASE (basetype, BINFO_TYPE (other_base_binfo)))
+                 && binfo_for_vbase (basetype, BINFO_TYPE (other_base_binfo)))
                goto got_it;
            }
          FORMAT_VBASE_NAME (name, basetype);
@@ -283,7 +297,7 @@ build_vbase_pointer (exp, type)
 
       /* Find the shared copy of TYPE; that's where the vtable offset
         is recorded.  */
-      vbase = BINFO_FOR_VBASE (type, TREE_TYPE (exp));
+      vbase = binfo_for_vbase (type, TREE_TYPE (exp));
       /* Find the virtual function table pointer.  */
       vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp));
       /* Compute the location where the offset will lie.  */
@@ -476,7 +490,9 @@ 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, get_vtbl_decl_for_binfo (basetype), 0);
+  s = build_unary_op (ADDR_EXPR, 
+                     get_vtbl_decl_for_binfo (TYPE_BINFO (basetype)), 
+                     0);
   s = build_tree_list (build_string (1, "s"), s);
 
   i = build_array_ref (vtbl, idx);
@@ -619,22 +635,25 @@ static tree
 get_vtable_name (type)
      tree type;
 {
-  tree type_id = build_typename_overload (type);
-  char *buf = (char *) alloca (strlen (VTABLE_NAME_PREFIX)
-                              + IDENTIFIER_LENGTH (type_id) + 2);
-  const char *ptr = IDENTIFIER_POINTER (type_id);
-  int i;
-  for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
-#if 0
-  /* We don't take off the numbers; build_secondary_vtable uses the
-     DECL_ASSEMBLER_NAME for the type, which includes the number
-     in `3foo'.  If we were to pull them off here, we'd end up with
-     something like `_vt.foo.3bar', instead of a uniform definition.  */
-  while (ptr[i] >= '0' && ptr[i] <= '9')
-    i += 1;
-#endif
-  sprintf (buf, "%s%s", VTABLE_NAME_PREFIX, ptr+i);
-  return get_identifier (buf);
+  if (flag_new_abi)
+    return mangle_vtbl_for_type (type);
+  else
+    return build_overload_with_type (get_identifier (VTABLE_NAME_PREFIX),
+                                    type);
+}
+
+/* Return an IDENTIFIER_NODE for the name of the virtual table table
+   for TYPE.  */
+
+tree
+get_vtt_name (type)
+     tree type;
+{
+  if (flag_new_abi)
+    return mangle_vtt_for_type (type);
+  else
+    return build_overload_with_type (get_identifier (VTT_NAME_PREFIX),
+                                    type);
 }
 
 /* Return the offset to the main vtable for a given base BINFO.  */
@@ -725,7 +744,8 @@ get_vtable_decl (type, complete)
   
   decl = build_vtable (type, name, void_type_node);
   decl = pushdecl_top_level (decl);
-  SET_IDENTIFIER_GLOBAL_VALUE (name, decl);
+  my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
+                     20000517);
   
   /* At one time the vtable info was grabbed 2 words at a time.  This
      fails on sparc unless you have 8-byte alignment.  (tiemann) */
@@ -741,6 +761,23 @@ get_vtable_decl (type, complete)
   return decl;
 }
 
+/* Returns a copy of the BINFO_VIRTUALS list in BINFO.  The
+   BV_VCALL_INDEX for each entry is cleared.  */
+
+static tree
+copy_virtuals (binfo)
+     tree binfo;
+{
+  tree copies;
+  tree t;
+
+  copies = copy_list (BINFO_VIRTUALS (binfo));
+  for (t = copies; t; t = TREE_CHAIN (t))
+    BV_VCALL_INDEX (t) = NULL_TREE;
+
+  return copies;
+}
+      
 /* Build the primary virtual function table for TYPE.  If BINFO is
    non-NULL, build the vtable starting with the initial approximation
    that it is the same as the one which is the head of the association
@@ -762,7 +799,7 @@ build_primary_vtable (binfo, type)
           no need to do it again.  */
        return 0;
       
-      virtuals = copy_list (BINFO_VIRTUALS (binfo));
+      virtuals = copy_virtuals (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));
@@ -822,7 +859,7 @@ build_secondary_vtable (binfo, for_type)
 #endif
 
   if (TREE_VIA_VIRTUAL (binfo))
-    my_friendly_assert (binfo == BINFO_FOR_VBASE (BINFO_TYPE (binfo),
+    my_friendly_assert (binfo == binfo_for_vbase (BINFO_TYPE (binfo),
                                                  current_class_type),
                        170);
 
@@ -836,11 +873,11 @@ build_secondary_vtable (binfo, for_type)
   SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type);
   
   /* Make fresh virtual list, so we can smash it later.  */
-  BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
+  BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
 
   if (TREE_VIA_VIRTUAL (binfo))
     {
-      tree binfo1 = BINFO_FOR_VBASE (BINFO_TYPE (binfo), for_type);
+      tree binfo1 = binfo_for_vbase (BINFO_TYPE (binfo), for_type);
 
       /* XXX - This should never happen, if it does, the caller should
         ensure that the binfo is from for_type's binfos, not from any
@@ -1011,7 +1048,7 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
 
       base_fndecl = BV_FN (v);
       BV_DELTA (v) = delta;
-      BV_VCALL_INDEX (v) = integer_zero_node;
+      BV_VCALL_INDEX (v) = NULL_TREE;
       BV_FN (v) = fndecl;
 
       /* Now assign virtual dispatch information, if unset.  We can
@@ -1085,7 +1122,6 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
 
   new_virtual = build_tree_list (NULL_TREE, fndecl);
   BV_DELTA (new_virtual) = integer_zero_node;
-  BV_VCALL_INDEX (new_virtual) = integer_zero_node;
 
   if (DECL_VINDEX (fndecl) == error_mark_node)
     {
@@ -1412,7 +1448,12 @@ alter_access (t, fdecl, access)
      tree fdecl;
      tree access;
 {
-  tree elem = purpose_member (t, DECL_ACCESS (fdecl));
+  tree elem;
+
+  if (!DECL_LANG_SPECIFIC (fdecl))
+    retrofit_lang_decl (fdecl);
+
+  elem = purpose_member (t, DECL_ACCESS (fdecl));
   if (elem)
     {
       if (TREE_VALUE (elem) != access)
@@ -1493,8 +1534,6 @@ handle_using_decl (using_decl, t)
 
   if (is_overloaded_fn (fdecl))
     flist = fdecl;
-  else if (! DECL_LANG_SPECIFIC (fdecl))
-    my_friendly_abort (20000221);
 
   if (! old_value)
     ;
@@ -1674,15 +1713,23 @@ dfs_mark_primary_bases (binfo, data)
   else
     {
       tree shared_binfo;
+      tree type;
 
-      shared_binfo 
-       = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
+      type = (tree) data;
+      shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
 
       /* 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;
+         /* Make sure the CLASSTYPE_VBASECLASSES list contains the
+            primary copy; it's the one that really exists.  */
+         if (base_binfo != shared_binfo)
+           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;
        }
     }
@@ -1723,7 +1770,7 @@ mark_primary_bases (type)
       if (!TREE_VIA_VIRTUAL (vbases))
        continue;
 
-      vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), type);
+      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.  */
@@ -1761,6 +1808,35 @@ 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
@@ -1828,19 +1904,50 @@ determine_primary_base (t, vfuns_p)
      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))
-    for (i = 0; i < n_baseclasses; ++i)
-      {
-       tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
-       tree basetype = BINFO_TYPE (base_binfo);
+    {
+      /* 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 (TREE_VIA_VIRTUAL (base_binfo) 
-           && CLASSTYPE_NEARLY_EMPTY_P (basetype))
-         {
-           set_primary_base (t, i, vfuns_p);
-           CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
-           break;
-         }
-      }
+      /* Loop over the baseclasses.  */
+      for (i = 0; i < n_baseclasses; ++i)
+       {
+         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) 
+               {
+                 candidate = i;
+                 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;
+           }
+       }
+
+      /* If we've got a primary base, use it.  */
+      if (candidate != -1) 
+       {
+         set_primary_base (t, candidate, vfuns_p);
+         CLASSTYPE_VFIELDS (t) 
+           = copy_list (CLASSTYPE_VFIELDS (TYPE_BINFO_BASETYPE (t, 
+                                                                candidate)));
+       }       
+    }
 
   /* Mark the primary base classes at this point.  */
   mark_primary_bases (t);
@@ -2284,18 +2391,21 @@ static int
 overrides (fndecl, base_fndecl)
      tree fndecl, base_fndecl;
 {
-  /* Destructors have special names.  */
-  if (DECL_DESTRUCTOR_P (base_fndecl) && DECL_DESTRUCTOR_P (fndecl))
+  /* One destructor overrides another if they are the same kind of
+     destructor.  */
+  if (DECL_DESTRUCTOR_P (base_fndecl) && DECL_DESTRUCTOR_P (fndecl)
+      && special_function_p (base_fndecl) == special_function_p (fndecl))
     return 1;
+  /* But a non-destructor never overrides a destructor, nor vice
+     versa, nor do different kinds of destructors override
+     one-another.  For example, a complete object destructor does not
+     override a deleting destructor.  */
   if (DECL_DESTRUCTOR_P (base_fndecl) || DECL_DESTRUCTOR_P (fndecl))
     return 0;
+
   if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
     {
       tree types, base_types;
-#if 0
-      retypes = TREE_TYPE (TREE_TYPE (fndecl));
-      base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl));
-#endif
       types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
       base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
       if ((TYPE_QUALS (TREE_TYPE (TREE_VALUE (base_types)))
@@ -2635,7 +2745,7 @@ modify_all_vtables (t, vfuns_p, overridden_virtuals)
              /* We don't need to adjust the `this' pointer when
                 calling this function.  */
              BV_DELTA (*fnsp) = integer_zero_node;
-             BV_VCALL_INDEX (*fnsp) = integer_zero_node;
+             BV_VCALL_INDEX (*fnsp) = NULL_TREE;
 
              /* This is an overridden function not already in our
                 vtable.  Keep it.  */
@@ -3438,6 +3548,13 @@ check_field_decls (t, access_decls, empty_p,
            |= CLASSTYPE_READONLY_FIELDS_NEED_INIT (type);
        }
 
+      /* Core issue 80: A nonstatic data member is required to have a
+        different name from the class iff the class has a
+        user-defined constructor.  */
+      if (DECL_NAME (x) == constructor_name (t)
+         && TYPE_HAS_CONSTRUCTOR (t))
+       cp_pedwarn_at ("field `%#D' with same name as class", x);
+
       /* We set DECL_C_BIT_FIELD in grokbitfield.
         If the type and width are valid, we'll also set DECL_BIT_FIELD.  */
       if (DECL_C_BIT_FIELD (x))
@@ -3499,7 +3616,7 @@ build_vtbl_or_vbase_field (name, assembler_name, type, class_type, fcontext,
   *empty_p = 0;
 
   /* Build the FIELD_DECL.  */
-  field = build_lang_decl (FIELD_DECL, name, type);
+  field = build_decl (FIELD_DECL, name, type);
   DECL_ASSEMBLER_NAME (field) = assembler_name;
   DECL_VIRTUAL_P (field) = 1;
   DECL_ARTIFICIAL (field) = 1;
@@ -3610,7 +3727,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
   while (1)
     {
       tree offset;
-      struct record_layout_info old_rli = *rli;
+      struct record_layout_info_s old_rli = *rli;
 
       /* Place this field.  */
       place_field (rli, decl);
@@ -3639,7 +3756,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
         a data member.  */
       if (binfo && flag_new_abi && layout_conflict_p (binfo, v))
        {
-         /* Undo the propogate_binfo_offsets call.  */
+         /* Undo the propagate_binfo_offsets call.  */
          offset = size_diffop (size_zero_node, offset);
          propagate_binfo_offsets (binfo, convert (ssizetype, offset));
         
@@ -3677,7 +3794,7 @@ layout_empty_base (binfo, eoc, binfo_offsets)
   
   /* This routine should only be used for empty classes.  */
   my_friendly_assert (is_empty_class (basetype), 20000321);
-  alignment = ssize_int (CLASSTYPE_ALIGN (basetype));
+  alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
 
   /* This is an empty base class.  We first try to put it at offset
      zero.  */
@@ -3719,7 +3836,7 @@ build_base_field (rli, binfo, empty_p, base_align, v)
        location information.  */
     return;
   
-  decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
+  decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
   DECL_ARTIFICIAL (decl) = 1;
   DECL_FIELD_CONTEXT (decl) = rli->t;
   DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
@@ -3913,6 +4030,8 @@ build_clone (fn, name)
   DECL_PENDING_INLINE_P (clone) = 0;
   /* And it hasn't yet been deferred.  */
   DECL_DEFERRED_FN (clone) = 0;
+  /* There's no magic VTT parameter in the clone.  */
+  DECL_VTT_PARM (clone) = NULL_TREE;
 
   /* The base-class destructor is not virtual.  */
   if (name == base_dtor_identifier)
@@ -3937,6 +4056,10 @@ build_clone (fn, name)
       parmtypes = TREE_CHAIN (parmtypes);
       /* Skip the in-charge parameter.  */
       parmtypes = TREE_CHAIN (parmtypes);
+       /* If this is subobject constructor or destructor, add the vtt
+        parameter.  */
+      if (DECL_NEEDS_VTT_PARM_P (clone))
+       parmtypes = hash_tree_chain (vtt_parm_type, parmtypes);
       TREE_TYPE (clone) 
        = build_cplus_method_type (basetype,
                                   TREE_TYPE (TREE_TYPE (clone)),
@@ -3958,6 +4081,18 @@ build_clone (fn, name)
            = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
          DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
        }
+
+      /* Add the VTT parameter.  */
+      if (DECL_NEEDS_VTT_PARM_P (clone))
+       {
+         tree parm;
+
+         parm = build_artificial_parm (vtt_parm_identifier,
+                                       vtt_parm_type);
+         TREE_CHAIN (parm) = TREE_CHAIN (DECL_ARGUMENTS (clone));
+         TREE_CHAIN (DECL_ARGUMENTS (clone)) = parm;
+       }
+
       for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
        {
          DECL_CONTEXT (parms) = clone;
@@ -4019,7 +4154,7 @@ clone_function_decl (fn, update_method_vec_p)
     {
       my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
 
-      /* For each destructor, we need two variants: an in-charge
+      /* For each destructor, we need three variants: an in-charge
         version, a not-in-charge version, and an in-charge deleting
         version.  We clone the deleting version first because that
         means it will go second on the TYPE_METHODS list -- and that
@@ -4348,7 +4483,7 @@ dfs_set_offset_for_shared_vbases (binfo, data)
       /* Update the shared copy.  */
       tree shared_binfo;
 
-      shared_binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), (tree) data);
+      shared_binfo = binfo_for_vbase (BINFO_TYPE (binfo), (tree) data);
       BINFO_OFFSET (shared_binfo) = BINFO_OFFSET (binfo);
     }
 
@@ -4371,7 +4506,7 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
       tree vbase;
       tree offset;
       
-      vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t);
+      vbase = binfo_for_vbase (BINFO_TYPE (binfo), t);
       offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
       propagate_binfo_offsets (binfo, offset);
     }
@@ -4420,13 +4555,14 @@ layout_virtual_bases (t, base_offsets)
     {
       tree vbase;
 
-      if (!TREE_VIA_VIRTUAL (vbases))
-       continue;
-
       if (flag_new_abi)
-       vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), t);
+       {
+         if (!TREE_VIA_VIRTUAL (vbases))
+           continue;
+         vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
+       }
       else
-       vbase = vbases;
+       vbase = TREE_VALUE (vbases);
 
       if (!BINFO_VBASE_PRIMARY_P (vbase))
        {
@@ -4458,9 +4594,15 @@ layout_virtual_bases (t, base_offsets)
                               *base_offsets);
          else
            {
+             tree offset;
+
+             offset = ssize_int (CEIL (dsize, BITS_PER_UNIT));
+             offset = size_diffop (offset, 
+                                   convert (ssizetype, 
+                                            BINFO_OFFSET (vbase)));
+
              /* And compute the offset of the virtual base.  */
-             propagate_binfo_offsets (vbase, 
-                                      ssize_int (CEIL (dsize, BITS_PER_UNIT)));
+             propagate_binfo_offsets (vbase, offset);
              /* Every virtual baseclass takes a least a UNIT, so that
                 we can take it's address and get something different
                 for each base.  */
@@ -4488,10 +4630,6 @@ 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 (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
@@ -4514,7 +4652,7 @@ layout_virtual_bases (t, base_offsets)
         vbases; 
         vbases = TREE_CHAIN (vbases))
       {
-       tree basetype = BINFO_TYPE (vbases);
+       tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
        if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
          cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
                      basetype, t);
@@ -4711,7 +4849,7 @@ layout_class_type (t, empty_p, vfuns_p,
     {
       tree padding;
 
-      padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
+      padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
       place_field (rli, padding);
       TYPE_NONCOPIED_PARTS (t) 
        = tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t));
@@ -4869,6 +5007,12 @@ finish_struct_1 (t)
   overridden_virtuals 
     = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
 
+  /* If we created a new vtbl pointer for this class, add it to the
+     list.  */
+  if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+    CLASSTYPE_VFIELDS (t) 
+      = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
+
   /* If necessary, create the primary vtable for this class.  */
   if (new_virtuals
       || overridden_virtuals
@@ -4931,12 +5075,6 @@ finish_struct_1 (t)
        = chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
     }
 
-  /* If we created a new vtbl pointer for this class, add it to the
-     list.  */
-  if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-    CLASSTYPE_VFIELDS (t) 
-      = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
-
   finish_struct_bits (t);
 
   /* Complete the rtl for any static member objects of the type we're
@@ -4989,6 +5127,8 @@ finish_struct_1 (t)
   /* Make the rtl for any new vtables we have created, and unmark
      the base types we marked.  */
   finish_vtbls (t);
+  /* Build the VTT for T.  */
+  build_vtt (t);
 
   if (TYPE_VFIELD (t))
     {
@@ -5227,6 +5367,8 @@ init_class_processing ()
   current_class_stack 
     = (class_stack_node_t) xmalloc (current_class_stack_size 
                                    * sizeof (struct class_stack_node));
+  VARRAY_TREE_INIT (local_classes, 8, "local_classes");
+  ggc_add_tree_varray_root (&local_classes, 1);
 
   access_default_node = build_int_2 (0, 0);
   access_public_node = build_int_2 (ak_public, 0);
@@ -6306,7 +6448,7 @@ 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), 
+         && BINFO_VBASE_PRIMARY_P (binfo_for_vbase (BINFO_TYPE (binfo), 
                                                     t))))
     fprintf (stderr, " primary");
   fprintf (stderr, "\n");
@@ -6321,12 +6463,7 @@ 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.  */
@@ -6347,16 +6484,16 @@ finish_vtbls (t)
         first, followed by the non-virtual secondary vtables in
         inheritance graph order.  */
       list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
-      TREE_TYPE (list) = t;
-      accumulate_vtbl_inits (TYPE_BINFO (t), list);
+      accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t),
+                            TYPE_BINFO (t), t, list);
       /* Then come the virtual bases, also in inheritance graph
         order.  */
       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);
+
+         accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
        }
 
       if (TYPE_BINFO_VTABLE (t))
@@ -6380,13 +6517,11 @@ dfs_finish_vtbls (binfo, data)
 {
   tree t = (tree) data;
 
-  if (!BINFO_PRIMARY_MARKED_P (binfo)
-      && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
-      && BINFO_NEW_VTABLE_MARKED (binfo, t))
+  if (BINFO_NEW_VTABLE_MARKED (binfo, t))
     initialize_vtable (binfo, 
-                      build_vtbl_initializer (binfo, t, NULL));
+                      build_vtbl_initializer (binfo, binfo, t, 
+                                              TYPE_BINFO (t), NULL));
 
-  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
   SET_BINFO_MARKED (binfo);
 
   return NULL_TREE;
@@ -6399,102 +6534,412 @@ initialize_vtable (binfo, inits)
      tree binfo;
      tree inits;
 {
-  tree context;
   tree decl;
 
   layout_vtable_decl (binfo, list_length (inits));
   decl = get_vtbl_decl_for_binfo (binfo);
+  initialize_array (decl, inits);
+}
+
+/* Initialize DECL (a declaration for a namespace-scope array) with
+   the INITS.  */
+
+static void
+initialize_array (decl, inits)
+  tree decl;
+  tree inits;
+{
+  tree context;
+
   context = DECL_CONTEXT (decl);
-  DECL_CONTEXT (decl) = 0;
+  DECL_CONTEXT (decl) = NULL_TREE;
   DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
   cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
   DECL_CONTEXT (decl) = context;
 }
 
+/* Build the VTT (virtual table table) for T.  */
+
+static void
+build_vtt (t)
+     tree t;
+{
+  tree inits;
+  tree type;
+  tree vtt;
+  tree index;
+
+  /* Under the old ABI, we don't use VTTs.  */
+  if (!flag_new_abi)
+    return;
+
+  /* Build up the initializers for the VTT.  */
+  inits = NULL_TREE;
+  index = size_zero_node;
+  build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
+
+  /* If we didn't need a VTT, we're done.  */
+  if (!inits)
+    return;
+
+  /* Figure out the type of the VTT.  */
+  type = build_index_type (size_int (list_length (inits)));
+  type = build_cplus_array_type (const_ptr_type_node, type);
+                                
+  /* Now, build the VTT object itself.  */
+  vtt = build_vtable (t, get_vtt_name (t), type);
+  pushdecl_top_level (vtt);
+  initialize_array (vtt, inits);
+}
+
+/* Recursively build the VTT-initializer for BINFO (which is in the
+   hierarchy dominated by T).  INITS points to the end of the
+   initializer list to date.  INDEX is the VTT index where the next
+   element will be placed.  */
+
+static tree *
+build_vtt_inits (binfo, t, inits, index)
+     tree binfo;
+     tree t;
+     tree *inits;
+     tree *index;
+{
+  int i;
+  tree b;
+  tree init;
+  tree secondary_vptrs;
+  int ctor_vtbl_p;
+
+  /* We only need VTTs for subobjects with virtual bases.  */
+  if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+    return inits;
+
+  /* We need to use a construction vtable if this is not the primary
+     VTT.  */
+  ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
+  if (ctor_vtbl_p)
+    {
+      build_ctor_vtbl_group (binfo, t);
+
+      /* Record the offset in the VTT where this sub-VTT can be found.  */
+      BINFO_SUBVTT_INDEX (binfo) = *index;
+    }
+
+  /* Add the address of the primary vtable for the complete object.  */
+  init = BINFO_VTABLE (binfo);
+  if (TREE_CODE (init) == TREE_LIST)
+    init = TREE_PURPOSE (init);
+  *inits = build_tree_list (NULL_TREE, init);
+  inits = &TREE_CHAIN (*inits);
+  BINFO_VPTR_INDEX (binfo) = *index;
+  *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
+                      
+  /* Recursively add the secondary VTTs for non-virtual bases.  */
+  for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+    {
+      b = BINFO_BASETYPE (binfo, i);
+      if (!TREE_VIA_VIRTUAL (b))
+       inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits,
+                                index);
+    }
+      
+  /* Add secondary virtual pointers for all subobjects of BINFO with
+     either virtual bases or virtual functions overridden along a
+     virtual path between the declaration and D, except subobjects
+     that are non-virtual primary bases.  */
+  secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
+  TREE_TYPE (secondary_vptrs) = *index;
+  dfs_walk_real (binfo,
+                dfs_build_vtt_inits,
+                NULL,
+                dfs_unmarked_real_bases_queue_p,
+                secondary_vptrs);
+  dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
+           BINFO_TYPE (binfo));
+  *index = TREE_TYPE (secondary_vptrs);
+
+  /* The secondary vptrs come back in reverse order.  After we reverse
+     them, and add the INITS, the last init will be the first element
+     of the chain.  */
+  secondary_vptrs = TREE_VALUE (secondary_vptrs);
+  if (secondary_vptrs)
+    {
+      *inits = nreverse (secondary_vptrs);
+      inits = &TREE_CHAIN (secondary_vptrs);
+      my_friendly_assert (*inits == NULL_TREE, 20000517);
+    }
+
+  /* Add the secondary VTTs for virtual bases.  */
+  for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
+    {
+      tree vbase;
+
+      if (!TREE_VIA_VIRTUAL (b))
+       continue;
+
+      vbase = binfo_for_vbase (BINFO_TYPE (b), t);
+      inits = build_vtt_inits (vbase, t, inits, index);
+    }
+
+  return inits;
+}
+
+/* Called from build_vtt_inits via dfs_walk.  */
+
+static tree
+dfs_build_vtt_inits (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree l; 
+  tree t;
+  tree init;
+  tree index;
+
+  l = (tree) data;
+  t = TREE_PURPOSE (l);
+
+  SET_BINFO_MARKED (binfo);
+
+  /* We don't care about bases that don't have vtables.  */
+  if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
+    return NULL_TREE;
+
+  /* We're only interested in proper subobjects of T.  */
+  if (same_type_p (BINFO_TYPE (binfo), t))
+    return NULL_TREE;
+
+  /* We're not interested in non-virtual primary bases.  */
+  if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
+    return NULL_TREE;
+
+  /* If BINFO doesn't have virtual bases, then we have to look to see
+     whether or not any virtual functions were overidden along a
+     virtual path between the declaration and T.  */
+  if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+    /* FIXME: Implement this.  */
+    ;
+
+  /* Record the index where this secondary vptr can be found.  */
+  index = TREE_TYPE (l);
+  BINFO_VPTR_INDEX (binfo) = index;
+  TREE_TYPE (l) = size_binop (PLUS_EXPR, index, 
+                             TYPE_SIZE_UNIT (ptr_type_node));
+
+  /* Add the initializer for the secondary vptr itself.  */
+  init = BINFO_VTABLE (binfo);
+  if (TREE_CODE (init) == TREE_LIST)
+    init = TREE_PURPOSE (init);
+  TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
+
+  return NULL_TREE;
+}
+
+/* Called from build_vtt_inits via dfs_walk.  */
+
+static tree
+dfs_fixup_binfo_vtbls (binfo, data)
+     tree binfo;
+     void *data ATTRIBUTE_UNUSED;
+{
+  CLEAR_BINFO_MARKED (binfo);
+
+  /* We don't care about bases that don't have vtables.  */
+  if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
+    return NULL_TREE;
+
+  /* If we scribbled the construction vtable vptr into BINFO, clear it
+     out now.  */
+  if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST)
+    BINFO_VTABLE (binfo) = TREE_VALUE (BINFO_VTABLE (binfo));
+
+  return NULL_TREE;
+}
+
+/* Build the construction vtable group for BINFO which is in the
+   hierarchy dominated by T.  */
+
+static void
+build_ctor_vtbl_group (binfo, t)
+     tree binfo;
+     tree t;
+{
+  tree list;
+  tree type;
+  tree vtbl;
+  tree inits;
+  tree id;
+
+  /* See if we've already create this construction vtable group.  */
+  if (flag_new_abi)
+    id = mangle_ctor_vtbl_for_type (t, binfo);
+  else
+    id = get_ctor_vtbl_name (t, binfo);
+  if (IDENTIFIER_GLOBAL_VALUE (id))
+    return;
+
+  /* Build a version of VTBL (with the wrong type) for use in
+     constructing the addresses of secondary vtables in the
+     construction vtable group.  */
+  vtbl = build_vtable (BINFO_TYPE (binfo), id, ptr_type_node);
+  list = build_tree_list (vtbl, NULL_TREE);
+  accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
+                        binfo, t, list);
+  inits = TREE_VALUE (list);
+
+  /* Figure out the type of the construction vtable.  */
+  type = build_index_type (size_int (list_length (inits)));
+  type = build_cplus_array_type (vtable_entry_type, type);
+  TREE_TYPE (vtbl) = type;
+
+  /* Initialize the construction vtable.  */
+  pushdecl_top_level (vtbl);
+  initialize_array (vtbl, inits);
+}
+
 /* Add the vtbl initializers for BINFO (and its non-primary,
-   non-virtual bases) to the list of INITS.  */
+   non-virtual bases) to the list of INITS.  BINFO is in the hierarchy
+   dominated by T.  ORIG_BINFO must have the same type as BINFO, but
+   may be different from BINFO if we are building a construction
+   vtable.  RTTI_BINFO gives the object that should be used as the
+   complete object for BINFO.  */
 
 static void
-accumulate_vtbl_inits (binfo, inits)
+accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
      tree binfo;
+     tree orig_binfo;
+     tree rtti_binfo;
+     tree t;
      tree inits;
 {
+  int i;
+  int ctor_vtbl_p;
+
+  my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
+                                  BINFO_TYPE (orig_binfo)),
+                     20000517);
+
+  /* This is a construction vtable if the RTTI type is not the most
+     derived type in the hierarchy.  */
+  ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+
+  /* If we're building a construction vtable, we're not interested in
+     subobjects that don't require construction vtables.  */
+  if (ctor_vtbl_p 
+      && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+    return;
+
+  /* Build the initializers for the BINFO-in-T vtable.  */
+  TREE_VALUE (inits) 
+    = chainon (TREE_VALUE (inits),
+              dfs_accumulate_vtbl_inits (binfo, orig_binfo,
+                                         rtti_binfo, t, inits));
+                     
   /* 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,
-                dfs_skip_vbases,
-                inits);
+     secondary vtable lies from the primary vtable.  We can't use
+     dfs_walk here because we need to iterate through bases of BINFO
+     and RTTI_BINFO simultaneously.  */
+  for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+    {
+      tree base_binfo;
+
+      base_binfo = BINFO_BASETYPE (binfo, i);
+      /* Skip virtual bases.  */
+      if (TREE_VIA_VIRTUAL (base_binfo))
+       continue;
+      accumulate_vtbl_inits (base_binfo,
+                            BINFO_BASETYPE (orig_binfo, i),
+                            rtti_binfo,
+                            t,
+                            inits);
+    }
 }
 
 /* Called from finish_vtbls via dfs_walk when using the new ABI.
    Accumulates the vtable initializers for all of the vtables into
-   TREE_VALUE (DATA).  */
+   TREE_VALUE (DATA).  Returns the initializers for the BINFO vtable.  */
 
 static tree
-dfs_accumulate_vtbl_inits (binfo, data)
+dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
      tree binfo;
-     void *data;
+     tree orig_binfo;
+     tree rtti_binfo;
+     tree t;
+     tree l;
 {
-  tree l;
-  tree t;
+  tree inits = NULL_TREE;
+  int ctor_vtbl_p;
 
-  l = (tree) data;
-  t = TREE_TYPE (l);
+  /* This is a construction vtable if the RTTI type is not the most
+     derived type in the hierarchy.  */
+  ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
 
-  if (!BINFO_PRIMARY_MARKED_P (binfo)
-      && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
-      && BINFO_NEW_VTABLE_MARKED (binfo, t))
+  if (BINFO_NEW_VTABLE_MARKED (binfo, t)
+      /* We need a new vtable, even for a primary base, when we're
+        building a construction vtable.  */
+      || (ctor_vtbl_p && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))))
     {
-      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);
+      inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
+                                     &non_fn_entries);
 
-      /* Set BINFO_VTABLE to the address where the VPTR should point.  */
+      /* Figure out the position to which the VPTR should point.  */
       vtbl = TREE_PURPOSE (l);
       vtbl = build1 (ADDR_EXPR, 
-                    build_pointer_type (TREE_TYPE (vtbl)),
+                    vtbl_ptr_type_node,
                     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), inits);
+      index = size_binop (MULT_EXPR,
+                         TYPE_SIZE_UNIT (vtable_entry_type),
+                         index);
+      vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
+      TREE_CONSTANT (vtbl) = 1;
+
+      /* For an ordinary vtable, set BINFO_VTABLE.  */
+      if (!ctor_vtbl_p)
+       BINFO_VTABLE (binfo) = vtbl;
+      /* For a construction vtable, we can't overwrite BINFO_VTABLE.
+        So, we make a TREE_LIST.  Later, dfs_fixup_binfo_vtbls will
+        straighten this out.  */
+      else
+       BINFO_VTABLE (binfo) = build_tree_list (vtbl,
+                                               BINFO_VTABLE (binfo));
     }
 
-  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
-
-  return NULL_TREE;
+  return inits;
 }
 
 /* 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.  If NON_FN_ENTRIES_P is not NULL,
-   *NON_FN_ENTRIES_P is set to the number of non-function entries in
-   the vtable.  */
+   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
+   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.
+
+   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.  */
 
 static tree
-build_vtbl_initializer (binfo, t, non_fn_entries_p)
+build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
      tree binfo;
+     tree orig_binfo;
      tree t;
+     tree rtti_binfo;
      int *non_fn_entries_p;
 {
-  tree v = BINFO_VIRTUALS (binfo);
-  tree inits = NULL_TREE;
+  tree v;
+  tree inits;
   tree vfun_inits;
   tree vbase;
   vcall_offset_data vod;
@@ -6514,10 +6959,10 @@ build_vtbl_initializer (binfo, t, non_fn_entries_p)
   for (vbase = CLASSTYPE_VBASECLASSES (t); 
        vbase; 
        vbase = TREE_CHAIN (vbase))
-    CLEAR_BINFO_VTABLE_PATH_MARKED (vbase);
+    CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
 
   /* Add entries to the vtable for RTTI.  */
-  inits = chainon (inits, build_rtti_vtbl_entries (binfo, t));
+  inits = chainon (inits, build_rtti_vtbl_entries (binfo, rtti_binfo));
 
   if (non_fn_entries_p)
     *non_fn_entries_p = list_length (inits);
@@ -6525,7 +6970,7 @@ build_vtbl_initializer (binfo, t, non_fn_entries_p)
   /* Go through all the ordinary virtual functions, building up
      initializers.  */
   vfun_inits = NULL_TREE;
-  while (v)
+  for (v = BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
     {
       tree delta;
       tree vcall_index;
@@ -6555,9 +7000,6 @@ build_vtbl_initializer (binfo, t, non_fn_entries_p)
       init = build_vtable_entry (delta, vcall_index, pfn);
       /* And add it to the chain of initializers.  */
       vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
-
-      /* Keep going.  */
-      v = TREE_CHAIN (v);
     }
 
   /* The initializers for virtual functions were built up in reverse
@@ -6636,7 +7078,7 @@ build_vbase_offset_vtbl_entries (binfo, vod)
 
       /* Find the instance of this virtual base in the complete
         object.  */
-      b = BINFO_FOR_VBASE (BINFO_TYPE (vbase), t);
+      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.  */
@@ -6657,7 +7099,7 @@ build_vbase_offset_vtbl_entries (binfo, vod)
          tree orig_vbase;
 
          /* Find the instance of this virtual base in the type of BINFO.  */
-         orig_vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbase),
+         orig_vbase = binfo_for_vbase (BINFO_TYPE (vbase),
                                        BINFO_TYPE (binfo));
 
          /* The vbase offset had better be the same.  */
@@ -6738,9 +7180,19 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
                                                BINFO_OFFSET (vod->vbase)))),
                     binfo_inits);
 
+      /* 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);
       /* Keep track of the vtable index where this vcall offset can be
         found.  */
-      BV_VCALL_INDEX (derived_virtuals) = vod->index;
+      else
+       BV_VCALL_INDEX (derived_virtuals) = vod->index;
+
       /* The next vcall offset will be found at a more negative
         offset.  */
       vod->index = fold (build (MINUS_EXPR, integer_type_node,
@@ -6823,15 +7275,16 @@ build_vcall_offset_vtbl_entries (binfo, vod)
 }
 
 /* Return vtbl initializers for the RTTI entries coresponding to the
-   BINFO's vtable.  BINFO is a part of the hierarchy dominated by 
-   T.  */
+   BINFO's vtable.  The RTTI entries should indicate the object given
+   by RTTI_BINFO.  */
 
 static tree
-build_rtti_vtbl_entries (binfo, t)
+build_rtti_vtbl_entries (binfo, rtti_binfo)
      tree binfo;
-     tree t;
+     tree rtti_binfo;
 {
   tree b;
+  tree t;
   tree basetype;
   tree offset;
   tree decl;
@@ -6840,6 +7293,7 @@ build_rtti_vtbl_entries (binfo, t)
 
   basetype = BINFO_TYPE (binfo);
   inits = NULL_TREE;
+  t = BINFO_TYPE (rtti_binfo);
 
   /* For a COM object there is no RTTI entry.  */
   if (CLASSTYPE_COM_INTERFACE (basetype))
@@ -6857,7 +7311,7 @@ build_rtti_vtbl_entries (binfo, t)
        break;
       b = primary_base;
     }
-  offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
+  offset = size_diffop (BINFO_OFFSET (rtti_binfo), 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
@@ -6917,6 +7371,9 @@ build_vtable_entry (delta, vcall_index, entry)
      tree vcall_index;
      tree entry;
 {
+  if (!vcall_index)
+    vcall_index = integer_zero_node;
+
   if (flag_vtable_thunks)
     {
       HOST_WIDE_INT idelta;