OSDN Git Service

revert mangling patch
[pf3gnuchains/gcc-fork.git] / gcc / cp / class.c
index 756b043..77a5b7e 100644 (file)
@@ -1,5 +1,6 @@
 /* Functions related to building classes and their related objects.
-   Copyright (C) 1987, 92-99, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -37,12 +38,6 @@ Boston, MA 02111-1307, USA.  */
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-/* This is how we tell when two virtual member functions are really the
-   same.  */
-#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
-
-extern void set_class_shadows PARAMS ((tree));
-
 /* The number of nested classes being processed.  If we are not in the
    scope of any class, this is zero.  */
 
@@ -67,11 +62,31 @@ typedef struct class_stack_node {
   splay_tree names_used;
 }* class_stack_node_t;
 
+typedef struct vcall_offset_data_s
+{
+  /* The binfo for the most-derived type.  */
+  tree derived;
+  /* The binfo for the virtual base for which we're building
+     initializers.  */
+  tree vbase;
+  /* The vcall offset initializers built up so far.  */
+  tree inits;
+  /* The vtable index of the next vcall or vbase offset.  */
+  tree index;
+  /* Nonzero if we are building the initializer for the primary
+     vtable.  */
+  int primary_p;
+} vcall_offset_data;
+
 /* The stack itself.  This is an dynamically resized array.  The
    number of elements allocated is CURRENT_CLASS_STACK_SIZE.  */
 static int current_class_stack_size;
 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));
@@ -79,28 +94,23 @@ static tree build_vtable_entry PARAMS ((tree, tree, tree));
 static tree get_vtable_name PARAMS ((tree));
 static tree get_derived_offset PARAMS ((tree, tree));
 static tree get_basefndecls PARAMS ((tree, tree));
-static void set_rtti_entry PARAMS ((tree, tree, tree));
-static void build_vtable PARAMS ((tree, tree));
-static void prepare_fresh_vtable PARAMS ((tree, tree));
-static tree dfs_fixup_vtable_deltas PARAMS ((tree, void *));
+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, tree, tree, tree,
+                                              tree));
 static void finish_vtbls PARAMS ((tree));
-static void modify_vtable_entry PARAMS ((tree, tree, tree, tree));
+static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
 static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
 static tree delete_duplicate_fields_1 PARAMS ((tree, tree));
 static void delete_duplicate_fields PARAMS ((tree));
 static void finish_struct_bits PARAMS ((tree));
-static int alter_access PARAMS ((tree, tree, tree, tree));
+static int alter_access PARAMS ((tree, tree, tree));
 static void handle_using_decl PARAMS ((tree, tree));
 static int overrides PARAMS ((tree, tree));
 static int strictly_overrides PARAMS ((tree, tree));
-static void merge_overrides PARAMS ((tree, tree, int, tree));
-static void override_one_vtable PARAMS ((tree, tree, tree));
 static void mark_overriders PARAMS ((tree, tree));
 static void check_for_override PARAMS ((tree, tree));
-static tree dfs_get_class_offset PARAMS ((tree, void *));
-static tree get_class_offset PARAMS ((tree, tree, tree, tree));
-static void modify_one_vtable PARAMS ((tree, tree, tree));
 static tree dfs_modify_vtables PARAMS ((tree, void *));
 static tree modify_all_vtables PARAMS ((tree, int *, tree));
 static void determine_primary_base PARAMS ((tree, int *));
@@ -113,44 +123,72 @@ static tree fixed_type_or_null PARAMS ((tree, int *));
 static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
                                                          int, tree));
 static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
-static tree build_vtbl_initializer PARAMS ((tree, tree));
+static tree build_vtbl_initializer PARAMS ((tree, tree, 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));
 static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
 static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, 
                                     int *));
-static int avoid_overlap PARAMS ((tree, tree, int *));
-static tree build_base_field PARAMS ((tree, tree, int *, int *, unsigned int *));
-static tree build_base_fields PARAMS ((tree, int *));
-static tree build_vbase_pointer_fields PARAMS ((tree, int *));
-static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, int *));
+static void build_base_field PARAMS ((record_layout_info, tree, int *,
+                                     unsigned int *, varray_type *));
+static varray_type build_base_fields PARAMS ((record_layout_info, int *));
+static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
+static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
+                                              int *));
 static void check_methods PARAMS ((tree));
 static void remove_zero_width_bit_fields PARAMS ((tree));
 static void check_bases PARAMS ((tree, int *, int *, int *));
 static void check_bases_and_members PARAMS ((tree, int *));
-static void create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
+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 propagate_binfo_offsets PARAMS ((tree, tree));
-static void layout_basetypes PARAMS ((tree));
-static void layout_virtual_bases PARAMS ((tree));
-static void remove_base_field PARAMS ((tree, tree, tree *));
-static void remove_base_fields PARAMS ((tree));
+static void layout_virtual_bases PARAMS ((tree, varray_type *));
 static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
 static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
-static tree dfs_build_vbase_offset_vtbl_entries PARAMS ((tree, void *));
-static tree build_vbase_offset_vtbl_entries PARAMS ((tree, tree));
-static tree dfs_vcall_offset_queue_p PARAMS ((tree, void *));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
 static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
-static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree));
-static tree dfs_count_virtuals PARAMS ((tree, void *));
-static void start_vtable PARAMS ((tree, int *));
+static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
 static void layout_vtable_decl PARAMS ((tree, int));
-static int num_vfun_entries PARAMS ((tree));
+static tree dfs_find_final_overrider PARAMS ((tree, void *));
+static tree find_final_overrider PARAMS ((tree, tree, tree));
+static tree dfs_find_base PARAMS ((tree, void *));
+static int make_new_vtable PARAMS ((tree, tree));
+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));
+static tree dfs_record_base_offsets PARAMS ((tree, void *));
+static void record_base_offsets PARAMS ((tree, varray_type *));
+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, 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, 
+                                                       vcall_offset_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));
+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.  */
 
@@ -171,12 +209,13 @@ int n_inner_fields_searched = 0;
    FIELD_DECLS.  */
 
 static tree
-build_vbase_pointer_fields (rec, empty_p)
-     tree rec;
+build_vbase_pointer_fields (rli, empty_p)
+     record_layout_info rli;
      int *empty_p;
 {
   /* Chain to hold all the new FIELD_DECLs which point at virtual
      base classes.  */
+  tree rec = rli->t;
   tree vbase_decls = NULL_TREE;
   tree binfos = TYPE_BINFO_BASETYPES (rec);
   int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
@@ -194,7 +233,7 @@ build_vbase_pointer_fields (rec, empty_p)
       register tree base_binfo = TREE_VEC_ELT (binfos, i);
       register tree basetype = BINFO_TYPE (base_binfo);
 
-      if (TYPE_SIZE (basetype) == 0)
+      if (!COMPLETE_TYPE_P (basetype))
        /* This error is now reported in xref_tag, thus giving better
           location information.  */
        continue;
@@ -219,7 +258,7 @@ build_vbase_pointer_fields (rec, 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);
@@ -227,9 +266,11 @@ build_vbase_pointer_fields (rec, empty_p)
                                            get_identifier (VTABLE_BASE),
                                            build_pointer_type (basetype),
                                            rec,
+                                           basetype,
                                            empty_p);
          BINFO_VPTR_FIELD (base_binfo) = decl;
          TREE_CHAIN (decl) = vbase_decls;
+         place_field (rli, decl);
          vbase_decls = decl;
          *empty_p = 0;
 
@@ -242,247 +283,6 @@ build_vbase_pointer_fields (rec, empty_p)
   return vbase_decls;
 }
 
-/* Called from build_vbase_offset_vtbl_entries via dfs_walk.  */
-
-static tree
-dfs_build_vbase_offset_vtbl_entries (binfo, data)
-     tree binfo;
-     void *data;
-{
-  tree list = (tree) data;
-
-  if (TREE_TYPE (list) == binfo)
-    /* The TREE_TYPE of LIST is the base class from which we started
-       walking.  If that BINFO is virtual it's not a virtual baseclass
-       of itself.  */
-    ;
-  else if (TREE_VIA_VIRTUAL (binfo))
-    {
-      tree init;
-      tree vbase;
-
-      /* Remember the index to the vbase offset for this virtual
-        base.  */
-      vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list));
-      if (!TREE_VALUE (list))
-       BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
-      else
-       {
-         BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
-         BINFO_VPTR_FIELD (vbase) = ssize_binop (MINUS_EXPR,
-                                                 BINFO_VPTR_FIELD (vbase),
-                                                 integer_one_node);
-       }
-
-      /* And record the offset at which this virtual base lies in the
-        vtable.  */
-      init = BINFO_OFFSET (binfo);
-      TREE_VALUE (list) = tree_cons (BINFO_VPTR_FIELD (vbase),
-                                    init, 
-                                    TREE_VALUE (list));
-    }
-
-  SET_BINFO_VTABLE_PATH_MARKED (binfo);
-  
-  return NULL_TREE;
-}
-
-/* Returns the initializers for the vbase offset entries in the vtable
-   for BINFO (which is part of the class hierarchy dominated by T), in
-   reverse order.  */
-
-static tree
-build_vbase_offset_vtbl_entries (binfo, t)
-     tree binfo;
-     tree t;
-{
-  tree inits;
-  tree init;
-  tree list;
-
-  /* Under the old ABI, pointers to virtual bases are stored in each
-     object.  */
-  if (!vbase_offsets_in_vtable_p ())
-    return NULL_TREE;
-
-  /* If there are no virtual baseclasses, then there is nothing to
-     do.  */
-  if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
-    return NULL_TREE;
-
-  inits = NULL_TREE;
-
-  /* The offsets are allocated in the reverse order of a
-     depth-first left-to-right traversal of the hierarchy.  We use
-     BINFO_VTABLE_PATH_MARKED because we are ourselves during a
-     dfs_walk, and so BINFO_MARKED is already in use.  */
-  list = build_tree_list (t, NULL_TREE);
-  TREE_TYPE (list) = binfo;
-  dfs_walk (binfo,
-           dfs_build_vbase_offset_vtbl_entries,
-           dfs_vtable_path_unmarked_real_bases_queue_p,
-           list);
-  dfs_walk (binfo,
-           dfs_vtable_path_unmark,
-           dfs_vtable_path_marked_real_bases_queue_p,
-           list);
-  inits = nreverse (TREE_VALUE (list));
-
-  /* We've now got offsets in the right order.  However, the offsets
-     we've stored are offsets from the beginning of the complete
-     object, and we need offsets from this BINFO.  */
-  for (init = inits; init; init = TREE_CHAIN (init))
-    {
-      tree exp = TREE_VALUE (init);
-
-      exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo));
-      exp = build1 (NOP_EXPR, vtable_entry_type, exp);
-      exp = fold (exp);
-      TREE_CONSTANT (exp) = 1;
-      /* The dfs_build_vbase_offset_vtbl_entries routine uses the
-        TREE_PURPOSE to scribble in.  But, we need to clear it now so
-        that the values are not perceived as labeled initializers.  */
-      TREE_PURPOSE (init) = NULL_TREE;
-      TREE_VALUE (init) = exp;
-    }
-
-  return inits;
-}
-
-typedef struct vcall_offset_data_s
-{
-  /* The binfo for the most-derived type.  */
-  tree derived;
-  /* The binfo for the virtual base for which we're building
-     initializers.  */
-  tree vbase;
-  /* The vcall offset initializers built up so far.  */
-  tree inits;
-  /* The number of vcall offsets accumulated.  */
-  int offsets;
-} vcall_offset_data;
-
-/* Called from build_vcall_offset_vtbl_entries via dfs_walk.  */
-
-static tree
-dfs_vcall_offset_queue_p (binfo, data)
-     tree binfo;
-     void *data;
-{
-  vcall_offset_data* vod = (vcall_offset_data *) data;
-
-  return (binfo == vod->vbase) ? binfo : dfs_skip_vbases (binfo, NULL);
-}
-
-/* Called from build_vcall_offset_vtbl_entries via dfs_walk.  */
-
-static tree
-dfs_build_vcall_offset_vtbl_entries (binfo, data)
-     tree binfo;
-     void *data;
-{
-  vcall_offset_data* vod;
-  tree virtuals;
-  tree binfo_inits;
-
-  /* Primary bases are not interesting; all of the virtual
-     function table entries have been overridden.  */
-  if (BINFO_PRIMARY_MARKED_P (binfo))
-     return NULL_TREE;
-
-  vod = (vcall_offset_data *) data;
-  binfo_inits = NULL_TREE;
-
-  /* We chain the offsets on in reverse order.  That's correct --
-     build_vtbl_initializer will straighten them out.  */
-  for (virtuals = skip_rtti_stuff (binfo,
-                                  BINFO_TYPE (binfo),
-                                  NULL);
-       virtuals;
-       virtuals = TREE_CHAIN (virtuals))
-    {
-      tree fn;
-      tree base;
-      tree base_binfo;
-      tree offset;
-
-      /* Figure out what function we're looking at.  */
-      fn = TREE_VALUE (virtuals);
-      base = DECL_CLASS_CONTEXT (fn);
-
-      /* The FN is comes from BASE.  So, we must caculate the
-        adjustment from the virtual base that derived from BINFO to
-        BASE.  */
-      base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
-      offset = ssize_binop (MINUS_EXPR,
-                           BINFO_OFFSET (base_binfo),
-                           BINFO_OFFSET (vod->vbase));
-      offset = build1 (NOP_EXPR, vtable_entry_type, offset);
-      offset = fold (offset);
-      TREE_CONSTANT (offset) = 1;
-      binfo_inits = tree_cons (NULL_TREE, offset, binfo_inits);
-    }
-
-  /* Now add the initializers we've just created to the list that will
-     be returned to our caller.  */
-  vod->inits = chainon (vod->inits, binfo_inits);
-
-  return NULL_TREE;
-}
-
-/* Returns the initializers for the vcall offset entries in the vtable
-   for BINFO (which is part of the class hierarchy dominated by T), in
-   reverse order.  */
-
-static tree
-build_vcall_offset_vtbl_entries (binfo, t)
-     tree binfo;
-     tree t;
-{
-  vcall_offset_data vod;
-
-  /* Under the old ABI, the adjustments to the `this' pointer were made
-     elsewhere.  */
-  if (!vcall_offsets_in_vtable_p ())
-    return NULL_TREE;
-
-  /* We only need these entries if this base is a virtual base.  */
-  if (!TREE_VIA_VIRTUAL (binfo))
-    return NULL_TREE;
-
-  /* We need a vcall offset for each of the virtual functions in this
-     vtable.  For example:
-
-       class A { virtual void f (); };
-       class B : virtual public A { };
-       class C: virtual public A, public B {};
-      
-     Now imagine:
-
-       B* b = new C;
-       b->f();
-
-     The location of `A' is not at a fixed offset relative to `B'; the
-     offset depends on the complete object derived from `B'.  So, 
-     `B' vtable contains an entry for `f' that indicates by what
-     amount the `this' pointer for `B' needs to be adjusted to arrive
-     at `A'.  
-
-     We need entries for all the functions in our primary vtable and
-     in our non-virtual bases vtables.  For each base, the entries
-     appear in the same order as in the base; but the bases themselves
-     appear in reverse depth-first, left-to-right order.  */
-  vod.derived = t;
-  vod.vbase = binfo;
-  vod.inits = NULL_TREE;
-  dfs_walk (binfo,
-           dfs_build_vcall_offset_vtbl_entries,
-           dfs_vcall_offset_queue_p,
-           &vod);
-
-  return vod.inits;
-}
-
 /* Returns a pointer to the virtual base class of EXP that has the
    indicated TYPE.  EXP is of class type, not a pointer type.  */
 
@@ -497,13 +297,14 @@ 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.  */
-      vbase_ptr = build_binary_op (PLUS_EXPR, 
-                                  vbase_ptr,
-                                  BINFO_VPTR_FIELD (vbase));
+      vbase_ptr = build (PLUS_EXPR, 
+                        TREE_TYPE (vbase_ptr),
+                        vbase_ptr,
+                        BINFO_VPTR_FIELD (vbase));
       vbase_ptr = build1 (NOP_EXPR, 
                          build_pointer_type (ptrdiff_type_node),
                          vbase_ptr);
@@ -557,16 +358,15 @@ build_vbase_path (code, type, expr, path, nonnull)
     expr = save_expr (expr);
   nonnull_expr = expr;
 
-  if (BINFO_INHERITANCE_CHAIN (path))
-    path = reverse_path (path);
+  path = reverse_path (path);
 
   basetype = BINFO_TYPE (path);
 
   while (path)
     {
-      if (TREE_VIA_VIRTUAL (path))
+      if (TREE_VIA_VIRTUAL (TREE_VALUE (path)))
        {
-         last_virtual = BINFO_TYPE (path);
+         last_virtual = BINFO_TYPE (TREE_VALUE (path));
          if (code == PLUS_EXPR)
            {
              changed = ! fixed_type_p;
@@ -608,8 +408,8 @@ build_vbase_path (code, type, expr, path, nonnull)
              return error_mark_node;
            }
        }
-      last = path;
-      path = BINFO_INHERITANCE_CHAIN (path);
+      last = TREE_VALUE (path);
+      path = TREE_CHAIN (path);
     }
   /* LAST is now the last basetype assoc on the path.  */
 
@@ -631,23 +431,18 @@ build_vbase_path (code, type, expr, path, nonnull)
   if (changed)
     {
       tree intype = TREE_TYPE (TREE_TYPE (expr));
+
       if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last))
-       {
-         tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0);
-         offset = BINFO_OFFSET (binfo);
-       }
+       offset
+         = BINFO_OFFSET (get_binfo (last, TYPE_MAIN_VARIANT (intype), 0));
     }
   else
     offset = BINFO_OFFSET (last);
 
-  if (TREE_INT_CST_LOW (offset))
+  if (! integer_zerop (offset))
     {
       /* Bash types to make the backend happy.  */
       offset = cp_convert (type, offset);
-#if 0
-      /* This shouldn't be necessary.  (mrs) */
-      expr = build1 (NOP_EXPR, type, expr);
-#endif
 
       /* If expr might be 0, we need to preserve that zeroness.  */
       if (nonnull == 0)
@@ -681,80 +476,6 @@ build_vbase_path (code, type, expr, path, nonnull)
 \f
 /* Virtual function things.  */
 
-/* Build an entry in the virtual function table.  DELTA is the offset
-   for the `this' pointer.  VCALL_INDEX is the vtable index containing
-   the vcall offset; zero if none.  FNDECL is the virtual function
-   itself.  */
-
-static tree
-build_vtable_entry (delta, vcall_index, fndecl)
-     tree delta;
-     tree vcall_index;
-     tree fndecl;
-{
-  tree pfn;
-
-  /* Take the address of the function, considering it to be of an
-     appropriate generic type.  */
-  pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
-  /* The address of a function can't change.  */
-  TREE_CONSTANT (pfn) = 1;
-
-  if (flag_vtable_thunks)
-    {
-      HOST_WIDE_INT idelta;
-      HOST_WIDE_INT ivindex;
-
-      idelta = TREE_INT_CST_LOW (delta);
-      ivindex = TREE_INT_CST_LOW (vcall_index);
-      if ((idelta || ivindex) 
-         && ! DECL_PURE_VIRTUAL_P (TREE_OPERAND (pfn, 0)))
-       {
-         pfn = make_thunk (pfn, idelta, ivindex);
-         pfn = build1 (ADDR_EXPR, vtable_entry_type, pfn);
-         TREE_READONLY (pfn) = 1;
-         TREE_CONSTANT (pfn) = 1;
-       }
-#ifdef GATHER_STATISTICS
-      n_vtable_entries += 1;
-#endif
-      return pfn;
-    }
-  else
-    {
-      extern int flag_huge_objects;
-      tree elems = tree_cons (NULL_TREE, delta,
-                             tree_cons (NULL_TREE, integer_zero_node,
-                                        build_tree_list (NULL_TREE, pfn)));
-      tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
-
-      /* We don't use vcall offsets when not using vtable thunks.  */
-      my_friendly_assert (integer_zerop (vcall_index), 20000125);
-
-      /* DELTA used to be constructed by `size_int' and/or size_binop,
-        which caused overflow problems when it was negative.  That should
-        be fixed now.  */
-
-      if (! int_fits_type_p (delta, delta_type_node))
-       {
-         if (flag_huge_objects)
-           sorry ("object size exceeds built-in limit for virtual function table implementation");
-         else
-           sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
-       }
-      
-      TREE_CONSTANT (entry) = 1;
-      TREE_STATIC (entry) = 1;
-      TREE_READONLY (entry) = 1;
-
-#ifdef GATHER_STATISTICS
-      n_vtable_entries += 1;
-#endif
-
-      return entry;
-    }
-}
-
 /* We want to give the assembler the vtable identifier as well as
    the offset to the function pointer.  So we generate
 
@@ -769,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, TYPE_BINFO_VTABLE (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);
@@ -840,7 +563,23 @@ build_vtbl_ref (instance, idx)
          && (TREE_CODE (instance) == RESULT_DECL
              || TREE_CODE (instance) == PARM_DECL
              || TREE_CODE (instance) == VAR_DECL))
-       vtbl = TYPE_BINFO_VTABLE (basetype);
+       {
+         vtbl = TYPE_BINFO_VTABLE (basetype);
+         /* Knowing the dynamic type of INSTANCE we can easily obtain
+            the correct vtable entry.  In the new ABI, we resolve
+            this back to be in terms of the primary vtable.  */
+         if (TREE_CODE (vtbl) == PLUS_EXPR)
+           {
+             idx = fold (build (PLUS_EXPR,
+                                TREE_TYPE (idx),
+                                idx,
+                                build (EXACT_DIV_EXPR,
+                                       TREE_TYPE (idx),
+                                       TREE_OPERAND (vtbl, 1),
+                                       TYPE_SIZE_UNIT (vtable_entry_type))));
+             vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
+           }
+       }
       else
        vtbl = build_vfield_ref (instance, basetype);
     }
@@ -896,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; prepare_fresh_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.  */
@@ -920,19 +662,17 @@ tree
 get_vfield_offset (binfo)
      tree binfo;
 {
-  tree tmp
-    = size_binop (FLOOR_DIV_EXPR,
-                 DECL_FIELD_BITPOS (TYPE_VFIELD (BINFO_TYPE (binfo))),
-                 size_int (BITS_PER_UNIT));
-  tmp = convert (sizetype, tmp);
-  return size_binop (PLUS_EXPR, tmp, BINFO_OFFSET (binfo));
+  return
+    size_binop (PLUS_EXPR, byte_position (TYPE_VFIELD (BINFO_TYPE (binfo))),
+               BINFO_OFFSET (binfo));
 }
 
 /* Get the offset to the start of the original binfo that we derived
    this binfo from.  If we find TYPE first, return the offset only
    that far.  The shortened search is useful because the this pointer
    on method calling is expected to point to a DECL_CONTEXT (fndecl)
-   object, and not a baseclass of it.  */
+   object, and not a baseclass of it.   */
+
 
 static tree
 get_derived_offset (binfo, type)
