OSDN Git Service

* class.c (build_base_path): Use build_address directly.
[pf3gnuchains/gcc-fork.git] / gcc / cp / class.c
index 8f188c4..272c4d6 100644 (file)
@@ -119,7 +119,7 @@ static void handle_using_decl (tree, tree);
 static void check_for_override (tree, tree);
 static tree dfs_modify_vtables (tree, void *);
 static tree modify_all_vtables (tree, tree);
-static void determine_primary_base (tree);
+static void determine_primary_bases (tree);
 static void finish_struct_methods (tree);
 static void maybe_warn_about_overly_private_class (tree);
 static int method_name_cmp (const void *, const void *);
@@ -147,7 +147,6 @@ static void include_empty_classes (record_layout_info);
 static void layout_class_type (tree, tree *);
 static void fixup_pending_inline (tree);
 static void fixup_inline_methods (tree);
-static void set_primary_base (tree, tree);
 static void propagate_binfo_offsets (tree, tree);
 static void layout_virtual_bases (record_layout_info, splay_tree);
 static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *);
@@ -182,7 +181,6 @@ static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree,
 static void build_rtti_vtbl_entries (tree, vtbl_init_data *);
 static void build_vcall_and_vbase_vtbl_entries (tree, 
                                                        vtbl_init_data *);
-static void mark_primary_bases (tree);
 static void clone_constructors_and_destructors (tree);
 static tree build_clone (tree, tree);
 static void update_vtable_entry_for_fn (tree, tree, tree, tree *, unsigned);
@@ -264,7 +262,7 @@ build_base_path (enum tree_code code,
       d_binfo = probe;
       if (is_empty_class (BINFO_TYPE (probe)))
        has_empty = true;
-      if (!v_binfo && TREE_VIA_VIRTUAL (probe))
+      if (!v_binfo && BINFO_VIRTUAL_P (probe))
        v_binfo = probe;
     }
 
@@ -272,11 +270,11 @@ build_base_path (enum tree_code code,
   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);
+  gcc_assert (code == MINUS_EXPR
+             ? same_type_p (BINFO_TYPE (binfo), probe)
+             : code == PLUS_EXPR
+             ? same_type_p (BINFO_TYPE (d_binfo), probe)
+             : false);
   
   if (binfo == d_binfo)
     /* Nothing to do.  */
@@ -321,7 +319,7 @@ build_base_path (enum tree_code code,
       expr = build_indirect_ref (expr, NULL);
       expr = build_simple_base_path (expr, binfo);
       if (want_pointer)
-       expr = build_unary_op (ADDR_EXPR, expr, 0);
+       expr = build_address (expr);
       target_type = TREE_TYPE (expr);
       goto out;
     }
@@ -343,16 +341,16 @@ build_base_path (enum tree_code code,
          t = TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived)));
          t = build_pointer_type (t);
          v_offset = convert (t, current_vtt_parm);
-         v_offset = build (PLUS_EXPR, t, v_offset,
-                           BINFO_VPTR_INDEX (derived));
+         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);
@@ -365,17 +363,17 @@ build_base_path (enum tree_code code,
                                                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;
     }
@@ -391,7 +389,7 @@ 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;
   
@@ -415,19 +413,12 @@ static tree
 build_simple_base_path (tree expr, tree binfo)
 {
   tree type = BINFO_TYPE (binfo);
-  tree d_binfo;
+  tree d_binfo = BINFO_INHERITANCE_CHAIN (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 ();
+      gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type);
       return expr;
     }
 
@@ -438,14 +429,13 @@ build_simple_base_path (tree expr, tree 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))
+       && DECL_FIELD_IS_BASE (field)
+       && TREE_TYPE (field) == type)
       return build_class_member_access_expr (expr, field,
                                             NULL_TREE, false);
 
   /* Didn't find the base field?!?  */
-  abort ();
+  gcc_unreachable ();
 }
 
 /* Convert OBJECT to the base TYPE.  If CHECK_ACCESS is true, an error
@@ -484,8 +474,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);
     }
@@ -558,7 +548,7 @@ build_vfn_ref (tree instance_ptr, tree idx)
                   build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
 
   /* Remember this as a method reference, for later devirtualization.  */
-  aref = build (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
+  aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
 
   return aref;
 }
@@ -581,6 +571,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.  */
@@ -601,13 +617,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;
 }
@@ -682,7 +722,7 @@ build_primary_vtable (tree binfo, tree type)
     }
   else
     {
-      my_friendly_assert (TREE_TYPE (decl) == vtbl_type_node, 20000118);
+      gcc_assert (TREE_TYPE (decl) == vtbl_type_node);
       virtuals = NULL_TREE;
     }
 
@@ -693,8 +733,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;
 }
@@ -795,42 +835,41 @@ 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)
+add_method (tree type, tree method)
 {
   int using;
-  int len;
-  int slot;
-  tree method_vec;
+  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));
 
-  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);
-
   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))
@@ -848,105 +887,38 @@ add_method (tree type, tree method, int error_p)
     }
   else
     {
-      int have_template_convs_p = 0;
-      
+      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;
        }
     }
