OSDN Git Service

* tree.h (build_int_cst): New, sign extended constant.
[pf3gnuchains/gcc-fork.git] / gcc / cp / class.c
index a224676..bd0d3f5 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions related to building classes and their related objects.
    Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003  Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -33,7 +33,6 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "output.h"
 #include "toplev.h"
-#include "lex.h"
 #include "target.h"
 #include "convert.h"
 
@@ -114,8 +113,6 @@ static int build_primary_vtable (tree, tree);
 static int build_secondary_vtable (tree);
 static void finish_vtbls (tree);
 static void modify_vtable_entry (tree, tree, tree, tree, tree *);
-static tree delete_duplicate_fields_1 (tree, tree);
-static void delete_duplicate_fields (tree);
 static void finish_struct_bits (tree);
 static int alter_access (tree, tree, tree);
 static void handle_using_decl (tree, tree);
@@ -129,8 +126,9 @@ static int method_name_cmp (const void *, const void *);
 static int resort_method_name_cmp (const void *, const void *);
 static void add_implicitly_declared_members (tree, int, int, int);
 static tree fixed_type_or_null (tree, int *, int *);
-static tree resolve_address_of_overloaded_function (tree, tree, int,
-                                                         int, int, tree);
+static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t,
+                                                   bool, tree);
+static tree build_simple_base_path (tree expr, tree binfo);
 static tree build_vtbl_ref_1 (tree, tree);
 static tree build_vtbl_initializer (tree, tree, tree, tree, int *);
 static int count_fields (tree);
@@ -166,9 +164,11 @@ static int make_new_vtable (tree, tree);
 static int maybe_indent_hierarchy (FILE *, int, int);
 static tree dump_class_hierarchy_r (FILE *, int, tree, tree, int);
 static void dump_class_hierarchy (tree);
+static void dump_class_hierarchy_1 (FILE *, int, tree);
 static void dump_array (FILE *, tree);
 static void dump_vtable (tree, tree, tree);
 static void dump_vtt (tree, tree);
+static void dump_thunk (FILE *, int, tree);
 static tree build_vtable (tree, tree, tree);
 static void initialize_vtable (tree, tree);
 static void initialize_array (tree, tree);
@@ -213,7 +213,7 @@ static tree get_vcall_index (tree, tree);
 /* Macros for dfs walking during vtt construction. See
    dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
    and dfs_fixup_binfo_vtbls.  */
-#define VTT_TOP_LEVEL_P(NODE) TREE_UNSIGNED (NODE)
+#define VTT_TOP_LEVEL_P(NODE) (TREE_LIST_CHECK (NODE)->common.unsigned_flag)
 #define VTT_MARKED_BINFO_P(NODE) TREE_USED (NODE)
 
 /* Variables shared between class.c and call.c.  */
@@ -225,7 +225,6 @@ int n_vtable_searches = 0;
 int n_vtable_elems = 0;
 int n_convert_harshness = 0;
 int n_compute_conversion_costs = 0;
-int n_build_method_call = 0;
 int n_inner_fields_searched = 0;
 #endif
 
@@ -254,6 +253,8 @@ build_base_path (enum tree_code code,
   tree ptr_target_type;
   int fixed_type_p;
   int want_pointer = TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE;
+  bool has_empty = false;
+  bool virtual_access;
 
   if (expr == error_mark_node || binfo == error_mark_node || !binfo)
     return error_mark_node;
@@ -261,20 +262,26 @@ build_base_path (enum tree_code code,
   for (probe = binfo; probe; probe = BINFO_INHERITANCE_CHAIN (probe))
     {
       d_binfo = probe;
-      if (!v_binfo && TREE_VIA_VIRTUAL (probe))
+      if (is_empty_class (BINFO_TYPE (probe)))
+       has_empty = true;
+      if (!v_binfo && BINFO_VIRTUAL_P (probe))
        v_binfo = probe;
     }
 
   probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
   if (want_pointer)
     probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe));
-  
+
   my_friendly_assert (code == MINUS_EXPR
                      ? same_type_p (BINFO_TYPE (binfo), probe)
                      : code == PLUS_EXPR
                      ? same_type_p (BINFO_TYPE (d_binfo), probe)
                      : false, 20010723);
   
+  if (binfo == d_binfo)
+    /* Nothing to do.  */
+    return expr;
+
   if (code == MINUS_EXPR && v_binfo)
     {
       error ("cannot convert from base `%T' to derived type `%T' via virtual base `%T'",
@@ -286,16 +293,40 @@ build_base_path (enum tree_code code,
     /* This must happen before the call to save_expr.  */
     expr = build_unary_op (ADDR_EXPR, expr, 0);
 
+  offset = BINFO_OFFSET (binfo);
   fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
-  if (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
+
+  /* Do we need to look in the vtable for the real offset?  */
+  virtual_access = (v_binfo && fixed_type_p <= 0);
+
+  /* Do we need to check for a null pointer?  */
+  if (want_pointer && !nonnull && (virtual_access || !integer_zerop (offset)))
+    null_test = error_mark_node;
+
+  /* Protect against multiple evaluation if necessary.  */
+  if (TREE_SIDE_EFFECTS (expr) && (null_test || virtual_access))
     expr = save_expr (expr);
 
-  if (want_pointer && !nonnull)
-    null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node);
-  
-  offset = BINFO_OFFSET (binfo);
-  
-  if (v_binfo && fixed_type_p <= 0)
+  /* Now that we've saved expr, build the real null test.  */
+  if (null_test)
+    null_test = fold (build2 (NE_EXPR, boolean_type_node,
+                             expr, integer_zero_node));
+
+  /* If this is a simple base reference, express it as a COMPONENT_REF.  */
+  if (code == PLUS_EXPR && !virtual_access
+      /* We don't build base fields for empty bases, and they aren't very
+        interesting to the optimizers anyway.  */
+      && !has_empty)
+    {
+      expr = build_indirect_ref (expr, NULL);
+      expr = build_simple_base_path (expr, binfo);
+      if (want_pointer)
+       expr = build_unary_op (ADDR_EXPR, expr, 0);
+      target_type = TREE_TYPE (expr);
+      goto out;
+    }
+
+  if (virtual_access)
     {
       /* Going via virtual base V_BINFO.  We need the static offset
          from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
@@ -307,43 +338,44 @@ build_base_path (enum tree_code code,
          /* In a base member initializer, we cannot rely on
             the vtable being set up. We have to use the vtt_parm.  */
          tree derived = BINFO_INHERITANCE_CHAIN (v_binfo);
-         
-         v_offset = build (PLUS_EXPR, TREE_TYPE (current_vtt_parm),
-                           current_vtt_parm, BINFO_VPTR_INDEX (derived));
-         
-         v_offset = build1 (INDIRECT_REF,
-                            TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))),
-                            v_offset);
-         
+         tree t;
+
+         t = TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived)));
+         t = build_pointer_type (t);
+         v_offset = convert (t, current_vtt_parm);
+         v_offset = build2 (PLUS_EXPR, t, v_offset,
+                            BINFO_VPTR_INDEX (derived));
+         v_offset = build_indirect_ref (v_offset, NULL);
        }
       else
        v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
                                     TREE_TYPE (TREE_TYPE (expr)));
       
-      v_offset = build (PLUS_EXPR, TREE_TYPE (v_offset),
-                       v_offset,  BINFO_VPTR_FIELD (v_binfo));
+      v_offset = build2 (PLUS_EXPR, TREE_TYPE (v_offset),
+                        v_offset,  BINFO_VPTR_FIELD (v_binfo));
       v_offset = build1 (NOP_EXPR, 
                         build_pointer_type (ptrdiff_type_node),
                         v_offset);
       v_offset = build_indirect_ref (v_offset, NULL);
       TREE_CONSTANT (v_offset) = 1;
+      TREE_INVARIANT (v_offset) = 1;
 
       offset = convert_to_integer (ptrdiff_type_node,
                                   size_diffop (offset, 
                                                BINFO_OFFSET (v_binfo)));
 
       if (!integer_zerop (offset))
-       v_offset = build (code, ptrdiff_type_node, v_offset, offset);
+       v_offset = build2 (code, ptrdiff_type_node, v_offset, offset);
 
       if (fixed_type_p < 0)
        /* Negative fixed_type_p means this is a constructor or destructor;
           virtual base layout is fixed in in-charge [cd]tors, but not in
           base [cd]tors.  */
-       offset = build (COND_EXPR, ptrdiff_type_node,
-                       build (EQ_EXPR, boolean_type_node,
-                              current_in_charge_parm, integer_zero_node),
-                       v_offset,
-                       BINFO_OFFSET (binfo));
+       offset = build3 (COND_EXPR, ptrdiff_type_node,
+                        build2 (EQ_EXPR, boolean_type_node,
+                                current_in_charge_parm, integer_zero_node),
+                        v_offset,
+                        BINFO_OFFSET (binfo));
       else
        offset = v_offset;
     }
@@ -359,21 +391,63 @@ build_base_path (enum tree_code code,
   expr = build1 (NOP_EXPR, ptr_target_type, expr);
 
   if (!integer_zerop (offset))
-    expr = build (code, ptr_target_type, expr, offset);
+    expr = build2 (code, ptr_target_type, expr, offset);
   else
     null_test = NULL;
   
   if (!want_pointer)
     expr = build_indirect_ref (expr, NULL);
 
+ out:
   if (null_test)
-    expr = build (COND_EXPR, target_type, null_test,
-                 build1 (NOP_EXPR, target_type, integer_zero_node),
-                 expr);
+    expr = fold (build3 (COND_EXPR, target_type, null_test, expr,
+                        fold (build1 (NOP_EXPR, target_type,
+                                      integer_zero_node))));
 
   return expr;
 }
 
+/* Subroutine of build_base_path; EXPR and BINFO are as in that function.
+   Perform a derived-to-base conversion by recursively building up a
+   sequence of COMPONENT_REFs to the appropriate base fields.  */
+
+static tree
+build_simple_base_path (tree expr, tree binfo)
+{
+  tree type = BINFO_TYPE (binfo);
+  tree d_binfo;
+  tree field;
+
+  /* For primary virtual bases, we can't just follow
+     BINFO_INHERITANCE_CHAIN.  */
+  d_binfo = BINFO_PRIMARY_BASE_OF (binfo);
+  if (d_binfo == NULL_TREE)
+    d_binfo = BINFO_INHERITANCE_CHAIN (binfo);
+
+  if (d_binfo == NULL_TREE)
+    {
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (expr)) != type)
+       abort ();
+      return expr;
+    }
+
+  /* Recurse.  */
+  expr = build_simple_base_path (expr, d_binfo);
+
+  for (field = TYPE_FIELDS (BINFO_TYPE (d_binfo));
+       field; field = TREE_CHAIN (field))
+    /* Is this the base field created by build_base_field?  */
+    if (TREE_CODE (field) == FIELD_DECL
+       && TREE_TYPE (field) == type
+       && DECL_ARTIFICIAL (field)
+       && DECL_IGNORED_P (field))
+      return build_class_member_access_expr (expr, field,
+                                            NULL_TREE, false);
+
+  /* Didn't find the base field?!?  */
+  abort ();
+}
+
 /* Convert OBJECT to the base TYPE.  If CHECK_ACCESS is true, an error
    message is emitted if TYPE is inaccessible.  OBJECT is assumed to
    be non-NULL.  */
@@ -410,8 +484,8 @@ convert_to_base_statically (tree expr, tree base)
       pointer_type = build_pointer_type (expr_type);
       expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
       if (!integer_zerop (BINFO_OFFSET (base)))
-         expr = build (PLUS_EXPR, pointer_type, expr, 
-                       build_nop (pointer_type, BINFO_OFFSET (base)));
+         expr = build2 (PLUS_EXPR, pointer_type, expr, 
+                        build_nop (pointer_type, BINFO_OFFSET (base)));
       expr = build_nop (build_pointer_type (BINFO_TYPE (base)), expr);
       expr = build1 (INDIRECT_REF, BINFO_TYPE (base), expr);
     }
@@ -444,7 +518,7 @@ build_vtbl_ref_1 (tree instance, tree idx)
       tree binfo = lookup_base (fixed_type, basetype,
                                ba_ignore|ba_quiet, NULL);
       if (binfo)
-       vtbl = BINFO_VTABLE (binfo);
+       vtbl = unshare_expr (BINFO_VTABLE (binfo));
     }
 
   if (!vtbl)
@@ -453,7 +527,8 @@ build_vtbl_ref_1 (tree instance, tree idx)
   assemble_external (vtbl);
 
   aref = build_array_ref (vtbl, idx);
-  TREE_CONSTANT (aref) = 1;
+  TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
+  TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
 
   return aref;
 }
@@ -466,13 +541,15 @@ build_vtbl_ref (tree instance, tree idx)
   return aref;
 }
 
-/* Given an object INSTANCE, return an expression which yields a
-   function pointer corresponding to vtable element INDEX.  */
+/* Given a stable object pointer INSTANCE_PTR, return an expression which
+   yields a function pointer corresponding to vtable element INDEX.  */
 
 tree
-build_vfn_ref (tree instance, tree idx)
+build_vfn_ref (tree instance_ptr, tree idx)
 {
-  tree aref = build_vtbl_ref_1 (instance, idx);
+  tree aref;
+
+  aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx);
 
   /* When using function descriptors, the address of the
      vtable entry is treated as a function pointer.  */
@@ -480,6 +557,9 @@ build_vfn_ref (tree instance, tree idx)
     aref = build1 (NOP_EXPR, TREE_TYPE (aref),
                   build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
 
+  /* Remember this as a method reference, for later devirtualization.  */
+  aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
+
   return aref;
 }
 
@@ -501,6 +581,32 @@ get_vtt_name (tree type)
   return mangle_vtt_for_type (type);
 }
 
+/* DECL is an entity associated with TYPE, like a virtual table or an
+   implicitly generated constructor.  Determine whether or not DECL
+   should have external or internal linkage at the object file
+   level.  This routine does not deal with COMDAT linkage and other
+   similar complexities; it simply sets TREE_PUBLIC if it possible for
+   entities in other translation units to contain copies of DECL, in
+   the abstract.  */
+
+void
+set_linkage_according_to_type (tree type, tree decl)
+{
+  /* If TYPE involves a local class in a function with internal
+     linkage, then DECL should have internal linkage too.  Other local
+     classes have no linkage -- but if their containing functions
+     have external linkage, it makes sense for DECL to have external
+     linkage too.  That will allow template definitions to be merged,
+     for example.  */
+  if (no_linkage_check (type, /*relaxed_p=*/true))
+    {
+      TREE_PUBLIC (decl) = 0;
+      DECL_INTERFACE_KNOWN (decl) = 1;
+    }
+  else
+    TREE_PUBLIC (decl) = 1;
+}
+
 /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
    (For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
    Use NAME for the name of the vtable, and VTABLE_TYPE for its type.  */
@@ -521,13 +627,37 @@ build_vtable (tree class_type, tree name, tree vtable_type)
   DECL_VIRTUAL_P (decl) = 1;
   DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
   DECL_VTABLE_OR_VTT_P (decl) = 1;
-
   /* 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));
-
-  import_export_vtable (decl, class_type, 0);
+  set_linkage_according_to_type (class_type, decl);
+  /* The vtable has not been defined -- yet.  */
+  DECL_EXTERNAL (decl) = 1;
+  DECL_NOT_REALLY_EXTERN (decl) = 1;
+
+  if (write_symbols == DWARF2_DEBUG)
+    /* Mark the VAR_DECL node representing the vtable itself as a
+       "gratuitous" one, thereby forcing dwarfout.c to ignore it.  It
+       is rather important that such things be ignored because any
+       effort to actually generate DWARF for them will run into
+       trouble when/if we encounter code like:
+       
+         #pragma interface
+        struct S { virtual void member (); };
+          
+       because the artificial declaration of the vtable itself (as
+       manufactured by the g++ front end) will say that the vtable is
+       a static member of `S' but only *after* the debug output for
+       the definition of `S' has already been output.  This causes
+       grief because the DWARF entry for the definition of the vtable
+       will try to refer back to an earlier *declaration* of the
+       vtable as a static member of `S' and there won't be one.  We
+       might be able to arrange to have the "vtable static member"
+       attached to the member list for `S' before the debug info for
+       `S' get written (which would solve the problem) but that would
+       require more intrusive changes to the g++ front end.  */
+    DECL_IGNORED_P (decl) = 1;
 
   return decl;
 }
@@ -613,8 +743,8 @@ build_primary_vtable (tree binfo, tree type)
 
   /* Initialize the association list for this type, based
      on our first approximation.  */
-  TYPE_BINFO_VTABLE (type) = decl;
-  TYPE_BINFO_VIRTUALS (type) = virtuals;
+  BINFO_VTABLE (TYPE_BINFO (type)) = decl;
+  BINFO_VIRTUALS (TYPE_BINFO (type)) = virtuals;
   SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type));
   return 1;
 }
@@ -715,144 +845,91 @@ modify_vtable_entry (tree t,
 }
 
 \f