@@ -941,58 +681,45 @@ get_derived_offset (binfo, type)
   tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
   tree offset2;
   int i;
+
   while (BINFO_BASETYPES (binfo)
-        && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
+        && (i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
     {
       tree binfos = BINFO_BASETYPES (binfo);
       if (BINFO_TYPE (binfo) == type)
        break;
       binfo = TREE_VEC_ELT (binfos, i);
     }
+
   offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
   return size_binop (MINUS_EXPR, offset1, offset2);
 }
 
-/* Update the rtti info for this class.  */
+/* Create a VAR_DECL for a primary or secondary vtable for
+   CLASS_TYPE.  Use NAME for the name of the vtable, and VTABLE_TYPE
+   for its type.  */
 
-static void
-set_rtti_entry (virtuals, offset, type)
-     tree virtuals, offset, type;
+static tree
+build_vtable (class_type, name, vtable_type)
+     tree class_type;
+     tree name;
+     tree vtable_type;
 {
   tree decl;
 
-  if (CLASSTYPE_COM_INTERFACE (type))
-    return;
+  decl = build_lang_decl (VAR_DECL, name, vtable_type);
+  DECL_CONTEXT (decl) = class_type;
+  DECL_ARTIFICIAL (decl) = 1;
+  TREE_STATIC (decl) = 1;
+#ifndef WRITABLE_VTABLES
+  /* Make them READONLY by default. (mrs) */
+  TREE_READONLY (decl) = 1;
+#endif
+  DECL_VIRTUAL_P (decl) = 1;
+  import_export_vtable (decl, class_type, 0);
 
-  if (flag_rtti)
-    decl = get_tinfo_decl (type);
-  else if (!new_abi_rtti_p ())
-    /* If someone tries to get RTTI information for a type compiled
-       without RTTI, they're out of luck.  By calling __pure_virtual
-       in this case, we give a small clue as to what went wrong.  We
-       could consider having a __no_typeinfo function as well, for a
-       more specific hint.  */
-    decl = abort_fndecl;
-  else
-    /* For the new-abi, we just point to the type_info object.  */
-    decl = NULL_TREE;
-
-  if (flag_vtable_thunks)
-    {
-      /* The first slot holds the offset.  */
-      BF_DELTA (virtuals) = offset;
-      BF_VCALL_INDEX (virtuals) = integer_zero_node;
-
-      /* The next node holds the decl.  */
-      virtuals = TREE_CHAIN (virtuals);
-      offset = integer_zero_node;
-    }
-
-  /* This slot holds the function to call.  */
-  BF_DELTA (virtuals) = offset;
-  BF_VCALL_INDEX (virtuals) = integer_zero_node;
-  BF_FN (virtuals) = decl;
-}
+  return decl;
+}
 
 /* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
    or even complete.  If this does not exist, create it.  If COMPLETE is
@@ -1000,7 +727,8 @@ set_rtti_entry (virtuals, offset, type)
    impossible to actually build the vtable, but is useful to get at those
    which are known to exist in the runtime.  */
 
-tree get_vtable_decl (type, complete)
+tree 
+get_vtable_decl (type, complete)
      tree type;
      int complete;
 {
@@ -1014,41 +742,50 @@ tree get_vtable_decl (type, complete)
       return decl;
     }
   
-  decl = build_lang_decl (VAR_DECL, name, void_type_node);
-  
-  /* Set TREE_PUBLIC and TREE_EXTERN as appropriate.  */
-  import_export_vtable (decl, type, 0);
-
+  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);
   
-  DECL_ARTIFICIAL (decl) = 1;
-  TREE_STATIC (decl) = 1;
-#ifndef WRITABLE_VTABLES
-  /* Make them READONLY by default. (mrs) */
-  TREE_READONLY (decl) = 1;
-#endif
   /* At one time the vtable info was grabbed 2 words at a time.  This
      fails on sparc unless you have 8-byte alignment.  (tiemann) */
   DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
                           DECL_ALIGN (decl));
 
-  DECL_VIRTUAL_P (decl) = 1;
-  
   if (complete)
-    cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+    {
+      DECL_EXTERNAL (decl) = 1;
+      cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+    }
 
-  DECL_CONTEXT (decl) = type;
   return decl;
 }
 
-/* Build a virtual function for type 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 list.  */
+/* Returns a copy of the BINFO_VIRTUALS list in BINFO.  The
+   BV_VCALL_INDEX for each entry is cleared.  */
 
-static void
-build_vtable (binfo, type)
+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
+   list.  Returns a non-zero value if a new vtable is actually
+   created.  */
+
+static int
+build_primary_vtable (binfo, type)
      tree binfo, type;
 {
   tree virtuals, decl;
@@ -1057,21 +794,15 @@ build_vtable (binfo, type)
   
   if (binfo)
     {
-      tree offset;
-
-      if (BINFO_NEW_VTABLE_MARKED (binfo))
+      if (BINFO_NEW_VTABLE_MARKED (binfo, type))
        /* We have already created a vtable for this base, so there's
           no need to do it again.  */
-       return;
-
-      virtuals = copy_list (BINFO_VIRTUALS (binfo));
-      TREE_TYPE (decl) = TREE_TYPE (BINFO_VTABLE (binfo));
-      DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
-
-      /* Now do rtti stuff.  */
-      offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
-      offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset);
-      set_rtti_entry (virtuals, offset, type);
+       return 0;
+      
+      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));
     }
   else
     {
@@ -1091,7 +822,8 @@ build_vtable (binfo, type)
   TYPE_BINFO_VIRTUALS (type) = virtuals;
 
   binfo = TYPE_BINFO (type);
-  SET_BINFO_NEW_VTABLE_MARKED (binfo);
+  SET_BINFO_NEW_VTABLE_MARKED (binfo, type);
+  return 1;
 }
 
 /* Give TYPE a new virtual function table which is initialized
@@ -1108,8 +840,8 @@ build_vtable (binfo, type)
    an object must remain the same, otherwise a binary incompatibility
    can result.  */
 
-static void
-prepare_fresh_vtable (binfo, for_type)
+static int
+build_secondary_vtable (binfo, for_type)
      tree binfo, for_type;
 {
   tree basetype;
@@ -1126,13 +858,48 @@ prepare_fresh_vtable (binfo, for_type)
   joiner = JOINER;
 #endif
 
-  if (BINFO_NEW_VTABLE_MARKED (binfo))
+  if (TREE_VIA_VIRTUAL (binfo))
+    my_friendly_assert (binfo == binfo_for_vbase (BINFO_TYPE (binfo),
+                                                 current_class_type),
+                       170);
+
+  if (BINFO_NEW_VTABLE_MARKED (binfo, current_class_type))
     /* We already created a vtable for this base.  There's no need to
        do it again.  */
-    return;
+    return 0;
 
-  basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo));
+  /* Remember that we've created a vtable for this BINFO, so that we
+     don't try to do so again.  */
+  SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type);
+  
+  /* Make fresh virtual list, so we can smash it later.  */
+  BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
+
+  if (TREE_VIA_VIRTUAL (binfo))
+    {
+      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
+        base type's.  We can remove all this code after a while.  */
+      if (binfo1 != binfo)
+       warning ("internal inconsistency: binfo offset error for rtti");
+
+      offset = BINFO_OFFSET (binfo1);
+    }
+  else
+    offset = BINFO_OFFSET (binfo);
+
+  /* In the new ABI, secondary vtables are laid out as part of the
+     same structure as the primary vtable.  */
+  if (merge_primary_and_secondary_vtables_p ())
+    {
+      BINFO_VTABLE (binfo) = NULL_TREE;
+      return 1;
+    }
 
+  /* Create the declaration for the secondary vtable.  */
+  basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo));
   buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype);
   i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1;
 
@@ -1210,113 +977,79 @@ prepare_fresh_vtable (binfo, for_type)
       buf2 = new_buf2;
     }
 
-  new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
-  /* Remember which class this vtable is really for.  */
-  DECL_CONTEXT (new_decl) = for_type;
-
-  DECL_ARTIFICIAL (new_decl) = 1;
-  TREE_STATIC (new_decl) = 1;
-  BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);
-  DECL_VIRTUAL_P (new_decl) = 1;
-#ifndef WRITABLE_VTABLES
-  /* Make them READONLY by default. (mrs) */
-  TREE_READONLY (new_decl) = 1;
-#endif
+  new_decl = build_vtable (for_type, name, TREE_TYPE (orig_decl));
   DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
-
-  /* Make fresh virtual list, so we can smash it later.  */
-  BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
-
-  if (TREE_VIA_VIRTUAL (binfo))
-    {
-      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
-        base type's.  We can remove all this code after a while.  */
-      if (binfo1 != binfo)
-       warning ("internal inconsistency: binfo offset error for rtti");
-
-      offset = BINFO_OFFSET (binfo1);
-    }
-  else
-    offset = BINFO_OFFSET (binfo);
-
-  set_rtti_entry (BINFO_VIRTUALS (binfo),
-                 ssize_binop (MINUS_EXPR, integer_zero_node, offset),
-                 for_type);
+  BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);
 
 #ifdef GATHER_STATISTICS
   n_vtables += 1;
   n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
 #endif
 
-  /* Set TREE_PUBLIC and TREE_EXTERN as appropriate.  */
-  import_export_vtable (new_decl, for_type, 0);
+  return 1;
+}
 
-  if (TREE_VIA_VIRTUAL (binfo))
-    my_friendly_assert (binfo == BINFO_FOR_VBASE (BINFO_TYPE (binfo),
-                                                 current_class_type),
-                       170);
-  SET_BINFO_NEW_VTABLE_MARKED (binfo);
+/* Create a new vtable for BINFO which is the hierarchy dominated by
+   T.  */
+
+static int
+make_new_vtable (t, binfo)
+     tree t;
+     tree binfo;
+{
+  if (binfo == TYPE_BINFO (t))
+    /* In this case, it is *type*'s vtable we are modifying.  We start
+       with the approximation that it's vtable is that of the
+       immediate base class.  */
+    return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))), 
+                                t);
+  else
+    /* This is our very own copy of `basetype' to play with.  Later,
+       we will fill in all the virtual functions that override the
+       virtual functions in these base classes which are not defined
+       by the current type.  */
+    return build_secondary_vtable (binfo, t);
 }
 
-/* Make V, an entry on the BINFO_VIRTUALS list for BINFO (which is in
-   the hierarchy dominated by T) list FNDECL as its BF_FN.  */
+/* Make *VIRTUALS, an entry on the BINFO_VIRTUALS list for BINFO
+   (which is in the hierarchy dominated by T) list FNDECL as its
+   BV_FN.  DELTA is the required constant adjustment from the `this'
+   pointer where the vtable entry appears to the `this' required when
+   the function is actually called.  */
 
 static void
-modify_vtable_entry (t, binfo, fndecl, v)
+modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
      tree t;
      tree binfo;
      tree fndecl;
-     tree v;
-{
-  tree base_offset, offset;
-  tree context = DECL_CLASS_CONTEXT (fndecl);
-  tree vfield = TYPE_VFIELD (t);
-  tree this_offset;
-  tree vcall_index;
-
-  offset = get_class_offset (context, t, binfo, fndecl);
-
-  /* Find the right offset for ythe this pointer based on the
-     base class we just found.  We have to take into
-     consideration the virtual base class pointers that we
-     stick in before the virtual function table pointer.
-
-     Also, we want just the delta between the most base class
-     that we derived this vfield from and us.  */
-  base_offset 
-    = size_binop (PLUS_EXPR,
-                 get_derived_offset (binfo, 
-                                     DECL_VIRTUAL_CONTEXT (BF_FN (v))),
-                 BINFO_OFFSET (binfo));
-  this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
-  vcall_index = integer_zero_node;
-
-  if (fndecl != BF_FN (v)
-      || !tree_int_cst_equal (this_offset, BF_DELTA (v))
-      || !tree_int_cst_equal (vcall_index, BF_VCALL_INDEX (v)))
+     tree delta;
+     tree *virtuals;
+{
+  tree v;
+
+  v = *virtuals;
+
+  if (fndecl != BV_FN (v)
+      || !tree_int_cst_equal (delta, BV_DELTA (v)))
     {
       tree base_fndecl;
 
-      /* Make sure we can modify the derived association with immunity.  */
-      if (binfo == TYPE_BINFO (t))
-       /* In this case, it is *type*'s vtable we are modifying.  We
-          start with the approximation that it's vtable is that of
-          the immediate base class.  */
-       build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
-      else
-       /* This is our very own copy of `basetype' to play with.
-          Later, we will fill in all the virtual functions that
-          override the virtual functions in these base classes which
-          are not defined by the current type.  */
-       prepare_fresh_vtable (binfo, t);
+      /* We need a new vtable for BINFO.  */
+      if (make_new_vtable (t, binfo))
+       {
+         /* If we really did make a new vtable, we also made a copy
+            of the BINFO_VIRTUALS list.  Now, we have to find the
+            corresponding entry in that list.  */
+         *virtuals = BINFO_VIRTUALS (binfo);
+         while (BV_FN (*virtuals) != BV_FN (v))
+           *virtuals = TREE_CHAIN (*virtuals);
+         v = *virtuals;
+       }
 
-      base_fndecl = BF_FN (v);
-      BF_DELTA (v) = this_offset;
-      BF_VCALL_INDEX (v) = vcall_index;
-      BF_FN (v) = fndecl;
+      base_fndecl = BV_FN (v);
+      BV_DELTA (v) = delta;
+      BV_VCALL_INDEX (v) = NULL_TREE;
+      BV_FN (v) = fndecl;
 
       /* Now assign virtual dispatch information, if unset.  We can
         dispatch this, through any overridden base function.  */
@@ -1328,42 +1061,52 @@ modify_vtable_entry (t, binfo, fndecl, v)
     }
 }
 
-/* Call this function whenever its known that a vtable for T is going
-   to be needed.  It's safe to call it more than once.  *HAS_VIRTUAL_P
-   is initialized to the number of slots that are reserved at the
-   beginning of the vtable for RTTI information.  */
+/* Return the index (in the virtual function table) of the first
+   virtual function.  */
+
+int
+first_vfun_index (t)
+     tree t;
+{
+  /* Under the old ABI, the offset-to-top and RTTI entries are at
+     indices zero and one; under the new ABI, the first virtual
+     function is at index zero.  */
+  if (!CLASSTYPE_COM_INTERFACE (t) && !flag_new_abi)
+    return flag_vtable_thunks ? 2 : 1;
+
+  return 0;
+}
+
+/* Set DECL_VINDEX for DECL.  VINDEX_P is the number of virtual
+   functions present in the vtable so far.  */
 
 static void
-start_vtable (t, has_virtual_p)
+set_vindex (t, decl, vfuns_p)
      tree t;
-     int *has_virtual_p;
+     tree decl;
+     int *vfuns_p;
 {
-  if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t))
-    {
-      /* If we are using thunks, use two slots at the front, one
-        for the offset pointer, one for the tdesc pointer.
-         For ARM-style vtables, use the same slot for both.  */
-      if (flag_vtable_thunks)
-       *has_virtual_p = 2;
-      else
-       *has_virtual_p = 1;
-    }
+  int vindex;
+
+  vindex = (*vfuns_p)++;
+  vindex += first_vfun_index (t);
+  DECL_VINDEX (decl) = build_shared_int_cst (vindex);
 }
 
 /* Add a virtual function to all the appropriate vtables for the class
    T.  DECL_VINDEX(X) should be error_mark_node, if we want to
    allocate a new slot in our table.  If it is error_mark_node, we
    know that no other function from another vtable is overridden by X.
-   HAS_VIRTUAL keeps track of how many virtuals there are in our main
-   vtable for the type, and we build upon the NEW_VIRTUALS list
+   VFUNS_P keeps track of how many virtuals there are in our
+   main vtable for the type, and we build upon the NEW_VIRTUALS list
    and return it.  */
 
 static void
 add_virtual_function (new_virtuals_p, overridden_virtuals_p,
-                     has_virtual, fndecl, t)
+                     vfuns_p, fndecl, t)
      tree *new_virtuals_p;
      tree *overridden_virtuals_p;
-     int *has_virtual;
+     int *vfuns_p;
      tree fndecl;
      tree t; /* Structure type.  */
 {
@@ -1377,8 +1120,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
     /* We've already dealt with this function.  */
     return;
 
-  new_virtual = build_tree_list (integer_zero_node, fndecl);
-  BF_VCALL_INDEX (new_virtual) = integer_zero_node;
+  new_virtual = build_tree_list (NULL_TREE, fndecl);
+  BV_DELTA (new_virtual) = integer_zero_node;
 
   if (DECL_VINDEX (fndecl) == error_mark_node)
     {
@@ -1388,10 +1131,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
       /* We remember that this was the base sub-object for rtti.  */
       CLASSTYPE_RTTI (t) = t;
 
-      start_vtable (t, has_virtual);
-
       /* Now assign virtual dispatch information.  */
-      DECL_VINDEX (fndecl) = build_shared_int_cst ((*has_virtual)++);
+      set_vindex (t, fndecl, vfuns_p);
       DECL_VIRTUAL_CONTEXT (fndecl) = t;
 
       /* Save the state we've computed on the NEW_VIRTUALS list.  */
@@ -1417,10 +1158,7 @@ void
 add_method (type, fields, method)
      tree type, *fields, method;
 {
-  /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
-     redundant.  */
-  DECL_CONTEXT (method) = type;
-  DECL_CLASS_CONTEXT (method) = type;
+  int using = (DECL_CONTEXT (method) != type);
   
   if (fields && *fields)
     *fields = build_overload (method, *fields);
@@ -1447,14 +1185,15 @@ add_method (type, fields, method)
       method_vec = CLASSTYPE_METHOD_VEC (type);
       len = TREE_VEC_LENGTH (method_vec);
 
-      if (DECL_NAME (method) == constructor_name (type))
-       /* A new constructor or destructor.  Constructors go in 
-          slot 0; destructors go in slot 1.  */
-       slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
+      /* Constructors and destructors go in special slots.  */
+      if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
+       slot = CLASSTYPE_CONSTRUCTOR_SLOT;
+      else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
+       slot = CLASSTYPE_DESTRUCTOR_SLOT;
       else
        {
          /* See if we already have an entry with this name.  */
-         for (slot = 2; slot < len; ++slot)
+         for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
            if (!TREE_VEC_ELT (method_vec, slot)
                || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, 
                                                          slot))) 
@@ -1536,20 +1275,27 @@ add_method (type, fields, method)
                     same name and the same parameter types cannot be
                     overloaded if any of them is a static member
                     function declaration.  */
-                 if (DECL_STATIC_FUNCTION_P (fn)
-                     != DECL_STATIC_FUNCTION_P (method))
+                 if ((DECL_STATIC_FUNCTION_P (fn)
+                      != DECL_STATIC_FUNCTION_P (method))
+                     || using)
                    {
                      tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
                      tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
 
                      if (! DECL_STATIC_FUNCTION_P (fn))
                        parms1 = TREE_CHAIN (parms1);
-                     else
+                     if (! DECL_STATIC_FUNCTION_P (method))
                        parms2 = TREE_CHAIN (parms2);
 
                      if (compparms (parms1, parms2))
-                       cp_error ("`%#D' and `%#D' cannot be overloaded",
-                                 fn, method);
+                       {
+                         if (using)
+                           /* Defer to the local function.  */
+                           return;
+                         else
+                           cp_error ("`%#D' and `%#D' cannot be overloaded",
+                                     fn, method);
+                       }
                    }
 
                  /* Since this is an ordinary function in a
@@ -1693,18 +1439,21 @@ delete_duplicate_fields (fields)
     TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
 }
 
-/* Change the access of FDECL to ACCESS in T.  The access to FDECL is
-   along the path given by BINFO.  Return 1 if change was legit,
-   otherwise return 0.  */
+/* Change the access of FDECL to ACCESS in T.  Return 1 if change was
+   legit, otherwise return 0.  */
 
 static int
-alter_access (t, binfo, fdecl, access)
+alter_access (t, fdecl, access)
      tree t;
-     tree binfo;
      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)
@@ -1724,7 +1473,7 @@ alter_access (t, binfo, fdecl, access)
     }
   else
     {
-      enforce_access (binfo, fdecl);
+      enforce_access (t, fdecl);
       DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
       return 1;
     }
@@ -1746,11 +1495,7 @@ handle_using_decl (using_decl, t)
     : access_public_node;
   tree fdecl, binfo;
   tree flist = NULL_TREE;
-  tree fields = TYPE_FIELDS (t);
-  tree method_vec = CLASSTYPE_METHOD_VEC (t);
-  tree tmp;
-  int i;
-  int n_methods;
+  tree old_value;
 
   binfo = binfo_or_else (ctype, t);
   if (! binfo)
@@ -1771,57 +1516,56 @@ handle_using_decl (using_decl, t)
       return;
     }
 
-  /* Functions are represented as TREE_LIST, with the purpose
-     being the type and the value the functions. Other members
-     come as themselves. */
-  if (TREE_CODE (fdecl) == TREE_LIST)
+  if (BASELINK_P (fdecl))
     /* Ignore base type this came from. */
     fdecl = TREE_VALUE (fdecl);
 
-  if (TREE_CODE (fdecl) == OVERLOAD)
+  old_value = IDENTIFIER_CLASS_VALUE (name);
+  if (old_value)
     {
-      /* We later iterate over all functions. */
-      flist = fdecl;
-      fdecl = OVL_FUNCTION (flist);
+      if (is_overloaded_fn (old_value))
+       old_value = OVL_CURRENT (old_value);
+
+      if (DECL_P (old_value) && DECL_CONTEXT (old_value) == t)
+       /* OK */;
+      else
+       old_value = NULL_TREE;
     }
-  
-  name = DECL_NAME (fdecl);
-  n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
-  for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); i++)
-    if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
-       == name)
-      {
-       cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
-       cp_error_at ("  because of local method `%#D' with same name",
-                    OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
-       return;
-      }
 
-  if (! DECL_LANG_SPECIFIC (fdecl))
-    /* We don't currently handle DECL_ACCESS for TYPE_DECLs; just return.  */
-    return;
-  
-  for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp))
-    if (DECL_NAME (tmp) == name)
-      {
-       cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
-       cp_error_at ("  because of local field `%#D' with same name", tmp);
-       return;
-      }
-  
-  /* Make type T see field decl FDECL with access ACCESS.*/
-  if (flist)
+  if (is_overloaded_fn (fdecl))
+    flist = fdecl;
+
+  if (! old_value)
+    ;
+  else if (is_overloaded_fn (old_value))
     {
-      while (flist)
+      if (flist)
+       /* It's OK to use functions from a base when there are functions with
+          the same name already present in the current class.  */;
+      else
        {
-         if (alter_access (t, binfo, OVL_FUNCTION (flist), 
-                           access) == 0)
-           return;
-         flist = OVL_CHAIN (flist);
+         cp_error ("`%D' invalid in `%#T'", using_decl, t);
+         cp_error_at ("  because of local method `%#D' with same name",
+                      OVL_CURRENT (old_value));
+         return;
        }
     }
   else
