OSDN Git Service

* parser.c (cp_parser_simple_type_specifier): Fix typo.
[pf3gnuchains/gcc-fork.git] / gcc / cp / search.c
index cab3bbb..63cb639 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 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.  */
@@ -81,76 +45,28 @@ struct vbase_info
   tree inits;
 };
 
-static tree lookup_field_1 PARAMS ((tree, tree));
-static int is_subobject_of_p PARAMS ((tree, tree, tree));
-static int is_subobject_of_p_1 PARAMS ((tree, tree, tree));
-static tree dfs_check_overlap PARAMS ((tree, void *));
-static tree dfs_no_overlap_yet PARAMS ((tree, void *));
-static base_kind lookup_base_r
-       PARAMS ((tree, tree, base_access, int, int, int, tree *));
-static int dynamic_cast_base_recurse PARAMS ((tree, tree, int, tree *));
-static tree marked_pushdecls_p PARAMS ((tree, void *));
-static tree unmarked_pushdecls_p PARAMS ((tree, void *));
-static tree dfs_debug_unmarkedp PARAMS ((tree, void *));
-static tree dfs_debug_mark PARAMS ((tree, void *));
-static tree dfs_get_vbase_types PARAMS ((tree, void *));
-static tree dfs_push_type_decls PARAMS ((tree, void *));
-static tree dfs_push_decls PARAMS ((tree, void *));
-static tree dfs_unuse_fields PARAMS ((tree, void *));
-static tree add_conversions PARAMS ((tree, void *));
-static int look_for_overrides_r PARAMS ((tree, tree));
-static struct search_level *push_search_level
-       PARAMS ((struct stack_level *, struct obstack *));
-static struct search_level *pop_search_level
-       PARAMS ((struct stack_level *));
-static tree bfs_walk
-       PARAMS ((tree, tree (*) (tree, void *), tree (*) (tree, void *),
-              void *));
-static tree lookup_field_queue_p PARAMS ((tree, void *));
-static int shared_member_p PARAMS ((tree));
-static tree lookup_field_r PARAMS ((tree, void *));
-static tree canonical_binfo PARAMS ((tree));
-static tree shared_marked_p PARAMS ((tree, void *));
-static tree shared_unmarked_p PARAMS ((tree, void *));
-static int  dependent_base_p PARAMS ((tree));
-static tree dfs_accessible_queue_p PARAMS ((tree, void *));
-static tree dfs_accessible_p PARAMS ((tree, void *));
-static tree dfs_access_in_type PARAMS ((tree, void *));
-static access_kind access_in_type PARAMS ((tree, tree));
-static tree dfs_canonical_queue PARAMS ((tree, void *));
-static tree dfs_assert_unmarked_p PARAMS ((tree, void *));
-static void assert_canonical_unmarked PARAMS ((tree));
-static int protected_accessible_p PARAMS ((tree, tree, tree));
-static int friend_accessible_p PARAMS ((tree, tree, tree));
-static void setup_class_bindings PARAMS ((tree, int));
-static int template_self_reference_p PARAMS ((tree, tree));
-static tree dfs_find_vbase_instance PARAMS ((tree, void *));
-static tree dfs_get_pure_virtuals PARAMS ((tree, void *));
-static tree dfs_build_inheritance_graph_order PARAMS ((tree, void *));
-
-/* Allocate a level of searching.  */
-
-static struct search_level *
-push_search_level (stack, obstack)
-     struct stack_level *stack;
-     struct obstack *obstack;
-{
-  struct search_level tem;
+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 dfs_debug_unmarkedp (tree, int, void *);
+static tree dfs_debug_mark (tree, void *);
+static tree add_conversions (tree, void *);
+static int look_for_overrides_r (tree, tree);
+static tree bfs_walk (tree, tree (*) (tree, void *),
+                     tree (*) (tree, int, void *), void *);
+static tree lookup_field_queue_p (tree, int, void *);
+static int shared_member_p (tree);
+static tree lookup_field_r (tree, void *);
+static tree dfs_accessible_queue_p (tree, int, void *);
+static tree dfs_accessible_p (tree, void *);
+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 int template_self_reference_p (tree, tree);
+static tree dfs_get_pure_virtuals (tree, void *);
 
-  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 (obstack)
-     struct stack_level *obstack;
-{
-  register struct search_level *stack = pop_stack_level (obstack);
-
-  return stack;
-}
 \f
 /* Variables for gathering statistics.  */
 #ifdef GATHER_STATISTICS
@@ -165,12 +81,8 @@ static int n_contexts_saved;
 \f
 /* Worker for lookup_base.  BINFO is the binfo we are searching at,
    BASE is the RECORD_TYPE we are searching for.  ACCESS is the
-   required access checks.  WITHIN_CURRENT_SCOPE, IS_NON_PUBLIC and
-   IS_VIRTUAL indicate how BINFO was reached from the start of the
-   search.  WITHIN_CURRENT_SCOPE is true if we met the current scope,
-   or friend thereof (this allows us to determine whether a protected
-   base is accessible or not).  IS_NON_PUBLIC indicates whether BINFO
-   is accessible and IS_VIRTUAL indicates if it is morally virtual.
+   required access checks.  IS_VIRTUAL indicates if BINFO is morally
+   virtual.
 
    If BINFO is of the required type, then *BINFO_PTR is examined to
    compare with any other instance of BASE we might have already
@@ -180,28 +92,14 @@ static int n_contexts_saved;
    Otherwise BINFO's bases are searched.  */
 
 static base_kind
-lookup_base_r (binfo, base, access, within_current_scope,
-              is_non_public, is_virtual, binfo_ptr)
-     tree binfo, base;
-     base_access access;
-     int within_current_scope;
-     int is_non_public;                /* inside a non-public part */
-     int is_virtual;           /* inside a virtual part */
-     tree *binfo_ptr;
+lookup_base_r (tree binfo, tree base, base_access access,
+              bool is_virtual,                 /* inside a virtual part */
+              tree *binfo_ptr)
 {
   int i;
-  tree bases;
+  tree base_binfo;
   base_kind found = bk_not_base;
   
-  if (access == ba_check
-      && !within_current_scope
-      && is_friend (BINFO_TYPE (binfo), current_scope ()))
-    {
-      /* Do not clear is_non_public here.  If A is a private base of B, A
-        is not allowed to convert a B* to an A*.  */
-      within_current_scope = 1;
-    }
-  
   if (same_type_p (BINFO_TYPE (binfo), base))
     {
       /* We have found a base. Check against what we have found
@@ -209,13 +107,10 @@ lookup_base_r (binfo, base, access, within_current_scope,
       found = bk_same_type;
       if (is_virtual)
        found = bk_via_virtual;
-      if (is_non_public)
-       found = bk_inaccessible;
       
       if (!*binfo_ptr)
        *binfo_ptr = binfo;
-      else if (!is_virtual || !tree_int_cst_equal (BINFO_OFFSET (binfo),
-                                                  BINFO_OFFSET (*binfo_ptr)))
+      else if (binfo != *binfo_ptr)
        {
          if (access != ba_any)
            *binfo_ptr = NULL;
@@ -228,36 +123,13 @@ lookup_base_r (binfo, base, access, within_current_scope,
       return found;
     }
   
-  bases = BINFO_BASETYPES (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);
-      int this_non_public = is_non_public;
-      int this_virtual = is_virtual;
       base_kind bk;
 
-      if (access <= ba_ignore)
-       ; /* no change */
-      else if (TREE_VIA_PUBLIC (base_binfo))
-       ; /* no change */
-      else if (access == ba_not_special)
-       this_non_public = 1;
-      else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope)
-       ; /* no change */
-      else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
-       ; /* no change */
-      else
-       this_non_public = 1;
-      
-      if (TREE_VIA_VIRTUAL (base_binfo))
-       this_virtual = 1;
-      
       bk = lookup_base_r (base_binfo, base,
-                         access, within_current_scope,
-                         this_non_public, this_virtual,
+                         access,
+                         is_virtual || BINFO_VIRTUAL_P (base_binfo),
                          binfo_ptr);
 
       switch (bk)
@@ -268,17 +140,9 @@ lookup_base_r (binfo, base, access, within_current_scope,
          found = bk;
          break;
          
-       case bk_inaccessible:
-         if (found == bk_not_base)
-           found = bk;
-         my_friendly_assert (found == bk_via_virtual
-                             || found == bk_inaccessible, 20010723);
-         
-         break;
-         
        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;
@@ -291,15 +155,45 @@ lookup_base_r (binfo, base, access, within_current_scope,
          
        case bk_not_base:
          break;
+
+       default:
+         abort ();
        }
     }
   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 (which might not be
-   canonical).  If KIND_PTR is non-NULL, fill with information about
-   what kind of base we discovered.
+   ACCESS specifies.  Return the binfo we discover.  If KIND_PTR is
+   non-NULL, fill with information about what kind of base we
+   discovered.
 
    If the base is inaccessible, or ambiguous, and the ba_quiet bit is
    not set in ACCESS, then an error is issued and error_mark_node is
@@ -307,13 +201,10 @@ lookup_base_r (binfo, base, access, within_current_scope,
    NULL_TREE is returned.  */
 
 tree
-lookup_base (t, base, access, kind_ptr)
-     tree t, base;
-     base_access access;
-     base_kind *kind_ptr;
+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)
@@ -329,40 +220,58 @@ lookup_base (t, base, access, 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));
-  
-  bk = lookup_base_r (t_binfo, base, access & ~ba_quiet,
-                     0, 0, 0, &binfo);
-
-  switch (bk)
+  else  
     {
-    case bk_inaccessible:
-      binfo = NULL_TREE;
-      if (!(access & ba_quiet))
-       {
-         error ("`%T' is an inaccessible base of `%T'", base, t);
-         binfo = error_mark_node;
-       }
-      break;
-    case bk_ambig:
-      if (access != ba_any)
-       {
-         binfo = NULL_TREE;
-         if (!(access & ba_quiet))
-           {
-             error ("`%T' is an ambiguous base of `%T'", base, t);
-             binfo = error_mark_node;
-           }
-       }
-      break;
-    default:;
+      t = complete_type (TYPE_MAIN_VARIANT (t));
+      t_binfo = TYPE_BINFO (t);
     }
   
+  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)
+    switch (bk)
+      {
+      case bk_not_base:
+       break;
+
+      case bk_ambig:
+       binfo = NULL_TREE;
+       if (!(access & ba_quiet))
+         {
+           error ("`%T' is an ambiguous base of `%T'", base, t);
+           binfo = error_mark_node;
+         }
+       break;
+
+      default:
+       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)
+           && !accessible_base_p (t, base))
+         {
+           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;
+         }
+       break;
+      }
+
   if (kind_ptr)
     *kind_ptr = bk;
   