-/* Add method METHOD to class TYPE.  If ERROR_P is true, we are adding
-   the method after the class has already been defined because a
-   declaration for it was seen.  (Even though that is erroneous, we
-   add the method for improved error recovery.)  */
+/* Add method METHOD to class TYPE.  */
 
 void
-add_method (tree type, tree method, int error_p)
-{
-  int using = (DECL_CONTEXT (method) != type);
-  int len;
-  int slot;
-  tree method_vec;
-  int template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
-                        && DECL_TEMPLATE_CONV_FN_P (method));
-
-  if (!CLASSTYPE_METHOD_VEC (type))
-    /* Make a new method vector.  We start with 8 entries.  We must
-       allocate at least two (for constructors and destructors), and
-       we're going to end up with an assignment operator at some point
-       as well.
-       
-       We could use a TREE_LIST for now, and convert it to a TREE_VEC
-       in finish_struct, but we would probably waste more memory
-       making the links in the list than we would by over-allocating
-       the size of the vector here.  Furthermore, we would complicate
-       all the code that expects this to be a vector.  */
-    CLASSTYPE_METHOD_VEC (type) = make_tree_vec (8);
+add_method (tree type, tree method)
+{
+  int using;
+  unsigned slot;
+  tree overload;
+  int template_conv_p;
+  VEC(tree) *method_vec;
+  bool complete_p;
+  bool insert_p = false;
+  tree current_fns;
+
+  if (method == error_mark_node)
+    return;
+
+  complete_p = COMPLETE_TYPE_P (type);
+  using = (DECL_CONTEXT (method) != type);
+  template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
+                     && DECL_TEMPLATE_CONV_FN_P (method));
 
   method_vec = CLASSTYPE_METHOD_VEC (type);
-  len = TREE_VEC_LENGTH (method_vec);
+  if (!method_vec)
+    {
+      /* Make a new method vector.  We start with 8 entries.  We must
+        allocate at least two (for constructors and destructors), and
+        we're going to end up with an assignment operator at some
+        point as well.  */
+      method_vec = VEC_alloc (tree, 8);
+      /* Create slots for constructors and destructors.  */
+      VEC_quick_push (tree, method_vec, NULL_TREE);
+      VEC_quick_push (tree, method_vec, NULL_TREE);
+      CLASSTYPE_METHOD_VEC (type) = method_vec;
+    }
 
   /* 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
     {
-      int have_template_convs_p = 0;
+      slot = CLASSTYPE_DESTRUCTOR_SLOT;
+      TYPE_HAS_DESTRUCTOR (type) = 1;
       
+      if (TYPE_FOR_JAVA (type))
+       error (DECL_ARTIFICIAL (method)
+              ? "Java class '%T' cannot have an implicit non-trivial destructor"
+              : "Java class '%T' cannot have a destructor",
+              DECL_CONTEXT (method));
+    }
+  else
+    {
+      bool conv_p = DECL_CONV_FN_P (method);
+      tree m;
+
+      insert_p = true;
       /* See if we already have an entry with this name.  */
-      for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
+      for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; 
+          VEC_iterate (tree, method_vec, slot, m);
+          ++slot)
        {
-         tree m = TREE_VEC_ELT (method_vec, slot);
-
-         if (!m)
-           break;
          m = OVL_CURRENT (m);
-         
          if (template_conv_p)
            {
-             have_template_convs_p = (TREE_CODE (m) == TEMPLATE_DECL
-                                      && DECL_TEMPLATE_CONV_FN_P (m));
-             
-             /* If we need to move things up, see if there's
-                space.  */
-             if (!have_template_convs_p)
-               {
-                 slot = len - 1;
-                 if (TREE_VEC_ELT (method_vec, slot))
-                   slot++;
-               }
+             if (TREE_CODE (m) == TEMPLATE_DECL
+                 && DECL_TEMPLATE_CONV_FN_P (m))
+               insert_p = false;
              break;
            }
-         if (DECL_NAME (m) == DECL_NAME (method))
+         if (conv_p && !DECL_CONV_FN_P (m))
            break;
-       }
-      
-      if (slot == len)
-       {
-         /* We need a bigger method vector.  */
-         int new_len;
-         tree new_vec;
-
-         /* In the non-error case, we are processing a class
-            definition.  Double the size of the vector to give room
-            for new methods.  */
-         if (!error_p)
-           new_len = 2 * len;
-         /* In the error case, the vector is already complete.  We
-            don't expect many errors, and the rest of the front-end
-            will get confused if there are empty slots in the vector.  */
-         else
-           new_len = len + 1;
-
-         new_vec = make_tree_vec (new_len);
-         memcpy (&TREE_VEC_ELT (new_vec, 0), &TREE_VEC_ELT (method_vec, 0),
-                 len * sizeof (tree));
-         len = new_len;
-         method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
-       }
-
-      if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
-       {
-         /* Type conversion operators have to come before ordinary
-            methods; add_conversions depends on this to speed up
-            looking for conversion operators.  So, if necessary, we
-            slide some of the vector elements up.  In theory, this
-            makes this algorithm O(N^2) but we don't expect many
-            conversion operators.  */
-         if (template_conv_p)
-           slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
-         else
-           for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
-             {
-               tree fn = TREE_VEC_ELT (method_vec, slot);
-  
-               if (!fn)
-                 /* There are no more entries in the vector, so we
-                    can insert the new conversion operator here.  */
-                 break;
-                 
-               if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
-                 /* We can insert the new function right at the
-                    SLOTth position.  */
-                 break;
-             }
-
-         if (template_conv_p && have_template_convs_p)
-           /*OK*/;
-         else if (!TREE_VEC_ELT (method_vec, slot))
-           /* There is nothing in the Ith slot, so we can avoid
-              moving anything.  */
-               ; 
-         else
+         if (DECL_NAME (m) == DECL_NAME (method))
            {
-             /* We know the last slot in the vector is empty
-                because we know that at this point there's room
-                for a new function.  */
-             memmove (&TREE_VEC_ELT (method_vec, slot + 1),
-                      &TREE_VEC_ELT (method_vec, slot),
-                      (len - slot - 1) * sizeof (tree));
-             TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
+             insert_p = false;
+             break;
            }
+         if (complete_p
+             && !DECL_CONV_FN_P (m)
+             && DECL_NAME (m) > DECL_NAME (method))
+           break;
        }
     }
-      
-  if (template_class_depth (type))
+  current_fns = insert_p ? NULL_TREE : VEC_index (tree, method_vec, slot);
+  
+  if (processing_template_decl)
     /* TYPE is a template class.  Don't issue any errors now; wait
        until instantiation time to complain.  */
     ;
@@ -861,9 +938,7 @@ add_method (tree type, tree method, int error_p)
       tree fns;
 
       /* Check to see if we've already got this method.  */
-      for (fns = TREE_VEC_ELT (method_vec, slot);
-          fns;
-          fns = OVL_NEXT (fns))
+      for (fns = current_fns; fns; fns = OVL_NEXT (fns))
        {
          tree fn = OVL_CURRENT (fns);
          tree parms1;
@@ -930,118 +1005,29 @@ add_method (tree type, tree method, int error_p)
        }
     }
 
-  /* Actually insert the new method.  */
-  TREE_VEC_ELT (method_vec, slot) 
-    = build_overload (method, TREE_VEC_ELT (method_vec, slot));
-
   /* Add the new binding.  */ 
-  if (!DECL_CONSTRUCTOR_P (method)
-      && !DECL_DESTRUCTOR_P (method))
-    push_class_level_binding (DECL_NAME (method),
-                             TREE_VEC_ELT (method_vec, slot));
-}
-
-/* Subroutines of finish_struct.  */
-
-/* Look through the list of fields for this struct, deleting
-   duplicates as we go.  This must be recursive to handle
-   anonymous unions.
-
-   FIELD is the field which may not appear anywhere in FIELDS.
-   FIELD_PTR, if non-null, is the starting point at which
-   chained deletions may take place.
-   The value returned is the first acceptable entry found
-   in FIELDS.
-
-   Note that anonymous fields which are not of UNION_TYPE are
-   not duplicates, they are just anonymous fields.  This happens
-   when we have unnamed bitfields, for example.  */
+  overload = build_overload (method, current_fns);
+  
+  if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
+    push_class_level_binding (DECL_NAME (method), overload);
 
-static tree
-delete_duplicate_fields_1 (tree field, tree fields)
-{
-  tree x;
-  tree prev = 0;
-  if (DECL_NAME (field) == 0)
+  if (insert_p)
     {
-      if (! ANON_AGGR_TYPE_P (TREE_TYPE (field)))
-       return fields;
-
-      for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x))
-       fields = delete_duplicate_fields_1 (x, fields);
-      return fields;
+      /* We only expect to add few methods in the COMPLETE_P case, so
+        just make room for one more method in that case.  */
+      if (VEC_reserve (tree, method_vec, complete_p ? 1 : -1))
+       CLASSTYPE_METHOD_VEC (type) = method_vec;
+      if (slot == VEC_length (tree, method_vec))
+       VEC_quick_push (tree, method_vec, overload);
+      else
+       VEC_quick_insert (tree, method_vec, slot, overload);
     }
   else
-    {
-      for (x = fields; x; prev = x, x = TREE_CHAIN (x))
-       {
-         if (DECL_NAME (x) == 0)
-           {
-             if (! ANON_AGGR_TYPE_P (TREE_TYPE (x)))
-               continue;
-             TYPE_FIELDS (TREE_TYPE (x))
-               = delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x)));
-             if (TYPE_FIELDS (TREE_TYPE (x)) == 0)
-               {
-                 if (prev == 0)
-                   fields = TREE_CHAIN (fields);
-                 else
-                   TREE_CHAIN (prev) = TREE_CHAIN (x);
-               }
-           }
-         else if (TREE_CODE (field) == USING_DECL)
-           /* A using declaration is allowed to appear more than
-              once.  We'll prune these from the field list later, and
-              handle_using_decl will complain about invalid multiple
-              uses.  */
-           ;
-         else if (DECL_NAME (field) == DECL_NAME (x))
-           {
-             if (TREE_CODE (field) == CONST_DECL
-                 && TREE_CODE (x) == CONST_DECL)
-               cp_error_at ("duplicate enum value `%D'", x);
-             else if (TREE_CODE (field) == CONST_DECL
-                      || TREE_CODE (x) == CONST_DECL)
-               cp_error_at ("duplicate field `%D' (as enum and non-enum)",
-                            x);
-             else if (DECL_DECLARES_TYPE_P (field)
-                      && DECL_DECLARES_TYPE_P (x))
-               {
-                 if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
-                   continue;
-                 cp_error_at ("duplicate nested type `%D'", x);
-               }
-             else if (DECL_DECLARES_TYPE_P (field)
-                      || DECL_DECLARES_TYPE_P (x))
-               {
-                 /* Hide tag decls.  */
-                 if ((TREE_CODE (field) == TYPE_DECL
-                      && DECL_ARTIFICIAL (field))
-                     || (TREE_CODE (x) == TYPE_DECL
-                         && DECL_ARTIFICIAL (x)))
-                   continue;
-                 cp_error_at ("duplicate field `%D' (as type and non-type)",
-                              x);
-               }
-             else
-               cp_error_at ("duplicate member `%D'", x);
-             if (prev == 0)
-               fields = TREE_CHAIN (fields);
-             else
-               TREE_CHAIN (prev) = TREE_CHAIN (x);
-           }
-       }
-    }
-  return fields;
+    /* Replace the current slot. */
+    VEC_replace (tree, method_vec, slot, overload);
 }
 
-static void
-delete_duplicate_fields (tree fields)
-{
-  tree x;
-  for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x))
-    TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
-}
+/* Subroutines of finish_struct.  */
 
 /* Change the access of FDECL to ACCESS in T.  Return 1 if change was
    legit, otherwise return 0.  */
@@ -1064,8 +1050,8 @@ alter_access (tree t, tree fdecl, tree access)
          if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)
            cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl));
          else
-           error ("conflicting access specifications for field `%s', ignored",
-                  IDENTIFIER_POINTER (DECL_NAME (fdecl)));
+           error ("conflicting access specifications for field `%E', ignored",
+                  DECL_NAME (fdecl));
        }
       else
        {
@@ -1104,7 +1090,11 @@ handle_using_decl (tree using_decl, tree t)
   binfo = lookup_base (t, ctype, ba_any, NULL);
   if (! binfo)
     {
-      error_not_base_type (t, ctype);
+      location_t saved_loc = input_location;
+
+      input_location = DECL_SOURCE_LOCATION (using_decl);
+      error_not_base_type (ctype, t);
+      input_location = saved_loc;
       return;
     }
   
@@ -1131,7 +1121,7 @@ handle_using_decl (tree using_decl, tree t)
     /* Ignore base type this came from.  */
     fdecl = BASELINK_FUNCTIONS (fdecl);
 
-  old_value = IDENTIFIER_CLASS_VALUE (name);
+  old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false);
   if (old_value)
     {
       if (is_overloaded_fn (old_value))
@@ -1168,18 +1158,18 @@ handle_using_decl (tree using_decl, tree t)
       return;
     }
   
-  /* Make type T see field decl FDECL with access ACCESS.*/
+  /* Make type T see field decl FDECL with access ACCESS.  */
   if (flist)
     for (; flist; flist = OVL_NEXT (flist))
       {
-       add_method (t, OVL_CURRENT (flist), /*error_p=*/0);
+       add_method (t, 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
+/* Run through the base classes of T, updating
    CANT_HAVE_DEFAULT_CTOR_P, CANT_HAVE_CONST_CTOR_P, and
    NO_CONST_ASN_REF_P.  Also set flag bits in T based on properties of
    the bases.  */
@@ -1190,45 +1180,20 @@ check_bases (tree t,
              int* cant_have_const_ctor_p,
              int* no_const_asn_ref_p)
 {
-  int n_baseclasses;
   int i;
   int seen_non_virtual_nearly_empty_base_p;
-  tree binfos;
+  tree base_binfo;
+  tree binfo;
 
-  binfos = TYPE_BINFO_BASETYPES (t);
-  n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
   seen_non_virtual_nearly_empty_base_p = 0;
 
-  /* An aggregate cannot have baseclasses.  */
-  CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0);
-
-  for (i = 0; i < n_baseclasses; ++i) 
+  for (binfo = TYPE_BINFO (t), i = 0;
+       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
-      tree base_binfo;
-      tree basetype;
-
-      /* Figure out what base we're looking at.  */
-      base_binfo = TREE_VEC_ELT (binfos, i);
-      basetype = TREE_TYPE (base_binfo);
-
-      /* If the type of basetype is incomplete, then we already
-        complained about that fact (and we should have fixed it up as
-        well).  */
-      if (!COMPLETE_TYPE_P (basetype))
-       {
-         int j;
-         /* The base type is of incomplete type.  It is
-            probably best to pretend that it does not
-            exist.  */
-         if (i == n_baseclasses-1)
-           TREE_VEC_ELT (binfos, i) = NULL_TREE;
-         TREE_VEC_LENGTH (binfos) -= 1;
-         n_baseclasses -= 1;
-         for (j = i; j+1 < n_baseclasses; j++)
-           TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
-         continue;
-       }
+      tree basetype = TREE_TYPE (base_binfo);
 
+      my_friendly_assert (COMPLETE_TYPE_P (basetype), 20040714);
+      
       /* Effective C++ rule 14.  We only need to check TYPE_POLYMORPHIC_P
         here because the case of virtual functions but non-virtual
         dtor is handled in finish_struct_1.  */
@@ -1258,7 +1223,7 @@ check_bases (tree t,
                         basetype);
        }
 
-      if (TREE_VIA_VIRTUAL (base_binfo))
+      if (BINFO_VIRTUAL_P (base_binfo))
        /* A virtual base does not effect nearly emptiness.  */
        ;
       else if (CLASSTYPE_NEARLY_EMPTY_P (basetype))
@@ -1313,7 +1278,7 @@ mark_primary_bases (tree type)
          /* A virtual binfo might have been copied from within
             another hierarchy. As we're about to use it as a primary
             base, make sure the offsets match.  */
-         if (TREE_VIA_VIRTUAL (base_binfo))
+         if (BINFO_VIRTUAL_P (base_binfo))
            {
              tree delta = size_diffop (convert (ssizetype,
                                                 BINFO_OFFSET (binfo)),
@@ -1335,8 +1300,8 @@ set_primary_base (tree t, tree binfo)
 
   CLASSTYPE_PRIMARY_BINFO (t) = binfo;
   basetype = BINFO_TYPE (binfo);
-  TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
-  TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
+  BINFO_VTABLE (TYPE_BINFO (t)) = BINFO_VTABLE (TYPE_BINFO (basetype));
+  BINFO_VIRTUALS (TYPE_BINFO (t)) = BINFO_VIRTUALS (TYPE_BINFO (basetype));
   TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
 }
 
@@ -1345,48 +1310,29 @@ set_primary_base (tree t, tree binfo)
 static void
 determine_primary_base (tree t)
 {
-  int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
-  tree vbases;
-  tree type_binfo;
+  unsigned i, n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
+  tree type_binfo = TYPE_BINFO (t);
+  tree vbase_binfo;
+  tree base_binfo;
+  VEC(tree) *vbases;
 
   /* If there are no baseclasses, there is certainly no primary base.  */
   if (n_baseclasses == 0)
     return;
 
-  type_binfo = TYPE_BINFO (t);
-
-  for (i = 0; i < n_baseclasses; i++)
+  for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, base_binfo); i++)
     {
-      tree base_binfo = BINFO_BASETYPE (type_binfo, i);
       tree basetype = BINFO_TYPE (base_binfo);
 
       if (TYPE_CONTAINS_VPTR_P (basetype))
        {
          /* We prefer a non-virtual base, although a virtual one will
             do.  */
-         if (TREE_VIA_VIRTUAL (base_binfo))
+         if (BINFO_VIRTUAL_P (base_binfo))
            continue;
 
          if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-           {
-             set_primary_base (t, base_binfo);
-             CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
-           }
-         else
-           {
-             tree vfields;
-
-             /* Only add unique vfields, and flatten them out as we go.  */
-             for (vfields = CLASSTYPE_VFIELDS (basetype);
-                  vfields;
-                  vfields = TREE_CHAIN (vfields))
-               if (VF_BINFO_VALUE (vfields) == NULL_TREE
-                   || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields)))
-                 CLASSTYPE_VFIELDS (t) 
-                   = tree_cons (base_binfo, 
-                                VF_BASETYPE_VALUE (vfields),
-                                CLASSTYPE_VFIELDS (t));
-           }
+           set_primary_base (t, base_binfo);
        }
     }
 