-      
+  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.  */
@@ -956,9 +928,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;
@@ -1025,15 +995,26 @@ 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));
+  overload = build_overload (method, current_fns);
+  
+  if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
+    push_class_level_binding (DECL_NAME (method), overload);
+
+  if (insert_p)
+    {
+      /* 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
+    /* Replace the current slot. */
+    VEC_replace (tree, method_vec, slot, overload);
 }
 
 /* Subroutines of finish_struct.  */
@@ -1049,7 +1030,7 @@ alter_access (tree t, tree fdecl, tree access)
   if (!DECL_LANG_SPECIFIC (fdecl))
     retrofit_lang_decl (fdecl);
 
-  my_friendly_assert (!DECL_DISCRIMINATOR_P (fdecl), 20030624);
+  gcc_assert (!DECL_DISCRIMINATOR_P (fdecl));
 
   elem = purpose_member (t, DECL_ACCESS (fdecl));
   if (elem)
@@ -1130,7 +1111,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))
@@ -1171,7 +1152,7 @@ handle_using_decl (tree using_decl, tree t)
   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
@@ -1189,45 +1170,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);
 
+      gcc_assert (COMPLETE_TYPE_P (basetype));
+      
       /* 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.  */
@@ -1257,7 +1213,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))
@@ -1289,192 +1245,132 @@ check_bases (tree t,
     }
 }
 
-/* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy
-   dominated by TYPE that are primary bases.  */
+/* Determine all the primary bases within T.  Sets BINFO_PRIMARY_BASE_P for
+   those that are primaries.  Sets BINFO_LOST_PRIMARY_P for those
+   that have had a nearly-empty virtual primary base stolen by some
+   other base in the heirarchy.  Determines CLASSTYPE_PRIMARY_BASE for
+   T.  */
 
 static void
-mark_primary_bases (tree type)
+determine_primary_bases (tree t)
 {
-  tree binfo;
-  
-  /* Walk the bases in inheritance graph order.  */
-  for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
+  unsigned i;
+  tree primary = NULL_TREE;
+  tree type_binfo = TYPE_BINFO (t);
+  tree base_binfo;
+
+  /* Determine the primary bases of our bases.  */
+  for (base_binfo = TREE_CHAIN (type_binfo); base_binfo;
+       base_binfo = TREE_CHAIN (base_binfo))
     {
-      tree base_binfo = get_primary_binfo (binfo);
+      tree primary = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (base_binfo));
 
-      if (!base_binfo)
-       /* Not a dynamic base.  */;
-      else if (BINFO_PRIMARY_P (base_binfo))
-       BINFO_LOST_PRIMARY_P (binfo) = 1;
-      else
+      /* See if we're the non-virtual primary of our inheritance
+        chain.  */
+      if (!BINFO_VIRTUAL_P (base_binfo))
        {
-         BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
-         /* 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))
-           {
-             tree delta = size_diffop (convert (ssizetype,
-                                                BINFO_OFFSET (binfo)),
-                                       convert (ssizetype,
-                                                BINFO_OFFSET (base_binfo)));
+         tree parent = BINFO_INHERITANCE_CHAIN (base_binfo);
+         tree parent_primary = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (parent));
          
-             propagate_binfo_offsets (base_binfo, delta);
-           }
+         if (parent_primary
+             && BINFO_TYPE (base_binfo) == BINFO_TYPE (parent_primary))
+           /* We are the primary binfo.  */
+           BINFO_PRIMARY_P (base_binfo) = 1;
        }
-    }
-}
-
-/* Make the BINFO the primary base of T.  */
-
-static void
-set_primary_base (tree t, tree binfo)
-{
-  tree basetype;
-
-  CLASSTYPE_PRIMARY_BINFO (t) = binfo;
-  basetype = BINFO_TYPE (binfo);
-  TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
-  TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
-  TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
-}
-
-/* Determine the primary class for T.  */
-
-static void
-determine_primary_base (tree t)
-{
-  unsigned i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
-  tree type_binfo;
-  tree vbase_binfo;
-
-  /* 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++)
-    {
-      tree base_binfo = BINFO_BASETYPE (type_binfo, i);
-      tree basetype = BINFO_TYPE (base_binfo);
-
-      if (TYPE_CONTAINS_VPTR_P (basetype))
+      /* Determine if we have a virtual primary base, and mark it so.
+       */
+      if (primary && BINFO_VIRTUAL_P (primary))
        {
-         /* We prefer a non-virtual base, although a virtual one will
-            do.  */
-         if (TREE_VIA_VIRTUAL (base_binfo))
-           continue;
+         tree this_primary = copied_binfo (primary, base_binfo);
 
-         if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-           {
-             set_primary_base (t, base_binfo);
-             CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
-           }
+         if (BINFO_PRIMARY_P (this_primary))
+           /* Someone already claimed this base.  */
+           BINFO_LOST_PRIMARY_P (base_binfo) = 1;
          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));
