OSDN Git Service

.:
[pf3gnuchains/gcc-fork.git] / gcc / cp / search.c
index b53784d..364e8f2 100644 (file)
@@ -1,7 +1,7 @@
 /* Breadth-first and depth-first routines for
    searching multiple-inheritance lattice for GNU C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -36,42 +36,6 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "stack.h"
 
-/* Obstack used for remembering decision points of breadth-first.  */
-
-static struct obstack search_obstack;
-
-/* Methods for pushing and popping objects to and from obstacks.  */
-
-struct stack_level *
-push_stack_level (obstack, tp, size)
-     struct obstack *obstack;
-     char *tp;  /* Sony NewsOS 5.0 compiler doesn't like void * here.  */
-     int size;
-{
-  struct stack_level *stack;
-  obstack_grow (obstack, tp, size);
-  stack = (struct stack_level *) ((char*)obstack_next_free (obstack) - size);
-  obstack_finish (obstack);
-  stack->obstack = obstack;
-  stack->first = (tree *) obstack_base (obstack);
-  stack->limit = obstack_room (obstack) / sizeof (tree *);
-  return stack;
-}
-
-struct stack_level *
-pop_stack_level (stack)
-     struct stack_level *stack;
-{
-  struct stack_level *tem = stack;
-  struct obstack *obstack = tem->obstack;
-  stack = tem->prev;
-  obstack_free (obstack, tem);
-  return stack;
-}
-
-#define search_level stack_level
-static struct search_level *search_stack;
-
 struct vbase_info 
 {
   /* The class dominating the hierarchy.  */
@@ -85,18 +49,10 @@ static tree dfs_check_overlap (tree, void *);
 static tree dfs_no_overlap_yet (tree, int, void *);
 static base_kind lookup_base_r (tree, tree, base_access, bool, tree *);
 static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
-static tree marked_pushdecls_p (tree, int, void *);
-static tree unmarked_pushdecls_p (tree, int, void *);
 static tree dfs_debug_unmarkedp (tree, int, void *);
 static tree dfs_debug_mark (tree, void *);
-static tree dfs_push_type_decls (tree, void *);
-static tree dfs_push_decls (tree, void *);
-static tree dfs_unuse_fields (tree, void *);
 static tree add_conversions (tree, void *);
 static int look_for_overrides_r (tree, tree);
-static struct search_level *push_search_level (struct stack_level *,
-                                              struct obstack *);
-static struct search_level *pop_search_level (struct stack_level *);
 static tree bfs_walk (tree, tree (*) (tree, void *),
                      tree (*) (tree, int, void *), void *);
 static tree lookup_field_queue_p (tree, int, void *);
@@ -108,30 +64,9 @@ static tree dfs_access_in_type (tree, void *);
 static access_kind access_in_type (tree, tree);
 static int protected_accessible_p (tree, tree, tree);
 static int friend_accessible_p (tree, tree, tree);
-static void setup_class_bindings (tree, int);
 static int template_self_reference_p (tree, tree);
 static tree dfs_get_pure_virtuals (tree, void *);
 
-/* Allocate a level of searching.  */
-
-static struct search_level *
-push_search_level (struct stack_level *stack, struct obstack *obstack)
-{
-  struct search_level tem;
-
-  tem.prev = stack;
-  return push_stack_level (obstack, (char *)&tem, sizeof (tem));
-}
-
-/* Discard a level of search allocation.  */
-
-static struct search_level *
-pop_search_level (struct stack_level *obstack)
-{
-  register struct search_level *stack = pop_stack_level (obstack);
-
-  return stack;
-}
 \f
 /* Variables for gathering statistics.  */
 #ifdef GATHER_STATISTICS
@@ -162,7 +97,7 @@ lookup_base_r (tree binfo, tree base, base_access access,
               tree *binfo_ptr)
 {
   int i;
-  tree bases, accesses;
+  tree base_binfo;
   base_kind found = bk_not_base;
   
   if (same_type_p (BINFO_TYPE (binfo), base))
@@ -188,19 +123,13 @@ lookup_base_r (tree binfo, tree base, base_access access,
       return found;
     }
   
-  bases = BINFO_BASETYPES (binfo);
-  accesses = BINFO_BASEACCESSES (binfo);
-  if (!bases)
-    return bk_not_base;
-  
-  for (i = TREE_VEC_LENGTH (bases); i--;)
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
-      tree base_binfo = TREE_VEC_ELT (bases, i);
       base_kind bk;
 
       bk = lookup_base_r (base_binfo, base,
                          access,
-                         is_virtual || TREE_VIA_VIRTUAL (base_binfo),
+                         is_virtual || BINFO_VIRTUAL_P (base_binfo),
                          binfo_ptr);
 
       switch (bk)
@@ -213,7 +142,7 @@ lookup_base_r (tree binfo, tree base, base_access access,
          
        case bk_same_type:
          bk = bk_proper_base;
-         /* FALLTHROUGH */
+         /* Fall through.  */
        case bk_proper_base:
          my_friendly_assert (found == bk_not_base, 20010723);
          found = bk;
@@ -234,6 +163,33 @@ lookup_base_r (tree binfo, tree base, base_access access,
   return found;
 }
 
+/* Returns true if type BASE is accessible in T.  (BASE is known to be
+   a (possibly non-proper) base class of T.)  */
+
+bool
+accessible_base_p (tree t, tree base)
+{
+  tree decl;
+
+  /* [class.access.base]
+
+     A base class is said to be accessible if an invented public
+     member of the base class is accessible.  
+
+     If BASE is a non-proper base, this condition is trivially
+     true.  */
+  if (same_type_p (t, base))
+    return true;
+  /* Rather than inventing a public member, we use the implicit
+     public typedef created in the scope of every class.  */
+  decl = TYPE_FIELDS (base);
+  while (!DECL_SELF_REFERENCE_P (decl))
+    decl = TREE_CHAIN (decl);
+  while (ANON_AGGR_TYPE_P (t))
+    t = TYPE_CONTEXT (t);
+  return accessible_p (t, decl);
+}
+
 /* Lookup BASE in the hierarchy dominated by T.  Do access checking as
    ACCESS specifies.  Return the binfo we discover.  If KIND_PTR is
    non-NULL, fill with information about what kind of base we
@@ -247,8 +203,8 @@ lookup_base_r (tree binfo, tree base, base_access access,
 tree
 lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
 {
-  tree binfo = NULL;           /* The binfo we've found so far.  */
-  tree t_binfo = NULL;
+  tree binfo = NULL_TREE;      /* The binfo we've found so far.  */
+  tree t_binfo = NULL_TREE;
   base_kind bk;
   
   if (t == error_mark_node || base == error_mark_node)
@@ -264,14 +220,18 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
       t_binfo = t;
       t = BINFO_TYPE (t);
     }
-  else 
-    t_binfo = TYPE_BINFO (t);
-
-  /* Ensure that the types are instantiated.  */
-  t = complete_type (TYPE_MAIN_VARIANT (t));
-  base = complete_type (TYPE_MAIN_VARIANT (base));
+  else  
+    {
+      t = complete_type (TYPE_MAIN_VARIANT (t));
+      t_binfo = TYPE_BINFO (t);
+    }
   
-  bk = lookup_base_r (t_binfo, base, access, 0, &binfo);
+  base = complete_type (TYPE_MAIN_VARIANT (base));
+
+  if (t_binfo)
+    bk = lookup_base_r (t_binfo, base, access, 0, &binfo);
+  else
+    bk = bk_not_base;
 
   /* Check that the base is unambiguous and accessible.  */
   if (access != ba_any)
@@ -290,41 +250,24 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
        break;
 
       default:
-       if (access != ba_ignore
+       if ((access & ~ba_quiet) != ba_ignore
            /* If BASE is incomplete, then BASE and TYPE are probably
               the same, in which case BASE is accessible.  If they
               are not the same, then TYPE is invalid.  In that case,
               there's no need to issue another error here, and
               there's no implicit typedef to use in the code that
               follows, so we skip the check.  */
-           && COMPLETE_TYPE_P (base))
+           && COMPLETE_TYPE_P (base)
+           && !accessible_base_p (t, base))
          {
-           tree decl;
-
-           /* [class.access.base]
-
-              A base class is said to be accessible if an invented public
-              member of the base class is accessible.  */
-           /* Rather than inventing a public member, we use the implicit
-              public typedef created in the scope of every class.  */
-           decl = TYPE_FIELDS (base);
-           while (TREE_CODE (decl) != TYPE_DECL
-                  || !DECL_ARTIFICIAL (decl)
-                  || DECL_NAME (decl) != constructor_name (base))
-             decl = TREE_CHAIN (decl);
-           while (ANON_AGGR_TYPE_P (t))
-             t = TYPE_CONTEXT (t);
-           if (!accessible_p (t, decl))
+           if (!(access & ba_quiet))
              {
-               if (!(access & ba_quiet))
-                 {
-                   error ("`%T' is an inaccessible base of `%T'", base, t);
-                   binfo = error_mark_node;
-                 }
-               else
-                 binfo = NULL_TREE;
-               bk = bk_inaccessible;
+               error ("`%T' is an inaccessible base of `%T'", base, t);
+               binfo = error_mark_node;
              }
+           else
+             binfo = NULL_TREE;
+           bk = bk_inaccessible;
          }
        break;
       }
@@ -341,8 +284,9 @@ static int
 dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
                           tree *offset_ptr)
 {
-  tree binfos, accesses;
-  int i, n_baselinks;
+  tree accesses;
+  tree base_binfo;
+  int i;
   int worst = -2;
   
   if (BINFO_TYPE (binfo) == subtype)
@@ -356,12 +300,9 @@ dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
         }
     }
   