@@ -372,19 +281,17 @@ lookup_base (t, base, access, kind_ptr)
 /* Worker function for get_dynamic_cast_base_type.  */
 
 static int
-dynamic_cast_base_recurse (subtype, binfo, via_virtual, offset_ptr)
-     tree subtype;
-     tree binfo;
-     int via_virtual;
-     tree *offset_ptr;
+dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
+                          tree *offset_ptr)
 {
-  tree binfos;
-  int i, n_baselinks;
+  tree accesses;
+  tree base_binfo;
+  int i;
   int worst = -2;
   
   if (BINFO_TYPE (binfo) == subtype)
     {
-      if (via_virtual)
+      if (is_via_virtual)
         return -1;
       else
         {
@@ -393,18 +300,17 @@ dynamic_cast_base_recurse (subtype, binfo, via_virtual, offset_ptr)
         }
     }
   
-  binfos = BINFO_BASETYPES (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;
       
-      if (!TREE_VIA_PUBLIC (base_binfo))
+      if (base_access != access_public_node)
         continue;
       rval = dynamic_cast_base_recurse
              (subtype, base_binfo,
-              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)
@@ -429,13 +335,11 @@ dynamic_cast_base_recurse (subtype, binfo, via_virtual, offset_ptr)
    BOFF == -3, SUBTYPE occurs as multiple public non-virtual bases.  */
 
 tree
-get_dynamic_cast_base_type (subtype, target)
-     tree subtype;
-     tree target;
+get_dynamic_cast_base_type (tree subtype, tree target)
 {
   tree offset = NULL_TREE;
   int boff = dynamic_cast_base_recurse (subtype, TYPE_BINFO (target),
-                                        0, &offset);
+                                        false, &offset);
   
   if (!boff)
     return offset;
@@ -444,20 +348,20 @@ get_dynamic_cast_base_type (subtype, target)
   return offset;
 }
 
-/* Search for a member with name NAME in a multiple inheritance lattice
-   specified by TYPE.  If it does not exist, return NULL_TREE.
+/* Search for a member with name NAME in a multiple inheritance
+   lattice specified by TYPE.  If it does not exist, return NULL_TREE.
    If the member is ambiguously referenced, return `error_mark_node'.
-   Otherwise, return the FIELD_DECL.  */
+   Otherwise, return a DECL with the indicated name.  If WANT_TYPE is
+   true, type declarations are preferred.  */
 
 /* Do a 1-level search for NAME as a member of TYPE.  The caller must
    figure out whether it can access this field.  (Since it is only one
    level, this is reasonable.)  */
 
-static tree
-lookup_field_1 (type, name)
-     tree type, name;
+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
@@ -474,8 +378,8 @@ lookup_field_1 (type, name)
       && 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)
@@ -492,14 +396,28 @@ lookup_field_1 (type, name)
            lo = i + 1;
          else
            {
+             field = NULL_TREE;
+
              /* We might have a nested class and a field with the
                 same name; we sorted them appropriately via
-                field_decl_cmp, so just look for the last field with
-                this name.  */
-             while (i + 1 < hi
-                    && DECL_NAME (fields[i+1]) == name)
-               ++i;
-             return fields[i];
+                field_decl_cmp, so just look for the first or last
+                field with this name.  */
+             if (want_type)
+               {
+                 do
+                   field = fields[i--];
+                 while (i >= lo && DECL_NAME (fields[i]) == name);
+                 if (TREE_CODE (field) != TYPE_DECL
+                     && !DECL_CLASS_TEMPLATE_P (field))
+                   field = NULL_TREE;
+               }
+             else
+               {
+                 do
+                   field = fields[i++];
+                 while (i < hi && DECL_NAME (fields[i]) == name);
+               }
+             return field;
            }
        }
       return NULL_TREE;
@@ -510,7 +428,7 @@ lookup_field_1 (type, name)
 #ifdef GATHER_STATISTICS
   n_calls_lookup_field_1++;
 #endif /* GATHER_STATISTICS */