-    alter_access (t, binfo, fdecl, access);
+    {
+      cp_error ("`%D' invalid in `%#T'", using_decl, t);
+      cp_error_at ("  because of local field `%#D' with same name", old_value);
+      return;
+    }
+  
+  /* Make type T see field decl FDECL with access ACCESS.*/
+  if (flist)
+    for (; flist; flist = OVL_NEXT (flist))
+      {
+       add_method (t, 0, OVL_CURRENT (flist));
+       alter_access (t, OVL_CURRENT (flist), access);
+      }
+  else
+    alter_access (t, fdecl, access);
 }
 \f
 /* Run through the base clases of T, updating
@@ -1861,7 +1605,7 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
       /* If the type of basetype is incomplete, then we already
         complained about that fact (and we should have fixed it up as
         well).  */
-      if (TYPE_SIZE (basetype) == 0)
+      if (!COMPLETE_TYPE_P (basetype))
        {
          int j;
          /* The base type is of incomplete type.  It is
@@ -1901,11 +1645,8 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
        {
          *cant_have_default_ctor_p = 1;
          if (! TYPE_HAS_CONSTRUCTOR (t))
-           {
-             cp_pedwarn ("base `%T' with only non-default constructor",
-                         basetype);
-             cp_pedwarn ("in class without a constructor");
-           }
+            cp_pedwarn ("base `%T' with only non-default constructor in class without a constructor",
+                        basetype);
        }
 
       /* If the base class is not empty or nearly empty, then this
@@ -1925,7 +1666,8 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
       /* A lot of properties from the bases also apply to the derived
         class.  */
       TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
-      TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
+      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) 
+       |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype);
       TYPE_HAS_COMPLEX_ASSIGN_REF (t) 
        |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
       TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
@@ -1948,13 +1690,112 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
     }
 }
 
+/* Called via dfs_walk from mark_primary_bases.  Sets
+   BINFO_PRIMARY_MARKED_P for BINFO, if appropriate.  */
+
+static tree
+dfs_mark_primary_bases (binfo, data)
+     tree binfo;
+     void *data;
+{
+  int i;
+  tree base_binfo;
+
+  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+    return NULL_TREE;
+
+  i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+  base_binfo = BINFO_BASETYPE (binfo, i);
+
+  if (!TREE_VIA_VIRTUAL (base_binfo))
+    /* Non-virtual base classes are easy.  */
+    BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+  else
+    {
+      tree shared_binfo;
+      tree type;
+
+      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))
+       {
+         /* 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;
+       }
+    }
+
+  return NULL_TREE;
+}
+
+/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
+   dominated by BINFO that are primary bases.  */
+
+static void
+mark_primary_bases (type)
+     tree type;
+{
+  tree vbases;
+
+  /* Mark the TYPE_BINFO hierarchy.  We need to mark primary bases in
+     pre-order to deal with primary virtual bases.  (The virtual base
+     would be skipped if it were not marked as primary, and that
+     requires getting to dfs_mark_primary_bases before
+     dfs_skip_nonprimary_vbases_unmarkedp has a chance to skip the
+     virtual base.)  */
+  dfs_walk_real (TYPE_BINFO (type), dfs_mark_primary_bases, NULL,
+                dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+  /* Now go through the virtual base classes in inheritance graph
+     order.  Any that are not already primary will need to be
+     allocated in TYPE, and so we need to mark their primary bases.  */
+  for (vbases = TYPE_BINFO (type); vbases; vbases = TREE_CHAIN (vbases))
+    {
+      tree vbase;
+
+      /* Make sure that only BINFOs appear on this list.
+        Historically, the TREE_CHAIN was used for other purposes, and
+        we want to make sure that none of those uses remain.  */
+      my_friendly_assert (TREE_CODE (vbases) == TREE_VEC, 20000402);
+
+      if (!TREE_VIA_VIRTUAL (vbases))
+       continue;
+
+      vbase = binfo_for_vbase (BINFO_TYPE (vbases), type);
+      if (BINFO_VBASE_PRIMARY_P (vbase))
+       /* This virtual base was already included in the hierarchy, so
+          there's nothing to do here.  */
+       continue;
+
+      /* Temporarily pretend that VBASE is primary so that its bases
+        will be walked; this is the real copy of VBASE.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 1;
+
+      /* Now, walk its bases.  */
+      dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
+                    dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+      /* VBASE wasn't really primary.  */
+      BINFO_PRIMARY_MARKED_P (vbase) = 0;
+    }
+}
+
 /* Make the Ith baseclass of T its primary base.  */
 
 static void
-set_primary_base (t, i, has_virtual_p)
+set_primary_base (t, i, vfuns_p)
      tree t;
      int i;
-     int *has_virtual_p;
+     int *vfuns_p;
 {
   tree basetype;
 
@@ -1964,15 +1805,44 @@ set_primary_base (t, i, has_virtual_p)
   TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
   TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
   CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
-  *has_virtual_p = CLASSTYPE_VSIZE (basetype);
+  *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
-determine_primary_base (t, has_virtual_p)
+determine_primary_base (t, vfuns_p)
      tree t;
-     int *has_virtual_p;
+     int *vfuns_p;
 {
   int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
 
@@ -1980,7 +1850,7 @@ determine_primary_base (t, has_virtual_p)
   if (n_baseclasses == 0)
     return;
 
-  *has_virtual_p = 0;
+  *vfuns_p = 0;
 
   for (i = 0; i < n_baseclasses; i++)
     {
@@ -2003,7 +1873,7 @@ determine_primary_base (t, has_virtual_p)
 
          if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
            {
-             set_primary_base (t, i, has_virtual_p);
+             set_primary_base (t, i, vfuns_p);
              CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
            }
          else
@@ -2021,8 +1891,8 @@ determine_primary_base (t, has_virtual_p)
                                 VF_BASETYPE_VALUE (vfields),
                                 CLASSTYPE_VFIELDS (t));
 
-             if (*has_virtual_p == 0)
-               set_primary_base (t, i, has_virtual_p);
+             if (!flag_new_abi && *vfuns_p == 0)
+               set_primary_base (t, i, vfuns_p);
            }
        }
     }
@@ -2034,19 +1904,50 @@ determine_primary_base (t, has_virtual_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, has_virtual_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);
@@ -2070,7 +1971,8 @@ finish_struct_bits (t)
       TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
       TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
       TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
-      TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t);
+      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants) 
+       = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
 
       TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (variants) 
        = TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);
@@ -2327,14 +2229,9 @@ method_name_cmp (m1, m2)
    list.  That allows them to be quickly deleted, and requires no
    extra storage.
 
-   If there are any constructors/destructors, they are moved to the
-   front of the list.  This makes pushclass more efficient.
-
-   @@ The above comment is obsolete.  It mostly describes what add_method
-   @@ and add_implicitly_declared_members do.
-
-   Sort methods that are not special (i.e., constructors, destructors, and
-   type conversion operators) so that we can find them faster in search.  */
+   Sort methods that are not special (i.e., constructors, destructors,
+   and type conversion operators) so that we can find them faster in
+   search.  */
 
 static void
 finish_struct_methods (t)
@@ -2342,7 +2239,6 @@ finish_struct_methods (t)
 {
   tree fn_fields;
   tree method_vec;
-  tree ctor_name = constructor_name (t);
   int slot, len;
 
   if (!TYPE_METHODS (t))
@@ -2363,52 +2259,10 @@ finish_struct_methods (t)
      and the next few with type conversion operators (if any).  */
   for (fn_fields = TYPE_METHODS (t); fn_fields; 
        fn_fields = TREE_CHAIN (fn_fields))
-    {
-      tree fn_name = DECL_NAME (fn_fields);
-
-      /* Clear out this flag.
-
-        @@ Doug may figure out how to break
-        @@ this with nested classes and friends.  */
-      DECL_IN_AGGR_P (fn_fields) = 0;
-
-      /* Note here that a copy ctor is private, so we don't dare generate
-        a default copy constructor for a class that has a member
-        of this type without making sure they have access to it.  */
-      if (fn_name == ctor_name)
-       {
-         tree parmtypes = FUNCTION_ARG_CHAIN (fn_fields);
-         tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
-         
-         if (TREE_CODE (parmtype) == REFERENCE_TYPE
-             && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t)
-           {
-             if (TREE_CHAIN (parmtypes) == NULL_TREE
-                 || TREE_CHAIN (parmtypes) == void_list_node
-                 || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
-               {
-                 if (TREE_PROTECTED (fn_fields))
-                   TYPE_HAS_NONPUBLIC_CTOR (t) = 1;
-                 else if (TREE_PRIVATE (fn_fields))
-                   TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
-               }
-           }
-       }
-      else if (fn_name == ansi_opname[(int) MODIFY_EXPR])
-       {
-         tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
-
-         if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields)))
-           {
-             if (TREE_PROTECTED (fn_fields))
-               TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1;
-             else if (TREE_PRIVATE (fn_fields))
-               TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 2;
-           }
-       }
-    }
+    /* Clear out this flag.  */
+    DECL_IN_AGGR_P (fn_fields) = 0;
 
-  if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1))
+  if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t))
     /* We thought there was a destructor, but there wasn't.  Some
        parse errors cause this anomalous situation.  */
     TYPE_HAS_DESTRUCTOR (t) = 0;
@@ -2497,9 +2351,9 @@ duplicate_tag_error (t)
   TYPE_NONCOPIED_PARTS (t) = NULL_TREE;
 }
 
-/* Make the BINFO's vtablehave N entries, including RTTI entries, but
-   not including vbase and vcall offsets.  Set its type and call the
-   backend to lay it out.  */
+/* Make the BINFO's vtablehave N entries, including RTTI entries,
+   vbase and vcall offsets, etc.  Set its type and call the backend
+   to lay it out.  */
 
 static void
 layout_vtable_decl (binfo, n)
@@ -2508,271 +2362,50 @@ layout_vtable_decl (binfo, n)
 {
   tree itype;
   tree atype;
+  tree vtable;
 
   itype = size_int (n);
-  itype = size_binop (PLUS_EXPR, 
-                     itype,
-                     num_extra_vtbl_entries (binfo));
   atype = build_cplus_array_type (vtable_entry_type, 
                                  build_index_type (itype));
   layout_type (atype);
 
   /* We may have to grow the vtable.  */
-  if (!same_type_p (TREE_TYPE (BINFO_VTABLE (binfo)), atype))
+  vtable = get_vtbl_decl_for_binfo (binfo);
+  if (!same_type_p (TREE_TYPE (vtable), atype))
     {
-      TREE_TYPE (BINFO_VTABLE (binfo)) = atype;
-      DECL_SIZE (BINFO_VTABLE (binfo)) = 0;
-      layout_decl (BINFO_VTABLE (binfo), 0);
+      TREE_TYPE (vtable) = atype;
+      DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = NULL_TREE;
+      layout_decl (vtable, 0);
+
       /* At one time the vtable info was grabbed 2 words at a time.  This
-        fails on sparc unless you have 8-byte alignment.  (tiemann) */
-      DECL_ALIGN (BINFO_VTABLE (binfo))
-       = MAX (TYPE_ALIGN (double_type_node),
-              DECL_ALIGN (BINFO_VTABLE (binfo)));
+        fails on Sparc unless you have 8-byte alignment.  */
+      DECL_ALIGN (vtable) = MAX (TYPE_ALIGN (double_type_node),
+                                DECL_ALIGN (vtable));
     }
 }
 
-/* Returns the number of virtual function table entries (excluding
-   RTTI information, vbase and vcall offests, etc.) in the vtable for
-   BINFO.  */
+/* True if we should override the given BASE_FNDECL with the given
+   FNDECL.  */
 
 static int
-num_vfun_entries (binfo)
-     tree binfo;
+overrides (fndecl, base_fndecl)
+     tree fndecl, base_fndecl;
 {
-  return list_length (skip_rtti_stuff (binfo,
-                                      BINFO_TYPE (binfo),
-                                      NULL));
-}
-
-/* Called from num_extra_vtbl_entries via dfs_walk.  */
+  /* 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;
 
-static tree
-dfs_count_virtuals (binfo, data)
-     tree binfo;
-     void *data;
-{
-  /* Non-primary bases are not interesting; all of the virtual
-     function table entries have been overridden.  */
-  if (!BINFO_PRIMARY_MARKED_P (binfo))
-    ((vcall_offset_data *) data)->offsets += num_vfun_entries (binfo);
-  
-  return NULL_TREE;
-}
-
-/* Returns the number of extra entries (at negative indices) required
-   for BINFO's vtable.  */
-
-tree
-num_extra_vtbl_entries (binfo)
-     tree binfo;
-{
-  tree type;
-  int entries;
-
-  type = BINFO_TYPE (binfo);
-  entries = 0;
-
-  /* There is an entry for the offset to each virtual base.  */
-  if (vbase_offsets_in_vtable_p ())
-    entries += list_length (CLASSTYPE_VBASECLASSES (type));
-
-  /* If this is a virtual base, there are entries for each virtual
-     function defined in this class or its bases.  */
-  if (vcall_offsets_in_vtable_p () && TREE_VIA_VIRTUAL (binfo))
-    {
-      vcall_offset_data vod;
-
-      vod.vbase = binfo;
-      vod.offsets = 0;
-      dfs_walk (binfo,
-               dfs_count_virtuals,
-               dfs_vcall_offset_queue_p,
-               &vod);
-      entries += vod.offsets;
-    }
-      
-  return entries ? size_int (entries) : size_zero_node;
-}
-
-/* Returns the offset (in bytes) from the beginning of BINFO's vtable
-   where the vptr should actually point.  */
-
-tree
-size_extra_vtbl_entries (binfo)
-     tree binfo;
-{
-  tree offset;
-
-  offset = size_binop (EXACT_DIV_EXPR,
-                      TYPE_SIZE (vtable_entry_type),
-                      size_int (BITS_PER_UNIT));
-  offset = size_binop (MULT_EXPR, offset, num_extra_vtbl_entries (binfo));
-  return fold (offset);
-}
-
-/* Construct the initializer for BINFOs virtual function table.  BINFO
-   is part of the hierarchy dominated by T.  */
-
-static tree
-build_vtbl_initializer (binfo, t)
-     tree binfo;
-     tree t;
-{
-  tree v = BINFO_VIRTUALS (binfo);
-  tree inits = NULL_TREE;
-  tree type = BINFO_TYPE (binfo);
-
-  /* Add entries to the vtable that indicate how to adjust the this
-     pointer when calling a virtual function in this class.  */
-  inits = build_vcall_offset_vtbl_entries (binfo, t);
-
-  /* Add entries to the vtable for offsets to our virtual bases.  */
-  inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
-                  inits);
-
-  /* Process the RTTI stuff at the head of the list.  If we're not
-     using vtable thunks, then the RTTI entry is just an ordinary
-     function, and we can process it just like the other virtual
-     function entries.  */
-  if (!CLASSTYPE_COM_INTERFACE (type) && flag_vtable_thunks)
-    {
-      tree offset;
-      tree init;
-
-      /* The first entry is an offset.  */
-      offset = TREE_PURPOSE (v);
-      my_friendly_assert (TREE_CODE (offset) == INTEGER_CST,
-                         19990727);
-
-      /* Convert the offset to look like a function pointer, so that
-        we can put it in the vtable.  */
-      init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
-      TREE_CONSTANT (init) = 1;
-      inits = tree_cons (NULL_TREE, init, inits);
-
-      v = TREE_CHAIN (v);
-      
-      if (new_abi_rtti_p ())
-        {
-          tree decl = TREE_VALUE (v);
-          
-          if (decl)
-            decl = build_unary_op (ADDR_EXPR, decl, 0);
-          else
-            decl = integer_zero_node;
-          decl = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
-          TREE_CONSTANT (decl) = 1;
-          decl = build_vtable_entry (integer_zero_node, integer_zero_node,
-                                     decl);
-          inits = tree_cons (NULL_TREE, decl, inits);
-          
-          v = TREE_CHAIN (v);
-        }
-      /* In the old abi the second entry (the tdesc pointer) is
-        just an ordinary function, so it can be dealt with like the
-        virtual functions.  */
-    }
-
-  /* Go through all the ordinary virtual functions, building up
-     initializers.  */
-  while (v)
-    {
-      tree delta;
-      tree vcall_index;
-      tree fn;
-      tree init;
-
-      /* Pull the offset for `this', and the function to call, out of
-        the list.  */
-      delta = BF_DELTA (v);
-      vcall_index = BF_VCALL_INDEX (v);
-      fn = BF_FN (v);
-      my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
-      my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
-
-      /* You can't call an abstract virtual function; it's abstract.
-        So, we replace these functions with __pure_virtual.  */
-      if (DECL_PURE_VIRTUAL_P (fn))
-       fn = abort_fndecl;
-
-      /* Package up that information for the vtable.  */
-      init = build_vtable_entry (delta, vcall_index, fn);
-      /* And add it to the chain of initializers.  */
-      inits = tree_cons (NULL_TREE, init, inits);
-
-      /* Keep going.  */
-      v = TREE_CHAIN (v);
-    }
-
-  /* The initializers were built up in reverse order; straighten them
-     out now.  */
-  inits = nreverse (inits);
-  /* Package all the initializers up as an array initializer.  */
-  return build_nt (CONSTRUCTOR, NULL_TREE, inits);
-}
-
-/* Called from finish_vtbls via dfs_walk.  */
-
-static tree
-dfs_finish_vtbls (binfo, data)
-     tree binfo;
-     void *data;
-{
-  if (!BINFO_PRIMARY_MARKED_P (binfo)
-      && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
-      && BINFO_NEW_VTABLE_MARKED (binfo))
-    {
-      tree decl;
-      tree context;
-      
-      layout_vtable_decl (binfo, list_length (BINFO_VIRTUALS (binfo)));
-      decl = BINFO_VTABLE (binfo);
-      context = DECL_CONTEXT (decl);
-      DECL_CONTEXT (decl) = 0;
-      DECL_INITIAL (decl) = build_vtbl_initializer (binfo, (tree) data);
-      cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
-      DECL_CONTEXT (decl) = context;
-    }
-
-  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
-  SET_BINFO_MARKED (binfo);
-
-  return NULL_TREE;
-}
-
-/* Create all the necessary vtables for T and its base classes.  */
-
-static void
-finish_vtbls (t)
-     tree t;
-{
-  dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, 
-           dfs_unmarked_real_bases_queue_p, t);
-  dfs_walk (TYPE_BINFO (t), dfs_unmark, 
-           dfs_marked_real_bases_queue_p, t);
-}
-
-/* True if we should override the given BASE_FNDECL with the given
-   FNDECL.  */
-
-static int
-overrides (fndecl, base_fndecl)
-     tree fndecl, base_fndecl;
-{
-  /* Destructors have special names.  */
-  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
-      && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
-    return 1;
-  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
-      || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (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)))
@@ -2783,202 +2416,241 @@ overrides (fndecl, base_fndecl)
   return 0;
 }
 
-/* Returns the BINFO_OFFSET for the base of BINFO that has the same
-   type as CONTEXT.  */
+typedef struct find_final_overrider_data_s {
+  /* The function for which we are trying to find a final overrider.  */
+  tree fn;
+  /* The base class in which the function was declared.  */
+  tree declaring_base;
+  /* The most derived class in the hierarchy.  */
+  tree most_derived_type;
+  /* The final overriding function.  */
+  tree overriding_fn;
+  /* The BINFO for the class in which the final overriding function
+     appears.  */
+  tree overriding_base;
+} find_final_overrider_data;
+
+/* Called from find_final_overrider via dfs_walk.  */
 
 static tree
-get_class_offset_1 (parent, binfo, context, t, fndecl)
-     tree parent, binfo, context, t, fndecl;
+dfs_find_final_overrider (binfo, data)
+     tree binfo;
+     void *data;
 {
-  tree binfos = BINFO_BASETYPES (binfo);
-  int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-  tree rval = NULL_TREE;
-
-  if (binfo == parent)
-    return error_mark_node;
+  find_final_overrider_data *ffod = (find_final_overrider_data *) data;
 
-  for (i = 0; i < n_baselinks; i++)
+  if (same_type_p (BINFO_TYPE (binfo), 
+                  BINFO_TYPE (ffod->declaring_base))
+      && tree_int_cst_equal (BINFO_OFFSET (binfo),
+                            BINFO_OFFSET (ffod->declaring_base)))
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      tree nrval;
+      tree path;
+      tree method;
 
-      if (TREE_VIA_VIRTUAL (base_binfo))
-       base_binfo = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), t);
-      nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl);
-      /* See if we have a new value */
-      if (nrval && (nrval != error_mark_node || rval==0))
+      /* We've found a path to the declaring base.  Walk down the path
+        looking for an overrider for FN.  */
+      for (path = reverse_path (binfo); 
+          path; 
+          path = TREE_CHAIN (path))
        {
-         /* Only compare if we have two offsets */
-         if (rval && rval != error_mark_node
-             && ! tree_int_cst_equal (nrval, rval))
-           {
-             /* Only give error if the two offsets are different */
-             error ("every virtual function must have a unique final overrider");
-             cp_error ("  found two (or more) `%T' class subobjects in `%T'", context, t);
-             cp_error ("  with virtual `%D' from virtual base class", fndecl);
-             return rval;
-           }
-         rval = nrval;
+         for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
+              method;
+              method = TREE_CHAIN (method))
+           if (DECL_VIRTUAL_P (method) && overrides (method, ffod->fn))
+             break;
+
+         if (method)
+           break;
        }