-  binfos = BINFO_BASETYPES (binfo);
-  accesses = BINFO_BASEACCESSES (binfo);
-  n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-  for (i = 0; i < n_baselinks; i++)
+  accesses = BINFO_BASE_ACCESSES (binfo);
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
       tree base_access = TREE_VEC_ELT (accesses, i);
       int rval;
       
@@ -369,7 +310,7 @@ dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
         continue;
       rval = dynamic_cast_base_recurse
              (subtype, base_binfo,
-              is_via_virtual || TREE_VIA_VIRTUAL (base_binfo), offset_ptr);
+              is_via_virtual || BINFO_VIRTUAL_P (base_binfo), offset_ptr);
       if (worst == -2)
         worst = rval;
       else if (rval >= 0)
@@ -420,7 +361,7 @@ get_dynamic_cast_base_type (tree subtype, tree target)
 tree
 lookup_field_1 (tree type, tree name, bool want_type)
 {
-  register tree field;
+  tree field;
 
   if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
       || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
@@ -437,8 +378,8 @@ lookup_field_1 (tree type, tree name, bool want_type)
       && DECL_LANG_SPECIFIC (TYPE_NAME (type))
       && DECL_SORTED_FIELDS (TYPE_NAME (type)))
     {
-      tree *fields = &TREE_VEC_ELT (DECL_SORTED_FIELDS (TYPE_NAME (type)), 0);
-      int lo = 0, hi = TREE_VEC_LENGTH (DECL_SORTED_FIELDS (TYPE_NAME (type)));
+      tree *fields = &DECL_SORTED_FIELDS (TYPE_NAME (type))->elts[0];
+      int lo = 0, hi = DECL_SORTED_FIELDS (TYPE_NAME (type))->len;
       int i;
 
       while (lo < hi)
@@ -501,12 +442,23 @@ lookup_field_1 (tree type, tree name, bool want_type)
            return temp;
        }
       if (TREE_CODE (field) == USING_DECL)