-  while (field)
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     {
 #ifdef GATHER_STATISTICS
       n_fields_searched++;
@@ -519,20 +437,34 @@ lookup_field_1 (type, name)
       if (DECL_NAME (field) == NULL_TREE
          && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
        {
-         tree temp = lookup_field_1 (TREE_TYPE (field), name);
+         tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type);
          if (temp)
            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.  */
-       ;
-      else if (DECL_NAME (field) == name)
+       {
+         /* 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 
+             || TREE_CODE (field) == TYPE_DECL
+             || DECL_CLASS_TEMPLATE_P (field)))
        return field;
-      field = TREE_CHAIN (field);
     }
   /* Not found.  */
   if (name == vptr_identifier)
@@ -561,7 +493,7 @@ lookup_field_1 (type, name)
    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;
@@ -583,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;
@@ -592,17 +524,26 @@ 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
-context_for_name_lookup (decl)
-     tree decl;
+context_for_name_lookup (tree decl)
 {
   /* [class.union]
      
@@ -620,92 +561,23 @@ context_for_name_lookup (decl)
   return context;
 }
 
-/* Return a canonical BINFO if BINFO is a virtual base, or just BINFO
-   otherwise.  */
-
-static tree
-canonical_binfo (binfo)
-     tree binfo;
-{
-  return (TREE_VIA_VIRTUAL (binfo)
-         ? TYPE_BINFO (BINFO_TYPE (binfo)) : binfo);
-}
-
-/* A queue function that simply ensures that we walk into the
-   canonical versions of virtual bases.  */
-
-static tree
-dfs_canonical_queue (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{
-  return canonical_binfo (binfo);
-}
-
-/* Called via dfs_walk from assert_canonical_unmarked.  */
-
-static tree
-dfs_assert_unmarked_p (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{
-  my_friendly_assert (!BINFO_MARKED (binfo), 0);
-  return NULL_TREE;
-}
-
-/* Asserts that all the nodes below BINFO (using the canonical
-   versions of virtual bases) are unmarked.  */
-
-static void
-assert_canonical_unmarked (binfo)
-     tree binfo;
-{
-  dfs_walk (binfo, dfs_assert_unmarked_p, dfs_canonical_queue, 0);
-}
-
-/* If BINFO is marked, return a canonical version of BINFO.
-   Otherwise, return NULL_TREE.  */
-
-static tree
-shared_marked_p (binfo, data)
-     tree binfo;
-     void *data;
-{
-  binfo = canonical_binfo (binfo);
-  return markedp (binfo, data);
-}
-
-/* If BINFO is not marked, return a canonical version of BINFO.
-   Otherwise, return NULL_TREE.  */
-
-static tree
-shared_unmarked_p (binfo, data)
-     tree binfo;
-     void *data;
-{
-  binfo = canonical_binfo (binfo);
-  return unmarkedp (binfo, data);
-}
-
 /* 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_LANG_FLAG_1 (NODE) << 1) | TREE_LANG_FLAG_6 (NODE)))
+  ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
 
 /* Set the access associated with NODE to ACCESS.  */
 
 #define SET_BINFO_ACCESS(NODE, ACCESS)                 \
-  ((TREE_LANG_FLAG_1 (NODE) = ((ACCESS) & 2) != 0),    \
-   (TREE_LANG_FLAG_6 (NODE) = ((ACCESS) & 1) != 0))
+  ((TREE_PUBLIC (NODE) = ((ACCESS) & 2) != 0), \
+   (TREE_PRIVATE (NODE) = ((ACCESS) & 1) != 0))
 
 /* Called from access_in_type via dfs_walk.  Calculate the access to
    DATA (which is really a DECL) in BINFO.  */
 
 static tree
-dfs_access_in_type (binfo, data)
-     tree binfo;
-     void *data;
+dfs_access_in_type (tree binfo, void *data)
 {
   tree decl = (tree) data;
   tree type = BINFO_TYPE (binfo);
@@ -713,7 +585,7 @@ dfs_access_in_type (binfo, 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;
@@ -731,51 +603,55 @@ dfs_access_in_type (binfo, data)
       if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
        {
          tree decl_access = purpose_member (type, DECL_ACCESS (decl));
+         
          if (decl_access)
-           access = ((access_kind) 
-                     TREE_INT_CST_LOW (TREE_VALUE (decl_access)));
+           {
+             decl_access = TREE_VALUE (decl_access);
+             
+             if (decl_access == access_public_node)
+               access = ak_public;
+             else if (decl_access == access_protected_node)
+               access = ak_protected;
+             else if (decl_access == access_private_node)
+               access = ak_private;
+             else
+               my_friendly_assert (false, 20030217);
+           }
        }
 
       if (!access)
        {
          int i;
-         int n_baselinks;
-         tree binfos;
+         tree base_binfo, accesses;
          
          /* Otherwise, scan our baseclasses, and pick the most favorable
             access.  */
-         binfos = BINFO_BASETYPES (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);
-             access_kind base_access 
-               = BINFO_ACCESS (canonical_binfo (base_binfo));
+             tree base_access = TREE_VEC_ELT (accesses, i);
+             access_kind base_access_now = BINFO_ACCESS (base_binfo);
 
-             if (base_access == ak_none || base_access == ak_private)
+             if (base_access_now == ak_none || base_access_now == ak_private)
                /* If it was not accessible in the base, or only
                   accessible as a private member, we can't access it
                   all.  */
-               base_access = ak_none;
-             else if (TREE_VIA_PROTECTED (base_binfo))
-               /* Public and protected members in the base are
+               base_access_now = ak_none;
+             else if (base_access == access_protected_node)
+               /* Public and protected members in the base become
                   protected here.  */
-               base_access = ak_protected;
-             else if (!TREE_VIA_PUBLIC (base_binfo))
-               /* Public and protected members in the base are
+               base_access_now = ak_protected;
+             else if (base_access == access_private_node)
+               /* Public and protected members in the base become
                   private here.  */
-               base_access = ak_private;
+               base_access_now = ak_private;
 
              /* See if the new access, via this base, gives more
                 access than our previous best access.  */
-             if (base_access != ak_none
-                 && (base_access == ak_public
-                     || (base_access == ak_protected
-                         && access != ak_public)
-                     || (base_access == ak_private 
-                         && access == ak_none)))
+             if (base_access_now != ak_none
+                 && (access == ak_none || base_access_now < access))
                {
-                 access = base_access;
+                 access = base_access_now;
 
                  /* If the new access is public, we can't do better.  */
                  if (access == ak_public)
@@ -790,7 +666,7 @@ dfs_access_in_type (binfo, data)
 
   /* Mark TYPE as visited so that if we reach it again we do not
      duplicate our efforts here.  */
-  SET_BINFO_MARKED (binfo);
+  BINFO_MARKED (binfo) = 1;
 
   return NULL_TREE;
 }
@@ -798,9 +674,7 @@ dfs_access_in_type (binfo, data)
 /* Return the access to DECL in TYPE.  */
 
 static access_kind
-access_in_type (type, decl)
-     tree type;
-     tree decl;
+access_in_type (tree type, tree decl)
 {
   tree binfo = TYPE_BINFO (type);
 
@@ -815,62 +689,52 @@ access_in_type (type, decl)
     The algorithm we use is to make a post-order depth-first traversal
     of the base-class hierarchy.  As we come up the tree, we annotate
     each node with the most lenient access.  */
-  dfs_walk_real (binfo, 0, dfs_access_in_type, shared_unmarked_p, decl);
-  dfs_walk (binfo, dfs_unmark, shared_marked_p,  0);
-  assert_canonical_unmarked (binfo);
+  dfs_walk_real (binfo, 0, dfs_access_in_type, unmarkedp, decl);
+  dfs_walk (binfo, dfs_unmark, markedp,  0);
 
   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 (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
 {
+  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 subclass.  */
-  if (!TREE_VIA_PUBLIC (binfo)
-      && !is_friend (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
-                    current_scope ()))
+     then we can't see it, unless we are a friend of the derived class.  */
+  if (BINFO_BASE_ACCESS (derived, ix) != access_public_node
+      && !is_friend (BINFO_TYPE (derived), current_scope ()))
     return NULL_TREE;
 
-  return canonical_binfo (binfo);
+  return binfo;
 }
 
-/* Called from dfs_accessible_p via dfs_walk.  */
+/* Called from accessible_p via dfs_walk.  */
 
 static tree
-dfs_accessible_p (binfo, data)
-     tree binfo;
-     void *data;
+dfs_accessible_p (tree binfo, void *data ATTRIBUTE_UNUSED)
 {
-  int protected_ok = data != 0;
   access_kind access;
 
-  SET_BINFO_MARKED (binfo);
+  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;
 }
 
 /* Returns nonzero if it is OK to access DECL through an object
-   indiated by BINFO in the context of DERIVED.  */
+   indicated by BINFO in the context of DERIVED.  */
 
 static int
-protected_accessible_p (decl, derived, binfo)
-     tree decl;
-     tree derived;
-     tree binfo;
+protected_accessible_p (tree decl, tree derived, tree binfo)
 {
   access_kind access;
 
@@ -930,10 +794,7 @@ protected_accessible_p (decl, derived, binfo)
    to access DECL through the object indicated by BINFO.  */
 
 static int
-friend_accessible_p (scope, decl, binfo)
-     tree scope;
-     tree decl;
-     tree binfo;
+friend_accessible_p (tree scope, tree decl, tree binfo)
 {
   tree befriending_classes;
   tree t;
@@ -986,27 +847,34 @@ friend_accessible_p (scope, decl, binfo)
    at the most derived class along the path indicated by BINFO.  */
 
 int 
-accessible_p (type, decl)
-     tree type;
-     tree decl;
-     
+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.  */
   int protected_ok = 0;
 
-  /* If we're not checking access, everything is accessible.  */
-  if (!scope_chain->check_access)
-    return 1;
-
   /* If this declaration is in a block or namespace scope, there's no
      access control.  */
   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;
@@ -1042,7 +910,7 @@ accessible_p (type, 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.  */
@@ -1050,83 +918,22 @@ accessible_p (type, 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, dfs_canonical_queue,  0);
-  assert_canonical_unmarked (binfo);
-
-  return t != NULL_TREE;
-}
-
-/* Recursive helper funciton for is_subobject_of_p; see that routine
-   for documentation of the parameters.  */
-
-static int
-is_subobject_of_p_1 (parent, binfo, most_derived)
-     tree parent, binfo, most_derived;
-{
-  tree binfos;
-  int i, n_baselinks;
-
-  if (parent == binfo)
+  access = access_in_type (type, decl);
+  if (access == ak_public
+      || (access == ak_protected && protected_ok))
     return 1;
-
-  binfos = BINFO_BASETYPES (binfo);
-  n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
-  /* Iterate through the base types.  */
-  for (i = 0; i < n_baselinks; i++)
+  else
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      tree base_type;
-
-      base_type = TREE_TYPE (base_binfo);
-      if (!CLASS_TYPE_P (base_type))
-       /* If we see a TEMPLATE_TYPE_PARM, or some such, as a base
-          class there's no way to descend into it.  */
-       continue;
-
-      /* Avoid walking into the same virtual base more than once.  */
-      if (TREE_VIA_VIRTUAL (base_binfo))
-       {
-         if (CLASSTYPE_MARKED4 (base_type))
-           continue;
-         SET_CLASSTYPE_MARKED4 (base_type);
-         base_binfo = binfo_for_vbase (base_type, most_derived);
-       }
-
-      if (is_subobject_of_p_1 (parent, base_binfo, most_derived))
-       return 1;
+      /* 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;
     }
-  return 0;
-}
-
-/* Routine to see if the sub-object denoted by the binfo PARENT can be
-   found as a base class and sub-object of the object denoted by
-   BINFO.  MOST_DERIVED is the most derived type of the hierarchy being
-   searched.  */
-
-static int
-is_subobject_of_p (tree parent, tree binfo, tree most_derived)
-{
-  int result;
-  tree vbase;
-
-  result = is_subobject_of_p_1 (parent, binfo, most_derived);
-  /* Clear the mark bits on virtual bases.  */
-  for (vbase = CLASSTYPE_VBASECLASSES (most_derived);
-       vbase;
-       vbase = TREE_CHAIN (vbase))
-    CLEAR_CLASSTYPE_MARKED4 (TREE_TYPE (TREE_VALUE (vbase)));
-
-  return result;
 }
 
 struct lookup_field_info {
@@ -1143,8 +950,6 @@ struct lookup_field_info {
   tree ambiguous;
   /* If nonzero, we are looking for types, not data members.  */
   int want_type;
-  /* If nonzero, RVAL was found by looking through a dependent base.  */
-  int from_dep_base_p;
   /* If something went wrong, a message indicating what.  */
   const char *errstr;
 };
@@ -1155,10 +960,9 @@ struct lookup_field_info {
    lookup_field via breadth_first_search.  */
 
 static tree
-lookup_field_queue_p (binfo, data)
-     tree binfo;
-     void *data;
+lookup_field_queue_p (tree derived, int ix, void *data)
 {
+  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.  */
@@ -1167,11 +971,13 @@ lookup_field_queue_p (binfo, data)
 
   /* If this base class is hidden by the best-known value so far, we
      don't need to look.  */
-  binfo = CANONICAL_BINFO (binfo, lfi->type);
-  if (!lfi->from_dep_base_p && lfi->rval_binfo
-      && is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
+  if (lfi->rval_binfo && original_binfo (binfo, lfi->rval_binfo))
     return NULL_TREE;
 
+  /* If this is a dependent base, don't look in it.  */
+  if (BINFO_DEPENDENT_BASE_P (binfo))
+    return NULL_TREE;
+  
   return binfo;
 }
 
@@ -1184,9 +990,7 @@ lookup_field_queue_p (binfo, data)
    Returns nonzero if DECL is such a declaration in a class TYPE.  */
 
 static int
-template_self_reference_p (type, decl)
-     tree type;
-     tree decl;
+template_self_reference_p (tree type, tree decl)
 {
   return  (CLASSTYPE_USE_TEMPLATE (type)
           && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
@@ -1207,8 +1011,7 @@ template_self_reference_p (type, decl)
    This function checks that T contains no nonstatic members.  */
 
 static int
-shared_member_p (t)
-     tree t;
+shared_member_p (tree t)
 {
   if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == TYPE_DECL \
       || TREE_CODE (t) == CONST_DECL)
@@ -1232,14 +1035,11 @@ shared_member_p (t)
    lookup_field via breadth_first_search.  */
 
 static tree
-lookup_field_r (binfo, data)
-     tree binfo;
-     void *data;
+lookup_field_r (tree binfo, void *data)
 {
   struct lookup_field_info *lfi = (struct lookup_field_info *) data;
   tree type = BINFO_TYPE (binfo);
   tree nval = NULL_TREE;
-  int from_dep_base_p;
 
   /* First, look for a function.  There can't be a function and a data
      member with the same name, and if there's a function and a type
@@ -1248,12 +1048,12 @@ lookup_field_r (binfo, 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)
     /* Look for a data member or type.  */
-    nval = lookup_field_1 (type, lfi->name);
+    nval = lookup_field_1 (type, lfi->name, lfi->want_type);
 
   /* If there is no declaration with the indicated name in this type,
      then there's nothing to do.  */
@@ -1278,11 +1078,12 @@ lookup_field_r (binfo, data)
        }
       else
        nval = NULL_TREE;
-      if (!nval)
+      if (!nval && CLASSTYPE_NESTED_UTDS (type) != NULL)
        {
-         nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type));
-         if (nval)
-           nval = TYPE_MAIN_DECL (TREE_VALUE (nval));
+          binding_entry e = binding_table_find (CLASSTYPE_NESTED_UTDS (type),
+                                                lfi->name);
+         if (e != NULL)
+           nval = TYPE_MAIN_DECL (e->type);
          else 
            return NULL_TREE;
        }
@@ -1293,40 +1094,14 @@ lookup_field_r (binfo, data)
       && template_self_reference_p (type, nval))
     return NULL_TREE;
 
-  from_dep_base_p = dependent_base_p (binfo);
-  if (lfi->from_dep_base_p && !from_dep_base_p)
-    {
-      /* If the new declaration is not found via a dependent base, and
-        the old one was, then we must prefer the new one.  We weren't
-        really supposed to be able to find the old one, so we don't
-        want to be affected by a specialization.  Consider:
-
-          struct B { typedef int I; };
-          template <typename T> struct D1 : virtual public B {}; 
-          template <typename T> struct D :
-          public D1, virtual pubic B { I i; };
-
-        The `I' in `D<T>' is unambigousuly `B::I', regardless of how
-        D1 is specialized.  */
-      lfi->from_dep_base_p = 0;
-      lfi->rval = NULL_TREE;
-      lfi->rval_binfo = NULL_TREE;
-      lfi->ambiguous = NULL_TREE;
-      lfi->errstr = 0;
-    }
-  else if (lfi->rval_binfo && !lfi->from_dep_base_p && from_dep_base_p)
-    /* Similarly, if the old declaration was not found via a dependent
-       base, and the new one is, ignore the new one.  */
-    return NULL_TREE;
-
   /* If the lookup already found a match, and the new value doesn't
      hide the old one, we might have an ambiguity.  */
-  if (lfi->rval_binfo && !is_subobject_of_p (lfi->rval_binfo, binfo, lfi->type))
+  if (lfi->rval_binfo && !original_binfo (lfi->rval_binfo, binfo))
     {
       if (nval == lfi->rval && shared_member_p (nval))
        /* The two things are really the same.  */
        ;
-      else if (is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
+      else if (original_binfo (binfo, lfi->rval_binfo))
        /* The previous value hides the new one.  */
        ;
       else
@@ -1350,18 +1125,7 @@ lookup_field_r (binfo, data)
     }
   else
     {
-      if (from_dep_base_p && TREE_CODE (nval) == TYPE_DECL
-         /* We need to return a member template class so we can
-            define partial specializations.  Is there a better
-            way?  */
-         && !DECL_CLASS_TEMPLATE_P (nval))
-       /* The thing we're looking for isn't a type, so the implicit
-          typename extension doesn't apply, so we just pretend we
-          didn't find anything.  */
-       return NULL_TREE;
-
       lfi->rval = nval;
-      lfi->from_dep_base_p = from_dep_base_p;
       lfi->rval_binfo = binfo;
     }
 
@@ -1408,9 +1172,7 @@ build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
    If nothing can be found return NULL_TREE and do not issue an error.  */
 
 tree
-lookup_member (xbasetype, name, protect, want_type)
-     register tree xbasetype, name;
-     int protect, want_type;
+lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 {
   tree rval, rval_binfo = NULL_TREE;
   tree type = NULL_TREE, basetype_path = NULL_TREE;
@@ -1425,39 +1187,32 @@ lookup_member (xbasetype, name, protect, want_type)
 
   const char *errstr = 0;
 
-  if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype)
-      && IDENTIFIER_CLASS_VALUE (name))
-    {
-      tree field = IDENTIFIER_CLASS_VALUE (name);
-      if (TREE_CODE (field) != FUNCTION_DECL
-         && ! (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;
-    }
+  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;
     }
-  else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
+  else
     {
+      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) == NULL_TREE,
-                         980827);
+      xbasetype = NULL_TREE;
     }
-  else
-    abort ();
 
-  complete_type (type);
+  type = complete_type (type);
+  if (!basetype_path)
+    basetype_path = TYPE_BINFO (type);
+
+  if (!basetype_path)
+    return NULL_TREE;
 
 #ifdef GATHER_STATISTICS
   n_calls_lookup_field++;
 #endif /* GATHER_STATISTICS */
 
-  memset ((PTR) &lfi, 0, sizeof (lfi));
+  memset (&lfi, 0, sizeof (lfi));
   lfi.type = type;
   lfi.name = name;
   lfi.want_type = want_type;
@@ -1485,9 +1240,8 @@ lookup_member (xbasetype, name, protect, want_type)
 
      In the case of overloaded function names, access control is
      applied to the function selected by overloaded resolution.  */
-  if (rval && protect && !is_overloaded_fn (rval)
-      && !enforce_access (xbasetype, rval))
-    return error_mark_node;
+  if (rval && protect && !is_overloaded_fn (rval))
+    perform_or_defer_access_check (basetype_path, rval);
 
   if (errstr && protect)
     {
@@ -1497,11 +1251,6 @@ lookup_member (xbasetype, name, protect, want_type)
       rval = error_mark_node;
     }
 
-  /* If the thing we found was found via the implicit typename
-     extension, build the typename type.  */
-  if (rval && lfi.from_dep_base_p && !DECL_CLASS_TEMPLATE_P (rval))
-    abort ();
-
   if (rval && is_overloaded_fn (rval)) 
     rval = build_baselink (rval_binfo, basetype_path, rval,
                           (IDENTIFIER_TYPENAME_P (name)
@@ -1513,14 +1262,13 @@ lookup_member (xbasetype, name, protect, want_type)
    return NULL_TREE.  */
 
 tree
-lookup_field (xbasetype, name, protect, want_type)
-     register tree xbasetype, name;
-     int protect, want_type;
+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;
@@ -1530,108 +1278,164 @@ lookup_field (xbasetype, name, protect, want_type)
    return NULL_TREE.  */
 
 tree
-lookup_fnfields (xbasetype, name, protect)
-     register tree xbasetype, name;
-     int protect;
+lookup_fnfields (tree xbasetype, tree name, int protect)
 {
-  tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
+  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;
 }
 
+/* Return the index in the CLASSTYPE_METHOD_VEC for CLASS_TYPE
+   corresponding to "operator TYPE ()", or -1 if there is no such
+   operator.  Only CLASS_TYPE itself is searched; this routine does
+   not scan the base classes of CLASS_TYPE.  */
+
+static int
+lookup_conversion_operator (tree class_type, tree type)
+{
+  int pass;
+  int i;
+  tree fn;
+  VEC(tree) *methods;
+
+  methods = CLASSTYPE_METHOD_VEC (class_type);
+
+  for (pass = 0; pass < 2; ++pass)
+    for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; 
+        VEC_iterate (tree, methods, i, fn); ++i)
+      {
+       /* 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.  */
+       fn = OVL_CURRENT (fn);
+       if (!DECL_CONV_FN_P (fn))
+         break;
+       
+       if (pass == 0)
+         {
+           /* On the first pass we only consider exact matches.  If
+              the types match, this slot is the one where the right
+              conversion operators can be found.  */
+           if (TREE_CODE (fn) != TEMPLATE_DECL
+               && same_type_p (DECL_CONV_FN_TYPE (fn), type))
+             return i;
+         }
+       else
+         {
+           /* On the second pass we look for template conversion
+              operators.  It may be possible to instantiate the
+              template to get the type desired.  All of the template
+              conversion operators share a slot.  By looking for
+              templates second we ensure that specializations are
+              preferred over templates.  */
+           if (TREE_CODE (fn) == TEMPLATE_DECL)
+             return i;
+         }
+      }
+
+  return -1;
+}
+
 /* TYPE is a class type. Return the index of the fields within
    the method vector with name NAME, or -1 is no such field exists.  */
 
 int
-lookup_fnfields_1 (type, name)
-     tree type, name;
+lookup_fnfields_1 (tree type, tree name)
 {
-  tree method_vec = (CLASS_TYPE_P (type)
-                    ? CLASSTYPE_METHOD_VEC (type)
-                    : NULL_TREE);
+  VEC(tree) *method_vec;
+  tree fn;
+  tree tmp;
+  size_t i;
+  
+  if (!CLASS_TYPE_P (type))
+    return -1;
 
-  if (method_vec != 0)
+  if (COMPLETE_TYPE_P (type))
     {
-      register int i;
-      register tree *methods = &TREE_VEC_ELT (method_vec, 0);
-      int len = TREE_VEC_LENGTH (method_vec);
-      tree tmp;
+      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)
+              && CLASSTYPE_LAZY_ASSIGNMENT_OP (type))
+       lazily_declare_fn (sfk_assignment_operator, type);
+    }
 
-#ifdef GATHER_STATISTICS
-      n_calls_lookup_fnfields_1++;
-#endif /* GATHER_STATISTICS */
+  method_vec = CLASSTYPE_METHOD_VEC (type);
+  if (!method_vec)
+    return -1;
 
-      /* Constructors are first...  */
-      if (name == ctor_identifier)
-       return (methods[CLASSTYPE_CONSTRUCTOR_SLOT] 
-               ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
-      /* and destructors are second.  */
-      if (name == dtor_identifier)
-       return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
-               ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
-
-      for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; 
-          i < len && methods[i]; 
-          ++i)
-       {
 #ifdef GATHER_STATISTICS
-         n_outer_fields_searched++;
+  n_calls_lookup_fnfields_1++;
 #endif /* GATHER_STATISTICS */
 
-         tmp = OVL_CURRENT (methods[i]);
-         if (DECL_NAME (tmp) == name)
-           return i;
+  /* Constructors are first...  */
+  if (name == ctor_identifier)
+    {
+      fn = CLASSTYPE_CONSTRUCTORS (type);
+      return fn ? CLASSTYPE_CONSTRUCTOR_SLOT : -1;
+    }
+  /* and destructors are second.  */
+  if (name == dtor_identifier)
+    {
+      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.  */
+  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 and we're past the conversion ops,
-            switch to binary search.  */
-         if (! DECL_CONV_FN_P (tmp)
-             && COMPLETE_TYPE_P (type))
-           {
-             int lo = i + 1, hi = len;
+  /* If the type is complete, use binary search.  */
+  if (COMPLETE_TYPE_P (type))
+    {
+      int lo;
+      int hi;
 
-             while (lo < hi)
-               {
-                 i = (lo + hi) / 2;
+      lo = i;
+      hi = VEC_length (tree, method_vec);
+      while (lo < hi)
+       {
+         i = (lo + hi) / 2;
 
 #ifdef GATHER_STATISTICS
-                 n_outer_fields_searched++;
+         n_outer_fields_searched++;
 #endif /* GATHER_STATISTICS */
 
-                 tmp = DECL_NAME (OVL_CURRENT (methods[i]));
-
-                 if (tmp > name)
-                   hi = i;
-                 else if (tmp < name)
-                   lo = i + 1;
-                 else
-                   return i;
-               }
-             break;
-           }
-       }
-
-      /* If we didn't find it, it might have been a template
-        conversion operator to a templated type.  If there are any,
-        such template conversion operators will all be overloaded on
-        the first conversion slot.  (Note that we don't look for this
-        case above so that we will always find specializations
-        first.)  */
-      if (IDENTIFIER_TYPENAME_P (name)) 
-       {
-         i = CLASSTYPE_FIRST_CONVERSION_SLOT;
-         if (i < len && methods[i])
-           {
-             tmp = OVL_CURRENT (methods[i]);
-             if (TREE_CODE (tmp) == TEMPLATE_DECL
-                 && DECL_TEMPLATE_CONV_FN_P (tmp))
-               return i;
-           }
+         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;
+         else
+           return i;
        }
     }
+  else
+    for (; VEC_iterate (tree, method_vec, i, fn); ++i)
+      {
+#ifdef GATHER_STATISTICS
+       n_outer_fields_searched++;
+#endif /* GATHER_STATISTICS */
+       if (DECL_NAME (OVL_CURRENT (fn)) == name)
+         return i;
+      }
 
   return -1;
 }
@@ -1660,10 +1464,11 @@ adjust_result_of_qualified_name_lookup (tree decl,
 
       my_friendly_assert (CLASS_TYPE_P (context_class), 20020808);
 
-      /* Look for the QUALIFYING_SCOPE as a base of the
-        CONTEXT_CLASS.  If QUALIFYING_SCOPE is ambiguous, we cannot
-        be sure yet than an error has occurred; perhaps the function
-        chosen by overload resolution will be static.  */
+      /* Look for the QUALIFYING_SCOPE as a base of the CONTEXT_CLASS.
+        Because we do not yet know which function will be chosen by
+        overload resolution, we cannot yet check either accessibility
+        or ambiguity -- in either case, the choice of a static member
+        function might make the usage valid.  */
       base = lookup_base (context_class, qualifying_scope,
                          ba_ignore | ba_quiet, NULL);
       if (base)
@@ -1684,69 +1489,91 @@ adjust_result_of_qualified_name_lookup (tree decl,
    type in the hierarchy, in a breadth-first preorder traversal.
    If it ever returns a non-NULL value, that value is immediately
    returned and the walk is terminated.  At each node, FN is passed a
-   BINFO indicating the path from the curently visited base-class to
+   BINFO indicating the path from the currently visited base-class to
    TYPE.  Before each base-class is walked QFN is called.  If the
    value returned is nonzero, the base-class is walked; otherwise it
    is not.  If QFN is NULL, it is treated as a function which always
    returns 1.  Both FN and QFN are passed the DATA whenever they are
-   called.  */
+   called.
+
+   Implementation notes: Uses a circular queue, which starts off on
+   the stack but gets moved to the malloc arena if it needs to be
+   enlarged.  The underflow and overflow conditions are
+   indistinguishable except by context: if head == tail and we just
+   moved the head pointer, the queue is empty, but if we just moved
+   the tail pointer, the queue is full.  
+   Start with enough room for ten concurrent base classes.  That
+   will be enough for most hierarchies.  */
+#define BFS_WALK_INITIAL_QUEUE_SIZE 10
 
 static tree
-bfs_walk (binfo, fn, qfn, data)
-     tree binfo;
-     tree (*fn) PARAMS ((tree, void *));
-     tree (*qfn) PARAMS ((tree, void *));
-     void *data;
+bfs_walk (tree binfo,
+         tree (*fn) (tree, void *),
+         tree (*qfn) (tree, int, void *),
+         void *data)
 {
-  size_t head;
-  size_t tail;
   tree rval = NULL_TREE;
-  /* An array of the base classes of BINFO.  These will be built up in
-     breadth-first order, except where QFN prunes the search.  */
-  varray_type bfs_bases;
 
-  /* Start with enough room for ten base classes.  That will be enough
-     for most hierarchies.  */
-  VARRAY_TREE_INIT (bfs_bases, 10, "search_stack");
+  tree bases_initial[BFS_WALK_INITIAL_QUEUE_SIZE];
+  /* A circular queue of the base classes of BINFO.  These will be
+     built up in breadth-first order, except where QFN prunes the
+     search.  */
+  size_t head, tail;
+  size_t base_buffer_size = BFS_WALK_INITIAL_QUEUE_SIZE;
+  tree *base_buffer = bases_initial;
 
-  /* Put the first type into the stack.  */
-  VARRAY_TREE (bfs_bases, 0) = binfo;
-  tail = 1;
+  head = tail = 0;
+  base_buffer[tail++] = binfo;
 
-  for (head = 0; head < tail; ++head)
+  while (head != tail)
     {
-      int i;
-      int n_baselinks;
-      tree binfos;
+      int n_bases, ix;
+      tree binfo = base_buffer[head++];
+      if (head == base_buffer_size)
+       head = 0;
 
-      /* Pull the next type out of the queue.  */
-      binfo = VARRAY_TREE (bfs_bases, head);
-
-      /* If this is the one we're looking for, we're done.  */
-      rval = (*fn) (binfo, data);
+      /* Is this the one we're looking for?  If so, we're done.  */
+      rval = fn (binfo, data);
       if (rval)
-       break;
+       goto done;
 
-      /* Queue up the base types.  */
-      binfos = BINFO_BASETYPES (binfo);
-      n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
-      for (i = 0; i < n_baselinks; i++)
+      n_bases = BINFO_N_BASE_BINFOS (binfo);
+      for (ix = 0; ix != n_bases; ix++)
        {
-         tree base_binfo = TREE_VEC_ELT (binfos, i);
-
+         tree base_binfo;
+         
          if (qfn)
-           base_binfo = (*qfn) (base_binfo, data);
-
-         if (base_binfo)
+           base_binfo = (*qfn) (binfo, ix, data);
+         else
+           base_binfo = BINFO_BASE_BINFO (binfo, ix);
+         
+         if (base_binfo)
            {
-             if (tail == VARRAY_SIZE (bfs_bases))
-               VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
-             VARRAY_TREE (bfs_bases, tail) = base_binfo;
-             ++tail;
+             base_buffer[tail++] = base_binfo;
+             if (tail == base_buffer_size)
+               tail = 0;
+             if (tail == head)
+               {
+                 tree *new_buffer = xmalloc (2 * base_buffer_size
+                                             * sizeof (tree));
+                 memcpy (&new_buffer[0], &base_buffer[0],
+                         tail * sizeof (tree));
+                 memcpy (&new_buffer[head + base_buffer_size],
+                         &base_buffer[head],
+                         (base_buffer_size - head) * sizeof (tree));
+                 if (base_buffer_size != BFS_WALK_INITIAL_QUEUE_SIZE)
+                   free (base_buffer);
+                 base_buffer = new_buffer;
+                 head += base_buffer_size;
+                 base_buffer_size *= 2;
+               }
            }
        }
     }
 
+ done:
+  if (base_buffer_size != BFS_WALK_INITIAL_QUEUE_SIZE)
+    free (base_buffer);
   return rval;
 }
 
@@ -1755,16 +1582,14 @@ bfs_walk (binfo, fn, qfn, data)
    in postorder.  */
 
 tree
-dfs_walk_real (binfo, prefn, postfn, qfn, data)
-     tree binfo;
-     tree (*prefn) PARAMS ((tree, void *));
-     tree (*postfn) PARAMS ((tree, void *));
-     tree (*qfn) PARAMS ((tree, void *));
-     void *data;
+dfs_walk_real (tree binfo,
+              tree (*prefn) (tree, void *),
+              tree (*postfn) (tree, void *),
+              tree (*qfn) (tree, int, void *),
+              void *data)
 {
   int i;
-  int n_baselinks;
-  tree binfos;
+  tree base_binfo;
   tree rval = NULL_TREE;
 
   /* Call the pre-order walking function.  */
@@ -1776,21 +1601,17 @@ dfs_walk_real (binfo, prefn, postfn, qfn, data)
     }
 
   /* Process the basetypes.  */
-  binfos = BINFO_BASETYPES (binfo);
-  n_baselinks = BINFO_N_BASETYPES (binfo);
-  for (i = 0; i < n_baselinks; i++)
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      
       if (qfn)
-       base_binfo = (*qfn) (base_binfo, data);
-
-      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.  */
@@ -1804,11 +1625,10 @@ dfs_walk_real (binfo, prefn, postfn, qfn, data)
    performed.  */
 
 tree
-dfs_walk (binfo, fn, qfn, data)
-     tree binfo;
-     tree (*fn) PARAMS ((tree, void *));
-     tree (*qfn) PARAMS ((tree, void *));
-     void *data;
+dfs_walk (tree binfo,
+         tree (*fn) (tree, void *),
+         tree (*qfn) (tree, int, void *),
+         void *data)
 {
   return dfs_walk_real (binfo, 0, fn, qfn, data);
 }
@@ -1817,8 +1637,7 @@ dfs_walk (binfo, fn, qfn, data)
    BASEFN. Issue diagnostic, and return zero, if unacceptable.  */
 
 int
-check_final_overrider (overrider, basefn)
-     tree overrider, basefn;
+check_final_overrider (tree overrider, tree basefn)
 {
   tree over_type = TREE_TYPE (overrider);
   tree base_type = TREE_TYPE (basefn);
@@ -1827,14 +1646,17 @@ check_final_overrider (overrider, 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))
           || (TREE_CODE (base_return) == TREE_CODE (over_return)
               && POINTER_TYPE_P (base_return)))
     {
-      /* Potentially covariant. */
+      /* Potentially covariant.  */
       unsigned base_quals, over_quals;
       
       fail = !POINTER_TYPE_P (base_return);
@@ -1865,10 +1687,8 @@ check_final_overrider (overrider, basefn)
           converting to void *, or qualification conversion.  */
        {
          /* 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);
+            (reference to) class type. We must reject them.  */
+         over_return = non_reference (TREE_TYPE (over_type));
          if (CLASS_TYPE_P (over_return))
            fail = 2;
        }
@@ -1879,8 +1699,6 @@ check_final_overrider (overrider, basefn)
     fail = 2;
   if (!fail)
     /* OK */;
-  else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
-    return 0;
   else
     {
       if (fail == 1)
@@ -1894,21 +1712,16 @@ check_final_overrider (overrider, 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;
     }
   
@@ -1926,18 +1739,16 @@ check_final_overrider (overrider, basefn)
    overridden.  */
 
 int
-look_for_overrides (type, fndecl)
-     tree type, fndecl;
+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);
@@ -1949,18 +1760,23 @@ look_for_overrides (type, fndecl)
    FNDECL.  */
 
 tree
-look_for_overrides_here (type, fndecl)
-     tree type, fndecl;
+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))
         {
@@ -1988,8 +1804,7 @@ look_for_overrides_here (type, fndecl)
    TYPE itself and its bases.  */
 
 static int
-look_for_overrides_r (type, fndecl)
-     tree type, fndecl;
+look_for_overrides_r (tree type, tree fndecl)
 {
   tree fn = look_for_overrides_here (type, fndecl);
   if (fn)
@@ -2014,71 +1829,10 @@ look_for_overrides_r (type, fndecl)
   return look_for_overrides (type, fndecl);
 }
 
-/* A queue function to use with dfs_walk that only walks into
-   canonical bases.  DATA should be the type of the complete object,
-   or a TREE_LIST whose TREE_PURPOSE is the type of the complete
-   object.  By using this function as a queue function, you will walk
-   over exactly those BINFOs that actually exist in the complete
-   object, including those for virtual base classes.  If you
-   SET_BINFO_MARKED for each binfo you process, you are further
-   guaranteed that you will walk into each virtual base class exactly
-   once.  */
-
-tree
-dfs_unmarked_real_bases_queue_p (binfo, data)
-     tree binfo;
-     void *data;
-{
-  if (TREE_VIA_VIRTUAL (binfo))
-    {
-      tree type = (tree) data;
-
-      if (TREE_CODE (type) == TREE_LIST)
-       type = TREE_PURPOSE (type);
-      binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
-    }
-  return unmarkedp (binfo, NULL);
-}
-
-/* Like dfs_unmarked_real_bases_queue_p but walks only into things
-   that are marked, rather than unmarked.  */
-
-tree
-dfs_marked_real_bases_queue_p (binfo, data)
-     tree binfo;
-     void *data;
-{
-  if (TREE_VIA_VIRTUAL (binfo))
-    {
-      tree type = (tree) data;
-
-      if (TREE_CODE (type) == TREE_LIST)
-       type = TREE_PURPOSE (type);
-      binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
-    }
-  return markedp (binfo, NULL);
-}
-
-/* A queue function that skips all virtual bases (and their 
-   bases).  */
-
-tree
-dfs_skip_vbases (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{
-  if (TREE_VIA_VIRTUAL (binfo))
-    return NULL_TREE;
-
-  return binfo;
-}
-
 /* Called via dfs_walk from dfs_get_pure_virtuals.  */
 
 static tree
-dfs_get_pure_virtuals (binfo, data)
-     tree binfo;
-     void *data;
+dfs_get_pure_virtuals (tree binfo, void *data)
 {
   tree type = (tree) data;
 
@@ -2098,7 +1852,7 @@ dfs_get_pure_virtuals (binfo, data)
                         CLASSTYPE_PURE_VIRTUALS (type));
     }
   
-  SET_BINFO_MARKED (binfo);
+  BINFO_MARKED (binfo) = 1;
 
   return NULL_TREE;
 }
@@ -2106,10 +1860,11 @@ dfs_get_pure_virtuals (binfo, data)
 /* Set CLASSTYPE_PURE_VIRTUALS for TYPE.  */
 
 void
-get_pure_virtuals (type)
-     tree type;
+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.  */
@@ -2120,22 +1875,18 @@ get_pure_virtuals (type)
      (A primary base is not interesting because the derived class of
      which it is a primary base will contain vtable entries for the
      pure virtuals in the base class.  */
-  dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, 
-           dfs_unmarked_real_bases_queue_p, type);
-  dfs_walk (TYPE_BINFO (type), dfs_unmark, 
-           dfs_marked_real_bases_queue_p, type);
+  dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, unmarkedp, type);
+  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 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);
@@ -2148,55 +1899,19 @@ get_pure_virtuals (type)
 /* DEPTH-FIRST SEARCH ROUTINES.  */
 
 tree 
-markedp (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{ 
-  return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
-}
-
-tree
-unmarkedp (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+markedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED) 
 {
-  return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
-}
-
-tree
-marked_vtable_pathp (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{ 
-  return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE; 
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
+  
+  return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
 }
 
 tree
-unmarked_vtable_pathp (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{ 
-  return !BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE; 
-}
-
-static tree
-marked_pushdecls_p (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED) 
 {
-  return (CLASS_TYPE_P (BINFO_TYPE (binfo))
-         && !dependent_base_p (binfo)
-         && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE; 
-}
-
-static tree
-unmarked_pushdecls_p (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{ 
-  return (CLASS_TYPE_P (BINFO_TYPE (binfo))
-         && !dependent_base_p (binfo)
-         && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
+  
+  return !BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
 }
 
 /* The worker functions for `dfs_walk'.  These do not need to
@@ -2204,111 +1919,12 @@ unmarked_pushdecls_p (binfo, data)
    a predicate function (above).  */
 
 tree
-dfs_unmark (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{ 
-  CLEAR_BINFO_MARKED (binfo); 
-  return NULL_TREE;
-}
-
-/* get virtual base class types.
-   This adds type to the vbase_types list in reverse dfs order.
-   Ordering is very important, so don't change it.  */
-
-static tree
-dfs_get_vbase_types (binfo, data)
-     tree binfo;
-     void *data;
+dfs_unmark (tree binfo, void *data ATTRIBUTE_UNUSED)
 {
-  tree type = (tree) data;
-
-  if (TREE_VIA_VIRTUAL (binfo))
-    CLASSTYPE_VBASECLASSES (type)
-      = tree_cons (BINFO_TYPE (binfo), 
-                  binfo, 
-                  CLASSTYPE_VBASECLASSES (type));
-  SET_BINFO_MARKED (binfo);
+  BINFO_MARKED (binfo) = 0;
   return NULL_TREE;
 }
 
-/* Called via dfs_walk from mark_primary_bases.  Builds the
-   inheritance graph order list of BINFOs.  */
-
-static tree
-dfs_build_inheritance_graph_order (binfo, data)
-     tree binfo;
-     void *data;
-{
-  tree *last_binfo = (tree *) data;
-
-  if (*last_binfo)
-    TREE_CHAIN (*last_binfo) = binfo;
-  *last_binfo = binfo;
-  SET_BINFO_MARKED (binfo);
-  return NULL_TREE;
-}
-
-/* Set CLASSTYPE_VBASECLASSES for TYPE.  */
-
-void
-get_vbase_types (type)
-     tree type;
-{
-  tree last_binfo;
-
-  CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
-  dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
-  /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
-     reverse it so that we get normal dfs ordering.  */
-  CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
-  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
-  /* Thread the BINFOs in inheritance-graph order.  */
-  last_binfo = NULL;
-  dfs_walk_real (TYPE_BINFO (type),
-                dfs_build_inheritance_graph_order,
-                NULL,
-                unmarkedp,
-                &last_binfo);
-  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
-}
-
-/* Called from find_vbase_instance via dfs_walk.  */
-
-static tree
-dfs_find_vbase_instance (binfo, data)
-     tree binfo;
-     void *data;
-{
-  tree base = TREE_VALUE ((tree) data);
-
-  if (BINFO_PRIMARY_P (binfo)
-      && same_type_p (BINFO_TYPE (binfo), base))
-    return binfo;
-
-  return NULL_TREE;
-}
-
-/* Find the real occurrence of the virtual BASE (a class type) in the
-   hierarchy dominated by TYPE.  */
-
-tree
-find_vbase_instance (base, type)
-     tree base;
-     tree type;
-{
-  tree instance;
-
-  instance = binfo_for_vbase (base, type);
-  if (!BINFO_PRIMARY_P (instance))
-    return instance;
-
-  return dfs_walk (TYPE_BINFO (type), 
-                  dfs_find_vbase_instance, 
-                  NULL,
-                  build_tree_list (type, base));
-}
-
 \f
 /* Debug info for C++ classes can get very large; try to avoid
    emitting it everywhere.
@@ -2318,8 +1934,7 @@ find_vbase_instance (base, type)
    linker.  */
 
 void
-maybe_suppress_debug_info (t)
-     tree t;
+maybe_suppress_debug_info (tree t)
 {
   /* We can't do the usual TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
      does not support name references between translation units.  It supports
@@ -2361,9 +1976,7 @@ maybe_suppress_debug_info (t)
    information anyway.  */
 
 static tree
-dfs_debug_mark (binfo, data)
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+dfs_debug_mark (tree binfo, void *data ATTRIBUTE_UNUSED)
 {
   tree t = BINFO_TYPE (binfo);
 
@@ -2376,10 +1989,10 @@ dfs_debug_mark (binfo, data)
    info for this base class.  */
 
 static tree 
-dfs_debug_unmarkedp (binfo, data) 
-     tree binfo;
-     void *data ATTRIBUTE_UNUSED;
-{ 
+dfs_debug_unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
+{
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
+  
   return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) 
          ? binfo : NULL_TREE);
 }
@@ -2392,8 +2005,7 @@ dfs_debug_unmarkedp (binfo, data)
    the vtables themselves, were optimized away.  */
 
 void
-note_debug_info_needed (type)
-     tree type;
+note_debug_info_needed (tree type)
 {
   if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)))
     {
@@ -2404,222 +2016,8 @@ note_debug_info_needed (type)
   dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
 }
 \f
-/* Subroutines of push_class_decls ().  */
-
-/* Returns 1 iff BINFO is a base we shouldn't really be able to see into,
-   because it (or one of the intermediate bases) depends on template parms.  */
-
-static int
-dependent_base_p (binfo)
-     tree binfo;
-{
-  for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
-    {
-      if (currently_open_class (TREE_TYPE (binfo)))
-       break;
-      if (uses_template_parms (TREE_TYPE (binfo)))
-       return 1;
-    }
-  return 0;
-}
-
-static void
-setup_class_bindings (name, type_binding_p)
-     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=*/1);
-      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=*/0);
-
-  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 (binfo, data)
-     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.  */
-  SET_BINFO_PUSHDECLS_MARKED (binfo);
-
-  return NULL_TREE;
-}
-
-/* Push class-level declarations for any names appearing in BINFO that
-   are not TYPE_DECLS.  */
-
-static tree
-dfs_push_decls (binfo, data)
-     tree binfo;
-     void *data;
-{
-  tree type;
-  tree method_vec;
-  int dep_base_p;
-
-  type = BINFO_TYPE (binfo);
-  dep_base_p = (processing_template_decl && type != current_class_type
-               && dependent_base_p (binfo));
-  if (!dep_base_p)
-    {
-      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);
-       }
-    }
-
-  CLEAR_BINFO_PUSHDECLS_MARKED (binfo);
-
-  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 (type)
-     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 (binfo, data)
-     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 (type)
-     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",
@@ -2633,13 +2031,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;
@@ -2652,24 +2044,24 @@ reinit_search_statistics ()
 }
 
 static tree
-add_conversions (binfo, data)
-     tree binfo;
-     void *data;
+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));
@@ -2677,8 +2069,27 @@ add_conversions (binfo, 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;
@@ -2691,13 +2102,13 @@ add_conversions (binfo, data)
    from which the conversion functions in this node were selected.  */
 
 tree
-lookup_conversions (type)
-     tree type;
+lookup_conversions (tree type)
 {
   tree t;
   tree conversions = NULL_TREE;
 
-  if (COMPLETE_TYPE_P (type))
+  complete_type (type);
+  if (TYPE_BINFO (type))
     bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
 
   for (t = conversions; t; t = TREE_CHAIN (t))
@@ -2716,22 +2127,21 @@ struct overlap_info
    at offset 0 in COMPARE_TYPE, and set found_overlap if so.  */
 
 static tree
-dfs_check_overlap (empty_binfo, data)
-     tree empty_binfo;
-     void *data;
+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;
     }
 
@@ -2741,11 +2151,11 @@ dfs_check_overlap (empty_binfo, data)
 /* Trivial function to stop base traversal when we find something.  */
 
 static tree
-dfs_no_overlap_yet (binfo, data)
-     tree binfo;
-     void *data;
+dfs_no_overlap_yet (tree derived, int ix, void *data)
 {
+  tree binfo = BINFO_BASE_BINFO (derived, ix);
   struct overlap_info *oi = (struct overlap_info *) data;
+  
   return !oi->found_overlap ? binfo : NULL_TREE;
 }
 
@@ -2753,8 +2163,7 @@ dfs_no_overlap_yet (binfo, data)
    offset 0 in NEXT_TYPE.  Used in laying out empty base class subobjects.  */
 
 int
-types_overlap_p (empty_type, next_type)
-     tree empty_type, next_type;
+types_overlap_p (tree empty_type, tree next_type)
 {
   struct overlap_info oi;
 
@@ -2767,45 +2176,15 @@ types_overlap_p (empty_type, 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 (var)
-     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.  */
 
 tree
-binfo_from_vbase (binfo)
-     tree binfo;
+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;
@@ -2816,29 +2195,109 @@ binfo_from_vbase (binfo)
    via virtual.  */
 
 tree
-binfo_via_virtual (binfo, limit)
-     tree binfo;
-     tree limit;
+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;
 }
 
-/* Returns the BINFO (if any) for the virtual baseclass T of the class
-   C from the CLASSTYPE_VBASECLASSES list.  */
+/* BINFO is a base binfo in the complete type BINFO_TYPE (HERE).
+   Find the equivalent binfo within whatever graph HERE is located.
+   This is the inverse of original_binfo.  */
 
 tree
-binfo_for_vbase (basetype, classtype)
-     tree basetype;
-     tree classtype;
+copied_binfo (tree binfo, tree here)
 {
+  tree result = NULL_TREE;
+  
+  if (BINFO_VIRTUAL_P (binfo))
+    {
+      tree t;
+
+      for (t = here; BINFO_INHERITANCE_CHAIN (t);
+          t = BINFO_INHERITANCE_CHAIN (t))
+       continue;
+
+      result = binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (t));
+    }
+  else if (BINFO_INHERITANCE_CHAIN (binfo))
+    {
+      tree cbinfo;
+      tree base_binfo;
+      int ix;
+      
+      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
+    {
+      my_friendly_assert (BINFO_TYPE (here) == BINFO_TYPE (binfo), 20030202);
+      result = here;
+    }
+
+  my_friendly_assert (result, 20030202);
+  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
+   is not a base binfo of HERE, returns NULL_TREE.  */
 
-  binfo = purpose_member (basetype, CLASSTYPE_VBASECLASSES (classtype));
-  return binfo ? TREE_VALUE (binfo) : NULL_TREE;
+tree
+original_binfo (tree binfo, tree here)
+{
+  tree result = NULL;
+  
+  if (BINFO_TYPE (binfo) == BINFO_TYPE (here))
+    result = here;
+  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;
+      
+      base_binfos = original_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
+      if (base_binfos)
+       {
+         int ix;
+         tree base_binfo;
+         
+         for (ix = 0; (base_binfo = BINFO_BASE_BINFO (base_binfos, ix)); ix++)
+           if (BINFO_TYPE (base_binfo) == BINFO_TYPE (binfo))
+             {
+               result = base_binfo;
+               break;
+             }
+       }
+    }
+  
+  return result;
 }
+