@@ -1395,29 +1341,27 @@ determine_primary_base (tree t)
 
   /* Find the indirect primary bases - those virtual bases which are primary
      bases of something else in this hierarchy.  */
-  for (vbases = CLASSTYPE_VBASECLASSES (t);
-       vbases;
-       vbases = TREE_CHAIN (vbases)) 
+  for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+       VEC_iterate (tree, vbases, i, vbase_binfo); i++)
     {
-      tree vbase_binfo = TREE_VALUE (vbases);
+      unsigned j;
 
-      /* See if this virtual base is an indirect primary base.  To be so,
-         it must be a primary base within the hierarchy of one of our
-         direct bases.  */
-      for (i = 0; i < n_baseclasses; ++i) 
+      /* See if this virtual base is an indirect primary base.  To be
+         so, it must be a primary base within the hierarchy of one of
+         our direct bases.  */
+      for (j = 0; BINFO_BASE_ITERATE (type_binfo, j, base_binfo); j++)
        {
-         tree basetype = TYPE_BINFO_BASETYPE (t, i);
-         tree v;
-
-         for (v = CLASSTYPE_VBASECLASSES (basetype); 
-              v; 
-              v = TREE_CHAIN (v))
+         unsigned k;
+         VEC (tree) *base_vbases;
+         tree base_vbase_binfo;
+         tree basetype = BINFO_TYPE (base_binfo);
+         
+         for (base_vbases = CLASSTYPE_VBASECLASSES (basetype), k = 0;
+              VEC_iterate (tree, base_vbases, k, base_vbase_binfo); k++)
            {
-             tree base_vbase = TREE_VALUE (v);
-             
-             if (BINFO_PRIMARY_P (base_vbase)
-                 && same_type_p (BINFO_TYPE (base_vbase),
-                                 BINFO_TYPE (vbase_binfo)))
+             if (BINFO_PRIMARY_P (base_vbase_binfo)
+                 && same_type_p (BINFO_TYPE (base_vbase_binfo),
+                                 BINFO_TYPE (vbase_binfo)))
                {
                  BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1;
                  break;
@@ -1448,7 +1392,7 @@ determine_primary_base (tree t)
        {
          tree basetype = BINFO_TYPE (base_binfo);
 
-         if (TREE_VIA_VIRTUAL (base_binfo) 
+         if (BINFO_VIRTUAL_P (base_binfo) 
              && CLASSTYPE_NEARLY_EMPTY_P (basetype))
            {
              /* If this is not an indirect primary base, then it's
@@ -1470,11 +1414,7 @@ determine_primary_base (tree t)
 
       /* If we've got a primary base, use it.  */
       if (candidate)
-       {
-         set_primary_base (t, candidate);
-         CLASSTYPE_VFIELDS (t) 
-           = copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
-       }       
+       set_primary_base (t, candidate);
     }
 
   /* Mark the primary base classes at this point.  */
@@ -1487,11 +1427,12 @@ determine_primary_base (tree t)
 static void
 finish_struct_bits (tree t)
 {
-  int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
-
+  tree variants;
+  
   /* Fix up variants (if any).  */
-  tree variants = TYPE_NEXT_VARIANT (t);
-  while (variants)
+  for (variants = TYPE_NEXT_VARIANT (t);
+       variants;
+       variants = TYPE_NEXT_VARIANT (variants))
     {
       /* These fields are in the _TYPE part of the node, not in
         the TYPE_LANG_SPECIFIC component, so they are not shared.  */
@@ -1504,46 +1445,34 @@ finish_struct_bits (tree t)
       TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (variants) 
        = TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);
       TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t);
-      TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t);
+      TYPE_USES_VIRTUAL_BASECLASSES (variants)
+       = TYPE_USES_VIRTUAL_BASECLASSES (t);
+      
+      TYPE_BINFO (variants) = TYPE_BINFO (t);
+
       /* Copy whatever these are holding today.  */
-      TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);
-      TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);
+      TYPE_VFIELD (variants) = TYPE_VFIELD (t);
+      TYPE_METHODS (variants) = TYPE_METHODS (t);
       TYPE_FIELDS (variants) = TYPE_FIELDS (t);
       TYPE_SIZE (variants) = TYPE_SIZE (t);
       TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t);
-      variants = TYPE_NEXT_VARIANT (variants);
     }
 
-  if (n_baseclasses && TYPE_POLYMORPHIC_P (t))
+  if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t))
     /* For a class w/o baseclasses, `finish_struct' has set
-       CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by
-       definition). Similarly for a class whose base classes do not
-       have vtables. When neither of these is true, we might have
-       removed abstract virtuals (by providing a definition), added
-       some (by declaring new ones), or redeclared ones from a base
-       class. We need to recalculate what's really an abstract virtual
-       at this point (by looking in the vtables).  */
-      get_pure_virtuals (t);
-
-  if (n_baseclasses)
-    {
-      /* Notice whether this class has type conversion functions defined.  */
-      tree binfo = TYPE_BINFO (t);
-      tree binfos = BINFO_BASETYPES (binfo);
-      tree basetype;
-
-      for (i = n_baseclasses-1; i >= 0; i--)
-       {
-         basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
-
-         TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype);
-       }
-    }
-
-  /* If this type has a copy constructor or a destructor, force its mode to
-     be BLKmode, and force its TREE_ADDRESSABLE bit to be nonzero.  This
-     will cause it to be passed by invisible reference and prevent it from
-     being returned in a register.  */
+       CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition).
+       Similarly for a class whose base classes do not have vtables.
+       When neither of these is true, we might have removed abstract
+       virtuals (by providing a definition), added some (by declaring
+       new ones), or redeclared ones from a base class.  We need to
+       recalculate what's really an abstract virtual at this point (by
+       looking in the vtables).  */
+    get_pure_virtuals (t);
+
+  /* If this type has a copy constructor or a destructor, force its
+     mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be
+     nonzero.  This will cause it to be passed by invisible reference
+     and prevent it from being returned in a register.  */
   if (! TYPE_HAS_TRIVIAL_INIT_REF (t) || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
     {
       tree variants;
@@ -1627,11 +1556,11 @@ maybe_warn_about_overly_private_class (tree t)
         constructors/destructors we want to use the code below that
         issues error messages specifically referring to
         constructors/destructors.)  */
-      int i;
+      unsigned i;
       tree binfo = TYPE_BINFO (t);
       
-      for (i = 0; i < BINFO_N_BASETYPES (binfo); i++)
-       if (BINFO_BASEACCESS (binfo, i) != access_private_node)
+      for (i = 0; i != BINFO_N_BASE_BINFOS (binfo); i++)
+       if (BINFO_BASE_ACCESS (binfo, i) != access_private_node)
          {
            has_nonprivate_method = 1;
            break;
@@ -1646,16 +1575,12 @@ maybe_warn_about_overly_private_class (tree t)
   /* Even if some of the member functions are non-private, the class
      won't be useful for much if all the constructors or destructors
      are private: such an object can never be created or destroyed.  */
-  if (TYPE_HAS_DESTRUCTOR (t))
+  if (TYPE_HAS_DESTRUCTOR (t)
+      && TREE_PRIVATE (CLASSTYPE_DESTRUCTORS (t)))
     {
-      tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
-
-      if (TREE_PRIVATE (dtor))
-       {
-         warning ("`%#T' only defines a private destructor and has no friends",
-                     t);
-         return;
-       }
+      warning ("`%#T' only defines a private destructor and has no friends",
+              t);
+      return;
     }
 
   if (TYPE_HAS_CONSTRUCTOR (t))
@@ -1675,9 +1600,7 @@ maybe_warn_about_overly_private_class (tree t)
       if (!TYPE_HAS_INIT_REF (t))
        nonprivate_ctor = 1;
       else 
-       for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
-            fn;
-            fn = OVL_NEXT (fn)) 
+       for (fn = CLASSTYPE_CONSTRUCTORS (t); fn; fn = OVL_NEXT (fn)) 
          {
            tree ctor = OVL_CURRENT (fn);
            /* Ideally, we wouldn't count copy constructors (or, in
@@ -1759,24 +1682,24 @@ resort_type_method_vec (void* obj,
                         gt_pointer_operator new_value,
                         void* cookie)
 {
-  tree method_vec = obj;
-  int len = TREE_VEC_LENGTH (method_vec);
-  int slot;
+  VEC(tree) *method_vec = (VEC(tree) *) obj;
+  int len = VEC_length (tree, method_vec);
+  size_t slot;
+  tree fn;
 
   /* The type conversion ops have to live at the front of the vec, so we
      can't sort them.  */
-  for (slot = 2; slot < len; ++slot)
-    {
-      tree fn = TREE_VEC_ELT (method_vec, slot);
-  
-      if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
-       break;
-    }
+  for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+       VEC_iterate (tree, method_vec, slot, fn);
+       ++slot)
+    if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+      break;
+
   if (len - slot > 1)
     {
       resort_data.new_value = new_value;
       resort_data.cookie = cookie;
-      qsort (&TREE_VEC_ELT (method_vec, slot), len - slot, sizeof (tree),
+      qsort (VEC_address (tree, method_vec) + slot, len - slot, sizeof (tree),
             resort_method_name_cmp);
     }
 }
@@ -1801,22 +1724,14 @@ static void
 finish_struct_methods (tree t)
 {
   tree fn_fields;
-  tree method_vec;
+  VEC(tree) *method_vec;
   int slot, len;
 
-  if (!TYPE_METHODS (t))
-    {
-      /* Clear these for safety; perhaps some parsing error could set
-        these incorrectly.  */
-      TYPE_HAS_CONSTRUCTOR (t) = 0;
-      TYPE_HAS_DESTRUCTOR (t) = 0;
-      CLASSTYPE_METHOD_VEC (t) = NULL_TREE;
-      return;
-    }
-
   method_vec = CLASSTYPE_METHOD_VEC (t);
-  my_friendly_assert (method_vec != NULL_TREE, 19991215);
-  len = TREE_VEC_LENGTH (method_vec);
+  if (!method_vec)
+    return;
+
+  len = VEC_length (tree, method_vec);
 
   /* First fill in entry 0 with the constructors, entry 1 with destructors,
      and the next few with type conversion operators (if any).  */
@@ -1834,23 +1749,16 @@ finish_struct_methods (tree t)
      no methods, then some public defaults are generated.  */
   maybe_warn_about_overly_private_class (t);
 
-  /* Now sort the methods.  */
-  while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
-    len--;
-  TREE_VEC_LENGTH (method_vec) = len;
-
   /* The type conversion ops have to live at the front of the vec, so we
      can't sort them.  */
-  for (slot = 2; slot < len; ++slot)
-    {
-      tree fn = TREE_VEC_ELT (method_vec, slot);
-  
-      if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
-       break;
-    }
+  for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+       VEC_iterate (tree, method_vec, slot, fn_fields);
+       ++slot)
+    if (!DECL_CONV_FN_P (OVL_CURRENT (fn_fields)))
+      break;
   if (len - slot > 1)
-    qsort (&TREE_VEC_ELT (method_vec, slot), len-slot, sizeof (tree),
-          method_name_cmp);
+    qsort (VEC_address (tree, method_vec) + slot,
+          len-slot, sizeof (tree), method_name_cmp);
 }
 
 /* Make BINFO's vtable have N entries, including RTTI entries,
@@ -1895,7 +1803,11 @@ same_signature_p (tree fndecl, tree base_fndecl)
   if (DECL_DESTRUCTOR_P (base_fndecl) || DECL_DESTRUCTOR_P (fndecl))
     return 0;
 
-  if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
+  if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl)
+      || (DECL_CONV_FN_P (fndecl)
+         && DECL_CONV_FN_P (base_fndecl)
+         && same_type_p (DECL_CONV_FN_TYPE (fndecl),
+                         DECL_CONV_FN_TYPE (base_fndecl))))
     {
       tree types, base_types;
       types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
@@ -1920,17 +1832,46 @@ base_derived_from (tree derived, tree base)
     {
       if (probe == derived)
        return true;
-      else if (TREE_VIA_VIRTUAL (probe))
+      else if (BINFO_VIRTUAL_P (probe))
        /* If we meet a virtual base, we can't follow the inheritance
           any more.  See if the complete type of DERIVED contains
           such a virtual base.  */
-       return purpose_member (BINFO_TYPE (probe),
-                              CLASSTYPE_VBASECLASSES (BINFO_TYPE (derived)))
-         != NULL_TREE;
+       return (binfo_for_vbase (BINFO_TYPE (probe), BINFO_TYPE (derived))
+               != NULL_TREE);
     }
   return false;
 }
 