-       
-      if (rval && BINFO_TYPE (binfo) == context)
+
+      /* If we found an overrider, record the overriding function, and
+        the base from which it came.  */
+      if (path)
        {
-         my_friendly_assert (rval == error_mark_node
-                             || tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999);
-         rval = BINFO_OFFSET (binfo);
+         if (ffod->overriding_fn && ffod->overriding_fn != method)
+           {
+             /* We've found a different overrider along a different
+                path.  That can be OK if the new one overrides the
+                old one.  Consider:
+             
+                  struct S { virtual void f(); };
+                  struct T : public virtual S { virtual void f(); };
+                  struct U : public virtual S, public virtual T {};
+             
+                Here `T::f' is the final overrider for `S::f'.  */
+             if (strictly_overrides (method, ffod->overriding_fn))
+               {
+                 ffod->overriding_fn = method;
+                 ffod->overriding_base = TREE_VALUE (path);
+               }
+             else if (!strictly_overrides (ffod->overriding_fn, method))
+               {
+                 cp_error ("no unique final overrider for `%D' in `%T'", 
+                           ffod->most_derived_type,
+                           ffod->fn);
+                 cp_error ("candidates are: `%#D'", ffod->overriding_fn);
+                 cp_error ("                `%#D'", method);
+                 return error_mark_node;
+               }
+           }
+         else if (ffod->overriding_base
+                  && (!tree_int_cst_equal 
+                      (BINFO_OFFSET (TREE_VALUE (path)),
+                       BINFO_OFFSET (ffod->overriding_base))))
+           {
+             /* We've found two instances of the same base that
+                provide overriders.  */
+             cp_error ("no unique final overrider for `%D' since there two instances of `%T' in `%T'", 
+                       ffod->fn,
+                       BINFO_TYPE (ffod->overriding_base),
+                       ffod->most_derived_type);
+             return error_mark_node;
+           }
+         else
+           {
+             ffod->overriding_fn = method;
+             ffod->overriding_base = TREE_VALUE (path);
+           }
        }
     }
-  return rval;
-}
-
-/* Called from get_class_offset via dfs_walk.  */
-
-static tree
-dfs_get_class_offset (binfo, data)
-     tree binfo;
-     void *data;
-{
-  tree list = (tree) data;
-  tree context = TREE_TYPE (list);
-
-  if (same_type_p (BINFO_TYPE (binfo), context))
-    {
-      if (TREE_VALUE (list))
-       return error_mark_node;
-      else
-       TREE_VALUE (list) = BINFO_OFFSET (binfo);
-    }
-  
-  SET_BINFO_MARKED (binfo);
 
   return NULL_TREE;
 }
 
-/* Returns the BINFO_OFFSET for the subobject of BINFO that has the
-   type given by CONTEXT.  */
+/* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for
+   FN and whose TREE_VALUE is the binfo for the base where the
+   overriding occurs.  BINFO (in the hierarchy dominated by T) is the
+   base object in which FN is declared.  */
 
 static tree
-get_class_offset (context, t, binfo, fndecl)
-     tree context, t, binfo, fndecl;
+find_final_overrider (t, binfo, fn)
+     tree t;
+     tree binfo;
+     tree fn;
 {
-  tree list;
-  tree offset;
-  int i;
+  find_final_overrider_data ffod;
 
-  if (context == t)
-    return integer_zero_node;
+  /* Getting this right is a little tricky.  This is legal:
 
-  if (BINFO_TYPE (binfo) == context)
-    return BINFO_OFFSET (binfo);
-
-  /* Check less derived binfos first.  */
-  while (BINFO_BASETYPES (binfo)
-        && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
-    {
-      tree binfos = BINFO_BASETYPES (binfo);
-      binfo = TREE_VEC_ELT (binfos, i);
-      if (BINFO_TYPE (binfo) == context)
-       return BINFO_OFFSET (binfo);
-    }
+       struct S { virtual void f (); };
+       struct T { virtual void f (); };
+       struct U : public S, public T { };
 
-  list = build_tree_list (t, NULL_TREE);
-  TREE_TYPE (list) = context;
-  offset = dfs_walk (TYPE_BINFO (t),
-                    dfs_get_class_offset,
-                    dfs_unmarked_real_bases_queue_p,
-                    list);
-  dfs_walk (TYPE_BINFO (t), dfs_unmark, dfs_marked_real_bases_queue_p, t);
+     even though calling `f' in `U' is ambiguous.  But, 
 
-  if (offset == error_mark_node)
-    {
-      error ("every virtual function must have a unique final overrider");
-      cp_error ("  found two (or more) `%T' class subobjects in `%T'", 
-               context, t);
-      cp_error ("  with virtual `%D' from virtual base class", fndecl);
-      offset = integer_zero_node;
-    }
-  else
-    offset = TREE_VALUE (list);
+       struct R { virtual void f(); };
+       struct S : virtual public R { virtual void f (); };
+       struct T : virtual public R { virtual void f (); };
+       struct U : public S, public T { };
 
-  my_friendly_assert (offset != NULL_TREE, 999);
-  my_friendly_assert (TREE_CODE (offset) == INTEGER_CST, 999);
+     is not -- there's no way  to decide whether to put `S::f' or
+     `T::f' in the vtable for `R'.  
+     
+     The solution is to look at all paths to BINFO.  If we find
+     different overriders along any two, then there is a problem.  */
+  ffod.fn = fn;
+  ffod.declaring_base = binfo;
+  ffod.most_derived_type = t;
+  ffod.overriding_fn = NULL_TREE;
+  ffod.overriding_base = NULL_TREE;
+
+  if (dfs_walk (TYPE_BINFO (t),
+               dfs_find_final_overrider,
+               NULL,
+               &ffod))
+    return error_mark_node;
 
-  return offset;
+  return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
 }
 
-/* Return the BINFO_VIRTUALS list for BINFO, without the RTTI stuff at
-   the front.  If non-NULL, N is set to the number of entries
-   skipped.  */
+/* Called via dfs_walk.  Returns BINFO if BINFO has the same type as
+   DATA (which is really an _TYPE node).  */
 
-tree
-skip_rtti_stuff (binfo, t, n)
+static tree
+dfs_find_base (binfo, data)
      tree binfo;
-     tree t;
-     unsigned HOST_WIDE_INT *n;
+     void *data;
 {
-  tree virtuals;
-
-  if (CLASSTYPE_COM_INTERFACE (t))
-    return 0;
-
-  if (n)
-    *n = 0;
-  virtuals = BINFO_VIRTUALS (binfo);
-  if (virtuals)
-    {
-      /* We always reserve a slot for the offset/tdesc entry.  */
-      if (n)
-       ++*n;
-      virtuals = TREE_CHAIN (virtuals);
-    }
-  if (flag_vtable_thunks && virtuals)
-    {
-      /* The second slot is reserved for the tdesc pointer when thunks
-         are used.  */
-      if (n)
-       ++*n;
-      virtuals = TREE_CHAIN (virtuals);
-    }
-
-  return virtuals;
+  return (same_type_p (BINFO_TYPE (binfo), (tree) data)
+         ? binfo : NULL_TREE);
 }
 
+/* Update a entry in the vtable for BINFO, which is in the hierarchy
+   dominated by T.  FN has been overridden in BINFO; VIRTUALS points
+   to the corresponding position in the BINFO_VIRTUALS list.  */
+
 static void
-modify_one_vtable (binfo, t, fndecl)
-     tree binfo, t, fndecl;
+update_vtable_entry_for_fn (t, binfo, fn, virtuals)
+     tree t;
+     tree binfo;
+     tree fn;
+     tree *virtuals;
 {
-  tree virtuals;
-  unsigned HOST_WIDE_INT n;
-  
-  /* If we're support RTTI then we always need a new vtable to point
-     to the RTTI information.  Under the new ABI we may need a new
-     vtable to contain vcall and vbase offsets.  */
-  if (flag_rtti || flag_new_abi)
-    {
-      if (binfo == TYPE_BINFO (t))
-       build_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))), t);
-      else
-       prepare_fresh_vtable (binfo, t);
-    }
-  if (fndecl == NULL_TREE)
+  tree b;
+  tree overrider;
+  tree vindex;
+  tree delta;
+  HOST_WIDE_INT vindex_val;
+  HOST_WIDE_INT i;
+
+  /* Find the function which originally caused this vtable
+     entry to be present.  */
+  vindex = DECL_VINDEX (fn);
+  b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
+  fn = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (b)));
+  i = first_vfun_index (BINFO_TYPE (b));
+  vindex_val = tree_low_cst (vindex, 0);
+  while (i < vindex_val)
+    {
+      fn = TREE_CHAIN (fn);
+      ++i;
+    }
+  fn = BV_FN (fn);
+
+  /* Handle the case of a virtual function defined in BINFO itself.  */
+  overrider = find_final_overrider (t, b, fn);
+  if (overrider == error_mark_node)
     return;
 
-  for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
-       virtuals;
-       virtuals = TREE_CHAIN (virtuals), ++n)
+  /* Compute the constant adjustment to the `this' pointer.  The
+     `this' pointer, when this function is called, will point at the
+     class whose vtable this is.  */
+  delta = size_binop (PLUS_EXPR,
+                     get_derived_offset (binfo,
+                                         DECL_VIRTUAL_CONTEXT (fn)),
+                     BINFO_OFFSET (binfo));
+  if (flag_new_abi)
     {
-      tree current_fndecl = BF_FN (virtuals);
-
-      /* We should never have an instance of __pure_virtual on the
-        BINFO_VIRTUALS list.  If we do, then we will never notice
-        that the function that should have been there instead has
-        been overridden.  */
-      my_friendly_assert (current_fndecl != abort_fndecl,
-                         19990727);
-
-      if (current_fndecl && overrides (fndecl, current_fndecl))
-       modify_vtable_entry (t, binfo, fndecl, virtuals);
+      /* Under the new ABI, we only need to adjust as far as the
+        nearest virtual base.  Then we use the vcall offset in the
+        virtual bases vtable.  */
+      for (b = binfo; b; b = BINFO_INHERITANCE_CHAIN (b))
+       {
+         if (TREE_VIA_VIRTUAL (b))
+           break;
+         if (same_type_p (BINFO_TYPE (b), 
+                          BINFO_TYPE (TREE_VALUE (overrider))))
+           break;
+       }
     }
+  else
+    b = NULL_TREE;
+
+  if (b && TREE_VIA_VIRTUAL (b))
+    /* The `this' pointer needs to be adjusted to the nearest virtual
+       base.  */
+    delta = size_diffop (BINFO_OFFSET (b), delta);
+  else
+    /* The `this' pointer needs to be adjusted from pointing to
+       BINFO to pointing at the base where the final overrider
+       appears.  */
+    delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta);
+
+  modify_vtable_entry (t, 
+                      binfo, 
+                      TREE_PURPOSE (overrider),
+                      delta,
+                      virtuals);
 }
 
 /* Called from modify_all_vtables via dfs_walk.  */
@@ -2994,8 +2666,30 @@ dfs_modify_vtables (binfo, data)
       /* Similarly, a base without a vtable needs no modification.  */
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
     {
-      tree list = (tree) data;
-      modify_one_vtable (binfo, TREE_PURPOSE (list), TREE_VALUE (list)); 
+      tree t;
+      tree virtuals;
+      tree old_virtuals;
+
+      t = (tree) data;
+
+      /* If we're supporting RTTI then we always need a new vtable to
+        point to the RTTI information.  Under the new ABI we may need
+        a new vtable to contain vcall and vbase offsets.  */
+      if (flag_rtti || flag_new_abi)
+       make_new_vtable (t, binfo);
+      
+      /* Now, go through each of the virtual functions in the virtual
+        function table for BINFO.  Find the final overrider, and
+        update the BINFO_VIRTUALS list appropriately.  */
+      for (virtuals = BINFO_VIRTUALS (binfo),
+            old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
+          virtuals;
+          virtuals = TREE_CHAIN (virtuals),
+            old_virtuals = TREE_CHAIN (old_virtuals))
+       update_vtable_entry_for_fn (t, 
+                                   binfo, 
+                                   BV_FN (old_virtuals),
+                                   &virtuals);
     }
 
   SET_BINFO_MARKED (binfo);
@@ -3013,31 +2707,21 @@ dfs_modify_vtables (binfo, data)
    which should therefore be appended to the end of the vtable for T.  */
 
 static tree
-modify_all_vtables (t, has_virtual_p, overridden_virtuals)
+modify_all_vtables (t, vfuns_p, overridden_virtuals)
      tree t;
-     int *has_virtual_p;
+     int *vfuns_p;
      tree overridden_virtuals;
 {
-  tree fns;
   tree binfo;
 
   binfo = TYPE_BINFO (t);
 
-  /* Even if there are no overridden virtuals, we want to go through
-     the hierarchy updating RTTI information.  */
-  if (!overridden_virtuals && TYPE_CONTAINS_VPTR_P (t) && flag_rtti)
-    overridden_virtuals = build_tree_list (NULL_TREE, NULL_TREE);
-
-  /* Iterate through each of the overriding functions, updating the
-     base vtables.  */
-  for (fns = overridden_virtuals; fns; fns = TREE_CHAIN (fns))
-    {
-      tree list;
-      list = build_tree_list (t, TREE_VALUE (fns));
-      dfs_walk (binfo, dfs_modify_vtables, 
-               dfs_unmarked_real_bases_queue_p, list);
-      dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
-    }
+  /* Update all of the vtables.  */
+  dfs_walk (binfo, 
+           dfs_modify_vtables, 
+           dfs_unmarked_real_bases_queue_p,
+           t);
+  dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
 
   /* If we should include overriding functions for secondary vtables
      in our primary vtable, add them now.  */
@@ -3049,20 +2733,19 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
        {
          tree fn = TREE_VALUE (*fnsp);
 
-         if (BINFO_VIRTUALS (binfo)
-             && !value_member (fn, BINFO_VIRTUALS (binfo)))
+         if (!BINFO_VIRTUALS (binfo)
+             || !value_member (fn, BINFO_VIRTUALS (binfo)))
            {
-             /* We know we need a vtable for this class now.  */
-             start_vtable (t, has_virtual_p);
              /* Set the vtable index.  */
-             DECL_VINDEX (fn) 
-               = build_shared_int_cst ((*has_virtual_p)++);
+             set_vindex (t, fn, vfuns_p);
              /* We don't need to convert to a base class when calling
                 this function.  */
              DECL_VIRTUAL_CONTEXT (fn) = t;
+
              /* We don't need to adjust the `this' pointer when
                 calling this function.  */
-             TREE_PURPOSE (*fnsp) = integer_zero_node;
+             BV_DELTA (*fnsp) = integer_zero_node;
+             BV_VCALL_INDEX (*fnsp) = NULL_TREE;
 
              /* This is an overridden function not already in our
                 vtable.  Keep it.  */
@@ -3080,38 +2763,6 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
   return overridden_virtuals;
 }
 
-/* Fixup all the delta entries in this one vtable that need updating.  */
-
-static tree
-dfs_fixup_vtable_deltas (binfo, data)
-     tree binfo;
-     void *data;
-{
-  tree virtuals;
-  unsigned HOST_WIDE_INT n;
-  tree t = (tree) data;
-
-  while (BINFO_PRIMARY_MARKED_P (binfo))
-    {
-      binfo = BINFO_INHERITANCE_CHAIN (binfo);
-      /* If BINFO is virtual then we'll handle this base later.  */
-      if (TREE_VIA_VIRTUAL (binfo))
-       return NULL_TREE;
-    }
-
-  for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
-       virtuals;
-       virtuals = TREE_CHAIN (virtuals), ++n)
-    {
-      tree fndecl = BF_FN (virtuals);
-
-      if (fndecl)
-       modify_vtable_entry (t, binfo, fndecl, virtuals);
-    }
-
-  return NULL_TREE;
-}
-
 /* Here, we already know that they match in every respect.
    All we have to check is where they had their declarations.  */
 
@@ -3119,189 +2770,26 @@ static int
 strictly_overrides (fndecl1, fndecl2)
      tree fndecl1, fndecl2;
 {
-  int distance = get_base_distance (DECL_CLASS_CONTEXT (fndecl2),
-                                   DECL_CLASS_CONTEXT (fndecl1),
+  int distance = get_base_distance (DECL_CONTEXT (fndecl2),
+                                   DECL_CONTEXT (fndecl1),
                                    0, (tree *)0);
   if (distance == -2 || distance > 0)
     return 1;
   return 0;
 }
 
-/* Merge overrides for one vtable.
-   If we want to merge in same function, we are fine.
-   else
-     if one has a DECL_CLASS_CONTEXT that is a parent of the
-       other, than choose the more derived one
-     else
-       potentially ill-formed (see 10.3 [class.virtual])
-       we have to check later to see if there was an
-       override in this class.  If there was ok, if not
-       then it is ill-formed.  (mrs)
+/* Get the base virtual function declarations in T that are either
+   overridden or hidden by FNDECL as a list.  We set TREE_PURPOSE with
+   the overrider/hider.  */
 
-   We take special care to reuse a vtable, if we can.  */
-
-static void
-override_one_vtable (binfo, old, t)
-     tree binfo, old, t;
-{
-  tree virtuals;
-  tree old_virtuals;
-  tree orig_binfo;
-  tree orig_virtuals;
-  enum { REUSE_NEW, REUSE_OLD, UNDECIDED, NEITHER } choose = UNDECIDED;
-
-  /* Either or both of BINFO or OLD might be primary base classes
-     because merge_overrides is called with a vbase from the class we
-     are definining and the corresponding vbase from one of its direct
-     bases.  */
-  orig_binfo = binfo;
-  while (BINFO_PRIMARY_MARKED_P (binfo))
-    {
-      binfo = BINFO_INHERITANCE_CHAIN (binfo);
-      /* If BINFO is virtual, then we'll handle this virtual base when
-        later.  */
-      if (TREE_VIA_VIRTUAL (binfo))
-       return;
-    }
-  while (BINFO_PRIMARY_MARKED_P (old))
-    old = BINFO_INHERITANCE_CHAIN (old);
-
-  /* If we have already committed to modifying it, then don't try and
-     reuse another vtable.  */
-  if (BINFO_NEW_VTABLE_MARKED (binfo))
-    choose = NEITHER;
-
-  virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL);
-  old_virtuals = skip_rtti_stuff (old, BINFO_TYPE (binfo), NULL);
-  orig_virtuals = skip_rtti_stuff (orig_binfo, BINFO_TYPE (binfo), NULL);
-
-  while (orig_virtuals)
-    {
-      tree fndecl = BF_FN (virtuals);
-      tree old_fndecl = BF_FN (old_virtuals);
-
-      /* First check to see if they are the same.  */
-      if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
-       {
-         /* No need to do anything.  */
-       }
-      else if (strictly_overrides (fndecl, old_fndecl))
-       {
-         if (choose == UNDECIDED)
-           choose = REUSE_NEW;
-         else if (choose == REUSE_OLD)
-           {
-             choose = NEITHER;
-             if (! BINFO_NEW_VTABLE_MARKED (binfo))
-               {
-                 prepare_fresh_vtable (binfo, t);
-                 override_one_vtable (binfo, old, t);
-                 return;
-               }
-           }
-       }
-      else if (strictly_overrides (old_fndecl, fndecl))
-       {
-         if (choose == UNDECIDED)
-           choose = REUSE_OLD;
-         else if (choose == REUSE_NEW)
-           {
-             choose = NEITHER;
-             if (! BINFO_NEW_VTABLE_MARKED (binfo))
-               {
-                 prepare_fresh_vtable (binfo, t);
-                 override_one_vtable (binfo, old, t);
-                 return;
-               }
-             TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
-           }
-         else if (choose == NEITHER)
-           {
-             TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
-           }  
-       }
-      else
-       {
-         choose = NEITHER;
-         if (! BINFO_NEW_VTABLE_MARKED (binfo))
-           {
-             prepare_fresh_vtable (binfo, t);
-             override_one_vtable (binfo, old, t);
-             return;
-           }
-         {
-           /* This MUST be overridden, or the class is ill-formed.  */
-           tree fndecl = BF_FN (virtuals);
-
-           fndecl = copy_node (fndecl);
-           copy_lang_decl (fndecl);
-           DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1;
-           /* Make sure we search for it later.  */
-           if (! CLASSTYPE_PURE_VIRTUALS (t))
-             CLASSTYPE_PURE_VIRTUALS (t) = error_mark_node;
-
-           /* We can use integer_zero_node, as we will core dump
-              if this is used anyway.  */
-           BF_DELTA (virtuals) = integer_zero_node;
-           BF_FN (virtuals) = fndecl;
-         }
-       }
-      virtuals = TREE_CHAIN (virtuals);
-      old_virtuals = TREE_CHAIN (old_virtuals);
-      orig_virtuals = TREE_CHAIN (orig_virtuals);
-    }
-
-  /* Let's reuse the old vtable.  */
-  if (choose == REUSE_OLD)
-    {
-      BINFO_VTABLE (binfo) = BINFO_VTABLE (old);
-      BINFO_VIRTUALS (binfo) = BINFO_VIRTUALS (old);
-    }
-}
-
-/* Merge in overrides for virtual bases.
-   BINFO is the hierarchy we want to modify, and OLD has the potential
-   overrides.  */
-
-static void
-merge_overrides (binfo, old, do_self, t)
-     tree binfo, old;
-     int do_self;
-     tree t;
-{
-  tree binfos = BINFO_BASETYPES (binfo);
-  tree old_binfos = BINFO_BASETYPES (old);
-  int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
-  /* Should we use something besides CLASSTYPE_VFIELDS? */
-  if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
-    {
-      override_one_vtable (binfo, old, t);
-    }
-
-  for (i = 0; i < n_baselinks; i++)
-    {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      tree old_base_binfo = TREE_VEC_ELT (old_binfos, i);
-      int is_not_base_vtable 
-       = !BINFO_PRIMARY_MARKED_P (base_binfo);
-      if (! TREE_VIA_VIRTUAL (base_binfo))
-       merge_overrides (base_binfo, old_base_binfo, is_not_base_vtable, t);
-    }
-}
-
-/* Get the base virtual function declarations in T that are either
-   overridden or hidden by FNDECL as a list.  We set TREE_PURPOSE with
-   the overrider/hider.  */
-
-static tree
-get_basefndecls (fndecl, t)
-     tree fndecl, t;
-{
-  tree methods = TYPE_METHODS (t);
-  tree base_fndecls = NULL_TREE;
-  tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
-  int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+static tree
+get_basefndecls (fndecl, t)
+     tree fndecl, t;
+{
+  tree methods = TYPE_METHODS (t);
+  tree base_fndecls = NULL_TREE;
+  tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
+  int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
 
   while (methods)
     {
@@ -3364,8 +2852,7 @@ check_for_override (decl, ctype)
       if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo)))
        {
          tree tmp = get_matching_virtual
-           (base_binfo, decl,
-            DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
+           (base_binfo, decl, DECL_DESTRUCTOR_P (decl));
 
          if (tmp && !found_overriden_fn)
            {
@@ -3507,7 +2994,7 @@ finish_struct_anon (t)
                continue;
 
              if (DECL_NAME (elt) == constructor_name (t))
-               cp_pedwarn_at ("ANSI C++ forbids member `%D' with same name as enclosing class",
+               cp_pedwarn_at ("ISO C++ forbids member `%D' with same name as enclosing class",
                               elt);
 
              if (TREE_CODE (elt) != FIELD_DECL)
@@ -3531,41 +3018,38 @@ finish_struct_anon (t)
     }
 }
 
-extern int interface_only, interface_unknown;
-
 /* Create default constructors, assignment operators, and so forth for
    the type indicated by T, if they are needed.
    CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
-   CANT_HAVE_ASSIGNMENT are nonzero if, for whatever reason, the class
-   cannot have a default constructor, copy constructor taking a const
-   reference argument, or an assignment operator, respectively.  If a
-   virtual destructor is created, its DECL is returned; otherwise the
-   return value is NULL_TREE.  */
+   CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, the
+   class cannot have a default constructor, copy constructor taking a
+   const reference argument, or an assignment operator taking a const
+   reference, respectively.  If a virtual destructor is created, its
+   DECL is returned; otherwise the return value is NULL_TREE.  */
 
 static tree
 add_implicitly_declared_members (t, cant_have_default_ctor,
                                 cant_have_const_cctor,
-                                cant_have_assignment)
+                                cant_have_const_assignment)
      tree t;
      int cant_have_default_ctor;
      int cant_have_const_cctor;
-     int cant_have_assignment;
+     int cant_have_const_assignment;
 {
   tree default_fn;
   tree implicit_fns = NULL_TREE;
-  tree name = TYPE_IDENTIFIER (t);
   tree virtual_dtor = NULL_TREE;
   tree *f;
 
   /* Destructor.  */
-  if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
     {
-      default_fn = cons_up_default_function (t, name, 0);
+      default_fn = implicitly_declare_fn (sfk_destructor, t, /*const_p=*/0);
       check_for_override (default_fn, t);
 
       /* If we couldn't make it work, then pretend we didn't need it.  */
       if (default_fn == void_type_node)
-       TYPE_NEEDS_DESTRUCTOR (t) = 0;
+       TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 0;
       else
        {
          TREE_CHAIN (default_fn) = implicit_fns;
@@ -3575,12 +3059,14 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
            virtual_dtor = default_fn;
        }
     }
-  TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
+  else
+    /* Any non-implicit destructor is non-trivial.  */
+    TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
 
   /* Default constructor.  */
   if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
     {
-      default_fn = cons_up_default_function (t, name, 2);
+      default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0);
       TREE_CHAIN (default_fn) = implicit_fns;
       implicit_fns = default_fn;
     }
@@ -3590,8 +3076,9 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
     {
       /* ARM 12.18: You get either X(X&) or X(const X&), but
         not both.  --Chip  */
-      default_fn = cons_up_default_function (t, name,
-                                            3 + cant_have_const_cctor);
+      default_fn 
+       = implicitly_declare_fn (sfk_copy_constructor, t,
+                                /*const_p=*/!cant_have_const_cctor);
       TREE_CHAIN (default_fn) = implicit_fns;
       implicit_fns = default_fn;
     }
@@ -3599,8 +3086,9 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
   /* Assignment operator.  */
   if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t))
     {
-      default_fn = cons_up_default_function (t, name,
-                                            5 + cant_have_assignment);
+      default_fn 
+       = implicitly_declare_fn (sfk_assignment_operator, t,
+                                /*const_p=*/!cant_have_const_assignment);
       TREE_CHAIN (default_fn) = implicit_fns;
       implicit_fns = default_fn;
     }