+             tree delta;
+             
+             BINFO_PRIMARY_P (this_primary) = 1;
+             BINFO_INHERITANCE_CHAIN (this_primary) = base_binfo;
+             
+             /* 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.  */
+             delta = size_diffop (convert (ssizetype,
+                                           BINFO_OFFSET (base_binfo)),
+                                  convert (ssizetype,
+                                           BINFO_OFFSET (this_primary)));
+         
+             propagate_binfo_offsets (this_primary, delta);
            }
        }
     }
 
-  if (!TYPE_VFIELD (t))
-    CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
-
-  /* Find the indirect primary bases - those virtual bases which are primary
-     bases of something else in this hierarchy.  */
-  for (i = 0; (vbase_binfo = VEC_iterate
-              (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
+  /* First look for a dynamic direct non-virtual base.  */
+  for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, base_binfo); i++)
     {
-      unsigned j;
+      tree basetype = BINFO_TYPE (base_binfo);
 
-      /* 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; j != n_baseclasses; ++j) 
+      if (TYPE_CONTAINS_VPTR_P (basetype) && !BINFO_VIRTUAL_P (base_binfo))
        {
-         unsigned k;
-         tree base_vbase_binfo;
-         tree basetype = TYPE_BINFO_BASETYPE (t, j);
-         
-         for (k = 0; (base_vbase_binfo = VEC_iterate
-                      (tree, CLASSTYPE_VBASECLASSES (basetype), k)); k++)
-           {
-             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;
-               }
-           }
-
-         /* If we've discovered that this virtual base is an indirect
-            primary base, then we can move on to the next virtual
-            base.  */
-         if (BINFO_INDIRECT_PRIMARY_P (vbase_binfo))
-           break;
+         primary = base_binfo;
+         goto found;
        }
     }
 
   /* A "nearly-empty" virtual base class can be the primary base
-     class, if no non-virtual polymorphic base can be found.  */
-  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+     class, if no non-virtual polymorphic base can be found.  Look for
+     a nearly-empty virtual dynamic base that is not already a primary
+     base of something in the heirarchy.  If there is no such base,
+     just pick the first nearly-empty virtual base.  */
+
+  for (base_binfo = TREE_CHAIN (type_binfo); base_binfo;
+       base_binfo = TREE_CHAIN (base_binfo))
+    if (BINFO_VIRTUAL_P (base_binfo)
+       && CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (base_binfo)))
+      {
+       if (!BINFO_PRIMARY_P (base_binfo))
+         {
+           /* Found one that is not primary.  */
+           primary = base_binfo;
+           goto found;
+         }
+       else if (!primary)
+         /* Remember the first candidate.  */
+         primary = base_binfo;
+      }
+  
+ found:
+  /* If we've got a primary base, use it.  */
+  if (primary)
     {
-      /* If not NULL, this is the best primary base candidate we have
-         found so far.  */
-      tree candidate = NULL_TREE;
-      tree base_binfo;
-
-      /* Loop over the baseclasses.  */
-      for (base_binfo = TYPE_BINFO (t);
-          base_binfo;
-          base_binfo = TREE_CHAIN (base_binfo))
+      tree basetype = BINFO_TYPE (primary);
+      
+      CLASSTYPE_PRIMARY_BINFO (t) = primary;
+      if (BINFO_PRIMARY_P (primary))
+       /* We are stealing a primary base.  */
+       BINFO_LOST_PRIMARY_P (BINFO_INHERITANCE_CHAIN (primary)) = 1;
+      BINFO_PRIMARY_P (primary) = 1;
+      if (BINFO_VIRTUAL_P (primary))
        {
-         tree basetype = BINFO_TYPE (base_binfo);
-
-         if (TREE_VIA_VIRTUAL (base_binfo) 
-             && CLASSTYPE_NEARLY_EMPTY_P (basetype))
-           {
-             /* If this is not an indirect primary base, then it's
-                definitely our primary base.  */
-             if (!BINFO_INDIRECT_PRIMARY_P (base_binfo))
-               {
-                 candidate = base_binfo;
-                 break;
-               }
+         tree delta;
 
-             /* If this is an indirect primary base, it still could be
-                our primary base -- unless we later find there's another
-                nearly-empty virtual base that isn't an indirect
-                primary base.  */
-             if (!candidate)
-               candidate = base_binfo;
-           }
+         BINFO_INHERITANCE_CHAIN (primary) = type_binfo;
+         /* 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.  */
+         delta = size_diffop (ssize_int (0),
+                              convert (ssizetype, BINFO_OFFSET (primary)));
+         
+         propagate_binfo_offsets (primary, delta);
        }
-
-      /* 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)));
-       }       
+      
+      primary = TYPE_BINFO (basetype);
+      
+      TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
+      BINFO_VTABLE (type_binfo) = BINFO_VTABLE (primary);
+      BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary);
     }
-
-  /* Mark the primary base classes at this point.  */
-  mark_primary_bases (t);
 }
 \f
 /* Set memoizing fields and bits of T (and its variants) for later
@@ -1483,11 +1379,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.  */
@@ -1500,46 +1397,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_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;
@@ -1623,11 +1508,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;
@@ -1667,9 +1552,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
@@ -1751,24 +1634,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);
     }
 }