+typedef struct count_depth_data {
+  /* The depth of the current subobject, with "1" as the depth of the
+     most derived object in the hierarchy.  */
+  size_t depth;
+  /* The maximum depth found so far.  */
+  size_t max_depth;
+} count_depth_data;
+
+/* Called from find_final_overrider via dfs_walk.  */
+
+static tree
+dfs_depth_post (tree binfo ATTRIBUTE_UNUSED, void *data)
+{
+  count_depth_data *cd = (count_depth_data *) data;
+  if (cd->depth > cd->max_depth)
+    cd->max_depth = cd->depth;
+  cd->depth--;
+  return NULL_TREE;
+}
+
+/* Called from find_final_overrider via dfs_walk.  */
+
+static tree
+dfs_depth_q (tree derived, int i, void *data)
+{
+  count_depth_data *cd = (count_depth_data *) data;
+  cd->depth++;
+  return BINFO_BASE_BINFO (derived, i);
+}
+
 typedef struct find_final_overrider_data_s {
   /* The function for which we are trying to find a final overrider.  */
   tree fn;
@@ -1940,81 +1881,85 @@ typedef struct find_final_overrider_data_s {
   tree most_derived_type;
   /* The candidate overriders.  */
   tree candidates;
-  /* Binfos which inherited virtually on the currrent path.  */
-  tree vpath;
+  /* Each entry in this array is the next-most-derived class for a
+     virtual base class along the current path.  */
+  tree *vpath_list;
+  /* A pointer one past the top of the VPATH_LIST.  */
+  tree *vpath;
 } find_final_overrider_data;
 
-/* Called from find_final_overrider via dfs_walk.  */
+/* Add the overrider along the current path to FFOD->CANDIDATES.
+   Returns true if an overrider was found; false otherwise.  */
 
-static tree
-dfs_find_final_overrider (tree binfo, void* data)
+static bool
+dfs_find_final_overrider_1 (tree binfo, 
+                           tree *vpath, 
+                           find_final_overrider_data *ffod)
 {
-  find_final_overrider_data *ffod = (find_final_overrider_data *) data;
+  tree method;
 
-  if (binfo == ffod->declaring_base)
+  /* If BINFO is not the most derived type, try a more derived class.
+     A definition there will overrider a definition here.  */
+  if (!same_type_p (BINFO_TYPE (binfo), ffod->most_derived_type))
     {
-      /* We've found a path to the declaring base.  Walk the path from
-        derived to base, looking for an overrider for FN.  */
-      tree path, probe, vpath;
+      tree derived;
+
+      if (BINFO_VIRTUAL_P (binfo))
+       derived = *--vpath;
+      else
+       derived = BINFO_INHERITANCE_CHAIN (binfo);
+      if (dfs_find_final_overrider_1 (derived, vpath, ffod))
+       return true;
+    }
 
-      /* Build the path, using the inheritance chain and record of
-        virtual inheritance.  */
-      for (path = NULL_TREE, probe = binfo, vpath = ffod->vpath;;)
+  method = look_for_overrides_here (BINFO_TYPE (binfo), ffod->fn);
+  if (method)
+    {
+      tree *candidate = &ffod->candidates;
+      
+      /* Remove any candidates overridden by this new function.  */
+      while (*candidate)
        {
-         path = tree_cons (NULL_TREE, probe, path);
-         if (same_type_p (BINFO_TYPE (probe), ffod->most_derived_type))
-           break;
-         if (TREE_VIA_VIRTUAL (probe))
-           {
-             probe = TREE_VALUE (vpath);
-             vpath = TREE_CHAIN (vpath);
-           }
+         /* If *CANDIDATE overrides METHOD, then METHOD
+            cannot override anything else on the list.  */
+         if (base_derived_from (TREE_VALUE (*candidate), binfo))
+           return true;
+         /* If METHOD overrides *CANDIDATE, remove *CANDIDATE.  */
+         if (base_derived_from (binfo, TREE_VALUE (*candidate)))
+           *candidate = TREE_CHAIN (*candidate);
          else
-           probe = BINFO_INHERITANCE_CHAIN (probe);
-       }
-      /* Now walk path, looking for overrides.  */
-      for (; path; path = TREE_CHAIN (path))
-       {
-         tree method = look_for_overrides_here
-           (BINFO_TYPE (TREE_VALUE (path)), ffod->fn);
-         
-         if (method)
-           {
-             tree *candidate = &ffod->candidates;
-             path = TREE_VALUE (path);
-
-             /* Remove any candidates overridden by this new function.  */
-             while (*candidate)
-               {
-                 /* If *CANDIDATE overrides METHOD, then METHOD
-                    cannot override anything else on the list.  */
-                 if (base_derived_from (TREE_VALUE (*candidate), path))
-                   return NULL_TREE;
-                 /* If METHOD overrides *CANDIDATE, remove *CANDIDATE.  */
-                 if (base_derived_from (path, TREE_VALUE (*candidate)))
-                   *candidate = TREE_CHAIN (*candidate);
-                 else
-                   candidate = &TREE_CHAIN (*candidate);
-               }
-             
-             /* Add the new function.  */
-             ffod->candidates = tree_cons (method, path, ffod->candidates);
-             break;
-           }
+           candidate = &TREE_CHAIN (*candidate);
        }
+      
+      /* Add the new function.  */
+      ffod->candidates = tree_cons (method, binfo, ffod->candidates);
+      return true;
     }
 
+  return false;
+}
+
+/* Called from find_final_overrider via dfs_walk.  */
+
+static tree
+dfs_find_final_overrider (tree binfo, void* data)
+{
+  find_final_overrider_data *ffod = (find_final_overrider_data *) data;
+
+  if (binfo == ffod->declaring_base)
+    dfs_find_final_overrider_1 (binfo, ffod->vpath, ffod);
+
   return NULL_TREE;
 }
 
 static tree
 dfs_find_final_overrider_q (tree derived, int ix, void *data)
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   find_final_overrider_data *ffod = (find_final_overrider_data *) data;
 
-  if (TREE_VIA_VIRTUAL (binfo))
-    ffod->vpath = tree_cons (NULL_TREE, derived, ffod->vpath);
+  if (BINFO_VIRTUAL_P (binfo))
+    *ffod->vpath++ = derived;
   
   return binfo;
 }
@@ -2024,8 +1969,8 @@ dfs_find_final_overrider_post (tree binfo, void *data)
 {
   find_final_overrider_data *ffod = (find_final_overrider_data *) data;
 
-  if (TREE_VIA_VIRTUAL (binfo) && TREE_CHAIN (ffod->vpath))
-    ffod->vpath = TREE_CHAIN (ffod->vpath);
+  if (BINFO_VIRTUAL_P (binfo))
+    ffod->vpath--;
   
   return NULL_TREE;
 }
@@ -2039,6 +1984,7 @@ static tree
 find_final_overrider (tree derived, tree binfo, tree fn)
 {
   find_final_overrider_data ffod;
+  count_depth_data cd;
 
   /* Getting this right is a little tricky.  This is valid:
 
@@ -2060,12 +2006,18 @@ find_final_overrider (tree derived, tree binfo, tree fn)
      different overriders along any two, then there is a problem.  */
   if (DECL_THUNK_P (fn))
     fn = THUNK_TARGET (fn);
-  
+
+  /* Determine the depth of the hierarchy.  */
+  cd.depth = 0;
+  cd.max_depth = 0;
+  dfs_walk (derived, dfs_depth_post, dfs_depth_q, &cd);
+
   ffod.fn = fn;
   ffod.declaring_base = binfo;
   ffod.most_derived_type = BINFO_TYPE (derived);
   ffod.candidates = NULL_TREE;
-  ffod.vpath = NULL_TREE;
+  ffod.vpath_list = (tree *) xcalloc (cd.max_depth, sizeof (tree));
+  ffod.vpath = ffod.vpath_list;
 
   dfs_walk_real (derived,
                 dfs_find_final_overrider,
@@ -2073,6 +2025,8 @@ find_final_overrider (tree derived, tree binfo, tree fn)
                 dfs_find_final_overrider_q,
                 &ffod);
 
+  free (ffod.vpath_list);
+
   /* If there was no winner, issue an error message.  */
   if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
     {
@@ -2090,17 +2044,19 @@ find_final_overrider (tree derived, tree binfo, tree fn)
 static tree
 get_vcall_index (tree fn, tree type)
 {
-  tree v;
+  VEC (tree_pair_s) *indices = CLASSTYPE_VCALL_INDICES (type);
+  tree_pair_p p;
+  unsigned ix;
 
-  for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
-    if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
-       || same_signature_p (fn, TREE_PURPOSE (v)))
-      break;
+  for (ix = 0; VEC_iterate (tree_pair_s, indices, ix, p); ix++)
+    if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (p->purpose))
+       || same_signature_p (fn, p->purpose))
+      return p->value;
 
   /* There should always be an appropriate index.  */
-  my_friendly_assert (v, 20021103);
+  abort ();
 
-  return TREE_VALUE (v);
+  return NULL_TREE;
 }
 
 /* Update an entry in the vtable for BINFO, which is in the hierarchy
@@ -2159,16 +2115,24 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
       
       if (DECL_THUNK_P (fn))
        {
+         my_friendly_assert (DECL_RESULT_THUNK_P (fn), 20031211);
          fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn));
          virtual_offset = THUNK_VIRTUAL_OFFSET (fn);
        }
       else
        fixed_offset = virtual_offset = NULL_TREE;
 
-      if (!virtual_offset)
+      if (virtual_offset)
+       /* Find the equivalent binfo within the return type of the
+          overriding function. We will want the vbase offset from
+          there.  */
+       virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset),
+                                         TREE_TYPE (over_return));
+      else if (!same_type_p (TREE_TYPE (over_return),
+                            TREE_TYPE (base_return)))
        {
          /* There was no existing virtual thunk (which takes
-            precidence).  */
+            precedence).  */
          tree thunk_binfo;
          base_kind kind;
          
@@ -2179,18 +2143,19 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
          if (thunk_binfo && (kind == bk_via_virtual
                              || !BINFO_OFFSET_ZEROP (thunk_binfo)))
            {
-             tree offset = BINFO_OFFSET (thunk_binfo);
+             tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
 
              if (kind == bk_via_virtual)
                {
                  /* We convert via virtual base. Find the virtual
                     base and adjust the fixed offset to be from there.  */
-                 while (!TREE_VIA_VIRTUAL (thunk_binfo))
+                 while (!BINFO_VIRTUAL_P (thunk_binfo))
                    thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
 
                  virtual_offset = thunk_binfo;
-                 offset = size_binop (MINUS_EXPR, offset,
-                                      BINFO_OFFSET (virtual_offset));
+                 offset = size_diffop
+                   (offset, convert
+                    (ssizetype, BINFO_OFFSET (virtual_offset)));
                }
              if (fixed_offset)
                /* There was an existing fixed offset, this must be
@@ -2229,7 +2194,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
       /* If we find a virtual base, and we haven't yet found the
         overrider, then there is a virtual base between the
         declaring base (first_defn) and the final overrider.  */
-      if (TREE_VIA_VIRTUAL (b))
+      if (BINFO_VIRTUAL_P (b))
        {
          virtual_base = b;
          break;
@@ -2252,15 +2217,13 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
         primary binfo which first introduced the function into the
         vtable.  If that enters a virtual base, we must use a vcall
         this-adjusting thunk.  Bleah! */
-      tree probe;
+      tree probe = first_defn;
+
+      while ((probe = get_primary_binfo (probe))
+            && (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix)
+       if (BINFO_VIRTUAL_P (probe))
+         virtual_base = probe;
       
-      for (probe = first_defn; (probe = get_primary_binfo (probe));)
-       {
-         if (TREE_VIA_VIRTUAL (probe))
-           virtual_base = probe;
-         if ((unsigned) list_length (BINFO_VIRTUALS (probe)) <= ix)
-           break;
-       }
       if (virtual_base)
        /* Even if we find a virtual base, the correct delta is
           between the overrider and the binfo we're building a vtable
@@ -2274,8 +2237,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
   if (virtual_base)
     /* The `this' pointer needs to be adjusted from the declaration to
        the nearest virtual base.  */
-    delta = size_diffop (BINFO_OFFSET (virtual_base),
-                        BINFO_OFFSET (first_defn));
+    delta = size_diffop (convert (ssizetype, BINFO_OFFSET (virtual_base)),
+                        convert (ssizetype, BINFO_OFFSET (first_defn)));
   else if (lost)
     /* If the nearest definition is in a lost primary, we don't need an
        entry in our vtable.  Except possibly in a constructor vtable,
@@ -2287,8 +2250,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
        BINFO to pointing at the base where the final overrider
        appears.  */
     virtual_covariant:
-    delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
-                        BINFO_OFFSET (binfo));
+    delta = size_diffop (convert (ssizetype,
+                                 BINFO_OFFSET (TREE_VALUE (overrider))),
+                        convert (ssizetype, BINFO_OFFSET (binfo)));
 
   modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
 
@@ -2302,15 +2266,18 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
 static tree
 dfs_modify_vtables (tree binfo, void* data)
 {
+  tree t = (tree) data;
+  
   if (/* There's no need to modify the vtable for a non-virtual
          primary base; we're not going to use that vtable anyhow.
         We do still need to do this for virtual primary bases, as they
         could become non-primary in a construction vtable.  */
-      (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
+      (!BINFO_PRIMARY_P (binfo) || BINFO_VIRTUAL_P (binfo))
       /* Similarly, a base without a vtable needs no modification.  */
-      && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+      && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))
+      /* Don't do the primary vtable, if it's new.  */
+      && (BINFO_TYPE (binfo) != t || CLASSTYPE_HAS_PRIMARY_BASE_P (t)))
     {
-      tree t = (tree) data;
       tree virtuals;
       tree old_virtuals;
       unsigned ix;
@@ -2390,13 +2357,13 @@ get_basefndecls (tree name, tree t)
 {
   tree methods;
   tree base_fndecls = NULL_TREE;
-  int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+  int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
   int i;
 
   /* Find virtual functions in T with the indicated NAME.  */
   i = lookup_fnfields_1 (t, name);
   if (i != -1)
-    for (methods = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), i);
+    for (methods = VEC_index (tree, CLASSTYPE_METHOD_VEC (t), i);
         methods;
         methods = OVL_NEXT (methods))
       {
@@ -2412,7 +2379,7 @@ get_basefndecls (tree name, tree t)
 
   for (i = 0; i < n_baseclasses; i++)
     {
-      tree basetype = TYPE_BINFO_BASETYPE (t, i);
+      tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t), i));
       base_fndecls = chainon (get_basefndecls (name, basetype),
                              base_fndecls);
     }
@@ -2434,7 +2401,8 @@ check_for_override (tree decl, tree ctype)
          override a virtual function from a base class.  */
     return;
   if ((DECL_DESTRUCTOR_P (decl)
-       || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)))
+       || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))
+       || DECL_CONV_FN_P (decl))
       && look_for_overrides (ctype, decl)
       && !DECL_STATIC_FUNCTION_P (decl))
     /* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor
@@ -2456,29 +2424,34 @@ check_for_override (tree decl, tree ctype)
 void
 warn_hidden (tree t)
 {
-  tree method_vec = CLASSTYPE_METHOD_VEC (t);
-  int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
-  int i;
+  VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (t);
+  tree fns;
+  size_t i;
 
   /* We go through each separately named virtual function.  */
-  for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i)
+  for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; 
+       VEC_iterate (tree, method_vec, i, fns);
+       ++i)
     {
-      tree fns;
+      tree fn;
       tree name;
       tree fndecl;
       tree base_fndecls;
+      tree base_binfo;
+      tree binfo;
       int j;
 
       /* All functions in this slot in the CLASSTYPE_METHOD_VEC will
         have the same name.  Figure out what name that is.  */
-      name = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
+      name = DECL_NAME (OVL_CURRENT (fns));
       /* There are no possibly hidden functions yet.  */
       base_fndecls = NULL_TREE;
       /* Iterate through all of the base classes looking for possibly
         hidden functions.  */
-      for (j = 0; j < CLASSTYPE_N_BASECLASSES (t); j++)
+      for (binfo = TYPE_BINFO (t), j = 0;
+          BINFO_BASE_ITERATE (binfo, j, base_binfo); j++)
        {
-         tree basetype = TYPE_BINFO_BASETYPE (t, j);
+         tree basetype = BINFO_TYPE (base_binfo);
          base_fndecls = chainon (get_basefndecls (name, basetype),
                                  base_fndecls);
        }
@@ -2488,9 +2461,9 @@ warn_hidden (tree t)
        continue;
 
       /* Remove any overridden functions.  */
-      for (fns = TREE_VEC_ELT (method_vec, i); fns; fns = OVL_NEXT (fns))
+      for (fn = fns; fn; fn = OVL_NEXT (fn))
        {
-         fndecl = OVL_CURRENT (fns);
+         fndecl = OVL_CURRENT (fn);
          if (DECL_VINDEX (fndecl))
            {
              tree *prev = &base_fndecls;
@@ -2512,8 +2485,7 @@ warn_hidden (tree t)
        {
          /* Here we know it is a hider, and no overrider exists.  */
          cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
-         cp_warning_at ("  by `%D'", 
-                        OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
+         cp_warning_at ("  by `%D'", fns);
          base_fndecls = TREE_CHAIN (base_fndecls);
        }
     }
@@ -2552,10 +2524,6 @@ finish_struct_anon (tree t)
                      || TYPE_ANONYMOUS_P (TREE_TYPE (elt))))
                continue;
 
-             if (constructor_name_p (DECL_NAME (elt), t))
-               cp_pedwarn_at ("ISO C++ forbids member `%D' with same name as enclosing class",
-                              elt);
-
              if (TREE_CODE (elt) != FIELD_DECL)
                {
                  cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
@@ -2617,8 +2585,6 @@ add_implicitly_declared_members (tree t,
   tree virtual_dtor = NULL_TREE;
   tree *f;
 
-  ++adding_implicit_members;
-
   /* Destructor.  */
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
     {
@@ -2644,38 +2610,35 @@ add_implicitly_declared_members (tree t,
   /* Default constructor.  */
   if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
     {
-      default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0);
-      TREE_CHAIN (default_fn) = implicit_fns;
-      implicit_fns = default_fn;
+      TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
+      CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
     }
 
   /* Copy constructor.  */
   if (! TYPE_HAS_INIT_REF (t) && ! TYPE_FOR_JAVA (t))
     {
-      /* ARM 12.18: You get either X(X&) or X(const X&), but
-        not both.  --Chip  */
-      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;
+      TYPE_HAS_INIT_REF (t) = 1;
+      TYPE_HAS_CONST_INIT_REF (t) = !cant_have_const_cctor;
+      CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
+      TYPE_HAS_CONSTRUCTOR (t) = 1;
     }
 
-  /* Assignment operator.  */
-  if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t))
+  /* If there is no assignment operator, one will be created if and
+     when it is needed.  For now, just record whether or not the type
+     of the parameter to the assignment operator will be a const or
+     non-const reference.  */
+  if (!TYPE_HAS_ASSIGN_REF (t) && !TYPE_FOR_JAVA (t))
     {
-      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;
+      TYPE_HAS_ASSIGN_REF (t) = 1;
+      TYPE_HAS_CONST_ASSIGN_REF (t) = !cant_have_const_assignment;
+      CLASSTYPE_LAZY_ASSIGNMENT_OP (t) = 1;
     }
-
+  
   /* Now, hook all of the new functions on to TYPE_METHODS,
      and add them to the CLASSTYPE_METHOD_VEC.  */
   for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
     {
-      add_method (t, *f, /*error_p=*/0);
+      add_method (t, *f);
       maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
     }
   if (abi_version_at_least (2))
@@ -2693,8 +2656,6 @@ add_implicitly_declared_members (tree t,
       *f = TYPE_METHODS (t);
       TYPE_METHODS (t) = implicit_fns;
     }
-
-  --adding_implicit_members;
 }
 
 /* Subroutine of finish_struct_1.  Recursively count the number of fields
@@ -2787,11 +2748,11 @@ check_bitfield_decl (tree field)
       else if (TREE_CODE (type) == ENUMERAL_TYPE
               && (0 > compare_tree_int (w,
                                         min_precision (TYPE_MIN_VALUE (type),
-                                                       TREE_UNSIGNED (type)))
+                                                       TYPE_UNSIGNED (type)))
                   ||  0 > compare_tree_int (w,
                                             min_precision
                                             (TYPE_MAX_VALUE (type),
-                                             TREE_UNSIGNED (type)))))
+                                             TYPE_UNSIGNED (type)))))
        cp_warning_at ("`%D' is too small to hold all values of `%#T'",
                       field, type);
     }
@@ -2929,16 +2890,13 @@ check_field_decls (tree t, tree *access_decls,
 {
   tree *field;
   tree *next;
-  int has_pointers;
+  bool has_pointers;
   int any_default_members;
 
-  /* First, delete any duplicate fields.  */
-  delete_duplicate_fields (TYPE_FIELDS (t));
-
   /* Assume there are no access declarations.  */
   *access_decls = NULL_TREE;
   /* Assume this class has no pointer members.  */
-  has_pointers = 0;
+  has_pointers = false;
   /* Assume none of the members of this class have default
      initializations.  */
   any_default_members = 0;
@@ -3003,9 +2961,30 @@ check_field_decls (tree t, tree *access_decls,
 
       /* If we've gotten this far, it's a data member, possibly static,
         or an enumerator.  */
-
       DECL_CONTEXT (x) = t;
 
+      /* When this goes into scope, it will be a non-local reference.  */
+      DECL_NONLOCAL (x) = 1;
+
+      if (TREE_CODE (t) == UNION_TYPE)
+       {
+         /* [class.union]
+
+            If a union contains a static data member, or a member of
+            reference type, the program is ill-formed.  */
+         if (TREE_CODE (x) == VAR_DECL)
+           {
+             cp_error_at ("`%D' may not be static because it is a member of a union", x);
+             continue;
+           }
+         if (TREE_CODE (type) == REFERENCE_TYPE)
+           {
+             cp_error_at ("`%D' may not have reference type `%T' because it is a member of a union",
+                          x, type);
+             continue;
+           }
+       }
+
       /* ``A local class cannot have static data members.'' ARM 9.4 */
       if (current_function_decl && TREE_STATIC (x))
        cp_error_at ("field `%D' in local class cannot be static", x);
@@ -3029,21 +3008,9 @@ check_field_decls (tree t, tree *access_decls,
       if (type == error_mark_node)
        continue;
          
-      /* When this goes into scope, it will be a non-local reference.  */
-      DECL_NONLOCAL (x) = 1;
-
-      if (TREE_CODE (x) == CONST_DECL)
+      if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
        continue;
 
-      if (TREE_CODE (x) == VAR_DECL)
-       {
-         if (TREE_CODE (t) == UNION_TYPE)
-           /* Unions cannot have static members.  */
-           cp_error_at ("field `%D' declared static in union", x);
-             
-         continue;
-       }
-
       /* Now it can only be a FIELD_DECL.  */
 
       if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
@@ -3070,9 +3037,22 @@ check_field_decls (tree t, tree *access_decls,
        }
 
       type = strip_array_types (type);
-      
-      if (TYPE_PTR_P (type))
-       has_pointers = 1;
+
+      /* This is used by -Weffc++ (see below). Warn only for pointers
+        to members which might hold dynamic memory. So do not warn
+        for pointers to functions or pointers to members.  */
+      if (TYPE_PTR_P (type)
+         && !TYPE_PTRFN_P (type)
+         && !TYPE_PTR_TO_MEMBER_P (type))
+       has_pointers = true;
+
+      if (CLASS_TYPE_P (type))
+       {
+         if (CLASSTYPE_REF_FIELDS_NEED_INIT (type))
+           SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
+         if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type))
+           SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t, 1);
+       }
 
       if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
        CLASSTYPE_HAS_MUTABLE (t) = 1;