@@ -3662,23 +3150,20 @@ check_bitfield_decl (field)
      tree field;
 {
   tree type = TREE_TYPE (field);
+  tree w = NULL_TREE;
 
-  /* Invalid bit-field size done by grokfield.  */
-  /* Detect invalid bit-field type. Simply checking if TYPE is
-     integral is insufficient, as that is the array core of the field
-     type. If TREE_TYPE (field) is integral, then TYPE must be the same.  */
+  /* Detect invalid bit-field type.  */
   if (DECL_INITIAL (field)
       && ! INTEGRAL_TYPE_P (TREE_TYPE (field)))
     {
       cp_error_at ("bit-field `%#D' with non-integral type", field);
-      DECL_INITIAL (field) = NULL;
+      w = error_mark_node;
     }
 
   /* Detect and ignore out of range field width.  */
   if (DECL_INITIAL (field))
     {
-      tree w = DECL_INITIAL (field);
-      register int width = 0;
+      w = DECL_INITIAL (field);
 
       /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs.  */
       STRIP_NOPS (w);
@@ -3686,71 +3171,70 @@ check_bitfield_decl (field)
       /* detect invalid field size.  */
       if (TREE_CODE (w) == CONST_DECL)
        w = DECL_INITIAL (w);
-      else if (TREE_READONLY_DECL_P (w))
+      else
        w = decl_constant_value (w);
 
       if (TREE_CODE (w) != INTEGER_CST)
        {
          cp_error_at ("bit-field `%D' width not an integer constant",
                       field);
-         DECL_INITIAL (field) = NULL_TREE;
+         w = error_mark_node;
        }
-      else if (width = TREE_INT_CST_LOW (w),
-              width < 0)
+      else if (tree_int_cst_sgn (w) < 0)
        {
-         DECL_INITIAL (field) = NULL;
          cp_error_at ("negative width in bit-field `%D'", field);
+         w = error_mark_node;
        }
-      else if (width == 0 && DECL_NAME (field) != 0)
+      else if (integer_zerop (w) && DECL_NAME (field) != 0)
        {
-         DECL_INITIAL (field) = NULL;
          cp_error_at ("zero width for bit-field `%D'", field);
+         w = error_mark_node;
        }
-      else if (width
-              > TYPE_PRECISION (long_long_unsigned_type_node))
-       {
-         /* The backend will dump if you try to use something too
-            big; avoid that.  */
-         DECL_INITIAL (field) = NULL;
-         sorry ("bit-fields larger than %d bits",
-                TYPE_PRECISION (long_long_unsigned_type_node));
-         cp_error_at ("  in declaration of `%D'", field);
-       }
-      else if (width > TYPE_PRECISION (type)
+      else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
               && TREE_CODE (type) != ENUMERAL_TYPE
               && TREE_CODE (type) != BOOLEAN_TYPE)
        cp_warning_at ("width of `%D' exceeds its type", field);
       else if (TREE_CODE (type) == ENUMERAL_TYPE
-              && ((min_precision (TYPE_MIN_VALUE (type),
-                                  TREE_UNSIGNED (type)) > width)
-                  || (min_precision (TYPE_MAX_VALUE (type),
-                                     TREE_UNSIGNED (type)) > width)))
+              && (0 > compare_tree_int (w,
+                                        min_precision (TYPE_MIN_VALUE (type),
+                                                       TREE_UNSIGNED (type)))
+                  ||  0 > compare_tree_int (w,
+                                            min_precision
+                                            (TYPE_MAX_VALUE (type),
+                                             TREE_UNSIGNED (type)))))
        cp_warning_at ("`%D' is too small to hold all values of `%#T'",
                       field, type);
+    }
+  
+  /* Remove the bit-field width indicator so that the rest of the
+     compiler does not treat that value as an initializer.  */
+  DECL_INITIAL (field) = NULL_TREE;
 
-      if (DECL_INITIAL (field))
-       {
-         DECL_INITIAL (field) = NULL_TREE;
-         DECL_FIELD_SIZE (field) = width;
-         DECL_BIT_FIELD (field) = 1;
+  if (w != error_mark_node)
+    {
+      DECL_SIZE (field) = convert (bitsizetype, w);
+      DECL_BIT_FIELD (field) = 1;
 
-         if (width == 0)
-           {
+      if (integer_zerop (w))
+       {
 #ifdef EMPTY_FIELD_BOUNDARY
-             DECL_ALIGN (field) = MAX (DECL_ALIGN (field), 
-                                       EMPTY_FIELD_BOUNDARY);
+         DECL_ALIGN (field) = MAX (DECL_ALIGN (field), 
+                                   EMPTY_FIELD_BOUNDARY);
 #endif
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-             if (PCC_BITFIELD_TYPE_MATTERS)
-               DECL_ALIGN (field) = MAX (DECL_ALIGN (field), 
-                                         TYPE_ALIGN (type));
+         if (PCC_BITFIELD_TYPE_MATTERS)
+           DECL_ALIGN (field) = MAX (DECL_ALIGN (field), 
+                                     TYPE_ALIGN (type));
 #endif
-           }
        }
     }
   else
-    /* Non-bit-fields are aligned for their type.  */
-    DECL_ALIGN (field) = MAX (DECL_ALIGN (field), TYPE_ALIGN (type));
+    {
+      /* Non-bit-fields are aligned for their type.  */
+      DECL_BIT_FIELD (field) = 0;
+      CLEAR_DECL_C_BIT_FIELD (field);
+      DECL_ALIGN (field) = MAX (DECL_ALIGN (field), TYPE_ALIGN (type));
+    }
 }
 
 /* FIELD is a non bit-field.  We are finishing the processing for its
@@ -3781,7 +3265,7 @@ check_field_decl (field, t, cant_have_const_ctor,
       tree fields;
 
       for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
-       if (TREE_CODE (field) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
+       if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
          check_field_decl (fields, t, cant_have_const_ctor,
                            cant_have_default_ctor, no_const_asn_ref,
                            any_default_members);
@@ -3799,7 +3283,7 @@ check_field_decl (field, t, cant_have_const_ctor,
          if (TYPE_NEEDS_CONSTRUCTING (type))
            cp_error_at ("member `%#D' with constructor not allowed in union",
                         field);
-         if (TYPE_NEEDS_DESTRUCTOR (type))
+         if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
            cp_error_at ("member `%#D' with destructor not allowed in union",
                         field);
          if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
@@ -3809,7 +3293,8 @@ check_field_decl (field, t, cant_have_const_ctor,
       else
        {
          TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
-         TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type);
+         TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) 
+           |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
          TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
          TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
        }
@@ -3944,7 +3429,7 @@ check_field_decls (t, access_decls, empty_p,
       /* If we've gotten this far, it's a data member, possibly static,
         or an enumerator.  */
 
-      DECL_FIELD_CONTEXT (x) = t;
+      DECL_CONTEXT (x) = t;
 
       /* ``A local class cannot have static data members.'' ARM 9.4 */
       if (current_function_decl && TREE_STATIC (x))
@@ -3975,9 +3460,6 @@ check_field_decls (t, access_decls, empty_p,
       if (type == error_mark_node)
        continue;
          
-      DECL_SAVED_INSNS (x) = 0;
-      DECL_FIELD_SIZE (x) = 0;
-
       /* When this goes into scope, it will be a non-local reference.  */
       DECL_NONLOCAL (x) = 1;
 
@@ -4066,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))
@@ -4106,17 +3595,19 @@ check_field_decls (t, access_decls, empty_p,
 /* Return a FIELD_DECL for a pointer-to-virtual-table or
    pointer-to-virtual-base.  The NAME, ASSEMBLER_NAME, and TYPE of the
    field are as indicated.  The CLASS_TYPE in which this field occurs
-   is also indicated.  *EMPTY_P is set to a non-zero value by this
+   is also indicated.  FCONTEXT is the type that is needed for the debug
+   info output routines.  *EMPTY_P is set to a non-zero value by this
    function to indicate that a class containing this field is
    non-empty.  */
 
 static tree
-build_vtbl_or_vbase_field (name, assembler_name, type, class_type, 
+build_vtbl_or_vbase_field (name, assembler_name, type, class_type, fcontext,
                           empty_p)
      tree name;
      tree assembler_name;
      tree type;
      tree class_type;
+     tree fcontext;
      int *empty_p;
 {
   tree field;
@@ -4125,131 +3616,304 @@ build_vtbl_or_vbase_field (name, assembler_name, type, class_type,
   *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;
   DECL_FIELD_CONTEXT (field) = class_type;
-  DECL_CLASS_CONTEXT (field) = class_type;
-  DECL_FCONTEXT (field) = class_type;
-  DECL_SAVED_INSNS (field) = 0;
-  DECL_FIELD_SIZE (field) = 0;
+  DECL_FCONTEXT (field) = fcontext;
   DECL_ALIGN (field) = TYPE_ALIGN (type);
 
   /* Return it.  */
   return field;
 }
 
-/* If the empty base field in DECL overlaps with a base of the same type in
-   NEWDECL, which is either another base field or the first data field of
-   the class, pad the base just before NEWDECL and return 1.  Otherwise,
-   return 0.  */
+/* Record the type of BINFO in the slot in DATA (which is really a
+   `varray_type *') corresponding to the BINFO_OFFSET.  */
+
+static tree
+dfs_record_base_offsets (binfo, data)
+     tree binfo;
+     void *data;
+{
+  varray_type *v;
+  unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
+
+  v = (varray_type *) data;
+  while (VARRAY_SIZE (*v) <= offset)
+    VARRAY_GROW (*v, 2 * VARRAY_SIZE (*v));
+  VARRAY_TREE (*v, offset) = tree_cons (NULL_TREE,
+                                       BINFO_TYPE (binfo),
+                                       VARRAY_TREE (*v, offset));
+
+  return NULL_TREE;
+}
+
+/* Add the offset of BINFO and its bases to BASE_OFFSETS.  */
+
+static void
+record_base_offsets (binfo, base_offsets)
+     tree binfo;
+     varray_type *base_offsets;
+{
+  dfs_walk (binfo,
+           dfs_record_base_offsets,
+           dfs_skip_vbases,
+           base_offsets);
+}
+
+/* Returns non-NULL if there is already an entry in DATA (which is
+   really a `varray_type') indicating that an object with the same
+   type of BINFO is already at the BINFO_OFFSET for BINFO.  */
+
+static tree
+dfs_search_base_offsets (binfo, data)
+     tree binfo;
+     void *data;
+{
+  if (is_empty_class (BINFO_TYPE (binfo)))
+    {
+      varray_type v = (varray_type) data;
+      /* Find the offset for this BINFO.  */
+      unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
+      tree t;
+
+      /* If we haven't yet encountered any objects at offsets that
+        big, then there's no conflict.  */
+      if (VARRAY_SIZE (v) <= offset)
+       return NULL_TREE;
+      /* Otherwise, go through the objects already allocated at this
+        offset.  */
+      for (t = VARRAY_TREE (v, offset); t; t = TREE_CHAIN (t))
+       if (same_type_p (TREE_VALUE (t), BINFO_TYPE (binfo)))
+         return binfo;
+    }
+
+  return NULL_TREE;
+}
+
+/* Returns non-zero if there's a conflict between BINFO and a base
+   already mentioned in BASE_OFFSETS if BINFO is placed at its current
+   BINFO_OFFSET.  */
 
 static int
-avoid_overlap (decl, newdecl, empty_p)
-     tree decl, newdecl;
-     int *empty_p;
+layout_conflict_p (binfo, base_offsets)
+     tree binfo;
+     varray_type base_offsets;
 {
-  tree field;
+  return dfs_walk (binfo, dfs_search_base_offsets, dfs_skip_vbases,
+                  base_offsets) != NULL_TREE;
+}
 
-  if (newdecl == NULL_TREE
-      || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
-    return 0;
+/* DECL is a FIELD_DECL corresponding either to a base subobject of a
+   non-static data member of the type indicated by RLI.  BINFO is the
+   binfo corresponding to the base subobject, or, if this is a
+   non-static data-member, a dummy BINFO for the type of the data
+   member.  BINFO may be NULL if checks to see if the field overlaps
+   an existing field with the same type are not required.  V maps
+   offsets to types already located at those offsets.  This function
+   determines the position of the DECL.  */
 
-  for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
-       field = TREE_CHAIN (field))
-    ;
+static void
+layout_nonempty_base_or_field (rli, decl, binfo, v)
+     record_layout_info rli;
+     tree decl;
+     tree binfo;
+     varray_type v;
+{
+  /* Try to place the field.  It may take more than one try if we have
+     a hard time placing the field without putting two objects of the
+     same type at the same address.  */
+  while (1)
+    {
+      tree offset;
+      struct record_layout_info_s old_rli = *rli;
 
-  DECL_SIZE (field) = integer_one_node;
-  /* The containing class cannot be empty; this field takes up space.  */
-  *empty_p = 0;
+      /* Place this field.  */
+      place_field (rli, decl);
+      
+      /* Now that we know where it wil be placed, update its
+        BINFO_OFFSET.  */
+      offset = byte_position (decl);
+      if (binfo)
+       propagate_binfo_offsets (binfo, 
+                                convert (ssizetype, offset));
+      /* We have to check to see whether or not there is already
+        something of the same type at the offset we're about to use.
+        For example:
+        
+        struct S {};
+        struct T : public S { int i; };
+        struct U : public S, public T {};
+        
+        Here, we put S at offset zero in U.  Then, we can't put T at
+        offset zero -- its S component would be at the same address
+        as the S we already allocated.  So, we have to skip ahead.
+        Since all data members, including those whose type is an
+        empty class, have non-zero size, any overlap can happen only
+        with a direct or indirect base-class -- it can't happen with
+        a data member.  */
+      if (binfo && flag_new_abi && layout_conflict_p (binfo, v))
+       {
+         /* Undo the propagate_binfo_offsets call.  */
+         offset = size_diffop (size_zero_node, offset);
+         propagate_binfo_offsets (binfo, convert (ssizetype, offset));
+        
+         /* Strip off the size allocated to this field.  That puts us
+            at the first place we could have put the field with
+            proper alignment.  */
+         *rli = old_rli;
+
+         /* Bump up by the alignment required for the type, without
+            virtual base classes.  */
+         rli->bitpos
+           = size_binop (PLUS_EXPR, rli->bitpos,
+                         bitsize_int (CLASSTYPE_ALIGN (BINFO_TYPE (binfo))));
+         normalize_rli (rli);
+       }
+      else
+       /* There was no conflict.  We're done laying out this field.  */
+       break;
+    }
+}
 
-  return 1;
+/* Layout the empty base BINFO.  EOC indicates the byte currently just
+   past the end of the class, and should be correctly aligned for a
+   class of the type indicated by BINFO; BINFO_OFFSETS gives the
+   offsets of the other bases allocated so far.  */
+
+static void
+layout_empty_base (binfo, eoc, binfo_offsets)
+     tree binfo;
+     tree eoc;
+     varray_type binfo_offsets;
+{
+  tree alignment;
+  tree basetype = BINFO_TYPE (binfo);
+  
+  /* This routine should only be used for empty classes.  */
+  my_friendly_assert (is_empty_class (basetype), 20000321);
+  alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
+
+  /* This is an empty base class.  We first try to put it at offset
+     zero.  */
+  if (layout_conflict_p (binfo, binfo_offsets))
+    {
+      /* That didn't work.  Now, we move forward from the next
+        available spot in the class.  */
+      propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
+      while (1) 
+       {
+         if (!layout_conflict_p (binfo, binfo_offsets))
+           /* We finally found a spot where there's no overlap.  */
+           break;
+
+         /* There's overlap here, too.  Bump along to the next spot.  */
+         propagate_binfo_offsets (binfo, alignment);
+       }
+    }
 }
 
-/* Build a FIELD_DECL for the base given by BINFO in T.  If the new
-   object is non-empty, clear *EMPTY_P.  Otherwise, set *SAW_EMPTY_P.
+/* Build a FIELD_DECL for the base given by BINFO in the class
+   indicated by RLI.  If the new object is non-empty, clear *EMPTY_P.
    *BASE_ALIGN is a running maximum of the alignments of any base
    class.  */
 
-static tree
-build_base_field (t, binfo, empty_p, saw_empty_p, base_align)
-     tree t;
+static void
+build_base_field (rli, binfo, empty_p, base_align, v)
+     record_layout_info rli;
      tree binfo;
      int *empty_p;
-     int *saw_empty_p;
      unsigned int *base_align;
+     varray_type *v;
 {
   tree basetype = BINFO_TYPE (binfo);
   tree decl;
 
-  if (TYPE_SIZE (basetype) == 0)
+  if (!COMPLETE_TYPE_P (basetype))
     /* This error is now reported in xref_tag, thus giving better
        location information.  */
-    return NULL_TREE;
+    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) = DECL_CLASS_CONTEXT (decl) = t;
+  DECL_FIELD_CONTEXT (decl) = rli->t;
   DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+  DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
   DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
   
-  if (flag_new_abi && DECL_SIZE (decl) == integer_zero_node)
-    {
-      *saw_empty_p = 1;
-      return decl;
-    }
-
-  /* The containing class is non-empty because it has a non-empty base
-     class.  */
-  *empty_p = 0;
-      
   if (! flag_new_abi)
     {
       /* Brain damage for backwards compatibility.  For no good
-        reason, the old layout_basetypes made every base at least
+        reason, the old basetype layout made every base have at least
         as large as the alignment for the bases up to that point,
-        gratuitously wasting space.  So we do the same thing
-        here.  */
+        gratuitously wasting space.  So we do the same thing here.  */
       *base_align = MAX (*base_align, DECL_ALIGN (decl));
       DECL_SIZE (decl)
-       = size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
-                        (int) (*base_align)));
+       = size_binop (MAX_EXPR, DECL_SIZE (decl), bitsize_int (*base_align));
+      DECL_SIZE_UNIT (decl)
+       = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+                     size_int (*base_align / BITS_PER_UNIT));
     }
 
-  return decl;
+  if (!integer_zerop (DECL_SIZE (decl)))
+    {
+      /* The containing class is non-empty because it has a non-empty
+        base class.  */
+      *empty_p = 0;
+
+      /* Try to place the field.  It may take more than one try if we
+        have a hard time placing the field without putting two
+        objects of the same type at the same address.  */
+      layout_nonempty_base_or_field (rli, decl, binfo, *v);
+    }
+  else
+    {
+      unsigned HOST_WIDE_INT eoc;
+
+      /* On some platforms (ARM), even empty classes will not be
+        byte-aligned.  */
+      eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
+      eoc = CEIL (eoc, DECL_ALIGN (decl)) * DECL_ALIGN (decl);
+      layout_empty_base (binfo, size_int (eoc), *v);
+    }
+
+  /* Check for inaccessible base classes.  If the same base class
+     appears more than once in the hierarchy, but isn't virtual, then
+     it's ambiguous.  */
+  if (get_base_distance (basetype, rli->t, 0, NULL) == -2)
+    cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
+               basetype, rli->t);
+  
+  /* Record the offsets of BINFO and its base subobjects.  */
+  record_base_offsets (binfo, v);
 }
 
-/* Returns a list of fields to stand in for the base class subobjects
-   of REC.  These fields are later removed by layout_basetypes.  */
+/* Layout all of the non-virtual base classes.  Returns a map from
+   offsets to types present at those offsets.  */
 