@@ -1793,22 +1676,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).  */
@@ -1826,23 +1701,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,
@@ -1916,7 +1784,7 @@ 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.  */
@@ -1926,6 +1794,36 @@ base_derived_from (tree derived, tree base)
   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;
@@ -1935,81 +1833,85 @@ typedef struct find_final_overrider_data_s {
   tree most_derived_type;
   /* The candidate overriders.  */
   tree candidates;
-  /* Binfos which inherited virtually on the current 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;
 }
@@ -2019,8 +1921,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;
 }
@@ -2034,6 +1936,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:
 
@@ -2055,12 +1958,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,
@@ -2068,6 +1977,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))
     {
@@ -2085,17 +1996,17 @@ 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);
-
-  return TREE_VALUE (v);
+  gcc_unreachable ();
 }
 
 /* Update an entry in the vtable for BINFO, which is in the hierarchy
@@ -2121,7 +2032,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
      calling FN through BINFO.  */
   for (b = binfo; ; b = get_primary_binfo (b))
     {
-      my_friendly_assert (b, 20021227);
+      gcc_assert (b);
       if (look_for_overrides_here (BINFO_TYPE (b), target_fn))
        break;
 
@@ -2154,7 +2065,7 @@ 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);
+         gcc_assert (DECL_RESULT_THUNK_P (fn));
          fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn));
          virtual_offset = THUNK_VIRTUAL_OFFSET (fn);
        }
@@ -2188,7 +2099,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
                {
                  /* 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;
@@ -2214,7 +2125,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
                                   fixed_offset, virtual_offset);
     }
   else
-    my_friendly_assert (!DECL_THUNK_P (fn), 20021231);
+    gcc_assert (!DECL_THUNK_P (fn));
   
   /* Assume that we will produce a thunk that convert all the way to
      the final overrider, and not to an intermediate virtual base.  */
@@ -2233,7 +2144,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;
@@ -2260,7 +2171,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
 
       while ((probe = get_primary_binfo (probe))
             && (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix)
-       if (TREE_VIA_VIRTUAL (probe))
+       if (BINFO_VIRTUAL_P (probe))
          virtual_base = probe;
       
       if (virtual_base)
@@ -2305,15 +2216,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;
@@ -2393,13 +2307,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))
       {
@@ -2415,7 +2329,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);
     }
@@ -2460,29 +2374,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);
        }
@@ -2492,9 +2411,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;
@@ -2516,8 +2435,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);
        }
     }
@@ -2642,38 +2560,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))
@@ -2925,13 +2840,13 @@ check_field_decls (tree t, tree *access_decls,
 {
   tree *field;
   tree *next;
-  int has_pointers;
+  bool has_pointers;
   int any_default_members;
 
   /* 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;
@@ -3072,9 +2987,14 @@ 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))
        {
@@ -3140,9 +3060,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);
       
@@ -3266,18 +3202,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;
 
@@ -3291,7 +3225,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));
@@ -3311,6 +3245,7 @@ walk_subobject_offsets (tree type,
       if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type))
        {
          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
@@ -3318,8 +3253,8 @@ walk_subobject_offsets (tree type,
             correct offsets for virtual bases are only known when
             working with the most derived type.  */
          if (vbases_p)
-           for (ix = 0; (binfo = VEC_iterate
-                         (tree, CLASSTYPE_VBASECLASSES (type), ix)); ix++)
+           for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
+                VEC_iterate (tree, vbases, ix, binfo); ix++)
              {
                r = walk_subobject_offsets (binfo,
                                            f,
@@ -3339,8 +3274,9 @@ walk_subobject_offsets (tree type,
                 above.)  */
              tree vbase = get_primary_binfo (type_binfo);
              
-             if (vbase && TREE_VIA_VIRTUAL (vbase)
-                 && BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
+             if (vbase && BINFO_VIRTUAL_P (vbase)
+                 && BINFO_PRIMARY_P (vbase)
+                 && BINFO_INHERITANCE_CHAIN (vbase) == type_binfo)
                {
                  r = (walk_subobject_offsets 
                       (vbase, f, offset,
@@ -3517,7 +3453,7 @@ layout_nonempty_base_or_field (record_layout_info rli,
        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))
@@ -3577,7 +3513,7 @@ layout_empty_base (tree binfo, tree eoc, splay_tree offsets)
   bool atend = false;
 
   /* This routine should only be used for empty classes.  */
-  my_friendly_assert (is_empty_class (basetype), 20000321);
+  gcc_assert (is_empty_class (basetype));
   alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
 
   if (!integer_zerop (BINFO_OFFSET (binfo)))
@@ -3657,6 +3593,7 @@ build_base_field (record_layout_info rli, tree binfo,
       DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
       DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
       DECL_IGNORED_P (decl) = 1;
+      DECL_FIELD_IS_BASE (decl) = 1;
 
       /* Try to place the field.  It may take more than one try if we
         have a hard time placing the field without putting two
@@ -3679,7 +3616,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;
@@ -3735,7 +3672,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.  */
@@ -3748,7 +3685,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.  */
@@ -3757,7 +3694,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,
@@ -3779,7 +3716,6 @@ check_methods (tree t)
       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))
@@ -3891,7 +3827,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);
@@ -3932,14 +3868,14 @@ 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
     {
-      my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
+      gcc_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn));
 
       /* For each destructor, we need three variants: an in-charge
         version, a not-in-charge version, and an in-charge deleting
@@ -3954,14 +3890,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.  */
@@ -4006,8 +3942,8 @@ adjust_clone_args (tree decl)
           decl_parms = TREE_CHAIN (decl_parms),
             clone_parms = TREE_CHAIN (clone_parms))
        {
-         my_friendly_assert (same_type_p (TREE_TYPE (decl_parms),
-                                          TREE_TYPE (clone_parms)), 20010424);
+         gcc_assert (same_type_p (TREE_TYPE (decl_parms),
+                                  TREE_TYPE (clone_parms)));
          
          if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
            {
@@ -4037,7 +3973,7 @@ adjust_clone_args (tree decl)
              break;
            }
        }
-      my_friendly_assert (!clone_parms, 20010424);
+      gcc_assert (!clone_parms);
     }
 }
 