@@ -3130,9 +3110,25 @@ check_field_decls (tree t, tree *access_decls,
                          &any_default_members);
     }
 
-  /* Effective C++ rule 11.  */
-  if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
-      && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
+  /* Effective C++ rule 11: if a class has dynamic memory held by pointers,
+     it should also define a copy constructor and an assignment operator to
+     implement the correct copy semantic (deep vs shallow, etc.). As it is
+     not feasible to check whether the constructors do allocate dynamic memory
+     and store it within members, we approximate the warning like this:
+
+     -- Warn only if there are members which are pointers
+     -- Warn only if there is a non-trivial constructor (otherwise,
+       there cannot be memory allocated).
+     -- Warn only if there is a non-trivial destructor. We assume that the
+       user at least implemented the cleanup correctly, and a destructor
+       is needed to free dynamic memory.
+       
+     This seems enough for pratical purposes.  */
+    if (warn_ecpp
+       && has_pointers
+       && TYPE_HAS_CONSTRUCTOR (t)
+       && TYPE_HAS_DESTRUCTOR (t)
+       && !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
     {
       warning ("`%#T' has pointer data members", t);
       
@@ -3256,18 +3252,16 @@ walk_subobject_offsets (tree type,
       /* Iterate through the direct base classes of TYPE.  */
       if (!type_binfo)
        type_binfo = TYPE_BINFO (type);
-      for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++i)
+      for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, binfo); i++)
        {
          tree binfo_offset;
 
-         binfo = BINFO_BASETYPE (type_binfo, i);
-
          if (abi_version_at_least (2) 
-             && TREE_VIA_VIRTUAL (binfo))
+             && BINFO_VIRTUAL_P (binfo))
            continue;
 
          if (!vbases_p 
-             && TREE_VIA_VIRTUAL (binfo) 
+             && BINFO_VIRTUAL_P (binfo) 
              && !BINFO_PRIMARY_P (binfo))
            continue;
 
@@ -3281,7 +3275,7 @@ walk_subobject_offsets (tree type,
              /* We cannot rely on BINFO_OFFSET being set for the base
                 class yet, but the offsets for direct non-virtual
                 bases can be calculated by going back to the TYPE.  */
-             orig_binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+             orig_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), i);
              binfo_offset = size_binop (PLUS_EXPR,           
                                         offset,
                                         BINFO_OFFSET (orig_binfo));
@@ -3298,9 +3292,10 @@ walk_subobject_offsets (tree type,
            return r;
        }
 