-static tree
-build_base_fields (rec, empty_p)
-     tree rec;
+static varray_type
+build_base_fields (rli, empty_p)
+     record_layout_info rli;
      int *empty_p;
 {
   /* Chain to hold all the new FIELD_DECLs which stand in for base class
      subobjects.  */
-  tree base_decls = NULL_TREE;
+  tree rec = rli->t;
   int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
-  tree decl, nextdecl;
-  int i, saw_empty = 0;
+  int i;
+  varray_type v;
   unsigned int base_align = 0;
 
+  /* Create the table mapping offsets to empty base classes.  */
+  VARRAY_TREE_INIT (v, 32, "v");
+
   /* Under the new ABI, the primary base class is always allocated
      first.  */
   if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
-    {
-      tree primary_base;
-
-      primary_base = CLASSTYPE_PRIMARY_BINFO (rec);
-      base_decls = chainon (build_base_field (rec, 
-                                             primary_base,
-                                             empty_p,
-                                             &saw_empty,
-                                             &base_align),
-                           base_decls);
-    }
+    build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), 
+                     empty_p, &base_align, &v);
 
   /* Now allocate the rest of the bases.  */
   for (i = 0; i < n_baseclasses; ++i)
@@ -4265,51 +3929,15 @@ build_base_fields (rec, empty_p)
 
       /* A primary virtual base class is allocated just like any other
         base class, but a non-primary virtual base is allocated
-        later, in layout_basetypes.  */
+        later, in layout_virtual_bases.  */
       if (TREE_VIA_VIRTUAL (base_binfo) 
          && !BINFO_PRIMARY_MARKED_P (base_binfo))
        continue;
 
-      base_decls = chainon (build_base_field (rec, base_binfo,
-                                             empty_p,
-                                             &saw_empty,
-                                             &base_align),
-                           base_decls);
+      build_base_field (rli, base_binfo, empty_p, &base_align, &v);
     }
 
-  /* Reverse the list of fields so we allocate the bases in the proper
-     order.  */
-  base_decls = nreverse (base_decls);
-
-  /* In the presence of empty base classes, we run the risk of allocating
-     two objects of the same class on top of one another.  Avoid that.  */
-  if (flag_new_abi && saw_empty)
-    for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
-      {
-       if (DECL_SIZE (decl) == integer_zero_node)
-         {
-           /* First step through the following bases until we find
-              an overlap or a non-empty base.  */
-           for (nextdecl = TREE_CHAIN (decl); nextdecl;
-                nextdecl = TREE_CHAIN (nextdecl))
-             {
-               if (avoid_overlap (decl, nextdecl, empty_p)
-                   || DECL_SIZE (nextdecl) != integer_zero_node)
-                 goto nextbase;
-             }
-
-           /* If we're still looking, also check against the first
-              field.  */
-           for (nextdecl = TYPE_FIELDS (rec);
-                nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
-                nextdecl = TREE_CHAIN (nextdecl))
-             /* keep looking */;
-           avoid_overlap (decl, nextdecl, empty_p);
-         }
-      nextbase:;
-      }
-
-  return base_decls;
+  return v;
 }
 
 /* Go through the TYPE_METHODS of T issuing any appropriate
@@ -4321,6 +3949,7 @@ check_methods (t)
      tree t;
 {
   tree x;
+  int seen_one_arg_array_delete_p = 0;
 
   for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
     {
@@ -4330,13 +3959,6 @@ check_methods (t)
       if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
        continue;
 
-      /* Do both of these, even though they're in the same union;
-        if the insn `r' member and the size `i' member are
-        different sizes, as on the alpha, the larger of the two
-        will end up with garbage in it.  */
-      DECL_SAVED_INSNS (x) = 0;
-      DECL_FIELD_SIZE (x) = 0;
-
       check_for_override (x, t);
       if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
        cp_error_at ("initializer specified for non-virtual method `%D'", x);
@@ -4350,9 +3972,230 @@ check_methods (t)
            CLASSTYPE_PURE_VIRTUALS (t)
              = tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t));
        }
+
+      if (DECL_ARRAY_DELETE_OPERATOR_P (x))
+       {
+         tree second_parm;
+
+         /* When dynamically allocating an array of this type, we
+            need a "cookie" to record how many elements we allocated,
+            even if the array elements have no non-trivial
+            destructor, if the usual array deallocation function
+            takes a second argument of type size_t.  The standard (in
+            [class.free]) requires that the second argument be set
+            correctly.  */
+         second_parm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (x)));
+         /* This is overly conservative, but we must maintain this
+            behavior for backwards compatibility.  */
+         if (!flag_new_abi && second_parm != void_list_node)
+           TYPE_VEC_DELETE_TAKES_SIZE (t) = 1;
+         /* Under the new ABI, we choose only those function that are
+            explicitly declared as `operator delete[] (void *,
+            size_t)'.  */
+         else if (flag_new_abi 
+                  && !seen_one_arg_array_delete_p
+                  && second_parm
+                  && TREE_CHAIN (second_parm) == void_list_node
+                  && same_type_p (TREE_VALUE (second_parm), sizetype))
+           TYPE_VEC_DELETE_TAKES_SIZE (t) = 1;
+         /* If there's no second parameter, then this is the usual
+            deallocation function.  */
+         else if (second_parm == void_list_node)
+           seen_one_arg_array_delete_p = 1;
+       }
+    }
+}
+
+/* FN is a constructor or destructor.  Clone the declaration to create
+   a specialized in-charge or not-in-charge version, as indicated by
+   NAME.  */
+
+static tree
+build_clone (fn, name)
+     tree fn;
+     tree name;
+{
+  tree parms;
+  tree clone;
+
+  /* Copy the function.  */
+  clone = copy_decl (fn);
+  /* Remember where this function came from.  */
+  DECL_CLONED_FUNCTION (clone) = fn;
+  /* Reset the function name.  */
+  DECL_NAME (clone) = name;
+  DECL_ASSEMBLER_NAME (clone) = DECL_NAME (clone);
+  /* There's no pending inline data for this function.  */
+  DECL_PENDING_INLINE_INFO (clone) = NULL;
+  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)
+    {
+      DECL_VIRTUAL_P (clone) = 0;
+      if (TREE_CODE (clone) != TEMPLATE_DECL)
+       DECL_VINDEX (clone) = NULL_TREE;
+    }
+
+  /* If there was an in-charge parameter, drop it from the function
+     type.  */
+  if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+    {
+      tree basetype;
+      tree parmtypes;
+      tree exceptions;
+
+      exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
+      basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
+      parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone));
+      /* Skip the `this' parameter.  */
+      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)),
+                                  parmtypes);
+      if (exceptions)
+       TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
+                                                    exceptions);
+    }
+
+  /* Copy the function parameters.  But, DECL_ARGUMENTS aren't
+     function parameters; instead, those are the template parameters.  */
+  if (TREE_CODE (clone) != TEMPLATE_DECL)
+    {
+      DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone));
+      /* Remove the in-charge parameter.  */
+      if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+       {
+         TREE_CHAIN (DECL_ARGUMENTS (clone))
+           = 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;
+         copy_lang_decl (parms);
+       }
+    }
+
+  /* Mangle the function name.  */
+  set_mangled_name_for_decl (clone);
+
+  /* Create the RTL for this function.  */
+  DECL_RTL (clone) = NULL_RTX;
+  rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof);
+  
+  /* Make it easy to find the CLONE given the FN.  */
+  TREE_CHAIN (clone) = TREE_CHAIN (fn);
+  TREE_CHAIN (fn) = clone;
+
+  /* If this is a template, handle the DECL_TEMPLATE_RESULT as well.  */
+  if (TREE_CODE (clone) == TEMPLATE_DECL)
+    {
+      tree result;
+
+      DECL_TEMPLATE_RESULT (clone) 
+       = build_clone (DECL_TEMPLATE_RESULT (clone), name);
+      result = DECL_TEMPLATE_RESULT (clone);
+      DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result));
+      DECL_TI_TEMPLATE (result) = clone;
+    }
+  else if (DECL_DEFERRED_FN (fn))
+    defer_fn (clone);
+
+  return clone;
+}
+
+/* Produce declarations for all appropriate clones of FN.  If
+   UPDATE_METHOD_VEC_P is non-zero, the clones are added to the
+   CLASTYPE_METHOD_VEC as well.  */
+
+void
+clone_function_decl (fn, update_method_vec_p)
+     tree fn;
+     int update_method_vec_p;
+{
+  tree clone;
+
+  if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
+    {
+      /* For each constructor, we need two variants: an in-charge version
+        and a not-in-charge version.  */
+      clone = build_clone (fn, complete_ctor_identifier);
+      if (update_method_vec_p)
+       add_method (DECL_CONTEXT (clone), NULL, clone);
+      clone = build_clone (fn, base_ctor_identifier);
+      if (update_method_vec_p)
+       add_method (DECL_CONTEXT (clone), NULL, clone);
+    }
+  else
+    {
+      my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
+
+      /* 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
+        corresponds to the correct layout order in the virtual
+        function table.  */
+      clone = build_clone (fn, deleting_dtor_identifier);
+      if (update_method_vec_p)
+       add_method (DECL_CONTEXT (clone), NULL, clone);
+      clone = build_clone (fn, complete_dtor_identifier);
+      if (update_method_vec_p)
+       add_method (DECL_CONTEXT (clone), NULL, clone);
+      clone = build_clone (fn, base_dtor_identifier);
+      if (update_method_vec_p)
+       add_method (DECL_CONTEXT (clone), NULL, clone);
     }
 }
 
+/* For each of the constructors and destructors in T, create an
+   in-charge and not-in-charge variant.  */
+
+static void
+clone_constructors_and_destructors (t)
+     tree t;
+{
+  tree fns;
+
+  /* We only clone constructors and destructors under the new ABI.  */
+  if (!flag_new_abi)
+    return;
+
+  /* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail
+     out now.  */
+  if (!CLASSTYPE_METHOD_VEC (t))
+    return;
+
+  for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+    clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
+  for (fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+    clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
+}
+
 /* Remove all zero-width bit-fields from T.  */
 
 static void
@@ -4448,29 +4291,30 @@ check_bases_and_members (t, empty_p)
                                   cant_have_const_ctor,
                                   no_const_asn_ref);
 
+  /* Create the in-charge and not-in-charge variants of constructors
+     and destructors.  */
+  clone_constructors_and_destructors (t);
+
+  /* Process the using-declarations.  */
+  for (; access_decls; access_decls = TREE_CHAIN (access_decls))
+    handle_using_decl (TREE_VALUE (access_decls), t);
+
   /* Build and sort the CLASSTYPE_METHOD_VEC.  */
   finish_struct_methods (t);
-
-  /* Process the access-declarations.  We wait until now to do this
-     because handle_using_decls requires that the CLASSTYPE_METHOD_VEC
-     be set up correctly.  */
-  while (access_decls)
-    {
-      handle_using_decl (TREE_VALUE (access_decls), t);
-      access_decls = TREE_CHAIN (access_decls);
-    }
 }
 
 /* If T needs a pointer to its virtual function table, set TYPE_VFIELD
-   accordingly, and, if necessary, add the TYPE_VFIELD to the
-   TYPE_FIELDS list.  */
+   accordingly.  If a new vfield was created (because T doesn't have a
+   primary base class), then the newly created field is returned.  It
+   is not added to the TYPE_FIELDS list; it is the caller's
+   responsibility to do that.  */
 
-static void
-create_vtable_ptr (t, empty_p, has_virtual_p, 
+static tree
+create_vtable_ptr (t, empty_p, vfuns_p,
                   new_virtuals_p, overridden_virtuals_p)
      tree t;
      int *empty_p;
-     int *has_virtual_p;
+     int *vfuns_p;
      tree *new_virtuals_p;
      tree *overridden_virtuals_p;
 {
@@ -4479,19 +4323,18 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
   /* Loop over the virtual functions, adding them to our various
      vtables.  */
   for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
-    if (DECL_VINDEX (fn))
+    if (DECL_VINDEX (fn) 
+       && !(flag_new_abi && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)))
       add_virtual_function (new_virtuals_p, overridden_virtuals_p,
-                           has_virtual_p, fn, t);
+                           vfuns_p, fn, t);
 
-  /* Even if there weren't any new virtual functions, we might need a
+  /* If we couldn't find an appropriate base class, create a new field
+     here.  Even if there weren't any new virtual functions, we might need a
      new virtual function table if we're supposed to include vptrs in
      all classes that need them.  */
-  if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())
-    start_vtable (t, has_virtual_p);
-    
-  /* If we couldn't find an appropriate base class, create a new field
-     here.  */
-  if (*has_virtual_p && !TYPE_VFIELD (t))
+  if (!TYPE_VFIELD (t)
+      && (*vfuns_p 
+         || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())))
     {
       /* We build this decl with vtbl_ptr_type_node, which is a
         `vtable_entry_type*'.  It might seem more precise to use
@@ -4517,31 +4360,20 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
                                     get_identifier (VFIELD_BASE),
                                     vtbl_ptr_type_node,
                                     t,
+                                    t,
                                     empty_p);
 
-      /* Add the new field to the list of fields in this class.  */
-      if (!flag_new_abi)
-       /* In the old ABI, the vtable pointer goes at the end of the
-          class.  */
-       TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t));
-      else
-       {
-         /* But in the new ABI, the vtable pointer is the first thing
-            in the class.  */
-         TYPE_FIELDS (t) = chainon (TYPE_VFIELD (t), TYPE_FIELDS (t));
-         /* If there were any baseclasses, they can't possibly be at
-            offset zero any more, because that's where the vtable
-            pointer is.  So, converting to a base class is going to
-            take work.  */
-         if (CLASSTYPE_N_BASECLASSES (t))
-           TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
-       }
+      if (flag_new_abi && CLASSTYPE_N_BASECLASSES (t))
+       /* If there were any baseclasses, they can't possibly be at
+          offset zero any more, because that's where the vtable
+          pointer is.  So, converting to a base class is going to
+          take work.  */
+       TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
 
-      /* We can't yet add this new field to the list of all virtual
-        function table pointers in this class.  The
-        modify_all_vtables function depends on this not being done.
-        So, it is done later, in finish_struct_1.  */
+      return TYPE_VFIELD (t);
     }
+
+  return NULL_TREE;
 }
 
 /* Fixup the inline function given by INFO now that the class is
@@ -4605,10 +4437,12 @@ dfs_propagate_binfo_offsets (binfo, data)
 {
   tree offset = (tree) data;
 
-  /* Update the BINFO_OFFSET for this base.  */
-  BINFO_OFFSET (binfo) 
-    = size_binop (PLUS_EXPR, BINFO_OFFSET (binfo), offset);
-
+  /* 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;
@@ -4637,103 +4471,24 @@ propagate_binfo_offsets (binfo, offset)
            NULL);
 }
 
-/* Remove *FIELD (which corresponds to the base given by BINFO) from
-   the field list for T.  */
+/* Called via dfs_walk from layout_virtual bases.  */
 
-static void
-remove_base_field (t, binfo, field)
-     tree t;
+static tree
+dfs_set_offset_for_shared_vbases (binfo, data)
      tree binfo;
-     tree *field;
+     void *data;
 {
-  tree basetype = BINFO_TYPE (binfo);
-  tree offset;
+  if (TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
+    {
+      /* Update the shared copy.  */
+      tree shared_binfo;
 
-  my_friendly_assert (TREE_TYPE (*field) == basetype, 23897);
+      shared_binfo = binfo_for_vbase (BINFO_TYPE (binfo), (tree) data);
+      BINFO_OFFSET (shared_binfo) = BINFO_OFFSET (binfo);
+    }
 
-  if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
-    cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
-               basetype, t);
-
-  offset
-    = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (*field)),
-                     BITS_PER_UNIT));
-  propagate_binfo_offsets (binfo, offset);
-
-  /* Remove this field.  */
-  *field = TREE_CHAIN (*field);
-}
-
-/* Remove the FIELD_DECLs created for T's base classes in
-   build_base_fields.  Simultaneously, update BINFO_OFFSET for all the
-   bases, except for non-primary virtual baseclasses.  */
-
-static void
-remove_base_fields (t)
-     tree t;
-{
-  int i;
-  tree *field;
-
-  /* Now propagate offset information throughout the lattice.
-     Simultaneously, remove the temporary FIELD_DECLS we created in
-     build_base_fields to refer to base types.  */
-  field = &TYPE_FIELDS (t);
-  if (TYPE_VFIELD (t) == *field)
-    {
-      /* If this class did not have a primary base, we create a
-        virtual function table pointer.  It will be the first thing
-        in the class, under the new ABI.  Skip it; the base fields
-        will follow it.  */
-      my_friendly_assert (flag_new_abi 
-                         && !CLASSTYPE_HAS_PRIMARY_BASE_P (t),
-                         19991218);
-      field = &TREE_CHAIN (*field);
-    }
-
-  /* Under the new ABI, the primary base is always allocated first.  */
-  if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-    remove_base_field (t, CLASSTYPE_PRIMARY_BINFO (t), field);
-
-  /* Now remove the rest of the bases.  */
-  for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
-    {
-      tree binfo;
-
-      /* Under the new ABI, we've already removed the primary base
-        above.  */
-      if (flag_new_abi && i == CLASSTYPE_VFIELD_PARENT (t))
-       continue;
-
-      binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
-
-      /* We treat a primary virtual base class just like an ordinary base
-        class.  But, non-primary virtual bases are laid out later.  */
-      if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
-       continue;
-
-      remove_base_field (t, binfo, field);
-    }
-}
-
-/* Called via dfs_walk from layout_virtual bases.  */
-
-static tree
-dfs_set_offset_for_shared_vbases (binfo, data)
-     tree binfo;
-     void *data;
-{
-  if (TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
-    {
-      /* Update the shared copy.  */
-      tree shared_binfo;
-
-      shared_binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), (tree) data);
-      BINFO_OFFSET (shared_binfo) = BINFO_OFFSET (binfo);
-    }
-
-  return NULL_TREE;
-}
+  return NULL_TREE;
+}
 
 /* Called via dfs_walk from layout_virtual bases.  */
 
@@ -4751,10 +4506,8 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
       tree vbase;
       tree offset;
       
-      vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t);
-      offset = ssize_binop (MINUS_EXPR, 
-                           BINFO_OFFSET (vbase),
-                           BINFO_OFFSET (binfo));
+      vbase = binfo_for_vbase (BINFO_TYPE (binfo), t);
+      offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
       propagate_binfo_offsets (binfo, offset);
     }
 
@@ -4762,47 +4515,105 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
 }
 
 /* Set BINFO_OFFSET for all of the virtual bases for T.  Update
-   TYPE_ALIGN and TYPE_SIZE for T.  */
+   TYPE_ALIGN and TYPE_SIZE for T.  BASE_OFFSETS is a varray mapping
+   offsets to the types at those offsets.  */
 
 static void
-layout_virtual_bases (t)
+layout_virtual_bases (t, base_offsets)
      tree t;
+     varray_type *base_offsets;
 {
-  tree vbase;
-  int dsize;
+  tree vbases;
+  unsigned HOST_WIDE_INT dsize;
+  unsigned HOST_WIDE_INT eoc;
+
+  if (CLASSTYPE_N_BASECLASSES (t) == 0)
+    return;
+
+#ifdef STRUCTURE_SIZE_BOUNDARY
+  /* Packed structures don't need to have minimum size.  */
+  if (! TYPE_PACKED (t))
+    TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
+#endif
 
   /* DSIZE is the size of the class without the virtual bases.  */
-  dsize = TREE_INT_CST_LOW (TYPE_SIZE (t));
+  dsize = tree_low_cst (TYPE_SIZE (t), 1);
+
   /* Make every class have alignment of at least one.  */
   TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
 
   /* Go through the virtual bases, allocating space for each virtual
-     base that is not already a primary base class.  */
-  for (vbase = CLASSTYPE_VBASECLASSES (t); 
-       vbase; 
-       vbase = TREE_CHAIN (vbase))
-    if (!BINFO_VBASE_PRIMARY_P (vbase))
-      {
-       /* This virtual base is not a primary base of any class in the
-          hierarchy, so we have to add space for it.  */
-       tree basetype;
-       unsigned int desired_align;
-
-       basetype = BINFO_TYPE (vbase);
-       desired_align = TYPE_ALIGN (basetype);
-       TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
-
-       /* Add padding so that we can put the virtual base class at an
-          appropriately aligned offset.  */
-       dsize = CEIL (dsize, desired_align) * desired_align;
-       /* And compute the offset of the virtual base.  */
-       propagate_binfo_offsets (vbase, 
-                                size_int (CEIL (dsize, BITS_PER_UNIT)));
-       /* Every virtual baseclass takes a least a UNIT, so that we can
-          take it's address and get something different for each base.  */
-       dsize += MAX (BITS_PER_UNIT,
-                     TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype)));
-      }
+     base that is not already a primary base class.  Under the new
+     ABI, these are allocated according to a depth-first left-to-right
+     postorder traversal; in the new ABI, inheritance graph order is
+     used instead.  */
+  for (vbases = (flag_new_abi 
+                ? TYPE_BINFO (t) 
+                : CLASSTYPE_VBASECLASSES (t));
+       vbases; 
+       vbases = TREE_CHAIN (vbases))
+    {
+      tree vbase;
+
+      if (flag_new_abi)
+       {
+         if (!TREE_VIA_VIRTUAL (vbases))
+           continue;
+         vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
+       }
+      else
+       vbase = TREE_VALUE (vbases);
+
+      if (!BINFO_VBASE_PRIMARY_P (vbase))
+       {
+         /* This virtual base is not a primary base of any class in the
+            hierarchy, so we have to add space for it.  */
+         tree basetype;
+         unsigned int desired_align;
+
+         basetype = BINFO_TYPE (vbase);
+
+         if (flag_new_abi)
+           desired_align = CLASSTYPE_ALIGN (basetype);
+         else
+           /* Under the old ABI, virtual bases were aligned as for the
+            entire base object (including its virtual bases).  That's
+            wasteful, in general.  */
+           desired_align = TYPE_ALIGN (basetype);
+         TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
+
+         /* Add padding so that we can put the virtual base class at an
+            appropriately aligned offset.  */
+         dsize = CEIL (dsize, desired_align) * desired_align;
+
+         /* Under the new ABI, we try to squish empty virtual bases in
+            just like ordinary empty bases.  */
+         if (flag_new_abi && is_empty_class (basetype))
+           layout_empty_base (vbase,
+                              size_int (CEIL (dsize, BITS_PER_UNIT)),
+                              *base_offsets);
+         else
+           {
+             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, offset);
+             /* Every virtual baseclass takes a least a UNIT, so that
+                we can take it's address and get something different
+                for each base.  */
+             dsize += MAX (BITS_PER_UNIT,
+                           tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
+           }
+
+         /* Keep track of the offsets assigned to this virtual base.  */
+         record_base_offsets (vbase, base_offsets);
+       }
+    }
 
   /* Make sure that all of the CLASSTYPE_VBASECLASSES have their
      BINFO_OFFSET set correctly.  Those we just allocated certainly
@@ -4820,52 +4631,68 @@ layout_virtual_bases (t)
      correctly.  */
   dfs_walk (TYPE_BINFO (t), 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
+     multiple such bases at the same location.  */
+  eoc = end_of_class (t, /*include_virtuals_p=*/1);
+  if (eoc * BITS_PER_UNIT > dsize)
+    dsize = (eoc + 1) * BITS_PER_UNIT;
+
   /* Now, make sure that the total size of the type is a multiple of
      its alignment.  */
   dsize = CEIL (dsize, TYPE_ALIGN (t)) * TYPE_ALIGN (t);
-  TYPE_SIZE (t) = size_int (dsize);
-  TYPE_SIZE_UNIT (t) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (t),
-                                  size_int (BITS_PER_UNIT));
+  TYPE_SIZE (t) = bitsize_int (dsize);
+  TYPE_SIZE_UNIT (t) = convert (sizetype,
+                               size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
+                                           bitsize_unit_node));
+
+  /* Check for ambiguous virtual bases.  */
+  if (extra_warnings)
+    for (vbases = CLASSTYPE_VBASECLASSES (t); 
+        vbases; 
+        vbases = TREE_CHAIN (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);
+      }
 }
 