@@ -4088,7 +4024,7 @@ type_requires_array_cookie (tree type)
   tree fns;
   bool has_two_argument_delete_p = false;
 
-  my_friendly_assert (CLASS_TYPE_P (type), 20010712);
+  gcc_assert (CLASS_TYPE_P (type));
 
   /* If there's a non-trivial destructor, we need a cookie.  In order
      to iterate through the array calling the destructor for each
@@ -4190,7 +4126,6 @@ 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);
 
@@ -4281,7 +4216,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
@@ -4351,6 +4286,7 @@ propagate_binfo_offsets (tree binfo, tree offset)
 {
   int i;
   tree primary_binfo;
+  tree base_binfo;
 
   /* Update BINFO's offset.  */
   BINFO_OFFSET (binfo)
@@ -4362,33 +4298,18 @@ propagate_binfo_offsets (tree binfo, tree offset)
   /* Find the primary base class.  */
   primary_binfo = get_primary_binfo (binfo);
 
+  if (primary_binfo && BINFO_INHERITANCE_CHAIN (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);
@@ -4407,7 +4328,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))
@@ -4436,7 +4357,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))
@@ -4498,30 +4419,32 @@ 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_P (base_binfo)
+             || BINFO_INHERITANCE_CHAIN (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 (i = 0; (binfo = VEC_iterate
-                (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
+    for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+        VEC_iterate (tree, vbases, i, base_binfo); i++)
       {
-       offset = end_of_base (binfo);
+       offset = end_of_base (base_binfo);
        if (INT_CST_LT_UNSIGNED (result, offset))
          result = offset;
       }
@@ -4543,13 +4466,16 @@ static void
 warn_about_ambiguous_bases (tree t)
 {
   int i;
+  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",
@@ -4558,8 +4484,8 @@ warn_about_ambiguous_bases (tree t)
 
   /* Check for ambiguous virtual bases.  */
   if (extra_warnings)
-    for (i = 0; (binfo = VEC_iterate
-                (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
+    for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+        VEC_iterate (tree, vbases, i, binfo); i++)
       {
        basetype = BINFO_TYPE (binfo);
        
@@ -4606,10 +4532,8 @@ include_empty_classes (record_layout_info rli)
        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);
+       gcc_assert (tree_int_cst_equal
+                   (rli->bitpos, round_down (rli->bitpos, BITS_PER_UNIT)));
       rli->bitpos 
        = size_binop (PLUS_EXPR, 
                      rli->bitpos,
@@ -4649,9 +4573,8 @@ layout_class_type (tree t, tree *virtuals_p)
   /* Start laying out the record.  */
   rli = start_record_layout (t);
 
-  /* If possible, we reuse the virtual function table pointer from one
-     of our base classes.  */
-  determine_primary_base (t);
+  /* Mark all the primary bases in the hierarchy.  */
+  determine_primary_bases (t);
 
   /* Create a pointer to our virtual function table.  */
   vptr = create_vtable_ptr (t, virtuals_p);
@@ -5002,10 +4925,8 @@ finish_struct_1 (tree t)
 
   if (COMPLETE_TYPE_P (t))
     {
-      if (IS_AGGR_TYPE (t))
-       error ("redefinition of `%#T'", t);
-      else
-       abort ();
+      gcc_assert (IS_AGGR_TYPE (t));
+      error ("redefinition of `%#T'", t);
       popclass ();
       return;
     }
@@ -5051,30 +4972,21 @@ finish_struct_1 (tree t)
     {
       tree primary = CLASSTYPE_PRIMARY_BINFO (t);
 
-      my_friendly_assert (same_type_p (DECL_FIELD_CONTEXT (vfield),
-                                      BINFO_TYPE (primary)),
-                         20010726);
+      gcc_assert (same_type_p (DECL_FIELD_CONTEXT (vfield),
+                              BINFO_TYPE (primary)));
       /* The vtable better be at the start.  */
-      my_friendly_assert (integer_zerop (DECL_FIELD_OFFSET (vfield)),
-                         20010726);
-      my_friendly_assert (integer_zerop (BINFO_OFFSET (primary)),
-                         20010726);
+      gcc_assert (integer_zerop (DECL_FIELD_OFFSET (vfield)));
+      gcc_assert (integer_zerop (BINFO_OFFSET (primary)));
       
       vfield = copy_decl (vfield);
       DECL_FIELD_CONTEXT (vfield) = t;
       TYPE_VFIELD (t) = vfield;
     }
   else
-    my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726);
+    gcc_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == 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))
     {
@@ -5092,15 +5004,14 @@ finish_struct_1 (tree t)
       int vindex;
       tree fn;
 
-      if (TYPE_BINFO_VTABLE (t))
-       my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)),
-                           20000116);
+      if (BINFO_VTABLE (TYPE_BINFO (t)))
+       gcc_assert (DECL_VIRTUAL_P (BINFO_VTABLE (TYPE_BINFO (t))));
       if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-       my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
-                           20000116);
+       gcc_assert (BINFO_VIRTUALS (TYPE_BINFO (t)) == NULL_TREE);
 
       /* 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)); 
@@ -5117,7 +5028,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);
        }
     }
 
@@ -5140,8 +5051,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),
@@ -5151,19 +5063,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);
@@ -5172,10 +5071,10 @@ 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)
+      && !DECL_VINDEX (CLASSTYPE_DESTRUCTORS (t)))
 
     {
-      tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
+      tree dtor = CLASSTYPE_DESTRUCTORS (t);
 
       /* Warn only if the dtor is non-private or the class has friends */
       if (!TREE_PRIVATE (dtor) ||
@@ -5248,8 +5147,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);
@@ -5309,9 +5224,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)
@@ -5326,11 +5238,23 @@ fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
       return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
 
     case ADDR_EXPR:
+      instance = TREE_OPERAND (instance, 0);
       if (nonnull)
-       *nonnull = 1;
-      return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+       {
+         /* Just because we see an ADDR_EXPR doesn't mean we're dealing
+            with a real object -- given &p->f, p can still be null.  */
+         tree t = get_base_address (instance);
+         /* ??? Probably should check DECL_WEAK here.  */
+         if (t && DECL_P (t))
+           *nonnull = 1;
+       }
+      return fixed_type_or_null (instance, nonnull, cdtorp);
 
     case COMPONENT_REF:
+      /* If this component is really a base class reference, then the field
+        itself isn't definitive.  */
+      if (DECL_FIELD_IS_BASE (TREE_OPERAND (instance, 1)))
+        return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
       return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp);
 
     case VAR_DECL:
@@ -5440,6 +5364,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.
 
@@ -5447,12 +5391,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)
@@ -5488,79 +5427,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_TEMPLATE_INFO (type) && !CLASSTYPE_USE_TEMPLATE (type))
-       {
-         /* If we are entering the scope of a template declaration (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, 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
@@ -5570,7 +5462,6 @@ void
 popclass (void)
 {
   poplevel_class ();
-  pop_class_decls ();
 
   current_class_depth--;
   current_class_name = current_class_stack[current_class_depth].name;
@@ -5769,11 +5660,10 @@ resolve_address_of_overloaded_function (tree target_type,
   /* By the time we get here, we should be seeing only real
      pointer-to-member types, not the internal POINTER_TYPE to
      METHOD_TYPE representation.  */
-  my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE
-                       && (TREE_CODE (TREE_TYPE (target_type)) 
-                           == METHOD_TYPE)), 0);
+  gcc_assert (TREE_CODE (target_type) != POINTER_TYPE
+             || TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE);
 
-  my_friendly_assert (is_overloaded_fn (overload), 20030910);
+  gcc_assert (is_overloaded_fn (overload));
   
   /* Check that the TARGET_TYPE is reasonable.  */
   if (TYPE_PTRFN_P (target_type))
@@ -6055,9 +5945,7 @@ 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;
+      gcc_unreachable ();
 
     case INDIRECT_REF:
     case ARRAY_REF:
@@ -6086,8 +5974,8 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
        if (addr != error_mark_node
            && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
          /* Do not lose object's side effects.  */
-         addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
-                       TREE_OPERAND (rhs, 0), addr);
+         addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr),
+                        TREE_OPERAND (rhs, 0), addr);
        return addr;
       }
 
@@ -6098,7 +5986,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
 
       /* This can happen if we are forming a pointer-to-member for a
         member template.  */
-      my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0);
+      gcc_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR);
 
       /* Fall through.  */
 
@@ -6122,14 +6010,13 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
 
     case TREE_LIST:
       /* Now we should have a baselink.  */
-      my_friendly_assert (BASELINK_P (rhs), 990412);
+      gcc_assert (BASELINK_P (rhs));
 
       return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags);
 
     case CALL_EXPR:
       /* This is too hard for now.  */
-      abort ();
-      return error_mark_node;
+      gcc_unreachable ();
 
     case PLUS_EXPR:
     case MINUS_EXPR:
@@ -6233,17 +6120,14 @@ 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;
 
     default:
-      abort ();
-      return error_mark_node;
+      gcc_unreachable ();
     }