-      if (abi_version_at_least (2))
+      if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type))
        {
-         tree vbase;
+         unsigned ix;
+         VEC (tree) *vbases;
 
          /* Iterate through the virtual base classes of TYPE.  In G++
             3.2, we included virtual bases in the direct base class
@@ -3308,11 +3303,9 @@ walk_subobject_offsets (tree type,
             correct offsets for virtual bases are only known when
             working with the most derived type.  */
          if (vbases_p)
-           for (vbase = CLASSTYPE_VBASECLASSES (type);
-                vbase;
-                vbase = TREE_CHAIN (vbase))
+           for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
+                VEC_iterate (tree, vbases, ix, binfo); ix++)
              {
-               binfo = TREE_VALUE (vbase);
                r = walk_subobject_offsets (binfo,
                                            f,
                                            size_binop (PLUS_EXPR,
@@ -3329,8 +3322,9 @@ walk_subobject_offsets (tree type,
              /* We still have to walk the primary base, if it is
                 virtual.  (If it is non-virtual, then it was walked
                 above.)  */
-             vbase = get_primary_binfo (type_binfo);
-             if (vbase && TREE_VIA_VIRTUAL (vbase)
+             tree vbase = get_primary_binfo (type_binfo);
+             
+             if (vbase && BINFO_VIRTUAL_P (vbase)
                  && BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
                {
                  r = (walk_subobject_offsets 
@@ -3486,14 +3480,14 @@ layout_nonempty_base_or_field (record_layout_info rli,
       /* Place this field.  */
       place_field (rli, decl);
       offset = byte_position (decl);
+
       /* 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:
+        For example, consider:
         
-        struct S {};
-        struct T : public S { int i; };
-        struct U : public S, public T {};
+          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
@@ -3502,9 +3496,13 @@ layout_nonempty_base_or_field (record_layout_info rli,
         empty class, have nonzero size, any overlap can happen only
         with a direct or indirect base-class -- it can't happen with
         a data member.  */
+      /* In a union, overlap is permitted; all members are placed at
+        offset zero.  */
+      if (TREE_CODE (rli->t) == UNION_TYPE)
+       break;
       /* G++ 3.2 did not check for overlaps when placing a non-empty
         virtual base.  */
-      if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
+      if (!abi_version_at_least (2) && binfo && BINFO_VIRTUAL_P (binfo))
        break;
       if (layout_conflict_p (field_p ? type : binfo, offset, 
                             offsets, field_p))
@@ -3566,14 +3564,18 @@ layout_empty_base (tree binfo, tree eoc, splay_tree offsets)
   /* This routine should only be used for empty classes.  */
   my_friendly_assert (is_empty_class (basetype), 20000321);
   alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
-  
-  if (abi_version_at_least (2))
-    BINFO_OFFSET (binfo) = size_zero_node;
-  if (warn_abi && !integer_zerop (BINFO_OFFSET (binfo)))
-    warning ("offset of empty base `%T' may not be ABI-compliant and may"
-            "change in a future version of GCC",
-            BINFO_TYPE (binfo));
 
+  if (!integer_zerop (BINFO_OFFSET (binfo)))
+    {
+      if (abi_version_at_least (2))
+       propagate_binfo_offsets
+         (binfo, size_diffop (size_zero_node, BINFO_OFFSET (binfo)));
+      else if (warn_abi)
+       warning ("offset of empty base `%T' may not be ABI-compliant and may"
+                "change in a future version of GCC",
+                BINFO_TYPE (binfo));
+    }
+  
   /* This is an empty base class.  We first try to put it at offset
      zero.  */
   if (layout_conflict_p (binfo,
@@ -3662,7 +3664,7 @@ build_base_field (record_layout_info rli, tree binfo,
       atend = layout_empty_base (binfo, eoc, offsets);
       /* A nearly-empty class "has no proper base class that is empty,
         not morally virtual, and at an offset other than zero."  */
-      if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
+      if (!BINFO_VIRTUAL_P (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
        {
          if (atend)
            CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
@@ -3718,7 +3720,7 @@ build_base_fields (record_layout_info rli,
   /* Chain to hold all the new FIELD_DECLs which stand in for base class
      subobjects.  */
   tree t = rli->t;
-  int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+  int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
   int i;
 
   /* The primary base class is always allocated first.  */
@@ -3731,7 +3733,7 @@ build_base_fields (record_layout_info rli,
     {
       tree base_binfo;
 
-      base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
+      base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (t), i);
 
       /* The primary base was already allocated above, so we don't
         need to allocate it again here.  */
@@ -3740,7 +3742,7 @@ build_base_fields (record_layout_info rli,
 
       /* Virtual bases are added at the end (a primary virtual base
         will have already been added).  */
-      if (TREE_VIA_VIRTUAL (base_binfo))
+      if (BINFO_VIRTUAL_P (base_binfo))
        continue;
 
       next_field = build_base_field (rli, base_binfo,
@@ -3759,15 +3761,9 @@ check_methods (tree t)
 
   for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
     {
-      /* If this was an evil function, don't keep it in class.  */
-      if (DECL_ASSEMBLER_NAME_SET_P (x) 
-         && IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
-       continue;
-
       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);
-
       /* The name of the field is the original field name
         Save this in auxiliary field for later overloading.  */
       if (DECL_VINDEX (x))
@@ -3834,12 +3830,15 @@ build_clone (tree fn, tree name)
        /* If this is subobject constructor or destructor, add the vtt
         parameter.  */
       TREE_TYPE (clone) 
-       = build_cplus_method_type (basetype,
-                                  TREE_TYPE (TREE_TYPE (clone)),
-                                  parmtypes);
+       = build_method_type_directly (basetype,
+                                     TREE_TYPE (TREE_TYPE (clone)),
+                                     parmtypes);
       if (exceptions)
        TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
                                                     exceptions);
+      TREE_TYPE (clone) 
+       = cp_build_type_attribute_variant (TREE_TYPE (clone),
+                                          TYPE_ATTRIBUTES (TREE_TYPE (fn)));
     }
 
   /* Copy the function parameters.  But, DECL_ARGUMENTS on a TEMPLATE_DECL
@@ -3876,7 +3875,7 @@ build_clone (tree fn, tree name)
 
   /* Create the RTL for this function.  */
   SET_DECL_RTL (clone, NULL_RTX);
-  rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof);
+  rest_of_decl_compilation (clone, /*top_level=*/1, at_eof);
   
   /* Make it easy to find the CLONE given the FN.  */
   TREE_CHAIN (clone) = TREE_CHAIN (fn);
@@ -3893,8 +3892,6 @@ build_clone (tree fn, tree name)
       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;
 }
@@ -3919,10 +3916,10 @@ clone_function_decl (tree fn, int update_method_vec_p)
         and a not-in-charge version.  */
       clone = build_clone (fn, complete_ctor_identifier);
       if (update_method_vec_p)
-       add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+       add_method (DECL_CONTEXT (clone), clone);
       clone = build_clone (fn, base_ctor_identifier);
       if (update_method_vec_p)
-       add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+       add_method (DECL_CONTEXT (clone), clone);
     }
   else
     {
@@ -3941,14 +3938,14 @@ clone_function_decl (tree fn, int update_method_vec_p)
        {
          clone = build_clone (fn, deleting_dtor_identifier);
          if (update_method_vec_p)
-           add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+           add_method (DECL_CONTEXT (clone), clone);
        }
       clone = build_clone (fn, complete_dtor_identifier);
       if (update_method_vec_p)
-       add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+       add_method (DECL_CONTEXT (clone), clone);
       clone = build_clone (fn, base_dtor_identifier);
       if (update_method_vec_p)
-       add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+       add_method (DECL_CONTEXT (clone), clone);
     }
 
   /* Note that this is an abstract function that is never emitted.  */
@@ -4013,9 +4010,9 @@ adjust_clone_args (tree decl)
                                           clone_parms);
                  TREE_TYPE (clone_parms) = TREE_TYPE (orig_clone_parms);
                }
-             type = build_cplus_method_type (basetype,
-                                             TREE_TYPE (TREE_TYPE (clone)),
-                                             clone_parms);
+             type = build_method_type_directly (basetype,
+                                                TREE_TYPE (TREE_TYPE (clone)),
+                                                clone_parms);
              if (exceptions)
                type = build_exception_variant (type, exceptions);
              TREE_TYPE (clone) = type;
@@ -4177,12 +4174,10 @@ check_bases_and_members (tree t)
   CLASSTYPE_NON_POD_P (t)
     |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t) 
        || TYPE_HAS_ASSIGN_REF (t));
-  TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
   TYPE_HAS_COMPLEX_ASSIGN_REF (t)
     |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
 
-  /* Synthesize any needed methods.  Note that methods will be synthesized
-     for anonymous unions; grok_x_components undoes that.  */
+  /* Synthesize any needed methods.   */
   add_implicitly_declared_members (t, cant_have_default_ctor,
                                   cant_have_const_ctor,
                                   no_const_asn_ref);
@@ -4238,7 +4233,7 @@ create_vtable_ptr (tree t, tree* virtuals_p)
     {
       /* We build this decl with vtbl_ptr_type_node, which is a
         `vtable_entry_type*'.  It might seem more precise to use
-        `vtable_entry_type (*)[N]' where N is the number of firtual
+        `vtable_entry_type (*)[N]' where N is the number of virtual
         functions.  However, that would require the vtable pointer in
         base classes to have a different type than the vtable pointer
         in derived classes.  We could make that happen, but that
@@ -4269,7 +4264,7 @@ create_vtable_ptr (tree t, tree* virtuals_p)
       /* This class is non-empty.  */
       CLASSTYPE_EMPTY_P (t) = 0;
 
-      if (CLASSTYPE_N_BASECLASSES (t))
+      if (BINFO_N_BASE_BINFOS (TYPE_BINFO (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
@@ -4339,6 +4334,7 @@ propagate_binfo_offsets (tree binfo, tree offset)
 {
   int i;
   tree primary_binfo;
+  tree base_binfo;
 
   /* Update BINFO's offset.  */
   BINFO_OFFSET (binfo)
@@ -4350,33 +4346,18 @@ propagate_binfo_offsets (tree binfo, tree offset)
   /* Find the primary base class.  */
   primary_binfo = get_primary_binfo (binfo);
 
+  if (primary_binfo && BINFO_PRIMARY_BASE_OF (primary_binfo) == binfo)
+    propagate_binfo_offsets (primary_binfo, offset);
+  
   /* Scan all of the bases, pushing the BINFO_OFFSET adjust
      downwards.  */
-  for (i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
     {
-      tree base_binfo;
-
-      /* On the first time through the loop, do the primary base.
-        Because the primary base need not be an immediate base, we
-        must handle the primary base specially.  */
-      if (i == -1) 
-       {
-         if (!primary_binfo) 
-           continue;
-
-         base_binfo = primary_binfo;
-       }
-      else
-       {
-         base_binfo = BINFO_BASETYPE (binfo, i);
-         /* Don't do the primary base twice.  */
-         if (base_binfo == primary_binfo)
-           continue;
-       }
+      /* Don't do the primary base twice.  */
+      if (base_binfo == primary_binfo)
+       continue;
 
-      /* Skip virtual bases that aren't our canonical primary base.  */
-      if (TREE_VIA_VIRTUAL (base_binfo)
-         && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo)
+      if (BINFO_VIRTUAL_P (base_binfo))
        continue;
 
       propagate_binfo_offsets (base_binfo, offset);
@@ -4395,7 +4376,7 @@ layout_virtual_bases (record_layout_info rli, splay_tree offsets)
   bool first_vbase = true;
   tree *next_field;
 
-  if (CLASSTYPE_N_BASECLASSES (t) == 0)
+  if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) == 0)
     return;
 
   if (!abi_version_at_least(2))
@@ -4424,7 +4405,7 @@ layout_virtual_bases (record_layout_info rli, splay_tree offsets)
      allocated in inheritance graph order.  */
   for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
     {
-      if (!TREE_VIA_VIRTUAL (vbase))
+      if (!BINFO_VIRTUAL_P (vbase))
        continue;
 
       if (!BINFO_PRIMARY_P (vbase))
@@ -4486,31 +4467,31 @@ static tree
 end_of_class (tree t, int include_virtuals_p)
 {
   tree result = size_zero_node;
+  VEC (tree) *vbases;
   tree binfo;
+  tree base_binfo;
   tree offset;
   int i;
 
-  for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+  for (binfo = TYPE_BINFO (t), i = 0;
+       BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
     {
-      binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
-
       if (!include_virtuals_p
-         && TREE_VIA_VIRTUAL (binfo) 
-         && BINFO_PRIMARY_BASE_OF (binfo) != TYPE_BINFO (t))
+         && BINFO_VIRTUAL_P (base_binfo) 
+         && BINFO_PRIMARY_BASE_OF (base_binfo) != TYPE_BINFO (t))
        continue;
 
-      offset = end_of_base (binfo);
+      offset = end_of_base (base_binfo);
       if (INT_CST_LT_UNSIGNED (result, offset))
        result = offset;
     }
 
   /* G++ 3.2 did not check indirect virtual bases.  */
   if (abi_version_at_least (2) && include_virtuals_p)
-    for (binfo = CLASSTYPE_VBASECLASSES (t); 
-        binfo; 
-        binfo = TREE_CHAIN (binfo))
+    for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+        VEC_iterate (tree, vbases, i, base_binfo); i++)
       {
-       offset = end_of_base (TREE_VALUE (binfo));
+       offset = end_of_base (base_binfo);
        if (INT_CST_LT_UNSIGNED (result, offset))
          result = offset;
       }
@@ -4532,13 +4513,16 @@ static void
 warn_about_ambiguous_bases (tree t)
 {
   int i;
-  tree vbases;
+  VEC (tree) *vbases;
   tree basetype;
+  tree binfo;
+  tree base_binfo;
 
   /* Check direct bases.  */
-  for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+  for (binfo = TYPE_BINFO (t), i = 0;
+       BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
     {
-      basetype = TYPE_BINFO_BASETYPE (t, i);
+      basetype = BINFO_TYPE (base_binfo);
 
       if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
        warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
@@ -4547,11 +4531,10 @@ warn_about_ambiguous_bases (tree t)
 
   /* Check for ambiguous virtual bases.  */
   if (extra_warnings)
-    for (vbases = CLASSTYPE_VBASECLASSES (t); 
-        vbases; 
-        vbases = TREE_CHAIN (vbases))
+    for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+        VEC_iterate (tree, vbases, i, binfo); i++)
       {
-       basetype = BINFO_TYPE (TREE_VALUE (vbases));
+       basetype = BINFO_TYPE (binfo);
        
        if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
          warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
@@ -4587,7 +4570,19 @@ include_empty_classes (record_layout_info rli)
   if (TREE_CODE (rli_size) == INTEGER_CST
       && INT_CST_LT_UNSIGNED (rli_size, eoc))
     {
-      rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
+      if (!abi_version_at_least (2))
+       /* In version 1 of the ABI, the size of a class that ends with
+          a bitfield was not rounded up to a whole multiple of a
+          byte.  Because rli_size_unit_so_far returns only the number
+          of fully allocated bytes, any extra bits were not included
+          in the size.  */
+       rli->bitpos = round_down (rli->bitpos, BITS_PER_UNIT);
+      else
+       /* The size should have been rounded to a whole byte.  */
+       my_friendly_assert (tree_int_cst_equal (rli->bitpos,
+                                               round_down (rli->bitpos,
+                                                           BITS_PER_UNIT)),
+                           20030903);
       rli->bitpos 
        = size_binop (PLUS_EXPR, 
                      rli->bitpos,
@@ -4748,6 +4743,15 @@ layout_class_type (tree t, tree *virtuals_p)
             field to the size of its declared type; the rest of the
             field is effectively invisible.  */
          DECL_SIZE (field) = TYPE_SIZE (type);
+         /* We must also reset the DECL_MODE of the field.  */
+         if (abi_version_at_least (2))
+           DECL_MODE (field) = TYPE_MODE (type);
+         else if (warn_abi
+                  && DECL_MODE (field) != TYPE_MODE (type))
+           /* Versions of G++ before G++ 3.4 did not reset the
+              DECL_MODE.  */
+           warning ("the offset of `%D' may not be ABI-compliant and may "
+                    "change in a future version of GCC", field);
        }
       else
        layout_nonempty_base_or_field (rli, field, NULL_TREE,
@@ -4795,6 +4799,7 @@ layout_class_type (tree t, tree *virtuals_p)
          DECL_BIT_FIELD (padding_field) = 1;
          DECL_SIZE (padding_field) = padding;
          DECL_CONTEXT (padding_field) = t;
+         DECL_ARTIFICIAL (padding_field) = 1;
          layout_nonempty_base_or_field (rli, padding_field,
                                         NULL_TREE, 
                                         empty_base_offsets);
@@ -4881,6 +4886,8 @@ layout_class_type (tree t, tree *virtuals_p)
            DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
            DECL_FIELD_BIT_OFFSET (*next_field)
              = DECL_FIELD_BIT_OFFSET (field);
+           DECL_SIZE (*next_field) = DECL_SIZE (field);
+           DECL_MODE (*next_field) = DECL_MODE (field);
            next_field = &TREE_CHAIN (*next_field);
          }
 
@@ -4921,6 +4928,11 @@ layout_class_type (tree t, tree *virtuals_p)
   /* Warn about bases that can't be talked about due to ambiguity.  */
   warn_about_ambiguous_bases (t);
 
+  /* Now that we're done with layout, give the base fields the real types.  */
+  for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+    if (DECL_ARTIFICIAL (field) && IS_FAKE_BASE_TYPE (TREE_TYPE (field)))
+      TREE_TYPE (field) = TYPE_CONTEXT (TREE_TYPE (field));
+
   /* Clean up.  */
   splay_tree_delete (empty_base_offsets);
 }
@@ -4988,7 +5000,7 @@ finish_struct_1 (tree t)
      bases and members and add implicitly generated methods.  */
   check_bases_and_members (t);
 
-  /* Find the key method */
+  /* Find the key method */
   if (TYPE_CONTAINS_VPTR_P (t))
     {
       CLASSTYPE_KEY_METHOD (t) = key_method (t);
@@ -5001,6 +5013,10 @@ finish_struct_1 (tree t)
 
   /* Layout the class itself.  */
   layout_class_type (t, &virtuals);
+  if (CLASSTYPE_AS_BASE (t) != t)
+    /* We use the base type for trivial assignments, and hence it
+       needs a mode.  */
+    compute_record_mode (CLASSTYPE_AS_BASE (t));
 
   /* Make sure that we get our own copy of the vfield FIELD_DECL.  */
   vfield = TYPE_VFIELD (t);
@@ -5026,12 +5042,6 @@ finish_struct_1 (tree t)
 
   virtuals = modify_all_vtables (t, nreverse (virtuals));
 
-  /* If we created a new vtbl pointer for this class, add it to the
-     list.  */
-  if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-    CLASSTYPE_VFIELDS (t) 
-      = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
-
   /* If necessary, create the primary vtable for this class.  */
   if (virtuals || TYPE_CONTAINS_VPTR_P (t))
     {
@@ -5049,15 +5059,16 @@ finish_struct_1 (tree t)
       int vindex;
       tree fn;
 
-      if (TYPE_BINFO_VTABLE (t))
-       my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)),
+      if (BINFO_VTABLE (TYPE_BINFO (t)))
+       my_friendly_assert (DECL_VIRTUAL_P (BINFO_VTABLE (TYPE_BINFO (t))),
                            20000116);
       if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-       my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
+       my_friendly_assert (BINFO_VIRTUALS (TYPE_BINFO (t)) == NULL_TREE,
                            20000116);
 
       /* Add entries for virtual functions introduced by this class.  */
-      TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), virtuals);
+      BINFO_VIRTUALS (TYPE_BINFO (t))
+       = chainon (BINFO_VIRTUALS (TYPE_BINFO (t)), virtuals);
 
       /* Set DECL_VINDEX for all functions declared in this class.  */
       for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t)); 
@@ -5074,7 +5085,7 @@ finish_struct_1 (tree t)
               thunk base function.  */
            DECL_VINDEX (fndecl) = NULL_TREE;
          else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
-           DECL_VINDEX (fndecl) = build_shared_int_cst (vindex);
+           DECL_VINDEX (fndecl) = build_int_cst (NULL_TREE, vindex);
        }
     }
 
@@ -5097,8 +5108,9 @@ finish_struct_1 (tree t)
   n_fields = count_fields (TYPE_FIELDS (t));
   if (n_fields > 7)
     {
-      struct sorted_fields_type *field_vec = ggc_alloc (sizeof (struct sorted_fields_type) 
-       + n_fields * sizeof (tree));
+      struct sorted_fields_type *field_vec = GGC_NEWVAR
+         (struct sorted_fields_type,
+          sizeof (struct sorted_fields_type) + n_fields * sizeof (tree));
       field_vec->len = n_fields;
       add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0);
       qsort (field_vec->elts, n_fields, sizeof (tree),
@@ -5108,19 +5120,6 @@ finish_struct_1 (tree t)
       DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec;
     }
 
-  if (TYPE_HAS_CONSTRUCTOR (t))
-    {
-      tree vfields = CLASSTYPE_VFIELDS (t);
-
-      for (vfields = CLASSTYPE_VFIELDS (t);
-          vfields; vfields = TREE_CHAIN (vfields))
-       /* Mark the fact that constructor for T could affect anybody
-          inheriting from T who wants to initialize vtables for
-          VFIELDS's type.  */
-       if (VF_BINFO_VALUE (vfields))
-         TREE_ADDRESSABLE (vfields) = 1;
-    }
-
   /* Make the rtl for any new vtables we have created, and unmark
      the base types we marked.  */
   finish_vtbls (t);
@@ -5129,8 +5128,17 @@ finish_struct_1 (tree t)
   build_vtt (t);
 
   if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t)
-      && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
-    warning ("`%#T' has virtual functions but non-virtual destructor", t);
+      && !DECL_VINDEX (CLASSTYPE_DESTRUCTORS (t)))
+
+    {
+      tree dtor = CLASSTYPE_DESTRUCTORS (t);
+
+      /* Warn only if the dtor is non-private or the class has friends */
+      if (!TREE_PRIVATE (dtor) ||
+         (CLASSTYPE_FRIEND_CLASSES (t) ||
+          DECL_FRIENDLIST (TYPE_MAIN_DECL (t))))
+       warning ("%#T' has virtual functions but non-virtual destructor", t);
+    }
 
   complete_vars (t);
 
@@ -5196,8 +5204,24 @@ finish_struct (tree t, tree attributes)
 
   if (processing_template_decl)
     {
+      tree x;
+
       finish_struct_methods (t);
       TYPE_SIZE (t) = bitsize_zero_node;
+
+      /* We need to emit an error message if this type was used as a parameter
+        and it is an abstract type, even if it is a template. We construct
+        a simple CLASSTYPE_PURE_VIRTUALS list without taking bases into
+        account and we call complete_vars with this type, which will check
+        the PARM_DECLS. Note that while the type is being defined,
+        CLASSTYPE_PURE_VIRTUALS contains the list of the inline friends
+        (see CLASSTYPE_INLINE_FRIENDS) so we need to clear it.  */
+      CLASSTYPE_PURE_VIRTUALS (t) = NULL_TREE;
+      for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
+       if (DECL_PURE_VIRTUAL_P (x))
+         CLASSTYPE_PURE_VIRTUALS (t)
+           = tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t));
+      complete_vars (t);
     }
   else
     finish_struct_1 (t);
@@ -5257,9 +5281,6 @@ fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
        }
       return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
 
-    case RTL_EXPR:
-      return NULL_TREE;
-
     case PLUS_EXPR:
     case MINUS_EXPR:
       if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
@@ -5388,6 +5409,26 @@ init_class_processing (void)
   ridpointers[(int) RID_PROTECTED] = access_protected_node;
 }
 
+/* Restore the cached PREVIOUS_CLASS_LEVEL.  */
+
+static void
+restore_class_cache (void)
+{
+  tree type;
+
+  /* We are re-entering the same class we just left, so we don't
+     have to search the whole inheritance matrix to find all the
+     decls to bind again.  Instead, we install the cached
+     class_shadowed list and walk through it binding names.  */
+  push_binding_level (previous_class_level);
+  class_binding_level = previous_class_level;
+  /* Restore IDENTIFIER_TYPE_VALUE.  */
+  for (type = class_binding_level->type_shadowed; 
+       type; 
+       type = TREE_CHAIN (type))
+    SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (type), TREE_TYPE (type));
+}
+
 /* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE as
    appropriate for TYPE.
 
@@ -5395,12 +5436,7 @@ init_class_processing (void)
    nodes of local TYPE_DECLs in the TREE_TYPE field of the name.
 
    For multiple inheritance, we perform a two-pass depth-first search
-   of the type lattice.  The first pass performs a pre-order search,
-   marking types after the type has had its fields installed in
-   the appropriate IDENTIFIER_CLASS_VALUE slot.  The second pass merely
-   unmarks the marked types.  If a field or member function name
-   appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of
-   that name becomes `error_mark_node'.  */
+   of the type lattice.  */
 
 void
 pushclass (tree type)
@@ -5436,79 +5472,32 @@ pushclass (tree type)
                              ? access_private_node 
                              : access_public_node);
 
-  if (previous_class_type != NULL_TREE
-      && (type != previous_class_type 
-         || !COMPLETE_TYPE_P (previous_class_type))
+  if (previous_class_level
+      && type != previous_class_level->this_entity
       && current_class_depth == 1)
     {
       /* Forcibly remove any old class remnants.  */
       invalidate_class_lookup_cache ();
     }
 
-  /* If we're about to enter a nested class, clear
-     IDENTIFIER_CLASS_VALUE for the enclosing classes.  */
-  if (current_class_depth > 1)
-    clear_identifier_class_values ();
-
-  pushlevel_class ();
-
-  if (type != previous_class_type || current_class_depth > 1)
-    {
-      push_class_decls (type);
-      if (CLASSTYPE_IS_TEMPLATE (type))
-       {
-         /* If we are entering the scope of a template (not a
-            specialization), we need to push all the using decls with
-            dependent scope too.  */
-         tree fields;
-
-         for (fields = TYPE_FIELDS (type);
-              fields; fields = TREE_CHAIN (fields))
-           if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields))
-             pushdecl_class_level (fields);
-       }
-    }
+  if (!previous_class_level 
+      || type != previous_class_level->this_entity
+      || current_class_depth > 1)
+    pushlevel_class ();
   else
-    {
-      tree item;
-
-      /* We are re-entering the same class we just left, so we don't
-        have to search the whole inheritance matrix to find all the
-        decls to bind again.  Instead, we install the cached
-        class_shadowed list, and walk through it binding names and
-        setting up IDENTIFIER_TYPE_VALUEs.  */
-      set_class_shadows (previous_class_values);
-      for (item = previous_class_values; item; item = TREE_CHAIN (item))
-       {
-         tree id = TREE_PURPOSE (item);
-         tree decl = TREE_TYPE (item);
-         
-         push_class_binding (id, decl);
-         if (TREE_CODE (decl) == TYPE_DECL)
-           set_identifier_type_value (id, TREE_TYPE (decl));
-       }
-      unuse_fields (type);
-    }
+    restore_class_cache ();
   
   cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));
 }
 
-/* When we exit a toplevel class scope, we save the
-   IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we
-   reenter the class.  Here, we've entered some other class, so we
-   must invalidate our cache.  */
+/* When we exit a toplevel class scope, we save its binding level so
+   that we can restore it quickly.  Here, we've entered some other
+   class, so we must invalidate our cache.  */
 
 void
 invalidate_class_lookup_cache (void)
 {
-  tree t;
-  
-  /* The IDENTIFIER_CLASS_VALUEs are no longer valid.  */
-  for (t = previous_class_values; t; t = TREE_CHAIN (t))
-    IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
-
-  previous_class_values = NULL_TREE;
-  previous_class_type = NULL_TREE;
+  previous_class_level = NULL;
 }
  
 /* Get out of the current class scope. If we were in a class scope
@@ -5518,7 +5507,6 @@ void
 popclass (void)
 {
   poplevel_class ();
-  pop_class_decls ();
 
   current_class_depth--;
   current_class_name = current_class_stack[current_class_depth].name;
@@ -5558,6 +5546,9 @@ currently_open_derived_class (tree t)
   if (dependent_type_p (t))
     return NULL_TREE;
 
+  if (!current_class_type)
+    return NULL_TREE;
+
   if (DERIVED_FROM_P (t, current_class_type))
     return current_class_type;
 
@@ -5648,7 +5639,7 @@ push_lang_context (tree name)
       current_lang_name = name;
     }
   else
-    error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name));
+    error ("language string `\"%E\"' not recognized", name);
 }
   
 /* Get out of the current language scope.  */
@@ -5664,18 +5655,17 @@ pop_lang_context (void)
 
 /* Given an OVERLOAD and a TARGET_TYPE, return the function that
    matches the TARGET_TYPE.  If there is no satisfactory match, return
-   error_mark_node, and issue an error message if COMPLAIN is
-   nonzero.  Permit pointers to member function if PTRMEM is nonzero.
-   If TEMPLATE_ONLY, the name of the overloaded function
-   was a template-id, and EXPLICIT_TARGS are the explicitly provided
+   error_mark_node, and issue a error & warning messages under control
+   of FLAGS.  Permit pointers to member function if FLAGS permits.  If
+   TEMPLATE_ONLY, the name of the overloaded function was a
+   template-id, and EXPLICIT_TARGS are the explicitly provided
    template arguments.  */
 
 static tree
 resolve_address_of_overloaded_function (tree target_type, 
                                        tree overload,
-                                       int complain,
-                                       int ptrmem,
-                                       int template_only,
+                                       tsubst_flags_t flags,
+                                       bool template_only,
                                        tree explicit_targs)
 {
   /* Here's what the standard says:
@@ -5719,9 +5709,8 @@ resolve_address_of_overloaded_function (tree target_type,
                        && (TREE_CODE (TREE_TYPE (target_type)) 
                            == METHOD_TYPE)), 0);
 
-  if (TREE_CODE (overload) == COMPONENT_REF)
-    overload = TREE_OPERAND (overload, 1);
-
+  my_friendly_assert (is_overloaded_fn (overload), 20030910);
+  
   /* Check that the TARGET_TYPE is reasonable.  */
   if (TYPE_PTRFN_P (target_type))
     /* This is OK.  */;
@@ -5737,7 +5726,7 @@ resolve_address_of_overloaded_function (tree target_type,
     }
   else 
     {
-      if (complain)
+      if (flags & tf_error)
        error ("\
 cannot resolve overloaded function `%D' based on conversion to type `%T'", 
                  DECL_NAME (OVL_FUNCTION (overload)), target_type);
@@ -5766,7 +5755,11 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
            /* We're looking for a non-static member, and this isn't
               one, or vice versa.  */
            continue;
-       
+
+         /* Ignore anticipated decls of undeclared builtins.  */
+         if (DECL_ANTICIPATED (fn))
+           continue;
+
          /* See if there's a match.  */
          fntype = TREE_TYPE (fn);
          if (is_ptrmem)
@@ -5827,8 +5820,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
            continue;
 
          /* Instantiate the template.  */
-         instantiation = instantiate_template (fn, targs,
-                                               complain ? tf_error : tf_none);
+         instantiation = instantiate_template (fn, targs, flags);
          if (instantiation == error_mark_node)
            /* Instantiation failed.  */
            continue;
@@ -5858,7 +5850,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
   if (matches == NULL_TREE)
     {
       /* There were *no* matches.  */
-      if (complain)
+      if (flags & tf_error)
        {
          error ("no matches converting function `%D' to type `%#T'", 
                    DECL_NAME (OVL_FUNCTION (overload)),
@@ -5879,7 +5871,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
     {
       /* There were too many matches.  */
 
-      if (complain)
+      if (flags & tf_error)
        {
          tree match;
 
@@ -5902,11 +5894,11 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
   fn = TREE_PURPOSE (matches);
 
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
-      && !ptrmem && !flag_ms_extensions)
+      && !(flags & tf_ptrmem_ok) && !flag_ms_extensions)
     {
       static int explained;
       
-      if (!complain)
+      if (!(flags & tf_error))
         return error_mark_node;
 
       pedwarn ("assuming pointer to member `%D'", fn);
@@ -5916,7 +5908,13 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
           explained = 1;
         }
     }
-  mark_used (fn);
+
+  /* If we're doing overload resolution purely for the purpose of
+     determining conversion sequences, we should not consider the
+     function used.  If this conversion sequence is selected, the
+     function will be marked as used at this point.  */
+  if (!(flags & tf_conv))
+    mark_used (fn);
 
   if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
     return build_unary_op (ADDR_EXPR, fn, 0);
@@ -5933,7 +5931,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
 
 /* This function will instantiate the type of the expression given in
    RHS to match the type of LHSTYPE.  If errors exist, then return
-   error_mark_node. FLAGS is a bit mask.  If ITF_COMPLAIN is set, then
+   error_mark_node. FLAGS is a bit mask.  If TF_ERROR is set, then
    we complain on errors.  If we are not complaining, never modify rhs,
    as overload resolution wants to try many possible instantiations, in
    the hope that at least one will work.
@@ -5944,14 +5942,13 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
 tree
 instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
 {
-  int complain = (flags & tf_error);
-  int allow_ptrmem = flags & tf_ptrmem_ok;
+  tsubst_flags_t flags_in = flags;
   
   flags &= ~tf_ptrmem_ok;
   
   if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
     {
-      if (complain)
+      if (flags & tf_error)
        error ("not enough type information");
       return error_mark_node;
     }
@@ -5968,7 +5965,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
        ;
       else
        {
-         if (complain)
+         if (flags & tf_error)
            error ("argument of type `%T' does not match `%T'",
                   TREE_TYPE (rhs), lhstype);
          return error_mark_node;
@@ -5994,7 +5991,6 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
     case CONVERT_EXPR:
     case SAVE_EXPR:
     case CONSTRUCTOR:
-    case BUFFER_REF:
       abort ();
       return error_mark_node;
 
@@ -6019,13 +6015,21 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
       return instantiate_type (lhstype, rhs, flags);
 
     case COMPONENT_REF:
-      return instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+      {
+       tree addr = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+
+       if (addr != error_mark_node
+           && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
+         /* Do not lose object's side effects.  */
+         addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr),
+                        TREE_OPERAND (rhs, 0), addr);
+       return addr;
+      }
 
     case OFFSET_REF:
       rhs = TREE_OPERAND (rhs, 1);
       if (BASELINK_P (rhs))
-       return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs),
-                                flags | allow_ptrmem);
+       return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags_in);
 
       /* This can happen if we are forming a pointer-to-member for a
         member template.  */