-/* Finish the work of layout_record, now taking virtual bases into account.
-   Also compute the actual offsets that our base classes will have.
-   This must be performed after the fields are laid out, since virtual
-   baseclasses must lay down at the end of the record.  */
+/* Returns the offset of the byte just past the end of the base class
+   with the highest offset in T.  If INCLUDE_VIRTUALS_P is zero, then
+   only non-virtual bases are included.  */
 
-static void
-layout_basetypes (rec)
-     tree rec;
+static unsigned HOST_WIDE_INT
+end_of_class (t, include_virtuals_p)
+     tree t;
+     int include_virtuals_p;
 {
-  tree vbase_types;
+  unsigned HOST_WIDE_INT result = 0;
+  int i;
 
-#ifdef STRUCTURE_SIZE_BOUNDARY
-  /* Packed structures don't need to have minimum size.  */
-  if (! TYPE_PACKED (rec))
-    TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), STRUCTURE_SIZE_BOUNDARY);
-#endif
+  for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+    {
+      tree base_binfo;
+      tree offset;
+      unsigned HOST_WIDE_INT end_of_base;
 
-  /* Remove the FIELD_DECLs we created for baseclasses in
-     build_base_fields.  Simultaneously, update the BINFO_OFFSETs for
-     everything in the hierarcy except non-primary virtual bases.  */
-  remove_base_fields (rec);
-
-  /* Allocate the virtual base classes.  */
-  layout_virtual_bases (rec);
-
-  /* Get all the virtual base types that this type uses.  The
-     TREE_VALUE slot holds the virtual baseclass type.  Note that
-     get_vbase_types makes copies of the virtual base BINFOs, so that
-     the vbase_types are unshared.  */
-  for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;
-       vbase_types = TREE_CHAIN (vbase_types))
-    if (extra_warnings)
-      {
-       tree basetype = BINFO_TYPE (vbase_types);
-       if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
-         cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
-                     basetype, rec);
-      }
+      base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
+
+      if (!include_virtuals_p
+         && TREE_VIA_VIRTUAL (base_binfo) 
+         && !BINFO_PRIMARY_MARKED_P (base_binfo))
+       continue;
+
+      offset = size_binop (PLUS_EXPR, 
+                          BINFO_OFFSET (base_binfo),
+                          CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo)));
+      end_of_base = tree_low_cst (offset, /*pos=*/1);
+      if (end_of_base > result)
+       result = end_of_base;
+    }
+
+  return result;
 }
 
 /* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T.  Calculate
@@ -4873,72 +4700,176 @@ layout_basetypes (rec)
    pointer.  */
 
 static void
-layout_class_type (t, empty_p, has_virtual_p, 
+layout_class_type (t, empty_p, vfuns_p, 
                   new_virtuals_p, overridden_virtuals_p)
      tree t;
      int *empty_p;
-     int *has_virtual_p;
+     int *vfuns_p;
      tree *new_virtuals_p;
      tree *overridden_virtuals_p;
 {
-  tree padding = NULL_TREE;
+  tree non_static_data_members;
+  tree field;
+  tree vptr;
+  record_layout_info rli;
+  varray_type v;
+  unsigned HOST_WIDE_INT eoc;
+
+  /* Keep track of the first non-static data member.  */
+  non_static_data_members = TYPE_FIELDS (t);
+
+  /* Start laying out the record.  */
+  rli = start_record_layout (t);
 
   /* If possible, we reuse the virtual function table pointer from one
      of our base classes.  */
-  determine_primary_base (t, has_virtual_p);
+  determine_primary_base (t, vfuns_p);
+
+  /* Create a pointer to our virtual function table.  */
+  vptr = create_vtable_ptr (t, empty_p, vfuns_p,
+                           new_virtuals_p, overridden_virtuals_p);
+
+  /* Under the new ABI, the vptr is always the first thing in the
+     class.  */
+  if (flag_new_abi && vptr)
+    {
+      TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+      place_field (rli, vptr);
+    }
 
   /* Add pointers to all of our virtual base-classes.  */
-  TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, empty_p),
+  TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
                             TYPE_FIELDS (t));
   /* Build FIELD_DECLs for all of the non-virtual base-types.  */
-  TYPE_FIELDS (t) = chainon (build_base_fields (t, empty_p), 
-                            TYPE_FIELDS (t));
-
-  /* Create a pointer to our virtual function table.  */
-  create_vtable_ptr (t, empty_p, has_virtual_p,
-                    new_virtuals_p, overridden_virtuals_p);
+  v = build_base_fields (rli, empty_p);
 
   /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS.  Thus,
      we have to save this before we start modifying
      TYPE_NONCOPIED_PARTS.  */
   fixup_inline_methods (t);
 
+  /* Layout the non-static data members.  */
+  for (field = non_static_data_members; field; field = TREE_CHAIN (field))
+    {
+      tree binfo;
+      tree type;
+      tree padding;
+
+      /* We still pass things that aren't non-static data members to
+        the back-end, in case it wants to do something with them.  */
+      if (TREE_CODE (field) != FIELD_DECL)
+       {
+         place_field (rli, field);
+         continue;
+       }
+
+      type = TREE_TYPE (field);
+
+      /* If this field is a bit-field whose width is greater than its
+        type, then there are some special rules for allocating it
+        under the new ABI.  Under the old ABI, there were no special
+        rules, but the back-end can't handle bitfields longer than a
+        `long long', so we use the same mechanism.  */
+      if (DECL_C_BIT_FIELD (field)
+         && ((flag_new_abi 
+              && INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
+             || (!flag_new_abi
+                 && 0 < compare_tree_int (DECL_SIZE (field),
+                                          TYPE_PRECISION
+                                          (long_long_unsigned_type_node)))))
+       {
+         integer_type_kind itk;
+         tree integer_type;
+
+         /* We must allocate the bits as if suitably aligned for the
+            longest integer type that fits in this many bits.  type
+            of the field.  Then, we are supposed to use the left over
+            bits as additional padding.  */
+         for (itk = itk_char; itk != itk_none; ++itk)
+           if (INT_CST_LT (DECL_SIZE (field), 
+                           TYPE_SIZE (integer_types[itk])))
+             break;
+
+         /* ITK now indicates a type that is too large for the
+            field.  We have to back up by one to find the largest
+            type that fits.  */
+         integer_type = integer_types[itk - 1];
+         padding = size_binop (MINUS_EXPR, DECL_SIZE (field), 
+                               TYPE_SIZE (integer_type));
+         DECL_SIZE (field) = TYPE_SIZE (integer_type);
+         DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
+       }
+      else
+       padding = NULL_TREE;
+
+      /* Create a dummy BINFO corresponding to this field.  */
+      binfo = make_binfo (size_zero_node, type, NULL_TREE, NULL_TREE);
+      unshare_base_binfos (binfo);
+      layout_nonempty_base_or_field (rli, field, binfo, v);
+
+      /* If we needed additional padding after this field, add it
+        now.  */
+      if (padding)
+       {
+         tree padding_field;
+
+         padding_field = build_decl (FIELD_DECL, 
+                                     NULL_TREE,
+                                     char_type_node); 
+         DECL_BIT_FIELD (padding_field) = 1;
+         DECL_SIZE (padding_field) = padding;
+         DECL_ALIGN (padding_field) = 1;
+         layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, v);
+       }
+    }
+
+  /* It might be the case that we grew the class to allocate a
+     zero-sized base class.  That won't be reflected in RLI, yet,
+     because we are willing to overlay multiple bases at the same
+     offset.  However, now we need to make sure that RLI is big enough
+     to reflect the entire class.  */
+  eoc = end_of_class (t, /*include_virtuals_p=*/0);
+  if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
+      && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
+    {
+      /* We don't handle zero-sized base classes specially under the
+        old ABI, so if we get here, we had better be operating under
+        the new ABI rules.  */
+      my_friendly_assert (flag_new_abi, 20000321);
+      rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc + 1));
+      rli->bitpos = bitsize_zero_node;
+    }
+
   /* We make all structures have at least one element, so that they
-     have non-zero size.  The field that we add here is fake, in the
-     sense that, for example, we don't want people to be able to
-     initialize it later.  So, we add it just long enough to let the
-     back-end lay out the type, and then remove it.  In the new ABI,
-     the class may be empty even if it has basetypes.  Therefore, we
-     add the fake field at the end of the fields list; if there are
-     already FIELD_DECLs on the list, their offsets will not be
-     disturbed.  */
+     have non-zero size.  In the new ABI, the class may be empty even
+     if it has basetypes.  Therefore, we add the fake field after all
+     the other fields; if there are already FIELD_DECLs on the list,
+     their offsets will not be disturbed.  */
   if (*empty_p)
     {
-      padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
-      TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), padding);
+      tree padding;
+
+      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));
       TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
     }
 
+  /* Under the old ABI, the vptr comes at the very end of the 
+     class.   */
+  if (!flag_new_abi && vptr)
+    {
+      place_field (rli, vptr);
+      TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vptr);
+    }
+  
   /* Let the back-end lay out the type. Note that at this point we
      have only included non-virtual base-classes; we will lay out the
      virtual base classes later.  So, the TYPE_SIZE/TYPE_ALIGN after
      this call are not necessarily correct; they are just the size and
      alignment when no virtual base clases are used.  */
-  layout_type (t);
-
-  /* If we added an extra field to make this class non-empty, remove
-     it now.  */
-  if (*empty_p)
-    {
-      tree *declp;
-
-      declp = &TYPE_FIELDS (t);
-      while (*declp != padding)
-       declp = &TREE_CHAIN (*declp);
-      *declp = TREE_CHAIN (*declp);
-    }
+  finish_record_layout (rli);
 
   /* Delete all zero-width bit-fields from the list of fields.  Now
      that the type is laid out they are no longer important.  */
@@ -4947,12 +4878,22 @@ layout_class_type (t, empty_p, has_virtual_p,
   /* Remember the size and alignment of the class before adding
      the virtual bases.  */
   if (*empty_p && flag_new_abi)
-    CLASSTYPE_SIZE (t) = integer_zero_node;
+    {
+      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))
-    CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
+    {
+      CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
+      CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
+    }
   else
-    CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
+    {
+      CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
+      CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
+    }
+
   CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
 
   /* Set the TYPE_DECL for this type to contain the right
@@ -4962,19 +4903,21 @@ layout_class_type (t, empty_p, has_virtual_p,
 
   /* Now fix up any virtual base class types that we left lying
      around.  We must get these done before we try to lay out the
-     virtual function table.  */
-  if (CLASSTYPE_N_BASECLASSES (t))
-    /* layout_basetypes will remove the base subobject fields.  */
-    layout_basetypes (t);
+     virtual function table.  As a side-effect, this will remove the
+     base subobject fields.  */
+  layout_virtual_bases (t, &v);
+
+  /* Clean up.  */
+  VARRAY_FREE (v);
 }
-     
+
 /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
    (or C++ class declaration).
 
    For C++, we must handle the building of derived classes.
    Also, C++ allows static class members.  The way that this is
    handled is to keep the field name where it is (as the DECL_NAME
-   of the field), and place the overloaded decl in the DECL_FIELD_BITPOS
+   of the field), and place the overloaded decl in the bit position
    of the field.  layout_record and layout_union will know about this.
 
    More C++ hair: inline functions have text in their
@@ -5000,7 +4943,7 @@ finish_struct_1 (t)
      tree t;
 {
   tree x;
-  int has_virtual;
+  int vfuns;
   /* The NEW_VIRTUALS is a TREE_LIST.  The TREE_VALUE of each node is
      a FUNCTION_DECL.  Each of these functions is a virtual function
      declared in T that does not override any virtual function from a
@@ -5014,7 +4957,7 @@ finish_struct_1 (t)
   tree vfield;
   int empty = 1;
 
-  if (TYPE_SIZE (t))
+  if (COMPLETE_TYPE_P (t))
     {
       if (IS_AGGR_TYPE (t))
        cp_error ("redefinition of `%#T'", t);
@@ -5031,7 +4974,7 @@ finish_struct_1 (t)
   TYPE_SIZE (t) = NULL_TREE;
   CLASSTYPE_GOT_SEMICOLON (t) = 0;
   CLASSTYPE_VFIELD_PARENT (t) = -1;
-  has_virtual = 0;
+  vfuns = 0;
   CLASSTYPE_RTTI (t) = NULL_TREE;
 
   /* Do end-of-class semantic processing: checking the validity of the
@@ -5039,45 +4982,9 @@ finish_struct_1 (t)
   check_bases_and_members (t, &empty);
 
   /* Layout the class itself.  */
-  layout_class_type (t, &empty, &has_virtual,
+  layout_class_type (t, &empty, &vfuns,
                     &new_virtuals, &overridden_virtuals);
 
-  if (TYPE_USES_VIRTUAL_BASECLASSES (t))
-    {
-      tree vbases;
-
-      vbases = CLASSTYPE_VBASECLASSES (t);
-
-      {
-       /* Now fixup overrides of all functions in vtables from all
-          direct or indirect virtual base classes.  */
-       tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
-       int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
-       for (i = 0; i < n_baseclasses; i++)
-         {
-           tree base_binfo = TREE_VEC_ELT (binfos, i);
-           tree basetype = BINFO_TYPE (base_binfo);
-           tree vbases;
-
-           vbases = CLASSTYPE_VBASECLASSES (basetype);
-           while (vbases)
-             {
-               tree vbase;
-               tree basetype_vbase;
-
-               vbase 
-                 = find_vbase_instance (BINFO_TYPE (vbases), t);
-               basetype_vbase 
-                 = find_vbase_instance (BINFO_TYPE (vbases), basetype);
-
-               merge_overrides (vbase, basetype_vbase, 1, t);
-               vbases = TREE_CHAIN (vbases);
-             }
-         }
-       }
-    }
-
   /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
      might need to know it for setting up the offsets in the vtable
      (or in thunks) below.  */
@@ -5086,45 +4993,27 @@ finish_struct_1 (t)
       && DECL_FIELD_CONTEXT (vfield) != t)
     {
       tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
-      tree offset = BINFO_OFFSET (binfo);
 
-      vfield = copy_node (vfield);
-      copy_lang_decl (vfield);
+      vfield = copy_decl (vfield);
 
-      if (! integer_zerop (offset))
-       offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT));
       DECL_FIELD_CONTEXT (vfield) = t;
-      DECL_CLASS_CONTEXT (vfield) = t;
-      DECL_FIELD_BITPOS (vfield)
-       = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield));
+      DECL_FIELD_OFFSET (vfield)
+       = size_binop (PLUS_EXPR,
+                     BINFO_OFFSET (binfo),
+                     DECL_FIELD_OFFSET (vfield));
       TYPE_VFIELD (t) = vfield;
     }
 
   overridden_virtuals 
-    = modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals));
+    = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
 
-  if (TYPE_USES_VIRTUAL_BASECLASSES (t))
-    {
-      tree vbases;
-      /* Now fixup any virtual function entries from virtual bases
-        that have different deltas.  This has to come after we do the
-        overridden virtuals.  */
-      vbases = CLASSTYPE_VBASECLASSES (t);
-      while (vbases)
-       {
-         tree vbase;
-
-         /* We might be able to shorten the amount of work we do by
-            only doing this for vtables that come from virtual bases
-            that have differing offsets, but don't want to miss any
-            entries.  */
-         vbase = find_vbase_instance (BINFO_TYPE (vbases), t);
-         dfs_walk (vbase, dfs_fixup_vtable_deltas, dfs_skip_vbases, t);
-         vbases = TREE_CHAIN (vbases);
-       }
-    }
+  /* 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 vtable for this class.  */
+  /* If necessary, create the primary vtable for this class.  */
   if (new_virtuals
       || overridden_virtuals
       || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))
@@ -5132,26 +5021,11 @@ finish_struct_1 (t)
       new_virtuals = nreverse (new_virtuals);
       /* We must enter these virtuals into the table.  */
       if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-       {
-         if (! CLASSTYPE_COM_INTERFACE (t))
-           {
-             /* The second slot is for the tdesc pointer when thunks
-                are used.  */
-             if (flag_vtable_thunks)
-               new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
-
-             /* The first slot is for the rtti offset.  */
-             new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
-
-             set_rtti_entry (new_virtuals,
-                             convert (ssizetype, integer_zero_node), t);
-           }
-         build_vtable (NULL_TREE, t);
-       }
-      else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
+       build_primary_vtable (NULL_TREE, t);
+      else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
        /* Here we know enough to change the type of our virtual
           function table, but we will wait until later this function.  */
-       build_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
+       build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
 
       /* If this type has basetypes with constructors, then those
         constructors might clobber the virtual function table.  But
@@ -5190,7 +5064,7 @@ finish_struct_1 (t)
        my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
                            20000116);
 
-      CLASSTYPE_VSIZE (t) = has_virtual;
+      CLASSTYPE_VSIZE (t) = vfuns;
       /* Entries for virtual functions defined in the primary base are
         followed by entries for new functions unique to this class.  */
       TYPE_BINFO_VIRTUALS (t) 
@@ -5201,16 +5075,6 @@ finish_struct_1 (t)
        = chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
     }
 
-  /* Now lay out the virtual function table.  */
-  if (has_virtual)
-    layout_vtable_decl (TYPE_BINFO (t), has_virtual);
-
-  /* If we created a new vtbl pointer for this class, add it to the
-     list.  */
-  if (TYPE_VFIELD (t) && CLASSTYPE_VFIELD_PARENT (t) == -1)
-    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
@@ -5260,7 +5124,13 @@ finish_struct_1 (t)
        }
     }
 
-  if (CLASSTYPE_VSIZE (t) != 0)
+  /* 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))
     {
       /* In addition to this one, all the other vfields should be listed.  */
       /* Before that can be done, we have to have FIELD_DECLs for them, and
@@ -5275,9 +5145,6 @@ finish_struct_1 (t)
                    t);
     }
 
-  /* Make the rtl for any new vtables we have created, and unmark
-     the base types we marked.  */
-  finish_vtbls (t);
   hack_incomplete_structures (t);
 
   if (warn_overloaded_virtual)
@@ -5337,7 +5204,7 @@ finish_struct (t, attributes)
   if (processing_template_decl)
     {
       finish_struct_methods (t);
-      TYPE_SIZE (t) = integer_zero_node;
+      TYPE_SIZE (t) = bitsize_zero_node;
     }
   else
     finish_struct_1 (t);
@@ -5488,7 +5355,7 @@ resolves_to_fixed_type_p (instance, nonnull)
     return 0;
   if (POINTER_TYPE_P (t))
     t = TREE_TYPE (t);
-  return same_type_p (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (fixed));
+  return same_type_ignoring_top_level_qualifiers_p (t, fixed);
 }
 
 \f
@@ -5500,15 +5367,17 @@ 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 (1, 0);
-  access_protected_node = build_int_2 (2, 0);
-  access_private_node = build_int_2 (3, 0);
+  access_public_node = build_int_2 (ak_public, 0);
+  access_protected_node = build_int_2 (ak_protected, 0);
+  access_private_node = build_int_2 (ak_private, 0);
   access_default_virtual_node = build_int_2 (4, 0);
-  access_public_virtual_node = build_int_2 (5, 0);
-  access_protected_virtual_node = build_int_2 (6, 0);
-  access_private_virtual_node = build_int_2 (7, 0);
+  access_public_virtual_node = build_int_2 (4 | ak_public, 0);
+  access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
+  access_private_virtual_node = build_int_2 (4 | ak_private, 0);
 }
 
 /* Set current scope to NAME. CODE tells us if this is a
@@ -5583,7 +5452,7 @@ pushclass (type, modify)
 
   if (previous_class_type != NULL_TREE
       && (type != previous_class_type 
-         || TYPE_SIZE (previous_class_type) == NULL_TREE)
+         || !COMPLETE_TYPE_P (previous_class_type))
       && current_class_depth == 1)
     {
       /* Forcibly remove any old class remnants.  */
@@ -5670,7 +5539,9 @@ popclass ()
     splay_tree_delete (current_class_stack[current_class_depth].names_used);
 }
 
-/* Returns 1 if current_class_type is either T or a nested type of T.  */
+/* Returns 1 if current_class_type is either T or a nested type of T.
+   We start looking from 1 because entry 0 is from global scope, and has
+   no type.  */
 
 int
 currently_open_class (t)
@@ -5679,12 +5550,32 @@ currently_open_class (t)
   int i;
   if (t == current_class_type)
     return 1;
-  for (i = 0; i < current_class_depth; ++i)
+  for (i = 1; i < current_class_depth; ++i)
     if (current_class_stack [i].type == t)
       return 1;
   return 0;
 }
 
+/* If either current_class_type or one of its enclosing classes are derived
+   from T, return the appropriate type.  Used to determine how we found
+   something via unqualified lookup.  */
+
+tree
+currently_open_derived_class (t)
+     tree t;
+{
+  int i;
+
+  if (DERIVED_FROM_P (t, current_class_type))
+    return current_class_type;
+
+  for (i = current_class_depth - 1; i > 0; --i)
+    if (DERIVED_FROM_P (t, current_class_stack[i].type))
+      return current_class_stack[i].type;
+
+  return NULL_TREE;
+}
+
 /* When entering a class scope, all enclosing class scopes' names with
    static meaning (static variables, static functions, types and enumerators)
    have to be visible.  This recursive function calls pushclass for all
@@ -5853,6 +5744,9 @@ resolve_address_of_overloaded_function (target_type,
                        && (TREE_CODE (TREE_TYPE (target_type)) 
                            == METHOD_TYPE)), 0);
 
+  if (TREE_CODE (overload) == COMPONENT_REF)
+    overload = TREE_OPERAND (overload, 1);
+
   /* Check that the TARGET_TYPE is reasonable.  */
   if (TYPE_PTRFN_P (target_type))
     /* This is OK.  */