+  return error_mark_node;
 }
 \f
 /* Return the name of the virtual function pointer field
@@ -6255,14 +6139,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,
@@ -6342,10 +6232,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
@@ -6381,7 +6274,7 @@ get_enclosing_class (tree type)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   return NULL_TREE;
@@ -6396,12 +6289,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 (innermost_scope_kind() != sk_class)
+  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)
@@ -6456,12 +6351,11 @@ get_vtbl_decl_for_binfo (tree binfo)
   decl = BINFO_VTABLE (binfo);
   if (decl && TREE_CODE (decl) == PLUS_EXPR)
     {
-      my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
-                         2000403);
+      gcc_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR);
       decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
     }
   if (decl)
-    my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
+    gcc_assert (TREE_CODE (decl) == VAR_DECL);
   return decl;
 }
 
@@ -6509,11 +6403,12 @@ 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) ",
-          type_as_string (binfo, TFF_PLAIN_IDENTIFIER),
+          type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER),
           (unsigned long) binfo);
   if (binfo != igo)
     {
@@ -6528,18 +6423,18 @@ 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");
 
   indented = 0;
-  if (BINFO_PRIMARY_BASE_OF (binfo))
+  if (BINFO_PRIMARY_P (binfo))
     {
       indented = maybe_indent_hierarchy (stream, indent + 3, indented);
       fprintf (stream, " primary-for %s (0x%lx)",
-              type_as_string (BINFO_PRIMARY_BASE_OF (binfo),
+              type_as_string (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
                               TFF_PLAIN_IDENTIFIER),
-              (unsigned long)BINFO_PRIMARY_BASE_OF (binfo));
+              (unsigned long)BINFO_INHERITANCE_CHAIN (binfo));
     }
   if (BINFO_LOST_PRIMARY_P (binfo))
     {
@@ -6585,21 +6480,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;
 }
@@ -6680,10 +6563,10 @@ dump_vtable (tree t, tree binfo, tree vtable)
       
       fprintf (stream, "%s for %s",
               ctor_vtbl_p ? "Construction vtable" : "Vtable",
-              type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
+              type_as_string (BINFO_TYPE (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));
        }
@@ -6773,19 +6656,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));
 }
 
@@ -6808,13 +6691,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);
   cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
-  DECL_CONTEXT (decl) = context;
 }
 
 /* Build the VTT (virtual table table) for T.
@@ -6876,7 +6754,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;
@@ -6922,19 +6800,15 @@ build_vtt_inits (tree binfo, tree t, tree* inits, tree* index)
   inits = &TREE_CHAIN (*inits);
   if (top_level_p)
     {
-      my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+      gcc_assert (!BINFO_VPTR_INDEX (binfo));
       BINFO_VPTR_INDEX (binfo) = *index;
     }
   *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
                       
   /* Recursively add the secondary VTTs for non-virtual bases.  */
-  for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
-    {
-      b = BINFO_BASETYPE (binfo, i);
-      if (!TREE_VIA_VIRTUAL (b))
-       inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, 
-                                inits, index);
-    }
+  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
@@ -6963,14 +6837,14 @@ build_vtt_inits (tree binfo, tree t, tree* inits, tree* index)
     {
       *inits = nreverse (secondary_vptrs);
       inits = &TREE_CHAIN (secondary_vptrs);
-      my_friendly_assert (*inits == NULL_TREE, 20000517);
+      gcc_assert (*inits == NULL_TREE);
     }
 
   /* Add the secondary VTTs for virtual bases.  */
   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);
@@ -7019,7 +6893,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
@@ -7032,20 +6906,20 @@ dfs_build_secondary_vptr_vtt_inits (tree binfo, void *data)
   index = TREE_TYPE (l);
   if (top_level_p)
     {
-      my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+      gcc_assert (!BINFO_VPTR_INDEX (binfo));
       BINFO_VPTR_INDEX (binfo) = index;
     }
   TREE_TYPE (l) = size_binop (PLUS_EXPR, index, 
                              TYPE_SIZE_UNIT (ptr_type_node));
 
   /* Add the initializer for the secondary vptr itself.  */
-  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,
          and use that base's vtable now.  */
-      while (BINFO_PRIMARY_BASE_OF (binfo))
-        binfo = BINFO_PRIMARY_BASE_OF (binfo);
+      while (BINFO_PRIMARY_P (binfo))
+        binfo = BINFO_INHERITANCE_CHAIN (binfo);
     }
   init = binfo_ctor_vtable (binfo);
   TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
@@ -7062,7 +6936,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;
@@ -7112,7 +6986,7 @@ build_ctor_vtbl_group (tree binfo, tree t)
   if (IDENTIFIER_GLOBAL_VALUE (id))
     return;
 
-  my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124);
+  gcc_assert (!same_type_p (BINFO_TYPE (binfo), t));
   /* Build a version of VTBL (with the wrong type) for use in
      constructing the addresses of secondary vtables in the
      construction vtable group.  */
@@ -7129,7 +7003,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);
       
@@ -7166,11 +7040,10 @@ 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),
-                                  BINFO_TYPE (orig_binfo)),
-                     20000517);
+  gcc_assert (same_type_p (BINFO_TYPE (binfo), BINFO_TYPE (orig_binfo)));
 
   /* If it doesn't have a vptr, we don't do anything.  */
   if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