@@ -6039,22 +6043,16 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
        tree args = TREE_OPERAND (rhs, 1);
 
        return
-         resolve_address_of_overloaded_function (lhstype,
-                                                 fns,
-                                                 complain,
-                                                 allow_ptrmem,
-                                                 /*template_only=*/1,
+         resolve_address_of_overloaded_function (lhstype, fns, flags_in,
+                                                 /*template_only=*/true,
                                                  args);
       }
 
     case OVERLOAD:
     case FUNCTION_DECL:
       return 
-       resolve_address_of_overloaded_function (lhstype, 
-                                               rhs,
-                                               complain,
-                                               allow_ptrmem,
-                                               /*template_only=*/0,
+       resolve_address_of_overloaded_function (lhstype, rhs, flags_in,
+                                               /*template_only=*/false,
                                                /*explicit_targs=*/NULL_TREE);
 
     case TREE_LIST:
@@ -6102,7 +6100,6 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
     case ABS_EXPR:
     case MAX_EXPR:
     case MIN_EXPR:
-    case FFS_EXPR:
 
     case BIT_AND_EXPR:
     case BIT_IOR_EXPR:
@@ -6116,7 +6113,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
     case PREDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      if (complain)
+      if (flags & tf_error)
        error ("invalid operation on uninstantiated type");
       return error_mark_node;
 
@@ -6132,14 +6129,14 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
     case TRUTH_NOT_EXPR:
-      if (complain)
+      if (flags & tf_error)
        error ("not enough type information");
       return error_mark_node;
 
     case COND_EXPR:
       if (type_unknown_p (TREE_OPERAND (rhs, 0)))
        {
-         if (complain)
+         if (flags & tf_error)
            error ("not enough type information");
          return error_mark_node;
        }
@@ -6171,9 +6168,6 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
       
       return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
     }
-    case ENTRY_VALUE_EXPR:
-      abort ();
-      return error_mark_node;
 
     case ERROR_MARK:
       return error_mark_node;