-       /* For now, we're just treating member using declarations as
-          old ARM-style access declarations.  Thus, there's no reason
-          to return a USING_DECL, and the rest of the compiler can't
-          handle it.  Once the class is defined, these are purged
-          from TYPE_FIELDS anyhow; see handle_using_decl.  */
-       continue;
+       {
+         /* We generally treat class-scope using-declarations as
+            ARM-style access specifications, because support for the
+            ISO semantics has not been implemented.  So, in general,
+            there's no reason to return a USING_DECL, and the rest of
+            the compiler cannot handle that.  Once the class is
+            defined, USING_DECLs are purged from TYPE_FIELDS; see
+            handle_using_decl.  However, we make special efforts to
+            make using-declarations in template classes work
+            correctly.  */
+         if (CLASSTYPE_TEMPLATE_INFO (type)
+             && !CLASSTYPE_USE_TEMPLATE (type)
+             && !TREE_TYPE (field))
+           ;
+         else
+           continue;
+       }
 
       if (DECL_NAME (field) == name
          && (!want_type 
@@ -541,7 +493,7 @@ lookup_field_1 (tree type, tree name, bool want_type)
    function.  If so, we know to put the decls into the class's scope.  */
 
 tree
-current_scope ()
+current_scope (void)
 {
   if (current_function_decl == NULL_TREE)
     return current_class_type;
@@ -563,7 +515,7 @@ current_scope ()
    not within a member function body of the local class.  */
 
 int
-at_function_scope_p ()
+at_function_scope_p (void)
 {
   tree cs = current_scope ();
   return cs && TREE_CODE (cs) == FUNCTION_DECL;
@@ -572,12 +524,22 @@ at_function_scope_p ()
 /* Returns true if the innermost active scope is a class scope.  */
 
 bool
-at_class_scope_p ()
+at_class_scope_p (void)
 {
   tree cs = current_scope ();
   return cs && TYPE_P (cs);
 }
 
+/* Returns true if the innermost active scope is a namespace scope.  */
+
+bool
+at_namespace_scope_p (void)
+{
+  /* We are in a namespace scope if we are not it a class scope or a
+     function scope.  */
+  return !current_scope();
+}
+
 /* Return the scope of DECL, as appropriate when doing name-lookup.  */
 
 tree
@@ -600,7 +562,7 @@ context_for_name_lookup (tree decl)
 }
 
 /* The accessibility routines use BINFO_ACCESS for scratch space
-   during the computation of the accssibility of some declaration.  */
+   during the computation of the accessibility of some declaration.  */
 
 #define BINFO_ACCESS(NODE) \
   ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
@@ -623,7 +585,7 @@ dfs_access_in_type (tree binfo, void *data)
 
   if (context_for_name_lookup (decl) == type)
     {
-      /* If we have desceneded to the scope of DECL, just note the
+      /* If we have descended to the scope of DECL, just note the
         appropriate access.  */
       if (TREE_PRIVATE (decl))
        access = ak_private;
@@ -660,17 +622,13 @@ dfs_access_in_type (tree binfo, void *data)
       if (!access)
        {
          int i;
-         int n_baselinks;
-         tree binfos, accesses;
+         tree base_binfo, accesses;
          
          /* Otherwise, scan our baseclasses, and pick the most favorable
             access.  */
-         binfos = BINFO_BASETYPES (binfo);
-         accesses = BINFO_BASEACCESSES (binfo);
-         n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-         for (i = 0; i < n_baselinks; ++i)
+         accesses = BINFO_BASE_ACCESSES (binfo);
+         for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
            {
-             tree base_binfo = TREE_VEC_ELT (binfos, i);
              tree base_access = TREE_VEC_ELT (accesses, i);
              access_kind base_access_now = BINFO_ACCESS (base_binfo);
 
@@ -737,39 +695,36 @@ access_in_type (tree type, tree decl)
   return BINFO_ACCESS (binfo);
 }
 
-/* Called from dfs_accessible_p via dfs_walk.  */
+/* Called from accessible_p via dfs_walk.  */
 
 static tree
 dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   
   if (BINFO_MARKED (binfo))
     return NULL_TREE;
 
   /* If this class is inherited via private or protected inheritance,
      then we can't see it, unless we are a friend of the derived class.  */
-  if (BINFO_BASEACCESS (derived, ix) != access_public_node
+  if (BINFO_BASE_ACCESS (derived, ix) != access_public_node
       && !is_friend (BINFO_TYPE (derived), current_scope ()))
     return NULL_TREE;
 
   return binfo;
 }
 
-/* Called from dfs_accessible_p via dfs_walk.  */
+/* Called from accessible_p via dfs_walk.  */
 
 static tree
-dfs_accessible_p (tree binfo, void *data)
+dfs_accessible_p (tree binfo, void *data ATTRIBUTE_UNUSED)
 {
-  int protected_ok = data != 0;
   access_kind access;
 
   BINFO_MARKED (binfo) = 1;
   access = BINFO_ACCESS (binfo);
-  if (access == ak_public || (access == ak_protected && protected_ok))
-    return binfo;
-  else if (access != ak_none
-          && is_friend (BINFO_TYPE (binfo), current_scope ()))
+  if (access != ak_none
+      && is_friend (BINFO_TYPE (binfo), current_scope ()))
     return binfo;
 
   return NULL_TREE;
@@ -896,6 +851,8 @@ accessible_p (tree type, tree decl)
 {
   tree binfo;
   tree t;
+  tree scope;
+  access_kind access;
 
   /* Nonzero if it's OK to access DECL if it has protected
      accessibility in TYPE.  */
@@ -906,6 +863,18 @@ accessible_p (tree type, tree decl)
   if (!TYPE_P (context_for_name_lookup (decl)))
     return 1;
 
+  /* There is no need to perform access checks inside a thunk.  */
+  scope = current_scope ();
+  if (scope && DECL_THUNK_P (scope))
+    return 1;
+
+  /* In a template declaration, we cannot be sure whether the
+     particular specialization that is instantiated will be a friend
+     or not.  Therefore, all access checks are deferred until
+     instantiation.  */
+  if (processing_template_decl)
+    return 1;
+
   if (!TYPE_P (type))
     {
       binfo = type;
@@ -941,7 +910,7 @@ accessible_p (tree type, tree decl)
 
   /* Now, loop through the classes of which we are a friend.  */
   if (!protected_ok)
-    protected_ok = friend_accessible_p (current_scope (), decl, binfo);
+    protected_ok = friend_accessible_p (scope, decl, binfo);
 
   /* Standardize the binfo that access_in_type will use.  We don't
      need to know what path was chosen from this point onwards.  */
@@ -949,18 +918,22 @@ accessible_p (tree type, tree decl)
 
   /* Compute the accessibility of DECL in the class hierarchy
      dominated by type.  */
-  access_in_type (type, decl);
-  /* Walk the hierarchy again, looking for a base class that allows
-     access.  */
-  t = dfs_walk (binfo, dfs_accessible_p, 
-               dfs_accessible_queue_p,
-               protected_ok ? &protected_ok : 0);
-  /* Clear any mark bits.  Note that we have to walk the whole tree
-     here, since we have aborted the previous walk from some point
-     deep in the tree.  */
-  dfs_walk (binfo, dfs_unmark, 0,  0);
-
-  return t != NULL_TREE;
+  access = access_in_type (type, decl);
+  if (access == ak_public
+      || (access == ak_protected && protected_ok))
+    return 1;
+  else
+    {
+      /* Walk the hierarchy again, looking for a base class that allows
+        access.  */
+      t = dfs_walk (binfo, dfs_accessible_p, dfs_accessible_queue_p, 0);
+      /* Clear any mark bits.  Note that we have to walk the whole tree
+        here, since we have aborted the previous walk from some point
+        deep in the tree.  */
+      dfs_walk (binfo, dfs_unmark, 0,  0);
+
+      return t != NULL_TREE;
+    }
 }
 
 struct lookup_field_info {
@@ -989,7 +962,7 @@ struct lookup_field_info {
 static tree
 lookup_field_queue_p (tree derived, int ix, void *data)
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   struct lookup_field_info *lfi = (struct lookup_field_info *) data;
 
   /* Don't look for constructors or destructors in base classes.  */
@@ -1075,7 +1048,7 @@ lookup_field_r (tree binfo, void *data)
     {
       int idx = lookup_fnfields_1 (type, lfi->name);
       if (idx >= 0)
-       nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
+       nval = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
     }
 
   if (!nval)
@@ -1216,7 +1189,7 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030624);
 
-  if (TREE_CODE (xbasetype) == TREE_VEC)
+  if (TREE_CODE (xbasetype) == TREE_BINFO)
     {
       type = BINFO_TYPE (xbasetype);
       basetype_path = xbasetype;
@@ -1225,22 +1198,15 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
     {
       my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)), 20030624);
       type = xbasetype;
-      basetype_path = TYPE_BINFO (type);
-      my_friendly_assert (!BINFO_INHERITANCE_CHAIN (basetype_path), 980827);
+      xbasetype = NULL_TREE;
     }
 
-  if (type == current_class_type && TYPE_BEING_DEFINED (type)
-      && IDENTIFIER_CLASS_VALUE (name))
-    {
-      tree field = IDENTIFIER_CLASS_VALUE (name);
-      if (! is_overloaded_fn (field)
-         && ! (want_type && TREE_CODE (field) != TYPE_DECL))
-       /* We're in the scope of this class, and the value has already
-          been looked up.  Just return the cached value.  */
-       return field;
-    }
+  type = complete_type (type);
+  if (!basetype_path)
+    basetype_path = TYPE_BINFO (type);
 
-  complete_type (type);
+  if (!basetype_path)
+    return NULL_TREE;
 
 #ifdef GATHER_STATISTICS
   n_calls_lookup_field++;
@@ -1300,8 +1266,9 @@ lookup_field (tree xbasetype, tree name, int protect, bool want_type)
 {
   tree rval = lookup_member (xbasetype, name, protect, want_type);
   
-  /* Ignore functions.  */
-  if (rval && BASELINK_P (rval))
+  /* Ignore functions, but propagate the ambiguity list.  */
+  if (!error_operand_p (rval)
+      && (rval && BASELINK_P (rval)))
     return NULL_TREE;
 
   return rval;
@@ -1315,8 +1282,9 @@ lookup_fnfields (tree xbasetype, tree name, int protect)
 {
   tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false);
 
-  /* Ignore non-functions.  */
-  if (rval && !BASELINK_P (rval))
+  /* Ignore non-functions, but propagate the ambiguity list.  */
+  if (!error_operand_p (rval)
+      && (rval && !BASELINK_P (rval)))
     return NULL_TREE;
 
   return rval;
@@ -1332,20 +1300,15 @@ lookup_conversion_operator (tree class_type, tree type)
 {
   int pass;
   int i;
+  tree fn;
+  VEC(tree) *methods;
 
-  tree methods = CLASSTYPE_METHOD_VEC (class_type);
+  methods = CLASSTYPE_METHOD_VEC (class_type);
 
   for (pass = 0; pass < 2; ++pass)
     for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; 
-        i < TREE_VEC_LENGTH (methods);
-        ++i)
+        VEC_iterate (tree, methods, i, fn); ++i)
       {
-       tree fn = TREE_VEC_ELT (methods, i);
-       /* The size of the vector may have some unused slots at the
-          end.  */
-       if (!fn)
-         break;
-
        /* All the conversion operators come near the beginning of the
           class.  Therefore, if FN is not a conversion operator, there
           is no matching conversion operator in CLASS_TYPE.  */
@@ -1384,49 +1347,69 @@ lookup_conversion_operator (tree class_type, tree type)
 int
 lookup_fnfields_1 (tree type, tree name)
 {
-  tree method_vec;
-  tree *methods;
+  VEC(tree) *method_vec;
+  tree fn;
   tree tmp;
-  int i;
-  int len;
-
+  size_t i;
+  
   if (!CLASS_TYPE_P (type))
     return -1;
 
-  method_vec = CLASSTYPE_METHOD_VEC (type);
+  if (COMPLETE_TYPE_P (type))
+    {
+      if ((name == ctor_identifier
+          || name == base_ctor_identifier
+          || name == complete_ctor_identifier))
+       {
+         if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
+           lazily_declare_fn (sfk_constructor, type);
+         if (CLASSTYPE_LAZY_COPY_CTOR (type))
+           lazily_declare_fn (sfk_copy_constructor, type);
+       }
+      else if (name == ansi_assopname(NOP_EXPR)
+              && !TYPE_HAS_ASSIGN_REF (type)
+              && !TYPE_FOR_JAVA (type))
+       lazily_declare_fn (sfk_assignment_operator, type);
+    }
 
+  method_vec = CLASSTYPE_METHOD_VEC (type);
   if (!method_vec)
     return -1;
 
-  methods = &TREE_VEC_ELT (method_vec, 0);
-  len = TREE_VEC_LENGTH (method_vec);
-
 #ifdef GATHER_STATISTICS
   n_calls_lookup_fnfields_1++;
 #endif /* GATHER_STATISTICS */
 
   /* Constructors are first...  */
   if (name == ctor_identifier)
-    return (methods[CLASSTYPE_CONSTRUCTOR_SLOT] 
-           ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
+    {
+      fn = CLASSTYPE_CONSTRUCTORS (type);
+      return fn ? CLASSTYPE_CONSTRUCTOR_SLOT : -1;
+    }
   /* and destructors are second.  */
   if (name == dtor_identifier)
-    return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
-           ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
+    {
+      fn = CLASSTYPE_DESTRUCTORS (type);
+      return fn ? CLASSTYPE_DESTRUCTOR_SLOT : -1;
+    }
   if (IDENTIFIER_TYPENAME_P (name))
     return lookup_conversion_operator (type, TREE_TYPE (name));
 
   /* Skip the conversion operators.  */
-  i = CLASSTYPE_FIRST_CONVERSION_SLOT;
-  while (i < len && methods[i] && DECL_CONV_FN_P (OVL_CURRENT (methods[i])))
-    i++;
+  for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+       VEC_iterate (tree, method_vec, i, fn);
+       ++i)
+    if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+      break;
 
   /* If the type is complete, use binary search.  */
   if (COMPLETE_TYPE_P (type))
     {
-      int lo = i;
-      int hi = len;
+      int lo;
+      int hi;
 
+      lo = i;
+      hi = VEC_length (tree, method_vec);
       while (lo < hi)
        {
          i = (lo + hi) / 2;
@@ -1435,13 +1418,9 @@ lookup_fnfields_1 (tree type, tree name)
          n_outer_fields_searched++;
 #endif /* GATHER_STATISTICS */
 
-         tmp = methods[i];
-         /* This slot may be empty; we allocate more slots than we
-            need.  In that case, the entry we're looking for is
-            closer to the beginning of the list.  */
-         if (tmp)
-           tmp = DECL_NAME (OVL_CURRENT (tmp));
-         if (!tmp || tmp > name)
+         tmp = VEC_index (tree, method_vec, i);
+         tmp = DECL_NAME (OVL_CURRENT (tmp));
+         if (tmp > name)
            hi = i;
          else if (tmp < name)
            lo = i + 1;
@@ -1450,14 +1429,12 @@ lookup_fnfields_1 (tree type, tree name)
        }
     }
   else
-    for (; i < len && methods[i]; ++i)
+    for (; VEC_iterate (tree, method_vec, i, fn); ++i)
       {
 #ifdef GATHER_STATISTICS
        n_outer_fields_searched++;
 #endif /* GATHER_STATISTICS */
-       
-       tmp = OVL_CURRENT (methods[i]);
-       if (DECL_NAME (tmp) == name)
+       if (DECL_NAME (OVL_CURRENT (fn)) == name)
          return i;
       }
 
@@ -1561,7 +1538,7 @@ bfs_walk (tree binfo,
       if (rval)
        goto done;
 
-      n_bases = BINFO_N_BASETYPES (binfo);
+      n_bases = BINFO_N_BASE_BINFOS (binfo);
       for (ix = 0; ix != n_bases; ix++)
        {
          tree base_binfo;
@@ -1569,7 +1546,7 @@ bfs_walk (tree binfo,
          if (qfn)
            base_binfo = (*qfn) (binfo, ix, data);
          else
-           base_binfo = BINFO_BASETYPE (binfo, ix);
+           base_binfo = BINFO_BASE_BINFO (binfo, ix);
          
          if (base_binfo)
            {
@@ -1612,6 +1589,8 @@ dfs_walk_real (tree binfo,
               tree (*qfn) (tree, int, void *),
               void *data)
 {
+  int i;
+  tree base_binfo;
   tree rval = NULL_TREE;
 
   /* Call the pre-order walking function.  */
@@ -1623,25 +1602,17 @@ dfs_walk_real (tree binfo,
     }
 
   /* Process the basetypes.  */
-  if (BINFO_BASETYPES (binfo))
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
-      int i, n = TREE_VEC_LENGTH (BINFO_BASETYPES (binfo));
-      for (i = 0; i != n; i++)
+      if (qfn)
        {
-         tree base_binfo;
-      
-         if (qfn)
-           base_binfo = (*qfn) (binfo, i, data);
-         else
-           base_binfo = BINFO_BASETYPE (binfo, i);
-         
-         if (base_binfo)
-           {
-             rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
-             if (rval)
-               return rval;
-           }
+         base_binfo = (*qfn) (binfo, i, data);
+         if (!base_binfo)
+           continue;
        }
+      rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
+      if (rval)
+       return rval;
     }
 
   /* Call the post-order walking function.  */
@@ -1676,7 +1647,10 @@ check_final_overrider (tree overrider, tree basefn)
   tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
   tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
   int fail = 0;
-  
+
+  if (DECL_INVALID_OVERRIDER_P (overrider))
+    return 0;
+
   if (same_type_p (base_return, over_return))
     /* OK */;
   else if ((CLASS_TYPE_P (over_return) && CLASS_TYPE_P (base_return))
@@ -1715,9 +1689,7 @@ check_final_overrider (tree overrider, tree basefn)
        {
          /* can_convert will permit user defined conversion from a
             (reference to) class type. We must reject them.  */
-         over_return = TREE_TYPE (over_type);
-         if (TREE_CODE (over_return) == REFERENCE_TYPE)
-           over_return = TREE_TYPE (over_return);
+         over_return = non_reference (TREE_TYPE (over_type));
          if (CLASS_TYPE_P (over_return))
            fail = 2;
        }
@@ -1728,8 +1700,6 @@ check_final_overrider (tree overrider, tree basefn)
     fail = 2;
   if (!fail)
     /* OK */;
-  else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
-    return 0;
   else
     {
       if (fail == 1)
@@ -1743,21 +1713,16 @@ check_final_overrider (tree overrider, tree basefn)
                       overrider);
          cp_error_at ("  overriding `%#D'", basefn);
        }
-      SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
-                                  DECL_CONTEXT (overrider));
+      DECL_INVALID_OVERRIDER_P (overrider) = 1;
       return 0;
     }
   
   /* Check throw specifier is at least as strict.  */
   if (!comp_except_specs (base_throw, over_throw, 0))
     {
-      if (!IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
-       {
-         cp_error_at ("looser throw specifier for `%#F'", overrider);
-         cp_error_at ("  overriding `%#F'", basefn);
-         SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
-                                     DECL_CONTEXT (overrider));
-       }
+      cp_error_at ("looser throw specifier for `%#F'", overrider);
+      cp_error_at ("  overriding `%#F'", basefn);
+      DECL_INVALID_OVERRIDER_P (overrider) = 1;
       return 0;
     }
   
@@ -1778,14 +1743,13 @@ int
 look_for_overrides (tree type, tree fndecl)
 {
   tree binfo = TYPE_BINFO (type);
-  tree basebinfos = BINFO_BASETYPES (binfo);
-  int nbasebinfos = basebinfos ? TREE_VEC_LENGTH (basebinfos) : 0;
+  tree base_binfo;
   int ix;
   int found = 0;
 
-  for (ix = 0; ix != nbasebinfos; ix++)
+  for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
     {
-      tree basetype = BINFO_TYPE (TREE_VEC_ELT (basebinfos, ix));
+      tree basetype = BINFO_TYPE (base_binfo);
       
       if (TYPE_POLYMORPHIC_P (basetype))
         found += look_for_overrides_r (basetype, fndecl);
@@ -1801,13 +1765,19 @@ look_for_overrides_here (tree type, tree fndecl)
 {
   int ix;
 
+  /* If there are no methods in TYPE (meaning that only implicitly
+     declared methods will ever be provided for TYPE), then there are
+     no virtual functions.  */
+  if (!CLASSTYPE_METHOD_VEC (type))
+    return NULL_TREE;
+
   if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
     ix = CLASSTYPE_DESTRUCTOR_SLOT;
   else
     ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
   if (ix >= 0)
     {
-      tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
+      tree fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
   
       for (; fns; fns = OVL_NEXT (fns))
         {
@@ -1893,7 +1863,9 @@ dfs_get_pure_virtuals (tree binfo, void *data)
 void
 get_pure_virtuals (tree type)
 {
-  tree vbases;
+  unsigned ix;
+  tree binfo;
+  VEC (tree) *vbases;
 
   /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
      is going to be overridden.  */
@@ -1910,14 +1882,12 @@ get_pure_virtuals (tree type)
   /* Put the pure virtuals in dfs order.  */
   CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
 
-  for (vbases = CLASSTYPE_VBASECLASSES (type); 
-       vbases; 
-       vbases = TREE_CHAIN (vbases))
+  for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
+       VEC_iterate (tree, vbases, ix, binfo); ix++)
     {
       tree virtuals;
-
-      for (virtuals = BINFO_VIRTUALS (TREE_VALUE (vbases));
-          virtuals;
+      
+      for (virtuals = BINFO_VIRTUALS (binfo); virtuals;
           virtuals = TREE_CHAIN (virtuals))
        {
          tree base_fndecl = BV_FN (virtuals);
@@ -1932,7 +1902,7 @@ get_pure_virtuals (tree type)
 tree 
 markedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED) 
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   
   return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
 }
@@ -1940,29 +1910,11 @@ markedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
 tree
 unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED) 
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   
   return !BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
 }
 
-static tree
-marked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
-{
-  tree binfo = BINFO_BASETYPE (derived, ix);
-  
-  return (!BINFO_DEPENDENT_BASE_P (binfo)
-         && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE; 
-}
-
-static tree
-unmarked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
-{ 
-  tree binfo = BINFO_BASETYPE (derived, ix);
-  
-  return (!BINFO_DEPENDENT_BASE_P (binfo)
-         && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
-}
-
 /* The worker functions for `dfs_walk'.  These do not need to
    test anything (vis a vis marking) if they are paired with
    a predicate function (above).  */
@@ -2040,7 +1992,7 @@ dfs_debug_mark (tree binfo, void *data ATTRIBUTE_UNUSED)
 static tree 
 dfs_debug_unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   
   return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) 
          ? binfo : NULL_TREE);
@@ -2065,186 +2017,8 @@ note_debug_info_needed (tree type)
   dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
 }
 \f
-/* Subroutines of push_class_decls ().  */
-
-static void
-setup_class_bindings (tree name, int type_binding_p)
-{
-  tree type_binding = NULL_TREE;
-  tree value_binding;
-
-  /* If we've already done the lookup for this declaration, we're
-     done.  */
-  if (IDENTIFIER_CLASS_VALUE (name))
-    return;
-
-  /* First, deal with the type binding.  */
-  if (type_binding_p)
-    {
-      type_binding = lookup_member (current_class_type, name,
-                                   /*protect=*/2, /*want_type=*/true);
-      if (TREE_CODE (type_binding) == TREE_LIST 
-         && TREE_TYPE (type_binding) == error_mark_node)
-       /* NAME is ambiguous.  */
-       push_class_level_binding (name, type_binding);
-      else
-       pushdecl_class_level (type_binding);
-    }
-
-  /* Now, do the value binding.  */
-  value_binding = lookup_member (current_class_type, name,
-                                /*protect=*/2, /*want_type=*/false);
-
-  if (type_binding_p
-      && (TREE_CODE (value_binding) == TYPE_DECL
-         || DECL_CLASS_TEMPLATE_P (value_binding)
-         || (TREE_CODE (value_binding) == TREE_LIST
-             && TREE_TYPE (value_binding) == error_mark_node
-             && (TREE_CODE (TREE_VALUE (value_binding))
-                 == TYPE_DECL))))
-    /* We found a type-binding, even when looking for a non-type
-       binding.  This means that we already processed this binding
-       above.  */;
-  else if (value_binding)
-    {
-      if (TREE_CODE (value_binding) == TREE_LIST 
-         && TREE_TYPE (value_binding) == error_mark_node)
-       /* NAME is ambiguous.  */
-       push_class_level_binding (name, value_binding);
-      else
-       {
-         if (BASELINK_P (value_binding))
-           /* NAME is some overloaded functions.  */
-           value_binding = BASELINK_FUNCTIONS (value_binding);
-         pushdecl_class_level (value_binding);
-       }
-    }
-}
-
-/* Push class-level declarations for any names appearing in BINFO that
-   are TYPE_DECLS.  */
-
-static tree
-dfs_push_type_decls (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
-  tree type;
-  tree fields;
-
-  type = BINFO_TYPE (binfo);
-  for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
-    if (DECL_NAME (fields) && TREE_CODE (fields) == TYPE_DECL
-       && !(!same_type_p (type, current_class_type)
-            && template_self_reference_p (type, fields)))
-      setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/1);
-
-  /* We can't just use BINFO_MARKED because envelope_add_decl uses
-     DERIVED_FROM_P, which calls get_base_distance.  */
-  BINFO_PUSHDECLS_MARKED (binfo) = 1;
-
-  return NULL_TREE;
-}
-
-/* Push class-level declarations for any names appearing in BINFO that
-   are not TYPE_DECLS.  */
-
-static tree
-dfs_push_decls (tree binfo, void *data)
-{
-  tree type = BINFO_TYPE (binfo);
-  tree method_vec;
-  tree fields;
-  
-  for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
-    if (DECL_NAME (fields) 
-       && TREE_CODE (fields) != TYPE_DECL
-       && TREE_CODE (fields) != USING_DECL
-       && !DECL_ARTIFICIAL (fields))
-      setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
-    else if (TREE_CODE (fields) == FIELD_DECL
-            && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
-      dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
-  
-  method_vec = (CLASS_TYPE_P (type) 
-               ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
-  
-  if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
-    {
-      tree *methods;
-      tree *end;
-      
-      /* Farm out constructors and destructors.  */
-      end = TREE_VEC_END (method_vec);
-      
-      for (methods = &TREE_VEC_ELT (method_vec, 2);
-          methods < end && *methods;
-          methods++)
-       setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)), 
-                             /*type_binding_p=*/0);
-    }
-
-  BINFO_PUSHDECLS_MARKED (binfo) = 0;
-
-  return NULL_TREE;
-}
-
-/* When entering the scope of a class, we cache all of the
-   fields that that class provides within its inheritance
-   lattice.  Where ambiguities result, we mark them
-   with `error_mark_node' so that if they are encountered
-   without explicit qualification, we can emit an error
-   message.  */
-
 void
-push_class_decls (tree type)
-{
-  search_stack = push_search_level (search_stack, &search_obstack);
-
-  /* Enter type declarations and mark.  */
-  dfs_walk (TYPE_BINFO (type), dfs_push_type_decls, unmarked_pushdecls_p, 0);
-
-  /* Enter non-type declarations and unmark.  */
-  dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
-}
-
-/* Here's a subroutine we need because C lacks lambdas.  */
-
-static tree
-dfs_unuse_fields (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
-  tree type = TREE_TYPE (binfo);
-  tree fields;
-
-  for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
-    {
-      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
-       continue;
-
-      TREE_USED (fields) = 0;
-      if (DECL_NAME (fields) == NULL_TREE
-         && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
-       unuse_fields (TREE_TYPE (fields));
-    }
-
-  return NULL_TREE;
-}
-
-void
-unuse_fields (tree type)
-{
-  dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp, 0);
-}
-
-void
-pop_class_decls ()
-{
-  /* We haven't pushed a search level when dealing with cached classes,
-     so we'd better not try to pop it.  */
-  if (search_stack)
-    search_stack = pop_search_level (search_stack);
-}
-
-void
-print_search_statistics ()
+print_search_statistics (void)
 {
 #ifdef GATHER_STATISTICS
   fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
@@ -2258,13 +2032,7 @@ print_search_statistics ()
 }
 
 void
-init_search_processing ()
-{
-  gcc_obstack_init (&search_obstack);
-}
-
-void
-reinit_search_statistics ()
+reinit_search_statistics (void)
 {
 #ifdef GATHER_STATISTICS
   n_fields_searched = 0;
@@ -2279,20 +2047,22 @@ reinit_search_statistics ()
 static tree
 add_conversions (tree binfo, void *data)
 {
-  int i;
-  tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+  size_t i;
+  VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
   tree *conversions = (tree *) data;
+  tree tmp;
 
   /* Some builtin types have no method vector, not even an empty one.  */
   if (!method_vec)
     return NULL_TREE;
 
-  for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
+  for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; 
+       VEC_iterate (tree, method_vec, i, tmp);
+       ++i)
     {
-      tree tmp = TREE_VEC_ELT (method_vec, i);
       tree name;
 
-      if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
+      if (!DECL_CONV_FN_P (OVL_CURRENT (tmp)))
        break;
 
       name = DECL_NAME (OVL_CURRENT (tmp));
@@ -2300,8 +2070,27 @@ add_conversions (tree binfo, void *data)
       /* Make sure we don't already have this conversion.  */
       if (! IDENTIFIER_MARKED (name))
        {
-         *conversions = tree_cons (binfo, tmp, *conversions);
-         IDENTIFIER_MARKED (name) = 1;
+         tree t;
+
+         /* Make sure that we do not already have a conversion
+            operator for this type.  Merely checking the NAME is not
+            enough because two conversion operators to the same type
+            may not have the same NAME.  */
+         for (t = *conversions; t; t = TREE_CHAIN (t))
+           {
+             tree fn;
+             for (fn = TREE_VALUE (t); fn; fn = OVL_NEXT (fn))
+               if (same_type_p (TREE_TYPE (name),
+                                DECL_CONV_FN_TYPE (OVL_CURRENT (fn))))
+                 break;
+             if (fn)
+               break;
+           }
+         if (!t)
+           {
+             *conversions = tree_cons (binfo, tmp, *conversions);
+             IDENTIFIER_MARKED (name) = 1;
+           }
        }
     }
   return NULL_TREE;
@@ -2320,7 +2109,8 @@ lookup_conversions (tree type)
   tree conversions = NULL_TREE;
 
   complete_type (type);
-  bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
+  if (TYPE_BINFO (type))
+    bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
 
   for (t = conversions; t; t = TREE_CHAIN (t))
     IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
@@ -2342,16 +2132,17 @@ dfs_check_overlap (tree empty_binfo, void *data)
 {
   struct overlap_info *oi = (struct overlap_info *) data;
   tree binfo;
+  
   for (binfo = TYPE_BINFO (oi->compare_type); 
        ; 
-       binfo = BINFO_BASETYPE (binfo, 0))
+       binfo = BINFO_BASE_BINFO (binfo, 0))
     {
       if (BINFO_TYPE (binfo) == BINFO_TYPE (empty_binfo))
        {
          oi->found_overlap = 1;
          break;
        }
-      else if (BINFO_BASETYPES (binfo) == NULL_TREE)
+      else if (!BINFO_N_BASE_BINFOS (binfo))
        break;
     }
 
@@ -2363,7 +2154,7 @@ dfs_check_overlap (tree empty_binfo, void *data)
 static tree
 dfs_no_overlap_yet (tree derived, int ix, void *data)
 {
-  tree binfo = BINFO_BASETYPE (derived, ix);
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   struct overlap_info *oi = (struct overlap_info *) data;
   
   return !oi->found_overlap ? binfo : NULL_TREE;
@@ -2386,34 +2177,6 @@ types_overlap_p (tree empty_type, tree next_type)
   return oi.found_overlap;
 }
 
-/* Given a vtable VAR, determine which of the inherited classes the vtable
-   inherits (in a loose sense) functions from.
-
-   FIXME: This does not work with the new ABI.  */
-
-tree
-binfo_for_vtable (tree var)
-{
-  tree main_binfo = TYPE_BINFO (DECL_CONTEXT (var));
-  tree binfos = TYPE_BINFO_BASETYPES (BINFO_TYPE (main_binfo));
-  int n_baseclasses = CLASSTYPE_N_BASECLASSES (BINFO_TYPE (main_binfo));
-  int i;
-
-  for (i = 0; i < n_baseclasses; i++)
-    {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      if (base_binfo != NULL_TREE && BINFO_VTABLE (base_binfo) == var)
-       return base_binfo;
-    }
-
-  /* If no secondary base classes matched, return the primary base, if
-     there is one.  */
-  if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (main_binfo)))
-    return get_primary_binfo (main_binfo);
-
-  return main_binfo;
-}
-
 /* Returns the binfo of the first direct or indirect virtual base derived
    from BINFO, or NULL if binfo is not via virtual.  */
 
@@ -2422,7 +2185,7 @@ binfo_from_vbase (tree binfo)
 {
   for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
     {
-      if (TREE_VIA_VIRTUAL (binfo))
+      if (BINFO_VIRTUAL_P (binfo))
        return binfo;
     }
   return NULL_TREE;
@@ -2438,7 +2201,7 @@ binfo_via_virtual (tree binfo, tree limit)
   for (; binfo && (!limit || !same_type_p (BINFO_TYPE (binfo), limit));
        binfo = BINFO_INHERITANCE_CHAIN (binfo))
     {
-      if (TREE_VIA_VIRTUAL (binfo))
+      if (BINFO_VIRTUAL_P (binfo))
        return binfo;
     }
   return NULL_TREE;
@@ -2453,36 +2216,29 @@ copied_binfo (tree binfo, tree here)
 {
   tree result = NULL_TREE;
   
-  if (TREE_VIA_VIRTUAL (binfo))
+  if (BINFO_VIRTUAL_P (binfo))
     {
       tree t;
 
       for (t = here; BINFO_INHERITANCE_CHAIN (t);
           t = BINFO_INHERITANCE_CHAIN (t))
        continue;
-      
-      result = purpose_member (BINFO_TYPE (binfo),
-                              CLASSTYPE_VBASECLASSES (BINFO_TYPE (t)));
-      result = TREE_VALUE (result);
+
+      result = binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (t));
     }
   else if (BINFO_INHERITANCE_CHAIN (binfo))
     {
-      tree base_binfos;
-      int ix, n;
+      tree cbinfo;
+      tree base_binfo;
+      int ix;
       
-      base_binfos = copied_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
-      base_binfos = BINFO_BASETYPES (base_binfos);
-      n = TREE_VEC_LENGTH (base_binfos);
-      for (ix = 0; ix != n; ix++)
-       {
-         tree base = TREE_VEC_ELT (base_binfos, ix);
-         
-         if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
-           {
-             result = base;
-             break;
-           }
-       }
+      cbinfo = copied_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
+      for (ix = 0; BINFO_BASE_ITERATE (cbinfo, ix, base_binfo); ix++)
+       if (BINFO_TYPE (base_binfo) == BINFO_TYPE (binfo))
+         {
+           result = base_binfo;
+           break;
+         }
     }
   else
     {
@@ -2494,6 +2250,20 @@ copied_binfo (tree binfo, tree here)
   return result;
 }
 
+tree
+binfo_for_vbase (tree base, tree t)
+{
+  unsigned ix;
+  tree binfo;
+  VEC (tree) *vbases;
+  
+  for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
+       VEC_iterate (tree, vbases, ix, binfo); ix++)
+    if (BINFO_TYPE (binfo) == base)
+      return binfo;
+  return NULL;
+}
+
 /* BINFO is some base binfo of HERE, within some other
    hierarchy. Return the equivalent binfo, but in the hierarchy
    dominated by HERE.  This is the inverse of copied_binfo.  If BINFO
@@ -2506,13 +2276,10 @@ original_binfo (tree binfo, tree here)
   
   if (BINFO_TYPE (binfo) == BINFO_TYPE (here))
     result = here;
-  else if (TREE_VIA_VIRTUAL (binfo))
-    {
-      result = purpose_member (BINFO_TYPE (binfo),
-                              CLASSTYPE_VBASECLASSES (BINFO_TYPE (here)));
-      if (result)
-       result = TREE_VALUE (result);
-    }
+  else if (BINFO_VIRTUAL_P (binfo))
+    result = (CLASSTYPE_VBASECLASSES (BINFO_TYPE (here))
+             ? binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (here))
+             : NULL_TREE);
   else if (BINFO_INHERITANCE_CHAIN (binfo))
     {
       tree base_binfos;
@@ -2520,20 +2287,15 @@ original_binfo (tree binfo, tree here)
       base_binfos = original_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
       if (base_binfos)
        {
-         int ix, n;
+         int ix;
+         tree base_binfo;
          
-         base_binfos = BINFO_BASETYPES (base_binfos);
-         n = TREE_VEC_LENGTH (base_binfos);
-         for (ix = 0; ix != n; ix++)
-           {
-             tree base = TREE_VEC_ELT (base_binfos, ix);
-             
-             if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
-               {
-                 result = base;
-                 break;
-               }
-           }
+         for (ix = 0; (base_binfo = BINFO_BASE_BINFO (base_binfos, ix)); ix++)
+           if (BINFO_TYPE (base_binfo) == BINFO_TYPE (binfo))
+             {
+               result = base_binfo;
+               break;
+             }
        }
     }