@@ -5917,6 +5811,7 @@ resolve_address_of_overloaded_function (target_type,
     {
       tree target_fn_type;
       tree target_arg_types;
+      tree target_ret_type;
       tree fns;
 
       if (is_ptrmem)
@@ -5925,6 +5820,7 @@ resolve_address_of_overloaded_function (target_type,
       else
        target_fn_type = TREE_TYPE (target_type);
       target_arg_types = TYPE_ARG_TYPES (target_fn_type);
+      target_ret_type = TREE_TYPE (target_fn_type);
          
       for (fns = overload; fns; fns = OVL_CHAIN (fns))
        {
@@ -5946,7 +5842,7 @@ resolve_address_of_overloaded_function (target_type,
          /* Try to do argument deduction.  */
          targs = make_tree_vec (DECL_NTPARMS (fn));
          if (fn_type_unification (fn, explicit_targs, targs,
-                                  target_arg_types, NULL_TREE,
+                                  target_arg_types, target_ret_type,
                                   DEDUCE_EXACT) != 0)
            /* Argument deduction failed.  */
            continue;
@@ -6060,6 +5956,7 @@ instantiate_type (lhstype, rhs, flags)
 {
   int complain = (flags & 1);
   int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
+  tree r;
 
   if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
     {
@@ -6120,8 +6017,9 @@ instantiate_type (lhstype, rhs, flags)
 
     case COMPONENT_REF:
       {
-       tree r = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+       r = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
 
+      comp:
        if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype)
            && complain && !flag_ms_extensions)
          {
@@ -6156,12 +6054,23 @@ instantiate_type (lhstype, rhs, flags)
       /* Fall through.  */
 
     case TEMPLATE_ID_EXPR:
-      return 
-       resolve_address_of_overloaded_function (lhstype,
-                                               TREE_OPERAND (rhs, 0),
-                                               complain,
-                                               /*template_only=*/1,
-                                               TREE_OPERAND (rhs, 1));
+      {
+       tree fns = TREE_OPERAND (rhs, 0);
+       tree args = TREE_OPERAND (rhs, 1);
+
+       r =
+         resolve_address_of_overloaded_function (lhstype,
+                                                 fns,
+                                                 complain,
+                                                 /*template_only=*/1,
+                                                 args);
+       if (TREE_CODE (fns) == COMPONENT_REF)
+         {
+           rhs = fns;
+           goto comp;
+         }
+       return r;
+      }
 
     case OVERLOAD:
       return 
@@ -6352,7 +6261,6 @@ build_self_reference ()
 
   DECL_NONLOCAL (value) = 1;
   DECL_CONTEXT (value) = current_class_type;
-  DECL_CLASS_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
 
   if (processing_template_decl)
@@ -6379,7 +6287,7 @@ is_empty_class (type)
     return 0;
 
   if (flag_new_abi)
-    return CLASSTYPE_SIZE (type) == integer_zero_node;
+    return integer_zerop (CLASSTYPE_SIZE (type));
 
   if (TYPE_BINFO_BASETYPES (type))
     return 0;
@@ -6491,17 +6399,41 @@ note_name_declared_in_class (name, decl)
         S.  */
       cp_error ("declaration of `%#D'", decl);
       cp_error_at ("changes meaning of `%s' from `%+#D'", 
-                  IDENTIFIER_POINTER (DECL_NAME (decl)),
+                  IDENTIFIER_POINTER (DECL_NAME (OVL_CURRENT (decl))),
                   (tree) n->value);
     }
 }
 
-/* Dump the offsets of all the bases rooted at BINFO to stderr.
-   INDENT should be zero when called from the top level; it is
-   incremented recursively.  */
+/* Returns the VAR_DECL for the complete vtable associated with
+   BINFO.  (Under the new ABI, secondary vtables are merged with
+   primary vtables; this function will return the VAR_DECL for the
+   primary vtable.)  */
 
-void
-dump_class_hierarchy (binfo, indent)
+tree
+get_vtbl_decl_for_binfo (binfo)
+     tree binfo;
+{
+  tree decl;
+
+  decl = BINFO_VTABLE (binfo);
+  if (decl && TREE_CODE (decl) == PLUS_EXPR)
+    {
+      my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
+                         2000403);
+      decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
+    }
+  if (decl)
+    my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
+  return decl;
+}
+
+/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
+   dominated by T) to stderr.  INDENT should be zero when called from
+   the top level; it is incremented recursively.  */
+
+static void
+dump_class_hierarchy_r (t, binfo, indent)
+     tree t;
      tree binfo;
      int indent;
 {
@@ -6511,10 +6443,990 @@ dump_class_hierarchy (binfo, indent)
           (unsigned long) binfo,
           type_as_string (binfo, TS_PLAIN));
   fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
-          TREE_INT_CST_LOW (BINFO_OFFSET (binfo)));
-  fprintf (stderr, " %s\n",
-          BINFO_PRIMARY_MARKED_P (binfo) ? "primary" : "");
+          tree_low_cst (BINFO_OFFSET (binfo), 0));
+  if (TREE_VIA_VIRTUAL (binfo))
+    fprintf (stderr, " virtual");
+  if (BINFO_PRIMARY_MARKED_P (binfo)
+      || (TREE_VIA_VIRTUAL (binfo) 
+         && BINFO_VBASE_PRIMARY_P (binfo_for_vbase (BINFO_TYPE (binfo), 
+                                                    t))))
+    fprintf (stderr, " primary");
+  fprintf (stderr, "\n");
 
   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
-    dump_class_hierarchy (BINFO_BASETYPE (binfo, i), indent + 2);
+    dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
+}
+
+/* Dump the BINFO hierarchy for T.  */
+
+void
+dump_class_hierarchy (t)
+     tree t;
+{
+  dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
+}
+
+/* Virtual function table initialization.  */
+
+/* Create all the necessary vtables for T and its base classes.  */
+
+static void
+finish_vtbls (t)
+     tree t;
+{
+  if (merge_primary_and_secondary_vtables_p ())
+    {
+      tree list;
+      tree vbase;
+
+      /* Under the new ABI, we lay out the primary and secondary
+        vtables in one contiguous vtable.  The primary vtable is
+        first, followed by the non-virtual secondary vtables in
+        inheritance graph order.  */
+      list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
+      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 (vbase, vbase, TYPE_BINFO (t), t, list);
+       }
+
+      if (TYPE_BINFO_VTABLE (t))
+       initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
+    }
+  else
+    {
+      dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, 
+               dfs_unmarked_real_bases_queue_p, t);
+      dfs_walk (TYPE_BINFO (t), dfs_unmark, 
+               dfs_marked_real_bases_queue_p, t);
+    }
+}
+
+/* Called from finish_vtbls via dfs_walk.  */
+
+static tree
+dfs_finish_vtbls (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree t = (tree) data;
+
+  if (BINFO_NEW_VTABLE_MARKED (binfo, t))
+    initialize_vtable (binfo, 
+                      build_vtbl_initializer (binfo, binfo, t, 
+                                              TYPE_BINFO (t), NULL));
+
+  SET_BINFO_MARKED (binfo);
+
+  return NULL_TREE;
+}
+
+/* Initialize the vtable for BINFO with the INITS.  */
+
+static void
+initialize_vtable (binfo, inits)
+     tree binfo;
+     tree inits;
+{
+  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) = 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.  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, 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.  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).  Returns the initializers for the BINFO vtable.  */
+
+static tree
+dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
+     tree binfo;
+     tree orig_binfo;
+     tree rtti_binfo;
+     tree t;
+     tree l;
+{
+  tree inits = NULL_TREE;
+  int ctor_vtbl_p;
+
+  /* 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_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 vtbl;
+      tree index;
+      int non_fn_entries;
+
+      /* Compute the initializer for this vtable.  */
+      inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
+                                     &non_fn_entries);
+
+      /* Figure out the position to which the VPTR should point.  */
+      vtbl = TREE_PURPOSE (l);
+      vtbl = build1 (ADDR_EXPR, 
+                    vtbl_ptr_type_node,
+                    vtbl);
+      index = size_binop (PLUS_EXPR,
+                         size_int (non_fn_entries),
+                         size_int (list_length (TREE_VALUE (l))));
+      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));
+    }
+
+  return inits;
+}
+
+/* Construct the initializer for BINFOs virtual function table.  BINFO
+   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, 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;
+  tree 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.primary_p = (binfo == TYPE_BINFO (t));
+  /* The first vbase or vcall offset is at index -3 in the vtable.  */
+  vod.index = build_int_2 (-3, -1);
+
+  /* Add the vcall and vbase offset entries.  */
+  build_vcall_and_vbase_vtbl_entries (binfo, &vod);
+  inits = vod.inits;
+  /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+     build_vbase_offset_vtbl_entries.  */
+  for (vbase = CLASSTYPE_VBASECLASSES (t); 
+       vbase; 
+       vbase = TREE_CHAIN (vbase))
+    CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
+
+  /* Add entries to the vtable for RTTI.  */
+  inits = chainon (inits, build_rtti_vtbl_entries (binfo, rtti_binfo));
+
+  if (non_fn_entries_p)
+    *non_fn_entries_p = list_length (inits);
+
+  /* Go through all the ordinary virtual functions, building up
+     initializers.  */
+  vfun_inits = NULL_TREE;
+  for (v = BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
+    {
+      tree delta;
+      tree vcall_index;
+      tree fn;
+      tree pfn;
+      tree init;
+
+      /* Pull the offset for `this', and the function to call, out of
+        the list.  */
+      delta = BV_DELTA (v);
+      vcall_index = BV_VCALL_INDEX (v);
+      fn = BV_FN (v);
+      my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
+      my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
+
+      /* You can't call an abstract virtual function; it's abstract.
+        So, we replace these functions with __pure_virtual.  */
+      if (DECL_PURE_VIRTUAL_P (fn))
+       fn = abort_fndecl;
+
+      /* Take the address of the function, considering it to be of an
+        appropriate generic type.  */
+      pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
+      /* The address of a function can't change.  */
+      TREE_CONSTANT (pfn) = 1;
+      /* Enter it in the vtable.  */
+      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);
+    }
+
+  /* The initializers for virtual functions were built up in reverse
+     order; straighten them out now.  */
+  vfun_inits = nreverse (vfun_inits);
+  
+  /* The complete initializer is the INITS, followed by the
+     VFUN_INITS.  */
+  return chainon (inits, vfun_inits);
+}
+
+/* Sets vod->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)
+     tree binfo;
+     vcall_offset_data *vod;
+{
+  tree b;
+  tree inits;
+
+  /* If this is a derived class, we must first create entries
+     corresponding to the base class.  These entries must go closer to
+     the vptr, so we save them up and add them to the end of the list
+     later.  */
+  inits = vod->inits;
+  vod->inits = NULL_TREE;
+  b = BINFO_PRIMARY_BINFO (binfo);
+  if (b)
+    build_vcall_and_vbase_vtbl_entries (b, vod);
+
+  /* Add the vbase entries for this base.  */
+  build_vbase_offset_vtbl_entries (binfo, vod);
+  /* Add the vcall entries for this base.  */
+  build_vcall_offset_vtbl_entries (binfo, vod);
+
+  vod->inits = chainon (vod->inits, inits);
+}
+
+/* Returns the initializers for the vbase offset entries in the vtable
+   for BINFO (which is part of the class hierarchy dominated by T), in
+   reverse order.  VBASE_OFFSET_INDEX gives the vtable index
+   where the next vbase offset will go.  */
+
+static void
+build_vbase_offset_vtbl_entries (binfo, vod)
+     tree binfo;
+     vcall_offset_data *vod;
+{
+  tree vbase;
+  tree t;
+
+  /* Under the old ABI, pointers to virtual bases are stored in each
+     object.  */
+  if (!vbase_offsets_in_vtable_p ())
+    return;
+
+  /* If there are no virtual baseclasses, then there is nothing to
+     do.  */
+  if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+    return;
+
+  t = vod->derived;
+
+  /* Go through the virtual bases, adding the offsets.  */
+  for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
+       vbase;
+       vbase = TREE_CHAIN (vbase))
+    {
+      tree b;
+      tree delta;
+      
+      if (!TREE_VIA_VIRTUAL (vbase))
+       continue;
+
+      /* Find the instance of this virtual base in the complete
+        object.  */
+      b = binfo_for_vbase (BINFO_TYPE (vbase), t);
+
+      /* If we've already got an offset for this virtual base, we
+        don't need another one.  */
+      if (BINFO_VTABLE_PATH_MARKED (b))
+       continue;
+      SET_BINFO_VTABLE_PATH_MARKED (b);
+
+      /* Figure out where we can find this vbase offset.  */
+      delta = size_binop (MULT_EXPR, 
+                         convert (ssizetype, vod->index),
+                         convert (ssizetype,
+                                  TYPE_SIZE_UNIT (vtable_entry_type)));
+      if (vod->primary_p)
+       BINFO_VPTR_FIELD (b) = delta;
+
+      if (binfo != TYPE_BINFO (t))
+       {
+         tree orig_vbase;
+
+         /* Find the instance of this virtual base in the type of BINFO.  */
+         orig_vbase = binfo_for_vbase (BINFO_TYPE (vbase),
+                                       BINFO_TYPE (binfo));
+
+         /* The vbase offset had better be the same.  */
+         if (!tree_int_cst_equal (delta,
+                                  BINFO_VPTR_FIELD (orig_vbase)))
+           my_friendly_abort (20000403);
+       }
+
+      /* The next vbase will come at a more negative offset.  */
+      vod->index = fold (build (MINUS_EXPR, integer_type_node,
+                               vod->index, integer_one_node));
+
+      /* The initializer is the delta from BINFO to this virtual base.
+        The vbase offsets go in reverse inheritance-graph order, and
+        we are walking in inheritance graph order so these end up in
+        the right order.  */
+      delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
+      vod->inits = tree_cons (NULL_TREE, 
+                             fold (build1 (NOP_EXPR, 
+                                           vtable_entry_type,
+                                           delta)),
+                             vod->inits);
+    }
+}
+
+/* Called from build_vcall_offset_vtbl_entries via dfs_walk.  */
+
+static tree
+dfs_build_vcall_offset_vtbl_entries (binfo, data)
+     tree binfo;
+     void *data;
+{
+  vcall_offset_data* vod;
+  tree derived_virtuals;
+  tree base_virtuals;
+  tree binfo_inits;
+  tree non_primary_binfo;
+  tree b;
+  int i;
+
+  vod = (vcall_offset_data *) data;
+  binfo_inits = NULL_TREE;
+
+  /* We might be a primary base class.  Go up the inheritance
+     hierarchy until we find the class of which we are a primary base:
+     it is the BINFO_VIRTUALS there that we need to consider.  */
+  non_primary_binfo = binfo;
+  while (BINFO_PRIMARY_MARKED_P (non_primary_binfo))
+    non_primary_binfo = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+
+  /* Skip virtuals that we have already handled in a primary base
+     class.  */
+  base_virtuals = BINFO_VIRTUALS (binfo);
+  derived_virtuals = BINFO_VIRTUALS (non_primary_binfo);
+  b = BINFO_PRIMARY_BINFO (binfo);
+  if (b)
+    for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (b)); ++i)
+      {
+       base_virtuals = TREE_CHAIN (base_virtuals);
+       derived_virtuals = TREE_CHAIN (derived_virtuals);
+      }
+
+  /* Make entries for the rest of the virtuals.  */
+  while (base_virtuals)
+    {
+      /* Figure out what function we're looking at.  */
+      tree fn = TREE_VALUE (derived_virtuals);
+      tree base = DECL_CONTEXT (fn);
+      /* The FN comes from BASE.  So, we must caculate the adjustment
+        from the virtual base that derived from BINFO to BASE.  */
+      tree base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
+
+      /* Compute the vcall offset.  */
+      binfo_inits
+       = tree_cons (NULL_TREE,
+                    fold (build1 (NOP_EXPR, vtable_entry_type,
+                                  size_diffop (BINFO_OFFSET (base_binfo),
+                                               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.  */
+      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,
+                               vod->index, integer_one_node));
+
+      /* Go to the next entries in the list.  */
+      derived_virtuals = TREE_CHAIN (derived_virtuals);
+      base_virtuals = TREE_CHAIN (base_virtuals);
+    }
+
+  /* The offests are built up in reverse order, so we straighten them
+     here.  We simultaneously add them to VOD->INITS; we're walking
+     the bases in inheritance graph order, and the initializers are
+     supposed to appear in reverse inheritance order, so that's
+     correct.  */
+  while (binfo_inits)
+    {
+      tree next;
+
+      next = TREE_CHAIN (binfo_inits);
+      TREE_CHAIN (binfo_inits) = vod->inits;
+      vod->inits = binfo_inits;
+      binfo_inits = next;
+    }
+
+  return NULL_TREE;
+}
+
+/* Adds the initializers for the vcall offset entries in the vtable
+   for BINFO (which is part of the class hierarchy dominated by T) to
+   VOD->INITS.  */
+
+static void
+build_vcall_offset_vtbl_entries (binfo, vod)
+     tree binfo;
+     vcall_offset_data *vod;
+{
+  tree inits;
+
+  /* Under the old ABI, the adjustments to the `this' pointer were made
+     elsewhere.  */
+  if (!vcall_offsets_in_vtable_p ())
+    return;
+
+  /* We only need these entries if this base is a virtual base.  */
+  if (!TREE_VIA_VIRTUAL (binfo))
+    return;
+
+  /* We need a vcall offset for each of the virtual functions in this
+     vtable.  For example:
+
+       class A { virtual void f (); };
+       class B : virtual public A { };
+       class C: virtual public A, public B {};
+      
+     Now imagine:
+
+       B* b = new C;
+       b->f();
+
+     The location of `A' is not at a fixed offset relative to `B'; the
+     offset depends on the complete object derived from `B'.  So, 
+     `B' vtable contains an entry for `f' that indicates by what
+     amount the `this' pointer for `B' needs to be adjusted to arrive
+     at `A'.  
+
+     We need entries for all the functions in our primary vtable and
+     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;
+  inits = vod->inits;
+  vod->inits = NULL_TREE;
+  dfs_walk_real (binfo,
+                dfs_build_vcall_offset_vtbl_entries,
+                NULL,
+                dfs_skip_vbases,
+                vod);
+  vod->inits = chainon (vod->inits, inits);
+}
+
+/* Return vtbl initializers for the RTTI entries coresponding to the
+   BINFO's vtable.  The RTTI entries should indicate the object given
+   by RTTI_BINFO.  */
+
+static tree
+build_rtti_vtbl_entries (binfo, rtti_binfo)
+     tree binfo;
+     tree rtti_binfo;
+{
+  tree b;
+  tree t;
+  tree basetype;
+  tree offset;
+  tree decl;
+  tree init;
+  tree inits;
+
+  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))
+    return inits;
+
+  /* To find the complete object, we will first convert to our most
+     primary base, and then add the offset in the vtbl to that value.  */
+  b = binfo;
+  while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)))
+    {
+      tree primary_base;
+
+      primary_base = BINFO_PRIMARY_BINFO (b);
+      if (!BINFO_PRIMARY_MARKED_P (primary_base))
+       break;
+      b = primary_base;
+    }
+  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
+     which returns a typeinfo object.  */
+  if (new_abi_rtti_p ())
+    {
+      if (flag_rtti)
+       decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
+      else
+       decl = integer_zero_node;
+
+      /* Convert the declaration to a type that can be stored in the
+        vtable.  */
+      init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
+      TREE_CONSTANT (init) = 1;
+    }
+  else
+    {
+      if (flag_rtti)
+       decl = get_tinfo_decl (t);
+      else
+       decl = abort_fndecl;
+
+      /* Convert the declaration to a type that can be stored in the
+        vtable.  */
+      init = build1 (ADDR_EXPR, vfunc_ptr_type_node, decl);
+      TREE_CONSTANT (init) = 1;
+      init = build_vtable_entry (offset, integer_zero_node, init);
+    }
+  inits = tree_cons (NULL_TREE, init, inits);
+
+  /* Add the offset-to-top entry.  It comes earlier in the vtable that
+     the the typeinfo entry.  */
+  if (flag_vtable_thunks)
+    {
+      /* Convert the offset to look like a function pointer, so that
+        we can put it in the vtable.  */
+      init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+      TREE_CONSTANT (init) = 1;
+      inits = tree_cons (NULL_TREE, init, inits);
+    }
+
+  return inits;
+}
+
+/* Build an entry in the virtual function table.  DELTA is the offset
+   for the `this' pointer.  VCALL_INDEX is the vtable index containing
+   the vcall offset; zero if none.  ENTRY is the virtual function
+   table entry itself.  It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
+   but it may not actually be a virtual function table pointer.  (For
+   example, it might be the address of the RTTI object, under the new
+   ABI.)  */
+
+static tree
+build_vtable_entry (delta, vcall_index, entry)
+     tree delta;
+     tree vcall_index;
+     tree entry;
+{
+  if (!vcall_index)
+    vcall_index = integer_zero_node;
+
+  if (flag_vtable_thunks)
+    {
+      HOST_WIDE_INT idelta;
+      HOST_WIDE_INT ivindex;
+      tree fn;
+
+      idelta = tree_low_cst (delta, 0);
+      ivindex = tree_low_cst (vcall_index, 0);
+      fn = TREE_OPERAND (entry, 0);
+      if ((idelta || ivindex) 
+         && fn != abort_fndecl
+         && !DECL_TINFO_FN_P (fn))
+       {
+         entry = make_thunk (entry, idelta, ivindex);
+         entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
+         TREE_READONLY (entry) = 1;
+         TREE_CONSTANT (entry) = 1;
+       }
+#ifdef GATHER_STATISTICS
+      n_vtable_entries += 1;
+#endif
+      return entry;
+    }
+  else
+    {
+      tree elems = tree_cons (NULL_TREE, delta,
+                             tree_cons (NULL_TREE, integer_zero_node,
+                                        build_tree_list (NULL_TREE, entry)));
+      tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
+
+      /* We don't use vcall offsets when not using vtable thunks.  */
+      my_friendly_assert (integer_zerop (vcall_index), 20000125);
+
+      /* DELTA used to be constructed by `size_int' and/or size_binop,
+        which caused overflow problems when it was negative.  That should
+        be fixed now.  */
+
+      if (! int_fits_type_p (delta, delta_type_node))
+       {
+         if (flag_huge_objects)
+           sorry ("object size exceeds built-in limit for virtual function table implementation");
+         else
+           sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
+       }
+      
+      TREE_CONSTANT (entry) = 1;
+      TREE_STATIC (entry) = 1;
+      TREE_READONLY (entry) = 1;
+
+#ifdef GATHER_STATISTICS
+      n_vtable_entries += 1;
+#endif
+
+      return entry;
+    }
 }