@@ -7194,15 +7067,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);
     }
@@ -7223,7 +7094,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
@@ -7240,24 +7111,26 @@ dfs_accumulate_vtbl_inits (tree binfo,
         RTTI_BINFO.
         3) We are primary to something not a base of RTTI_BINFO.  */
          
-      tree b = BINFO_PRIMARY_BASE_OF (binfo);
+      tree b;
       tree last = NULL_TREE;
 
       /* First, look through the bases we are primary to for RTTI_BINFO
         or a virtual base.  */
-      for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+      b = binfo;
+      while (BINFO_PRIMARY_P (b))
        {
+         b = BINFO_INHERITANCE_CHAIN (b);
          last = b;
-         if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
-           break;
+         if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
+           goto found;
        }
       /* 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)
-           break;
-
+      for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
+       if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
+         break;
+    found:
+      
       /* If we found RTTI_BINFO, this is case 1.  If we found a virtual
         base B and it is a base of RTTI_BINFO, this is case 2.  In
         either case, we share our vtable with LAST, i.e. the
@@ -7292,7 +7165,7 @@ dfs_accumulate_vtbl_inits (tree binfo,
       index = size_binop (MULT_EXPR,
                          TYPE_SIZE_UNIT (vtable_entry_type),
                          index);
-      vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
+      vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
     }
 
   if (ctor_vtbl_p)
@@ -7300,7 +7173,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.  */
@@ -7344,7 +7217,8 @@ build_vtbl_initializer (tree binfo,
   vtbl_init_data vid;
   unsigned ix;
   tree vbinfo;
-
+  VEC (tree) *vbases;
+  
   /* Initialize VID.  */
   memset (&vid, 0, sizeof (vid));
   vid.binfo = binfo;
@@ -7355,7 +7229,7 @@ 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 = ssize_int(-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
 
   /* Add entries to the vtable for RTTI.  */
   build_rtti_vtbl_entries (binfo, &vid);
@@ -7369,8 +7243,8 @@ build_vtbl_initializer (tree binfo,
   
   /* Clear BINFO_VTABLE_PATH_MARKED; it's set by
      build_vbase_offset_vtbl_entries.  */
-  for (ix = 0; (vbinfo = VEC_iterate
-               (tree, CLASSTYPE_VBASECLASSES (t), ix)); ix++)
+  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.  */
@@ -7451,8 +7325,8 @@ build_vtbl_initializer (tree binfo,
          delta = BV_DELTA (v);
          vcall_index = BV_VCALL_INDEX (v);
 
-         my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
-         my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
+         gcc_assert (TREE_CODE (delta) == INTEGER_CST);
+         gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
 
          /* You can't call an abstract virtual function; it's abstract.
             So, we replace these functions with __pure_virtual.  */
@@ -7479,9 +7353,9 @@ 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;
 
@@ -7554,7 +7428,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;
@@ -7574,7 +7448,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
@@ -7596,12 +7470,8 @@ build_vbase_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
        BINFO_VPTR_FIELD (b) = delta;
 
       if (binfo != TYPE_BINFO (t))
-       {
-         /* The vbase offset had better be the same.  */
-         my_friendly_assert (tree_int_cst_equal (delta,
-                                                 BINFO_VPTR_FIELD (vbase)),
-                             20030202);
-       }
+       /* The vbase offset had better be the same.  */
+       gcc_assert (tree_int_cst_equal (delta, BINFO_VPTR_FIELD (vbase)));
 
       /* The next vbase will come at a more negative offset.  */
       vid->index = size_binop (MINUS_EXPR, vid->index,
@@ -7632,7 +7502,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:
@@ -7655,7 +7525,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);
@@ -7669,12 +7539,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.  */
@@ -7686,14 +7557,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.  */
@@ -7737,10 +7603,9 @@ 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 ();
+             gcc_assert (non_primary_binfo == vid->vbase);
              non_primary_binfo = vid->binfo;
              break;
            }
@@ -7811,10 +7676,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,
@@ -7878,7 +7747,8 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
       tree primary_base;
 
       primary_base = get_primary_binfo (b);
-      my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127);
+      gcc_assert (BINFO_PRIMARY_P (primary_base)
+                 && BINFO_INHERITANCE_CHAIN (primary_base) == b);
       b = primary_base;
     }
   offset = size_diffop (BINFO_OFFSET (vid->rtti_binfo), BINFO_OFFSET (b));
@@ -7911,7 +7781,7 @@ 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 = TYPE_BINFO_VIRTUALS (known_type); 
+  tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
   tree fndecl;
 
   while (i != index)
@@ -7924,9 +7794,10 @@ cp_fold_obj_type_ref (tree ref, tree known_type)
   fndecl = BV_FN (v);
 
 #ifdef ENABLE_CHECKING
-  if (!tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), DECL_VINDEX (fndecl)))
-    abort ();
+  gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref),
+                                 DECL_VINDEX (fndecl)));
 #endif
 
   return build_address (fndecl);
 }
+