@@ -6193,14 +6187,20 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
 static tree
 get_vfield_name (tree type)
 {
-  tree binfo = TYPE_BINFO (type);
+  tree binfo, base_binfo;
   char *buf;
 
-  while (BINFO_BASETYPES (binfo)
-        && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
-        && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
-    binfo = BINFO_BASETYPE (binfo, 0);
+  for (binfo = TYPE_BINFO (type);
+       BINFO_N_BASE_BINFOS (binfo);
+       binfo = base_binfo)
+    {
+      base_binfo = BINFO_BASE_BINFO (binfo, 0);
 
+      if (BINFO_VIRTUAL_P (base_binfo)
+         || !TYPE_CONTAINS_VPTR_P (BINFO_TYPE (base_binfo)))
+       break;
+    }
+  
   type = BINFO_TYPE (binfo);
   buf = alloca (sizeof (VFIELD_NAME_FORMAT) + TYPE_NAME_LENGTH (type) + 2);
   sprintf (buf, VFIELD_NAME_FORMAT,
@@ -6214,8 +6214,6 @@ print_class_statistics (void)
 #ifdef GATHER_STATISTICS
   fprintf (stderr, "convert_harshness = %d\n", n_convert_harshness);
   fprintf (stderr, "compute_conversion_costs = %d\n", n_compute_conversion_costs);
-  fprintf (stderr, "build_method_call = %d (inner = %d)\n",
-          n_build_method_call, n_inner_fields_searched);
   if (n_vtables)
     {
       fprintf (stderr, "vtables = %d; vtable searches = %d\n",
@@ -6282,10 +6280,13 @@ contains_empty_class_p (tree type)
   if (CLASS_TYPE_P (type))
     {
       tree field;
+      tree binfo;
+      tree base_binfo;
       int i;
 
-      for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
-       if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
+      for (binfo = TYPE_BINFO (type), i = 0;
+          BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+       if (contains_empty_class_p (BINFO_TYPE (base_binfo)))
          return true;
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        if (TREE_CODE (field) == FIELD_DECL
@@ -6336,12 +6337,14 @@ maybe_note_name_used_in_class (tree name, tree decl)
   splay_tree names_used;
 
   /* If we're not defining a class, there's nothing to do.  */
-  if (!current_class_type || !TYPE_BEING_DEFINED (current_class_type))
+  if (!(innermost_scope_kind() == sk_class
+       && TYPE_BEING_DEFINED (current_class_type)))
     return;
   
   /* If there's already a binding for this NAME, then we don't have
      anything to worry about.  */
-  if (IDENTIFIER_CLASS_VALUE (name))
+  if (lookup_member (current_class_type, name, 
+                    /*protect=*/0, /*want_type=*/false))
     return;
 
   if (!current_class_stack[current_class_depth - 1].names_used)
@@ -6449,7 +6452,8 @@ dump_class_hierarchy_r (FILE *stream,
                         int indent)
 {
   int indented = 0;
-  tree base_binfos;
+  tree base_binfo;
+  int i;
   
   indented = maybe_indent_hierarchy (stream, indent, 0);
   fprintf (stream, "%s (0x%lx) ",
@@ -6468,7 +6472,7 @@ dump_class_hierarchy_r (FILE *stream,
     fprintf (stream, " empty");
   else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
     fprintf (stream, " nearly-empty");
-  if (TREE_VIA_VIRTUAL (binfo))
+  if (BINFO_VIRTUAL_P (binfo))
     fprintf (stream, " virtual");
   fprintf (stream, "\n");
 
@@ -6525,21 +6529,9 @@ dump_class_hierarchy_r (FILE *stream,
       if (indented)
        fprintf (stream, "\n");
     }
-  
-  base_binfos = BINFO_BASETYPES (binfo);
-  if (base_binfos)
-    {
-      int ix, n;
-
-      n = TREE_VEC_LENGTH (base_binfos);
-      for (ix = 0; ix != n; ix++)
-       {
-         tree base_binfo = TREE_VEC_ELT (base_binfos, ix);
 
-         igo = dump_class_hierarchy_r (stream, flags, base_binfo,
-                                       igo, indent + 2);
-       }
-    }
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+    igo = dump_class_hierarchy_r (stream, flags, base_binfo, igo, indent + 2);
   
   return igo;
 }
@@ -6547,14 +6539,8 @@ dump_class_hierarchy_r (FILE *stream,
 /* Dump the BINFO hierarchy for T.  */
 
 static void
-dump_class_hierarchy (tree t)
+dump_class_hierarchy_1 (FILE *stream, int flags, tree t)
 {
-  int flags;
-  FILE *stream = dump_begin (TDI_class, &flags);
-
-  if (!stream)
-    return;
-  
   fprintf (stream, "Class %s\n", type_as_string (t, TFF_PLAIN_IDENTIFIER));
   fprintf (stream, "   size=%lu align=%lu\n",
           (unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
@@ -6566,7 +6552,27 @@ dump_class_hierarchy (tree t)
                           / BITS_PER_UNIT));
   dump_class_hierarchy_r (stream, flags, TYPE_BINFO (t), TYPE_BINFO (t), 0);
   fprintf (stream, "\n");
-  dump_end (TDI_class, stream);
+}
+
+/* Debug interface to hierarchy dumping.  */
+
+extern void
+debug_class (tree t)
+{
+  dump_class_hierarchy_1 (stderr, TDF_SLIM, t);
+}
+
+static void
+dump_class_hierarchy (tree t)
+{
+  int flags;
+  FILE *stream = dump_begin (TDI_class, &flags);
+
+  if (stream)
+    {
+      dump_class_hierarchy_1 (stream, flags, t);
+      dump_end (TDI_class, stream);
+    }
 }
 
 static void
@@ -6609,7 +6615,7 @@ dump_vtable (tree t, tree binfo, tree vtable)
               type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
       if (ctor_vtbl_p)
        {
-         if (!TREE_VIA_VIRTUAL (binfo))
+         if (!BINFO_VIRTUAL_P (binfo))
            fprintf (stream, " (0x%lx instance)", (unsigned long)binfo);
          fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER));
        }
@@ -6641,6 +6647,51 @@ dump_vtt (tree t, tree vtt)
   dump_end (TDI_class, stream);
 }
 
+/* Dump a function or thunk and its thunkees.  */
+
+static void
+dump_thunk (FILE *stream, int indent, tree thunk)
+{
+  static const char spaces[] = "        ";
+  tree name = DECL_NAME (thunk);
+  tree thunks;
+      
+  fprintf (stream, "%.*s%p %s %s", indent, spaces,
+          (void *)thunk,
+          !DECL_THUNK_P (thunk) ? "function"
+          : DECL_THIS_THUNK_P (thunk) ? "this-thunk" : "covariant-thunk",
+          name ? IDENTIFIER_POINTER (name) : "<unset>");
+  if (DECL_THUNK_P (thunk))
+    {
+      HOST_WIDE_INT fixed_adjust = THUNK_FIXED_OFFSET (thunk);
+      tree virtual_adjust = THUNK_VIRTUAL_OFFSET (thunk);
+
+      fprintf (stream, " fixed=" HOST_WIDE_INT_PRINT_DEC, fixed_adjust);
+      if (!virtual_adjust)
+       /*NOP*/;
+      else if (DECL_THIS_THUNK_P (thunk))
+       fprintf (stream, " vcall="  HOST_WIDE_INT_PRINT_DEC,
+                tree_low_cst (virtual_adjust, 0));
+      else
+       fprintf (stream, " vbase=" HOST_WIDE_INT_PRINT_DEC "(%s)",
+                tree_low_cst (BINFO_VPTR_FIELD (virtual_adjust), 0),
+                type_as_string (BINFO_TYPE (virtual_adjust), TFF_SCOPE));
+      if (THUNK_ALIAS (thunk))
+       fprintf (stream, " alias to %p", (void *)THUNK_ALIAS (thunk));
+    }
+  fprintf (stream, "\n");
+  for (thunks = DECL_THUNKS (thunk); thunks; thunks = TREE_CHAIN (thunks))
+    dump_thunk (stream, indent + 2, thunks);
+}
+
+/* Dump the thunks for FN.  */
+
+extern void
+debug_thunks (tree fn)
+{
+  dump_thunk (stderr, 0, fn);
+}
+
 /* Virtual function table initialization.  */
 
 /* Create all the necessary vtables for T and its base classes.  */
@@ -6654,19 +6705,19 @@ finish_vtbls (tree t)
   /* 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);
+  list = build_tree_list (BINFO_VTABLE (TYPE_BINFO (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))
+      if (!BINFO_VIRTUAL_P (vbase))
        continue;
       accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
     }
 
-  if (TYPE_BINFO_VTABLE (t))
+  if (BINFO_VTABLE (TYPE_BINFO (t)))
     initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
 }
 
@@ -6689,14 +6740,8 @@ initialize_vtable (tree binfo, tree inits)
 static void
 initialize_array (tree decl, tree inits)
 {
-  tree context;
-
-  context = DECL_CONTEXT (decl);
-  DECL_CONTEXT (decl) = NULL_TREE;
   DECL_INITIAL (decl) = build_constructor (NULL_TREE, inits);
-  TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) = 1;
   cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
-  DECL_CONTEXT (decl) = context;
 }
 
 /* Build the VTT (virtual table table) for T.
@@ -6758,7 +6803,7 @@ binfo_ctor_vtable (tree binfo)
       vt = BINFO_VTABLE (binfo);
       if (TREE_CODE (vt) == TREE_LIST)
        vt = TREE_VALUE (vt);
-      if (TREE_CODE (vt) == TREE_VEC)
+      if (TREE_CODE (vt) == TREE_BINFO)
        binfo = vt;
       else
        break;
@@ -6810,13 +6855,9 @@ build_vtt_inits (tree binfo, tree t, tree* inits, tree* 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);
-    }
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, b); ++i)
+    if (!BINFO_VIRTUAL_P (b))
+      inits = build_vtt_inits (BINFO_BASE_BINFO (binfo, i), t, inits, index);
       
   /* Add secondary virtual pointers for all subobjects of BINFO with
      either virtual bases or reachable along a virtual path, except
@@ -6852,7 +6893,7 @@ build_vtt_inits (tree binfo, tree t, tree* inits, tree* index)
   if (top_level_p)
     for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
       {
-       if (!TREE_VIA_VIRTUAL (b))
+       if (!BINFO_VIRTUAL_P (b))
          continue;
        
        inits = build_vtt_inits (b, t, inits, index);
@@ -6872,15 +6913,13 @@ build_vtt_inits (tree binfo, tree t, tree* inits, tree* index)
   return inits;
 }
 
-/* Called from build_vtt_inits via dfs_walk.  BINFO is the binfo
-   for the base in most derived. DATA is a TREE_LIST who's
-   TREE_CHAIN is the type of the base being
-   constructed whilst this secondary vptr is live.  The TREE_UNSIGNED
-   flag of DATA indicates that this is a constructor vtable.  The
+/* Called from build_vtt_inits via dfs_walk.  BINFO is the binfo for the base
+   in most derived. DATA is a TREE_LIST who's TREE_CHAIN is the type of the
+   base being constructed whilst this secondary vptr is live.  The
    TREE_TOP_LEVEL flag indicates that this is the primary VTT.  */
 
 static tree
-dfs_build_secondary_vptr_vtt_inits (tree binfo, voiddata)
+dfs_build_secondary_vptr_vtt_inits (tree binfo, void *data)
 {
   tree l; 
   tree t;
@@ -6903,7 +6942,7 @@ dfs_build_secondary_vptr_vtt_inits (tree binfo, void* data)
     return NULL_TREE;
 
   /* We're not interested in non-virtual primary bases.  */
-  if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_P (binfo))
+  if (!BINFO_VIRTUAL_P (binfo) && BINFO_PRIMARY_P (binfo))
     return NULL_TREE;
 
   /* If BINFO has virtual bases or is reachable via a virtual path
@@ -6923,7 +6962,7 @@ dfs_build_secondary_vptr_vtt_inits (tree binfo, void* data)
                              TYPE_SIZE_UNIT (ptr_type_node));
 
   /* Add the initializer for the secondary vptr itself.  */
-  if (top_level_p && TREE_VIA_VIRTUAL (binfo))
+  if (top_level_p && BINFO_VIRTUAL_P (binfo))
     {
       /* It's a primary virtual base, and this is not the construction
          vtable. Find the base this is primary of in the inheritance graph,
@@ -6946,7 +6985,7 @@ static tree
 dfs_ctor_vtable_bases_queue_p (tree derived, int ix,
                               void* data)
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   
   if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data))
     return NULL_TREE;
@@ -7013,7 +7052,7 @@ build_ctor_vtbl_group (tree binfo, tree t)
     {
       tree b;
 
-      if (!TREE_VIA_VIRTUAL (vbase))
+      if (!BINFO_VIRTUAL_P (vbase))
        continue;
       b = copied_binfo (vbase, binfo);
       
@@ -7050,6 +7089,7 @@ accumulate_vtbl_inits (tree binfo,
                        tree inits)
 {
   int i;
+  tree base_binfo;
   int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
 
   my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
@@ -7078,15 +7118,13 @@ accumulate_vtbl_inits (tree binfo,
      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)
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
     {
-      tree base_binfo = BINFO_BASETYPE (binfo, i);
-      
       /* Skip virtual bases.  */
-      if (TREE_VIA_VIRTUAL (base_binfo))
+      if (BINFO_VIRTUAL_P (base_binfo))
        continue;
       accumulate_vtbl_inits (base_binfo,
-                            BINFO_BASETYPE (orig_binfo, i),
+                            BINFO_BASE_BINFO (orig_binfo, i),
                             rtti_binfo, t,
                             inits);
     }
@@ -7107,7 +7145,7 @@ dfs_accumulate_vtbl_inits (tree binfo,
   int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
 
   if (ctor_vtbl_p
-      && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
+      && BINFO_VIRTUAL_P (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
     {
       /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
         primary virtual base.  If it is not the same primary in
@@ -7132,14 +7170,14 @@ dfs_accumulate_vtbl_inits (tree binfo,
       for (; b; b = BINFO_PRIMARY_BASE_OF (b))
        {
          last = b;
-         if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
+         if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
            break;
        }
       /* If we run out of primary links, keep looking down our
         inheritance chain; we might be an indirect primary.  */
       if (b == NULL_TREE)
        for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
-         if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
+         if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
            break;
 
       /* If we found RTTI_BINFO, this is case 1.  If we found a virtual
@@ -7147,8 +7185,7 @@ dfs_accumulate_vtbl_inits (tree binfo,
         either case, we share our vtable with LAST, i.e. the
         derived-most base within B of which we are a primary.  */
       if (b == rtti_binfo
-         || (b && purpose_member (BINFO_TYPE (b),
-                                  CLASSTYPE_VBASECLASSES (BINFO_TYPE (rtti_binfo)))))
+         || (b && binfo_for_vbase (BINFO_TYPE (b), BINFO_TYPE (rtti_binfo))))
        /* Just set our BINFO_VTABLE to point to LAST, as we may not have
           set LAST's BINFO_VTABLE yet.  We'll extract the actual vptr in
           binfo_ctor_vtable after everything's been set up.  */
@@ -7170,18 +7207,14 @@ dfs_accumulate_vtbl_inits (tree binfo,
 
       /* Figure out the position to which the VPTR should point.  */
       vtbl = TREE_PURPOSE (l);
-      vtbl = build1 (ADDR_EXPR, 
-                    vtbl_ptr_type_node,
-                    vtbl);
-      TREE_CONSTANT (vtbl) = 1;
+      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;
+      vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
     }
 
   if (ctor_vtbl_p)
@@ -7189,7 +7222,7 @@ dfs_accumulate_vtbl_inits (tree binfo,
        So, we make a TREE_LIST.  Later, dfs_fixup_binfo_vtbls will
        straighten this out.  */
     BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
-  else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
+  else if (BINFO_PRIMARY_P (binfo) && BINFO_VIRTUAL_P (binfo))
     inits = NULL_TREE;
   else
      /* For an ordinary vtable, set BINFO_VTABLE.  */
@@ -7230,9 +7263,11 @@ build_vtbl_initializer (tree binfo,
 {
   tree v, b;
   tree vfun_inits;
-  tree vbase;
   vtbl_init_data vid;
-
+  unsigned ix;
+  tree vbinfo;
+  VEC (tree) *vbases;
+  
   /* Initialize VID.  */
   memset (&vid, 0, sizeof (vid));
   vid.binfo = binfo;
@@ -7243,7 +7278,8 @@ build_vtbl_initializer (tree binfo,
   vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
   vid.generate_vcall_entries = true;
   /* The first vbase or vcall offset is at index -3 in the vtable.  */
-  vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
+  vid.index = build_int_cst (ssizetype,
+                            -3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
 
   /* Add entries to the vtable for RTTI.  */
   build_rtti_vtbl_entries (binfo, &vid);
@@ -7254,12 +7290,12 @@ build_vtbl_initializer (tree binfo,
   VARRAY_TREE_INIT (vid.fns, 32, "fns");
   /* Add the vcall and vbase offset entries.  */
   build_vcall_and_vbase_vtbl_entries (binfo, &vid);
+  
   /* Clear BINFO_VTABLE_PATH_MARKED; it's set by
      build_vbase_offset_vtbl_entries.  */
-  for (vbase = CLASSTYPE_VBASECLASSES (t); 
-       vbase; 
-       vbase = TREE_CHAIN (vbase))
-    BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase)) = 0;
+  for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
+       VEC_iterate (tree, vbases, ix, vbinfo); ix++)
+    BINFO_VTABLE_PATH_MARKED (vbinfo) = 0;
 
   /* If the target requires padding between data entries, add that now.  */
   if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
@@ -7299,6 +7335,11 @@ build_vtbl_initializer (tree binfo,
        {
          if (!DECL_NAME (fn))
            finish_thunk (fn);
+         if (THUNK_ALIAS (fn))
+           {
+             fn = THUNK_ALIAS (fn);
+             BV_FN (v) = fn;
+           }
          fn_original = THUNK_TARGET (fn);
        }
       
@@ -7350,8 +7391,6 @@ build_vtbl_initializer (tree binfo,
          /* Take the address of the function, considering it to be of an
             appropriate generic type.  */
          init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
-         /* The address of a function can't change.  */
-         TREE_CONSTANT (init) = 1;
        }
 
       /* And add it to the chain of initializers.  */
@@ -7364,10 +7403,11 @@ build_vtbl_initializer (tree binfo,
          else
            for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
              {
-               tree fdesc = build (FDESC_EXPR, vfunc_ptr_type_node,
-                                   TREE_OPERAND (init, 0),
-                                   build_int_2 (i, 0));
+               tree fdesc = build2 (FDESC_EXPR, vfunc_ptr_type_node,
+                                    TREE_OPERAND (init, 0),
+                                    build_int_cst (NULL_TREE, i));
                TREE_CONSTANT (fdesc) = 1;
+               TREE_INVARIANT (fdesc) = 1;
 
                vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
              }
@@ -7438,7 +7478,7 @@ build_vbase_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
         base (possibly multi-level) of vid->binfo, or we wouldn't
         have called build_vcall_and_vbase_vtbl_entries for it.  But it
         might be a lost primary, so just skip down to vid->binfo.  */
-      if (TREE_VIA_VIRTUAL (non_primary_binfo))
+      if (BINFO_VIRTUAL_P (non_primary_binfo))
        {
          non_primary_binfo = vid->binfo;
          break;
@@ -7458,7 +7498,7 @@ build_vbase_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
       tree b;
       tree delta;
       
-      if (!TREE_VIA_VIRTUAL (vbase))
+      if (!BINFO_VIRTUAL_P (vbase))
        continue;
 
       /* Find the instance of this virtual base in the complete
@@ -7516,7 +7556,7 @@ build_vcall_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
   /* We only need these entries if this base is a virtual base.  We
      compute the indices -- but do not add to the vtable -- when
      building the main vtable for a class.  */
-  if (TREE_VIA_VIRTUAL (binfo) || binfo == TYPE_BINFO (vid->derived))
+  if (BINFO_VIRTUAL_P (binfo) || binfo == TYPE_BINFO (vid->derived))
     {
       /* We need a vcall offset for each of the virtual functions in this
         vtable.  For example:
@@ -7539,7 +7579,7 @@ build_vcall_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
       vid->vbase = binfo;
       /* If we are just computing the vcall indices -- but do not need
         the actual entries -- not that.  */
-      if (!TREE_VIA_VIRTUAL (binfo))
+      if (!BINFO_VIRTUAL_P (binfo))
        vid->generate_vcall_entries = false;
       /* Now, walk through the non-virtual bases, adding vcall offsets.  */
       add_vcall_offset_vtbl_entries_r (binfo, vid);
@@ -7553,12 +7593,13 @@ add_vcall_offset_vtbl_entries_r (tree binfo, vtbl_init_data* vid)
 {
   int i;
   tree primary_binfo;
+  tree base_binfo;
 
   /* Don't walk into virtual bases -- except, of course, for the
      virtual base for which we are building vcall offsets.  Any
      primary virtual base will have already had its offsets generated
      through the recursion in build_vcall_and_vbase_vtbl_entries.  */
-  if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo)
+  if (BINFO_VIRTUAL_P (binfo) && vid->vbase != binfo)
     return;
   
   /* If BINFO has a primary base, process it first.  */
@@ -7570,14 +7611,9 @@ add_vcall_offset_vtbl_entries_r (tree binfo, vtbl_init_data* vid)
   add_vcall_offset_vtbl_entries_1 (binfo, vid);
 
   /* Scan the non-primary bases of BINFO.  */
-  for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i) 
-    {
-      tree base_binfo;
-      
-      base_binfo = BINFO_BASETYPE (binfo, i);
-      if (base_binfo != primary_binfo)
-       add_vcall_offset_vtbl_entries_r (base_binfo, vid);
-    }
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+    if (base_binfo != primary_binfo)
+      add_vcall_offset_vtbl_entries_r (base_binfo, vid);
 }
 
 /* Called from build_vcall_offset_vtbl_entries_r.  */
@@ -7621,7 +7657,7 @@ add_vcall_offset_vtbl_entries_1 (tree binfo, vtbl_init_data* vid)
             base (possibly multi-level) of vid->binfo, or we wouldn't
             have called build_vcall_and_vbase_vtbl_entries for it.  But it
             might be a lost primary, so just skip down to vid->binfo.  */
-         if (TREE_VIA_VIRTUAL (non_primary_binfo))
+         if (BINFO_VIRTUAL_P (non_primary_binfo))
            {
              if (non_primary_binfo != vid->vbase)
                abort ();
@@ -7695,10 +7731,14 @@ add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
      the vtable for the most derived class, remember the vcall
      offset.  */
   if (vid->binfo == TYPE_BINFO (vid->derived))
-    CLASSTYPE_VCALL_INDICES (vid->derived) 
-      = tree_cons (orig_fn, vid->index, 
-                  CLASSTYPE_VCALL_INDICES (vid->derived));
-
+    {
+      tree_pair_p elt = VEC_safe_push (tree_pair_s,
+                                      CLASSTYPE_VCALL_INDICES (vid->derived),
+                                      NULL);
+      elt->purpose = orig_fn;
+      elt->value = vid->index;
+    }
+  
   /* The next vcall offset will be found at a more negative
      offset.  */
   vid->index = size_binop (MINUS_EXPR, vid->index,
@@ -7786,3 +7826,32 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
   *vid->last_init = build_tree_list (NULL_TREE, init);
   vid->last_init = &TREE_CHAIN (*vid->last_init);
 }
+
+/* Fold a OBJ_TYPE_REF expression to the address of a function.
+   KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF).  */
+
+tree
+cp_fold_obj_type_ref (tree ref, tree known_type)
+{
+  HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+  HOST_WIDE_INT i = 0;
+  tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
+  tree fndecl;
+
+  while (i != index)
+    {
+      i += (TARGET_VTABLE_USES_DESCRIPTORS
+           ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
+      v = TREE_CHAIN (v);
+    }
+
+  fndecl = BV_FN (v);
+
+#ifdef ENABLE_CHECKING
+  if (!tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), DECL_VINDEX (fndecl)))
+    abort ();
+#endif
+
+  return build_address (fndecl);
+}
+