Annotation of gcc/cp/search.c, revision 1.1

1.1     ! root        1: /* Breadth-first and depth-first routines for
        !             2:    searching multiple-inheritance lattice for GNU C++.
        !             3:    Copyright (C) 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
        !             4:    Contributed by Michael Tiemann ([email protected])
        !             5: 
        !             6: This file is part of GNU CC.
        !             7: 
        !             8: GNU CC is free software; you can redistribute it and/or modify
        !             9: it under the terms of the GNU General Public License as published by
        !            10: the Free Software Foundation; either version 2, or (at your option)
        !            11: any later version.
        !            12: 
        !            13: GNU CC is distributed in the hope that it will be useful,
        !            14: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            16: GNU General Public License for more details.
        !            17: 
        !            18: You should have received a copy of the GNU General Public License
        !            19: along with GNU CC; see the file COPYING.  If not, write to
        !            20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            21: 
        !            22: /* High-level class interface. */
        !            23: 
        !            24: #include "config.h"
        !            25: #include "tree.h"
        !            26: #include <stdio.h>
        !            27: #include "cp-tree.h"
        !            28: #include "obstack.h"
        !            29: #include "flags.h"
        !            30: 
        !            31: #define obstack_chunk_alloc xmalloc
        !            32: #define obstack_chunk_free free
        !            33: 
        !            34: void init_search ();
        !            35: extern struct obstack *current_obstack;
        !            36: 
        !            37: #include "stack.h"
        !            38: 
        !            39: /* Obstack used for remembering decision points of breadth-first.  */
        !            40: static struct obstack search_obstack;
        !            41: 
        !            42: /* Methods for pushing and popping objects to and from obstacks.  */
        !            43: struct stack_level *
        !            44: push_stack_level (obstack, tp, size)
        !            45:      struct obstack *obstack;
        !            46:      char *tp;  /* Sony NewsOS 5.0 compiler doesn't like void * here.  */
        !            47:      int size;
        !            48: {
        !            49:   struct stack_level *stack;
        !            50:   obstack_grow (obstack, tp, size);
        !            51:   stack = (struct stack_level *) ((char*)obstack_next_free (obstack) - size);
        !            52:   obstack_finish (obstack);
        !            53:   stack->obstack = obstack;
        !            54:   stack->first = (tree *) obstack_base (obstack);
        !            55:   stack->limit = obstack_room (obstack) / sizeof (tree *);
        !            56:   return stack;
        !            57: }
        !            58: 
        !            59: struct stack_level *
        !            60: pop_stack_level (stack)
        !            61:      struct stack_level *stack;
        !            62: {
        !            63:   struct stack_level *tem = stack;
        !            64:   struct obstack *obstack = tem->obstack;
        !            65:   stack = tem->prev;
        !            66:   obstack_free (obstack, tem);
        !            67:   return stack;
        !            68: }
        !            69: 
        !            70: #define search_level stack_level
        !            71: static struct search_level *search_stack;
        !            72: 
        !            73: static tree lookup_field_1 ();
        !            74: static int lookup_fnfields_1 ();
        !            75: static void dfs_walk ();
        !            76: static int markedp ();
        !            77: static void dfs_unmark ();
        !            78: static void dfs_init_vbase_pointers ();
        !            79: 
        !            80: static tree vbase_types;
        !            81: static tree vbase_decl, vbase_decl_ptr;
        !            82: static tree vbase_decl_ptr_intermediate;
        !            83: static tree vbase_init_result;
        !            84: 
        !            85: /* Allocate a level of searching.  */
        !            86: static struct search_level *
        !            87: push_search_level (stack, obstack)
        !            88:      struct stack_level *stack;
        !            89:      struct obstack *obstack;
        !            90: {
        !            91:   struct search_level tem;
        !            92: 
        !            93:   tem.prev = stack;
        !            94:   return push_stack_level (obstack, (char *)&tem, sizeof (tem));
        !            95: }
        !            96: 
        !            97: /* Discard a level of search allocation.  */
        !            98: static struct search_level *
        !            99: pop_search_level (obstack)
        !           100:      struct stack_level *obstack;
        !           101: {
        !           102:   register struct search_level *stack = pop_stack_level (obstack);
        !           103: 
        !           104:   return stack;
        !           105: }
        !           106: 
        !           107: /* Search memoization.  */
        !           108: struct type_level
        !           109: {
        !           110:   struct stack_level base;
        !           111: 
        !           112:   /* First object allocated in obstack of entries.  */
        !           113:   char *entries;
        !           114: 
        !           115:   /* Number of types memoized in this context.  */
        !           116:   int len;
        !           117: 
        !           118:   /* Type being memoized; save this if we are saving
        !           119:      memoized contexts.  */
        !           120:   tree type;
        !           121: };
        !           122: 
        !           123: /* Obstack used for memoizing member and member function lookup.  */
        !           124: 
        !           125: static struct obstack type_obstack, type_obstack_entries;
        !           126: static struct type_level *type_stack;
        !           127: static tree _vptr_name;
        !           128: 
        !           129: /* Make things that look like tree nodes, but allocate them
        !           130:    on type_obstack_entries.  */
        !           131: static int my_tree_node_counter;
        !           132: static tree my_tree_cons (), my_build_string ();
        !           133: 
        !           134: extern int flag_memoize_lookups, flag_save_memoized_contexts;
        !           135: 
        !           136: /* Variables for gathering statistics.  */
        !           137: static int my_memoized_entry_counter;
        !           138: static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];
        !           139: static int memoized_fields_searched[2];
        !           140: static int n_fields_searched;
        !           141: static int n_calls_lookup_field, n_calls_lookup_field_1;
        !           142: static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;
        !           143: static int n_calls_get_base_type;
        !           144: static int n_outer_fields_searched;
        !           145: static int n_contexts_saved;
        !           146: 
        !           147: /* Local variables to help save memoization contexts.  */
        !           148: static tree prev_type_memoized;
        !           149: static struct type_level *prev_type_stack;
        !           150: 
        !           151: /* This list is used by push_class_decls to know what decls need to
        !           152:    be pushed into class scope.  */
        !           153: static tree closed_envelopes = NULL_TREE;
        !           154: 
        !           155: /* Allocate a level of type memoization context.  */
        !           156: static struct type_level *
        !           157: push_type_level (stack, obstack)
        !           158:      struct stack_level *stack;
        !           159:      struct obstack *obstack;
        !           160: {
        !           161:   struct type_level tem;
        !           162: 
        !           163:   tem.base.prev = stack;
        !           164: 
        !           165:   obstack_finish (&type_obstack_entries);
        !           166:   tem.entries = (char *) obstack_base (&type_obstack_entries);
        !           167:   tem.len = 0;
        !           168:   tem.type = NULL_TREE;
        !           169: 
        !           170:   return (struct type_level *)push_stack_level (obstack, (char *)&tem, sizeof (tem));
        !           171: }
        !           172: 
        !           173: /* Discard a level of type memoization context.  */
        !           174: 
        !           175: static struct type_level *
        !           176: pop_type_level (stack)
        !           177:      struct type_level *stack;
        !           178: {
        !           179:   obstack_free (&type_obstack_entries, stack->entries);
        !           180:   return (struct type_level *)pop_stack_level ((struct stack_level *)stack);
        !           181: }
        !           182: 
        !           183: /* Make something that looks like a TREE_LIST, but
        !           184:    do it on the type_obstack_entries obstack.  */
        !           185: static tree
        !           186: my_tree_cons (purpose, value, chain)
        !           187:      tree purpose, value, chain;
        !           188: {
        !           189:   tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_list));
        !           190:   ++my_tree_node_counter;
        !           191:   TREE_TYPE (p) = NULL_TREE;
        !           192:   ((HOST_WIDE_INT *)p)[3] = 0;
        !           193:   TREE_SET_CODE (p, TREE_LIST);
        !           194:   TREE_PURPOSE (p) = purpose;
        !           195:   TREE_VALUE (p) = value;
        !           196:   TREE_CHAIN (p) = chain;
        !           197:   return p;
        !           198: }
        !           199: 
        !           200: static tree
        !           201: my_build_string (str)
        !           202:      char *str;
        !           203: {
        !           204:   tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_string));
        !           205:   ++my_tree_node_counter;
        !           206:   TREE_TYPE (p) = 0;
        !           207:   ((int *)p)[3] = 0;
        !           208:   TREE_SET_CODE (p, STRING_CST);
        !           209:   TREE_STRING_POINTER (p) = str;
        !           210:   TREE_STRING_LENGTH (p) = strlen (str);
        !           211:   return p;
        !           212: }
        !           213: 
        !           214: /* Memoizing machinery to make searches for multiple inheritance
        !           215:    reasonably efficient.  */
        !           216: #define MEMOIZE_HASHSIZE 8
        !           217: typedef struct memoized_entry
        !           218: {
        !           219:   struct memoized_entry *chain;
        !           220:   int uid;
        !           221:   tree data_members[MEMOIZE_HASHSIZE];
        !           222:   tree function_members[MEMOIZE_HASHSIZE];
        !           223: } *ME;
        !           224: 
        !           225: #define MEMOIZED_CHAIN(ENTRY) (((ME)ENTRY)->chain)
        !           226: #define MEMOIZED_UID(ENTRY) (((ME)ENTRY)->uid)
        !           227: #define MEMOIZED_FIELDS(ENTRY,INDEX) (((ME)ENTRY)->data_members[INDEX])
        !           228: #define MEMOIZED_FNFIELDS(ENTRY,INDEX) (((ME)ENTRY)->function_members[INDEX])
        !           229: /* The following is probably a lousy hash function.  */
        !           230: #define MEMOIZED_HASH_FN(NODE) (((long)(NODE)>>4)&(MEMOIZE_HASHSIZE - 1))
        !           231: 
        !           232: static struct memoized_entry *
        !           233: my_new_memoized_entry (chain)
        !           234:      struct memoized_entry *chain;
        !           235: {
        !           236:   struct memoized_entry *p =
        !           237:     (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
        !           238:                                            sizeof (struct memoized_entry));
        !           239:   bzero ((char *) p, sizeof (struct memoized_entry));
        !           240:   MEMOIZED_CHAIN (p) = chain;
        !           241:   MEMOIZED_UID (p) = ++my_memoized_entry_counter;
        !           242:   return p;
        !           243: }
        !           244: 
        !           245: /* Make an entry in the memoized table for type TYPE
        !           246:    that the entry for NAME is FIELD.  */
        !           247: 
        !           248: tree
        !           249: make_memoized_table_entry (type, name, function_p)
        !           250:      tree type, name;
        !           251:      int function_p;
        !           252: {
        !           253:   int index = MEMOIZED_HASH_FN (name);
        !           254:   tree entry, *prev_entry;
        !           255: 
        !           256:   memoized_adds[function_p] += 1;
        !           257:   if (CLASSTYPE_MTABLE_ENTRY (type) == 0)
        !           258:     {
        !           259:       obstack_ptr_grow (&type_obstack, type);
        !           260:       obstack_blank (&type_obstack, sizeof (struct memoized_entry *));
        !           261:       CLASSTYPE_MTABLE_ENTRY (type) = (char *)my_new_memoized_entry ((struct memoized_entry *)0);
        !           262:       type_stack->len++;
        !           263:       if (type_stack->len * 2 >= type_stack->base.limit)
        !           264:        my_friendly_abort (88);
        !           265:     }
        !           266:   if (function_p)
        !           267:     prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
        !           268:   else
        !           269:     prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
        !           270: 
        !           271:   entry = my_tree_cons (name, NULL_TREE, *prev_entry);
        !           272:   *prev_entry = entry;
        !           273: 
        !           274:   /* Don't know the error message to give yet.  */
        !           275:   TREE_TYPE (entry) = error_mark_node;
        !           276: 
        !           277:   return entry;
        !           278: }
        !           279: 
        !           280: /* When a new function or class context is entered, we build
        !           281:    a table of types which have been searched for members.
        !           282:    The table is an array (obstack) of types.  When a type is
        !           283:    entered into the obstack, its CLASSTYPE_MTABLE_ENTRY
        !           284:    field is set to point to a new record, of type struct memoized_entry.
        !           285: 
        !           286:    A non-NULL TREE_TYPE of the entry contains an access control error message.
        !           287: 
        !           288:    The slots for the data members are arrays of tree nodes.
        !           289:    These tree nodes are lists, with the TREE_PURPOSE
        !           290:    of this list the known member name, and the TREE_VALUE
        !           291:    as the FIELD_DECL for the member.
        !           292: 
        !           293:    For member functions, the TREE_PURPOSE is again the
        !           294:    name of the member functions for that class,
        !           295:    and the TREE_VALUE of the list is a pairs
        !           296:    whose TREE_PURPOSE is a member functions of this name,
        !           297:    and whose TREE_VALUE is a list of known argument lists this
        !           298:    member function has been called with.  The TREE_TYPE of the pair,
        !           299:    if non-NULL, is an error message to print.  */
        !           300: 
        !           301: /* Tell search machinery that we are entering a new context, and
        !           302:    to update tables appropriately.
        !           303: 
        !           304:    TYPE is the type of the context we are entering, which can
        !           305:    be NULL_TREE if we are not in a class's scope.
        !           306: 
        !           307:    USE_OLD, if nonzero tries to use previous context.  */
        !           308: void
        !           309: push_memoized_context (type, use_old)
        !           310:      tree type;
        !           311:      int use_old;
        !           312: {
        !           313:   int len;
        !           314:   tree *tem;
        !           315: 
        !           316:   if (prev_type_stack)
        !           317:     {
        !           318:       if (use_old && prev_type_memoized == type)
        !           319:        {
        !           320: #ifdef GATHER_STATISTICS
        !           321:          n_contexts_saved++;
        !           322: #endif
        !           323:          type_stack = prev_type_stack;
        !           324:          prev_type_stack = 0;
        !           325: 
        !           326:          tem = &type_stack->base.first[0];
        !           327:          len = type_stack->len;
        !           328:          while (len--)
        !           329:            CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)tem[len*2+1];
        !           330:          return;
        !           331:        }
        !           332:       /* Otherwise, need to pop old stack here.  */
        !           333:       type_stack = pop_type_level (prev_type_stack);
        !           334:       prev_type_memoized = 0;
        !           335:       prev_type_stack = 0;
        !           336:     }
        !           337: 
        !           338:   type_stack = push_type_level ((struct stack_level *)type_stack,
        !           339:                                &type_obstack);
        !           340:   type_stack->type = type;
        !           341: }
        !           342: 
        !           343: /* Tell search machinery that we have left a context.
        !           344:    We do not currently save these contexts for later use.
        !           345:    If we wanted to, we could not use pop_search_level, since
        !           346:    poping that level allows the data we have collected to
        !           347:    be clobbered; a stack of obstacks would be needed.  */
        !           348: void
        !           349: pop_memoized_context (use_old)
        !           350:      int use_old;
        !           351: {
        !           352:   int len;
        !           353:   tree *tem = &type_stack->base.first[0];
        !           354: 
        !           355:   if (! flag_save_memoized_contexts)
        !           356:     use_old = 0;
        !           357:   else if (use_old)
        !           358:     {
        !           359:       len = type_stack->len;
        !           360:       while (len--)
        !           361:        tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]);
        !           362: 
        !           363:       prev_type_stack = type_stack;
        !           364:       prev_type_memoized = type_stack->type;
        !           365:     }
        !           366: 
        !           367:   if (flag_memoize_lookups)
        !           368:     {
        !           369:       len = type_stack->len;
        !           370:       while (len--)
        !           371:        CLASSTYPE_MTABLE_ENTRY (tem[len*2])
        !           372:          = (char *)MEMOIZED_CHAIN (CLASSTYPE_MTABLE_ENTRY (tem[len*2]));
        !           373:     }
        !           374:   if (! use_old)
        !           375:     type_stack = pop_type_level (type_stack);
        !           376:   else
        !           377:     type_stack = (struct type_level *)type_stack->base.prev;
        !           378: }
        !           379: 
        !           380: #if 0                          /* unused */
        !           381: /* This is the newer recursive depth first search routine. */
        !           382: /* Return non-zero if PARENT is directly derived from TYPE.  By directly
        !           383:    we mean it's only one step up the inheritance lattice.  We check this
        !           384:    by walking horizontally across the types that TYPE directly inherits
        !           385:    from, to see if PARENT is among them.  This is used by get_binfo and
        !           386:    by compute_access.  */
        !           387: static int
        !           388: immediately_derived (parent, type)
        !           389:      tree parent, type;
        !           390: {
        !           391:   if (TYPE_BINFO (type))
        !           392:     {
        !           393:       tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
        !           394:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !           395: 
        !           396:       for (i = 0; i < n_baselinks; i++)
        !           397:        {
        !           398:          tree base_binfo = TREE_VEC_ELT (binfos, i);
        !           399: 
        !           400:          if (parent == BINFO_TYPE (base_binfo))
        !           401:            return 1;
        !           402:        }
        !           403:     }
        !           404:   return 0;
        !           405: }
        !           406: #endif
        !           407: 
        !           408: /* Check whether the type given in BINFO is derived from PARENT.  If
        !           409:    it isn't, return 0.  If it is, but the derivation is MI-ambiguous
        !           410:    AND protect != 0, emit an error message and return error_mark_node.
        !           411: 
        !           412:    Otherwise, if TYPE is derived from PARENT, return the actual base
        !           413:    information, unless a one of the protection violations below
        !           414:    occurs, in which case emit an error message and return error_mark_node.
        !           415: 
        !           416:    If PROTECT is 1, then check if access to a public field of PARENT
        !           417:    would be private.  Also check for ambiguity.  */
        !           418: 
        !           419: tree
        !           420: get_binfo (parent, binfo, protect)
        !           421:      register tree parent, binfo;
        !           422:      int protect;
        !           423: {
        !           424:   tree type;
        !           425:   int dist;
        !           426:   tree rval = NULL_TREE;
        !           427:   
        !           428:   if (TREE_CODE (parent) == TREE_VEC)
        !           429:     parent = BINFO_TYPE (parent);
        !           430:   /* unions cannot participate in inheritance relationships */
        !           431:   else if (TREE_CODE (parent) == UNION_TYPE)
        !           432:     return NULL_TREE;
        !           433:   else if (TREE_CODE (parent) != RECORD_TYPE)
        !           434:     my_friendly_abort (89);
        !           435: 
        !           436:   if (TREE_CODE (binfo) == TREE_VEC)
        !           437:     type = BINFO_TYPE (binfo);
        !           438:   else if (TREE_CODE (binfo) == RECORD_TYPE)
        !           439:     type = binfo;
        !           440:   else if (TREE_CODE (binfo) == UNION_TYPE)
        !           441:     return NULL_TREE;
        !           442:   else
        !           443:     my_friendly_abort (90);
        !           444:   
        !           445:   dist = get_base_distance (parent, binfo, protect, &rval);
        !           446: 
        !           447:   if (dist == -3)
        !           448:     {
        !           449:       cp_error ("fields of `%T' are inaccessible in `%T' due to private inheritance",
        !           450:                parent, type);
        !           451:       return error_mark_node;
        !           452:     }
        !           453:   else if (dist == -2 && protect)
        !           454:     {
        !           455:       cp_error ("type `%T' is ambiguous base class for type `%T'", parent,
        !           456:                type);
        !           457:       return error_mark_node;
        !           458:     }
        !           459: 
        !           460:   return rval;
        !           461: }
        !           462: 
        !           463: /* This is the newer depth first get_base_distance routine.  */
        !           464: static int
        !           465: get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
        !           466:                             rval_private_ptr, new_binfo_ptr, parent, path_ptr,
        !           467:                             protect, via_virtual_ptr, via_virtual)
        !           468:      tree binfo, basetype_path, *new_binfo_ptr, parent, *path_ptr;
        !           469:      int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr,
        !           470:        via_virtual;
        !           471: {
        !           472:   tree binfos;
        !           473:   int i, n_baselinks;
        !           474: 
        !           475:   if (BINFO_TYPE (binfo) == parent || binfo == parent)
        !           476:     {
        !           477:       if (rval == -1)
        !           478:        {
        !           479:          rval = depth;
        !           480:          *rval_private_ptr = is_private;
        !           481:          *new_binfo_ptr = binfo;
        !           482:          *via_virtual_ptr = via_virtual;
        !           483:        }
        !           484:       else
        !           485:        {
        !           486:          int same_object = (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
        !           487:                                                 BINFO_OFFSET (binfo))
        !           488:                             && *via_virtual_ptr && via_virtual);
        !           489:                             
        !           490:          if (*via_virtual_ptr && via_virtual==0)
        !           491:            {
        !           492:              *rval_private_ptr = is_private;
        !           493:              *new_binfo_ptr = binfo;
        !           494:              *via_virtual_ptr = via_virtual;
        !           495:            }
        !           496:          else if (same_object)
        !           497:            {
        !           498:              if (*rval_private_ptr && ! is_private)
        !           499:                {
        !           500:                  *rval_private_ptr = is_private;
        !           501:                  *new_binfo_ptr = binfo;
        !           502:                  *via_virtual_ptr = via_virtual;
        !           503:                }
        !           504:              return rval;
        !           505:            }
        !           506: 
        !           507:          rval = -2;
        !           508:        }
        !           509:       return rval;
        !           510:     }
        !           511: 
        !           512:   binfos = BINFO_BASETYPES (binfo);
        !           513:   n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !           514:   depth += 1;
        !           515: 
        !           516:   /* Process base types.  */
        !           517:   for (i = 0; i < n_baselinks; i++)
        !           518:     {
        !           519:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !           520: 
        !           521:       /* Find any specific instance of a virtual base, when searching with
        !           522:         a binfo... */
        !           523:       if (BINFO_MARKED (base_binfo) == 0 || TREE_CODE (parent) == TREE_VEC)
        !           524:        {
        !           525:          int via_private
        !           526:            = (protect
        !           527:               && (is_private
        !           528:                   || (!TREE_VIA_PUBLIC (base_binfo)
        !           529:                       && !is_friend (BINFO_TYPE (binfo), current_scope ()))));
        !           530:          int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
        !           531:          int was;
        !           532: 
        !           533:          /* When searching for a non-virtual, we cannot mark
        !           534:             virtually found binfos. */
        !           535:          if (! this_virtual)
        !           536:            SET_BINFO_MARKED (base_binfo);
        !           537: 
        !           538: #define WATCH_VALUES(rval, via_private) (rval == -1 ? 3 : via_private)
        !           539: 
        !           540:          was = WATCH_VALUES (rval, *via_virtual_ptr);
        !           541:          rval = get_base_distance_recursive (base_binfo, depth, via_private,
        !           542:                                              binfo, rval, rval_private_ptr,
        !           543:                                              new_binfo_ptr, parent, path_ptr,
        !           544:                                              protect, via_virtual_ptr,
        !           545:                                              this_virtual);
        !           546:          /* watch for updates; only update if path is good. */
        !           547:          if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was)
        !           548:            BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
        !           549:          if (rval == -2 && *via_virtual_ptr == 0)
        !           550:            return rval;
        !           551: 
        !           552: #undef WATCH_VALUES
        !           553: 
        !           554:        }
        !           555:     }
        !           556: 
        !           557:   return rval;
        !           558: }
        !           559: 
        !           560: /* Return the number of levels between type PARENT and the type given
        !           561:    in BINFO, following the leftmost path to PARENT not found along a
        !           562:    virtual path, if there are no real PARENTs (all come from virtual
        !           563:    base classes), then follow the leftmost path to PARENT.
        !           564: 
        !           565:    Return -1 if TYPE is not derived from PARENT.
        !           566:    Return -2 if PARENT is an ambiguous base class of TYPE, and PROTECT is
        !           567:     non-negative.
        !           568:    Return -3 if PARENT is private to TYPE, and PROTECT is non-zero.
        !           569: 
        !           570:    If PATH_PTR is non-NULL, then also build the list of types
        !           571:    from PARENT to TYPE, with TREE_VIA_VIRUAL and TREE_VIA_PUBLIC
        !           572:    set.
        !           573: 
        !           574:    PARENT can also be a binfo, in which case that exact parent is found
        !           575:    and no other.  convert_pointer_to_real uses this functionality.
        !           576: 
        !           577:    If BINFO is a binfo, its BINFO_INHERITANCE_CHAIN will be left alone.  */
        !           578: 
        !           579: int
        !           580: get_base_distance (parent, binfo, protect, path_ptr)
        !           581:      register tree parent, binfo;
        !           582:      int protect;
        !           583:      tree *path_ptr;
        !           584: {
        !           585:   int rval;
        !           586:   int rval_private = 0;
        !           587:   tree type;
        !           588:   tree new_binfo = NULL_TREE;
        !           589:   int via_virtual;
        !           590:   int watch_access = protect;
        !           591: 
        !           592:   if (TREE_CODE (parent) != TREE_VEC)
        !           593:     parent = TYPE_MAIN_VARIANT (parent);
        !           594: 
        !           595:   if (TREE_CODE (binfo) == TREE_VEC)
        !           596:     type = BINFO_TYPE (binfo);
        !           597:   else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
        !           598:     {
        !           599:       type = binfo;
        !           600:       binfo = TYPE_BINFO (type);
        !           601: 
        !           602:       if (path_ptr)
        !           603:        BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
        !           604:     }
        !           605:   else
        !           606:     my_friendly_abort (92);
        !           607: 
        !           608:   if (parent == type || parent == binfo)
        !           609:     {
        !           610:       /* If the distance is 0, then we don't really need
        !           611:         a path pointer, but we shouldn't let garbage go back.  */
        !           612:       if (path_ptr)
        !           613:        *path_ptr = binfo;
        !           614:       return 0;
        !           615:     }
        !           616: 
        !           617:   if (path_ptr)
        !           618:     watch_access = 1;
        !           619: 
        !           620:   rval = get_base_distance_recursive (binfo, 0, 0, NULL_TREE, -1,
        !           621:                                      &rval_private, &new_binfo, parent,
        !           622:                                      path_ptr, watch_access, &via_virtual, 0);
        !           623: 
        !           624:   dfs_walk (binfo, dfs_unmark, markedp);
        !           625: 
        !           626:   /* Access restrictions don't count if we found an ambiguous basetype.  */
        !           627:   if (rval == -2 && protect >= 0)
        !           628:     rval_private = 0;
        !           629: 
        !           630:   if (rval && protect && rval_private)
        !           631:     return -3;
        !           632: 
        !           633:   /* find real virtual base classes. */
        !           634:   if (rval == -1 && TREE_CODE (parent) == TREE_VEC
        !           635:       && parent == binfo_member (BINFO_TYPE (parent),
        !           636:                                 CLASSTYPE_VBASECLASSES (type)))
        !           637:     {
        !           638:       BINFO_INHERITANCE_CHAIN (parent) = binfo;
        !           639:       new_binfo = parent;
        !           640:       rval = 1;
        !           641:     }
        !           642: 
        !           643:   if (path_ptr)
        !           644:     *path_ptr = new_binfo;
        !           645:   return rval;
        !           646: }
        !           647: 
        !           648: /* Search for a member with name NAME in a multiple inheritance lattice
        !           649:    specified by TYPE.  If it does not exist, return NULL_TREE.
        !           650:    If the member is ambiguously referenced, return `error_mark_node'.
        !           651:    Otherwise, return the FIELD_DECL.  */
        !           652: 
        !           653: /* Do a 1-level search for NAME as a member of TYPE.  The caller must
        !           654:    figure out whether it can access this field.  (Since it is only one
        !           655:    level, this is reasonable.)  */
        !           656: static tree
        !           657: lookup_field_1 (type, name)
        !           658:      tree type, name;
        !           659: {
        !           660:   register tree field = TYPE_FIELDS (type);
        !           661: 
        !           662: #ifdef GATHER_STATISTICS
        !           663:   n_calls_lookup_field_1++;
        !           664: #endif
        !           665:   while (field)
        !           666:     {
        !           667: #ifdef GATHER_STATISTICS
        !           668:       n_fields_searched++;
        !           669: #endif
        !           670:       if (DECL_NAME (field) == NULL_TREE
        !           671:          && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
        !           672:        {
        !           673:          tree temp = lookup_field_1 (TREE_TYPE (field), name);
        !           674:          if (temp)
        !           675:            return temp;
        !           676:        }
        !           677:       if (DECL_NAME (field) == name)
        !           678:        {
        !           679:          if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL)
        !           680:              && DECL_ASSEMBLER_NAME (field) != NULL)
        !           681:            GNU_xref_ref(current_function_decl,
        !           682:                         IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (field)));
        !           683:          return field;
        !           684:        }
        !           685:       field = TREE_CHAIN (field);
        !           686:     }
        !           687:   /* Not found.  */
        !           688:   if (name == _vptr_name)
        !           689:     {
        !           690:       /* Give the user what s/he thinks s/he wants.  */
        !           691:       if (TYPE_VIRTUAL_P (type))
        !           692:        return CLASSTYPE_VFIELD (type);
        !           693:     }
        !           694:   return NULL_TREE;
        !           695: }
        !           696: 
        !           697: /* There are a number of cases we need to be aware of here:
        !           698:                         current_class_type     current_function_decl
        !           699:    * global                    NULL                    NULL
        !           700:    * fn-local                  NULL                    SET
        !           701:    * class-local               SET                     NULL
        !           702:    * class->fn                 SET                     SET
        !           703:    * fn->class                 SET                     SET
        !           704: 
        !           705:    Those last two make life interesting.  If we're in a function which is
        !           706:    itself inside a class, we need decls to go into the fn's decls (our
        !           707:    second case below).  But if we're in a class and the class itself is
        !           708:    inside a function, we need decls to go into the decls for the class.  To
        !           709:    achieve this last goal, we must see if, when both current_class_decl and
        !           710:    current_function_decl are set, the class was declared inside that
        !           711:    function.  If so, we know to put the decls into the class's scope.  */
        !           712: 
        !           713: tree
        !           714: current_scope ()
        !           715: {
        !           716:   if (current_function_decl == NULL_TREE)
        !           717:     return current_class_type;
        !           718:   if (current_class_type == NULL_TREE)
        !           719:     return current_function_decl;
        !           720:   if (DECL_CLASS_CONTEXT (current_function_decl) == current_class_type)
        !           721:     return current_function_decl;
        !           722: 
        !           723:   return current_class_type;
        !           724: }
        !           725: 
        !           726: /* Compute the access of FIELD.  This is done by computing
        !           727:    the access available to each type in BASETYPES (which comes
        !           728:    as a list of [via_public/basetype] in reverse order, namely base
        !           729:    class before derived class).  The first one which defines a
        !           730:    access defines the access for the field.  Otherwise, the
        !           731:    access of the field is that which occurs normally.
        !           732: 
        !           733:    Uses global variables CURRENT_CLASS_TYPE and
        !           734:    CURRENT_FUNCTION_DECL to use friend relationships
        !           735:    if necessary.
        !           736: 
        !           737:    This will be static when lookup_fnfield comes into this file.
        !           738: 
        !           739:    access_public means that the field can be accessed by the current lexical
        !           740:    scope.
        !           741: 
        !           742:    access_protected means that the field cannot be accessed by the current
        !           743:    lexical scope because it is protected.
        !           744: 
        !           745:    access_private means that the field cannot be accessed by the current
        !           746:    lexical scope because it is private. */
        !           747: 
        !           748: #if 0
        !           749: #define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public
        !           750: #define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected
        !           751: #define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private
        !           752: #else
        !           753: #define PUBLIC_RETURN return access_public
        !           754: #define PROTECTED_RETURN return access_protected
        !           755: #define PRIVATE_RETURN return access_private
        !           756: #endif
        !           757: 
        !           758: #if 0
        !           759: /* Disabled with DECL_PUBLIC &c.  */
        !           760: static tree previous_scope = NULL_TREE;
        !           761: #endif
        !           762: 
        !           763: enum access_type
        !           764: compute_access (basetype_path, field)
        !           765:      tree basetype_path, field;
        !           766: {
        !           767:   enum access_type access;
        !           768:   tree types;
        !           769:   tree context;
        !           770:   int protected_ok, via_protected;
        !           771:   extern int flag_access_control;
        !           772: #if 1
        !           773:   /* Replaces static decl above.  */
        !           774:   tree previous_scope;
        !           775: #endif
        !           776:   int static_mem =
        !           777:     ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
        !           778:      || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
        !           779: 
        !           780:   if (! flag_access_control)
        !           781:     return access_public;
        !           782: 
        !           783:   /* The field lives in the current class.  */
        !           784:   if (BINFO_TYPE (basetype_path) == current_class_type)
        !           785:     return access_public;
        !           786: 
        !           787: #if 0
        !           788:   /* Disabled until pushing function scope clears these out.  If ever.  */
        !           789:   /* Make these special cases fast.  */
        !           790:   if (current_scope () == previous_scope)
        !           791:     {
        !           792:       if (DECL_PUBLIC (field))
        !           793:        return access_public;
        !           794:       if (DECL_PROTECTED (field))
        !           795:        return access_protected;
        !           796:       if (DECL_PRIVATE (field))
        !           797:        return access_private;
        !           798:     }
        !           799: #endif
        !           800: 
        !           801:   previous_scope = current_scope ();
        !           802:   
        !           803:   context = DECL_CLASS_CONTEXT (field);
        !           804:   if (context == NULL_TREE)
        !           805:     context = DECL_CONTEXT (field);
        !           806: 
        !           807:   /* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
        !           808:      slot set to the union type rather than the record type containing
        !           809:      the anonymous union.  In this case, DECL_FIELD_CONTEXT is correct.  */
        !           810:   if (context && TREE_CODE (context) == UNION_TYPE
        !           811:       && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
        !           812:     context = DECL_FIELD_CONTEXT (field);
        !           813: 
        !           814:   /* Virtual function tables are never private.  But we should know that
        !           815:      we are looking for this, and not even try to hide it.  */
        !           816:   if (DECL_NAME (field) && VFIELD_NAME_P (DECL_NAME (field)) == 1)
        !           817:     PUBLIC_RETURN;
        !           818: 
        !           819:   /* Member found immediately within object.  */
        !           820:   if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE)
        !           821:     {
        !           822:       /* Are we (or an enclosing scope) friends with the class that has
        !           823:          FIELD? */
        !           824:       if (is_friend (context, previous_scope))
        !           825:        PUBLIC_RETURN;
        !           826: 
        !           827:       /* If it's private, it's private, you letch.  */
        !           828:       if (TREE_PRIVATE (field))
        !           829:        PRIVATE_RETURN;
        !           830: 
        !           831:       /* ARM $11.5.  Member functions of a derived class can access the
        !           832:         non-static protected members of a base class only through a
        !           833:         pointer to the derived class, a reference to it, or an object
        !           834:         of it. Also any subsequently derived classes also have
        !           835:         access.  */
        !           836:       else if (TREE_PROTECTED (field))
        !           837:        {
        !           838:          if (current_class_type
        !           839:              && static_mem
        !           840:              && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
        !           841:            PUBLIC_RETURN;
        !           842:          else
        !           843:            PROTECTED_RETURN;
        !           844:        }
        !           845:       else
        !           846:        PUBLIC_RETURN;
        !           847:     }
        !           848: 
        !           849:   /* must reverse more than one element */
        !           850:   basetype_path = reverse_path (basetype_path);
        !           851:   types = basetype_path;
        !           852:   via_protected = 0;
        !           853:   access = access_default;
        !           854:   protected_ok = static_mem && current_class_type
        !           855:     && ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type);
        !           856: 
        !           857:   while (1)
        !           858:     {
        !           859:       tree member;
        !           860:       tree binfo = types;
        !           861:       tree type = BINFO_TYPE (binfo);
        !           862:       int private_ok = 0;
        !           863: 
        !           864:       /* Friends of a class can see protected members of its bases.
        !           865:          Note that classes are their own friends.  */
        !           866:       if (is_friend (type, previous_scope))
        !           867:        {
        !           868:          protected_ok = 1;
        !           869:          private_ok = 1;
        !           870:        }
        !           871: 
        !           872:       member = purpose_member (type, DECL_ACCESS (field));
        !           873:       if (member)
        !           874:        {
        !           875:          access = (enum access_type) TREE_VALUE (member);
        !           876:          break;
        !           877:        }
        !           878: 
        !           879:       types = BINFO_INHERITANCE_CHAIN (types);
        !           880: 
        !           881:       /* If the next type was VIA_PROTECTED, then fields of all remaining
        !           882:         classes past that one are *at least* protected.  */
        !           883:       if (types)
        !           884:        {
        !           885:          if (TREE_VIA_PROTECTED (types))
        !           886:            via_protected = 1;
        !           887:          else if (! TREE_VIA_PUBLIC (types) && ! private_ok)
        !           888:            {
        !           889:              access = access_private;
        !           890:              break;
        !           891:            }
        !           892:        }
        !           893:       else
        !           894:        break;
        !           895:     }
        !           896:   reverse_path (basetype_path);
        !           897: 
        !           898:   /* No special visibilities apply.  Use normal rules.  */
        !           899: 
        !           900:   if (access == access_default)
        !           901:     {
        !           902:       if (is_friend (context, previous_scope))
        !           903:        access = access_public;
        !           904:       else if (TREE_PRIVATE (field))
        !           905:        access = access_private;
        !           906:       else if (TREE_PROTECTED (field))
        !           907:        access = access_protected;
        !           908:       else
        !           909:        access = access_public;
        !           910:     }
        !           911: 
        !           912:   if (access == access_public && via_protected)
        !           913:     access = access_protected;
        !           914: 
        !           915:   if (access == access_protected && protected_ok)
        !           916:     access = access_public;
        !           917: 
        !           918: #if 0
        !           919:   if (access == access_public)
        !           920:     DECL_PUBLIC (field) = 1;
        !           921:   else if (access == access_protected)
        !           922:     DECL_PROTECTED (field) = 1;
        !           923:   else if (access == access_private)
        !           924:     DECL_PRIVATE (field) = 1;
        !           925:   else my_friendly_abort (96);
        !           926: #endif
        !           927:   return access;
        !           928: }
        !           929: 
        !           930: /* Routine to see if the sub-object denoted by the binfo PARENT can be
        !           931:    found as a base class and sub-object of the object denoted by
        !           932:    BINFO.  This routine relies upon binfos not being shared, except
        !           933:    for binfos for virtual bases.  */
        !           934: static int
        !           935: is_subobject_of_p (parent, binfo)
        !           936:      tree parent, binfo;
        !           937: {
        !           938:   tree binfos = BINFO_BASETYPES (binfo);
        !           939:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !           940: 
        !           941:   if (parent == binfo)
        !           942:     return 1;
        !           943: 
        !           944:   /* Process and/or queue base types.  */
        !           945:   for (i = 0; i < n_baselinks; i++)
        !           946:     {
        !           947:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !           948:       if (TREE_VIA_VIRTUAL (base_binfo))
        !           949:        base_binfo = TYPE_BINFO (BINFO_TYPE (base_binfo));
        !           950:       if (is_subobject_of_p (parent, base_binfo))
        !           951:        return 1;
        !           952:     }
        !           953:   return 0;
        !           954: }
        !           955: 
        !           956: /* See if a one FIELD_DECL hides another.  This routine is meant to
        !           957:    correspond to ANSI working paper Sept 17, 1992 10p4.  The two
        !           958:    binfos given are the binfos corresponding to the particular places
        !           959:    the FIELD_DECLs are found.  This routine relies upon binfos not
        !           960:    being shared, except for virtual bases. */
        !           961: static int
        !           962: hides (hider_binfo, hidee_binfo)
        !           963:      tree hider_binfo, hidee_binfo;
        !           964: {
        !           965:   /* hider hides hidee, if hider has hidee as a base class and
        !           966:      the instance of hidee is a sub-object of hider.  The first
        !           967:      part is always true is the second part is true.
        !           968: 
        !           969:      When hider and hidee are the same (two ways to get to the exact
        !           970:      same member) we consider either one as hiding the other. */
        !           971:   return is_subobject_of_p (hidee_binfo, hider_binfo);
        !           972: }
        !           973: 
        !           974: /* Very similar to lookup_fnfields_1 but it ensures that at least one
        !           975:    function was declared inside the class given by TYPE.  It really should
        !           976:    only return functions that match the given TYPE.  */
        !           977: static int
        !           978: lookup_fnfields_here (type, name)
        !           979:      tree type, name;
        !           980: {
        !           981:   int index = lookup_fnfields_1 (type, name);
        !           982:   tree fndecls;
        !           983: 
        !           984:   if (index <= 0)
        !           985:     return index;
        !           986:   fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
        !           987:   while (fndecls)
        !           988:     {
        !           989:       if (TYPE_MAIN_VARIANT (DECL_CLASS_CONTEXT (fndecls))
        !           990:          == TYPE_MAIN_VARIANT (type))
        !           991:        return index;
        !           992:       fndecls = TREE_CHAIN (fndecls);
        !           993:     }
        !           994:   return -1;
        !           995: }
        !           996: 
        !           997: /* Look for a field named NAME in an inheritance lattice dominated by
        !           998:    XBASETYPE.  PROTECT is zero if we can avoid computing access
        !           999:    information, otherwise it is 1.  WANT_TYPE is 1 when we should only
        !          1000:    return TYPE_DECLs, if no TYPE_DECL can be found return NULL_TREE.
        !          1001: 
        !          1002:    It was not clear what should happen if WANT_TYPE is set, and an
        !          1003:    ambiguity is found.  At least one use (lookup_name) to not see
        !          1004:    the error.  */
        !          1005: tree
        !          1006: lookup_field (xbasetype, name, protect, want_type)
        !          1007:      register tree xbasetype, name;
        !          1008:      int protect, want_type;
        !          1009: {
        !          1010:   int head = 0, tail = 0;
        !          1011:   tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
        !          1012:   tree type, basetype_chain, basetype_path;
        !          1013:   enum access_type this_v = access_default;
        !          1014:   tree entry, binfo, binfo_h;
        !          1015:   enum access_type own_access = access_default;
        !          1016:   int vbase_name_p = VBASE_NAME_P (name);
        !          1017: 
        !          1018:   /* rval_binfo is the binfo associated with the found member, note,
        !          1019:      this can be set with useful information, even when rval is not
        !          1020:      set, because it must deal with ALL members, not just non-function
        !          1021:      members.  It is used for ambiguity checking and the hidden
        !          1022:      checks.  Whereas rval is only set if a proper (not hidden)
        !          1023:      non-function member is found.  */
        !          1024: 
        !          1025:   /* rval_binfo_h and binfo_h are binfo values used when we perform the
        !          1026:      hiding checks, as virtual base classes may not be shared.  The strategy
        !          1027:      is we always go into the the binfo hierarchy owned by TYPE_BINFO of
        !          1028:      virtual base classes, as we cross virtual base class lines.  This way
        !          1029:      we know that binfo of a virtual base class will always == itself when
        !          1030:      found along any line.  (mrs)  */
        !          1031: 
        !          1032:   char *errstr = 0;
        !          1033: 
        !          1034:   /* Set this to nonzero if we don't know how to compute
        !          1035:      accurate error messages for access control.  */
        !          1036:   int index = MEMOIZED_HASH_FN (name);
        !          1037: 
        !          1038:   /* If we are looking for a constructor in a templated type, use the
        !          1039:      unspecialized name, as that is how we store it.  */
        !          1040:   if (IDENTIFIER_TEMPLATE (name))
        !          1041:     name = constructor_name (name);
        !          1042: 
        !          1043:   if (TREE_CODE (xbasetype) == TREE_VEC)
        !          1044:     {
        !          1045:       type = BINFO_TYPE (xbasetype);
        !          1046:       basetype_path = xbasetype;
        !          1047:     }
        !          1048:   else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
        !          1049:     {
        !          1050:       type = xbasetype;
        !          1051:       basetype_path = TYPE_BINFO (xbasetype);
        !          1052:       BINFO_VIA_PUBLIC (basetype_path) = 1;
        !          1053:       BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
        !          1054:     }
        !          1055:   else my_friendly_abort (97);
        !          1056: 
        !          1057:   if (CLASSTYPE_MTABLE_ENTRY (type))
        !          1058:     {
        !          1059:       tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
        !          1060: 
        !          1061:       while (tem && TREE_PURPOSE (tem) != name)
        !          1062:        {
        !          1063:          memoized_fields_searched[0]++;
        !          1064:          tem = TREE_CHAIN (tem);
        !          1065:        }
        !          1066:       if (tem)
        !          1067:        {
        !          1068:          if (protect && TREE_TYPE (tem))
        !          1069:            {
        !          1070:              error (TREE_STRING_POINTER (TREE_TYPE (tem)),
        !          1071:                     IDENTIFIER_POINTER (name),
        !          1072:                     TYPE_NAME_STRING (DECL_FIELD_CONTEXT (TREE_VALUE (tem))));
        !          1073:              return error_mark_node;
        !          1074:            }
        !          1075:          if (TREE_VALUE (tem) == NULL_TREE)
        !          1076:            memoized_fast_rejects[0] += 1;
        !          1077:          else
        !          1078:            memoized_fast_finds[0] += 1;
        !          1079:          return TREE_VALUE (tem);
        !          1080:        }
        !          1081:     }
        !          1082: 
        !          1083: #ifdef GATHER_STATISTICS
        !          1084:   n_calls_lookup_field++;
        !          1085: #endif
        !          1086:   if (protect && flag_memoize_lookups && ! global_bindings_p ())
        !          1087:     entry = make_memoized_table_entry (type, name, 0);
        !          1088:   else
        !          1089:     entry = 0;
        !          1090: 
        !          1091:   rval = lookup_field_1 (type, name);
        !          1092:   if (rval || lookup_fnfields_here (type, name)>=0)
        !          1093:     {
        !          1094:       rval_binfo = basetype_path;
        !          1095:       rval_binfo_h = rval_binfo;
        !          1096:     }
        !          1097: 
        !          1098:   if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
        !          1099:     rval = NULL_TREE;
        !          1100: 
        !          1101:   if (rval)
        !          1102:     {
        !          1103:       if (protect)
        !          1104:        {
        !          1105:          if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
        !          1106:            this_v = compute_access (basetype_path, rval);
        !          1107:          if (TREE_CODE (rval) == CONST_DECL)
        !          1108:            {
        !          1109:              if (this_v == access_private)
        !          1110:                errstr = "enum `%D' is a private value of class `%T'";
        !          1111:              else if (this_v == access_protected)
        !          1112:                errstr = "enum `%D' is a protected value of class `%T'";
        !          1113:            }
        !          1114:          else
        !          1115:            {
        !          1116:              if (this_v == access_private)
        !          1117:                errstr = "member `%D' is a private member of class `%T'";
        !          1118:              else if (this_v == access_protected)
        !          1119:                errstr = "member `%D' is a protected member of class `%T'";
        !          1120:            }
        !          1121:        }
        !          1122: 
        !          1123:       if (entry)
        !          1124:        {
        !          1125:          if (errstr)
        !          1126:            {
        !          1127:              /* This depends on behavior of lookup_field_1!  */
        !          1128:              tree error_string = my_build_string (errstr);
        !          1129:              TREE_TYPE (entry) = error_string;
        !          1130:            }
        !          1131:          else
        !          1132:            {
        !          1133:              /* Let entry know there is no problem with this access.  */
        !          1134:              TREE_TYPE (entry) = NULL_TREE;
        !          1135:            }
        !          1136:          TREE_VALUE (entry) = rval;
        !          1137:        }
        !          1138: 
        !          1139:       if (errstr && protect)
        !          1140:        {
        !          1141:          cp_error (errstr, name, type);
        !          1142:          return error_mark_node;
        !          1143:        }
        !          1144:       return rval;
        !          1145:     }
        !          1146: 
        !          1147:   basetype_chain = build_tree_list (NULL_TREE, basetype_path);
        !          1148:   TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
        !          1149:   TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
        !          1150:   TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
        !          1151: 
        !          1152:   /* The ambiguity check relies upon breadth first searching. */
        !          1153: 
        !          1154:   search_stack = push_search_level (search_stack, &search_obstack);
        !          1155:   binfo = basetype_path;
        !          1156:   binfo_h = binfo;
        !          1157: 
        !          1158:   while (1)
        !          1159:     {
        !          1160:       tree binfos = BINFO_BASETYPES (binfo);
        !          1161:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          1162:       tree nval;
        !          1163: 
        !          1164:       /* Process and/or queue base types.  */
        !          1165:       for (i = 0; i < n_baselinks; i++)
        !          1166:        {
        !          1167:          tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          1168:          if (BINFO_FIELDS_MARKED (base_binfo) == 0)
        !          1169:            {
        !          1170:              tree btypes;
        !          1171: 
        !          1172:              SET_BINFO_FIELDS_MARKED (base_binfo);
        !          1173:              btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
        !          1174:              TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
        !          1175:              TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
        !          1176:              TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
        !          1177:              if (TREE_VIA_VIRTUAL (base_binfo))
        !          1178:                btypes = tree_cons (NULL_TREE,
        !          1179:                                    TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
        !          1180:                                    btypes);
        !          1181:              else
        !          1182:                btypes = tree_cons (NULL_TREE,
        !          1183:                                    TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
        !          1184:                                    btypes);
        !          1185:              obstack_ptr_grow (&search_obstack, btypes);
        !          1186:              tail += 1;
        !          1187:              if (tail >= search_stack->limit)
        !          1188:                my_friendly_abort (98);
        !          1189:            }
        !          1190:        }
        !          1191: 
        !          1192:       /* Process head of queue, if one exists.  */
        !          1193:       if (head >= tail)
        !          1194:        break;
        !          1195: 
        !          1196:       basetype_chain = search_stack->first[head++];
        !          1197:       binfo_h = TREE_VALUE (basetype_chain);
        !          1198:       basetype_chain = TREE_CHAIN (basetype_chain);
        !          1199:       basetype_path = TREE_VALUE (basetype_chain);
        !          1200:       if (TREE_CHAIN (basetype_chain))
        !          1201:        BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
        !          1202:       else
        !          1203:        BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
        !          1204: 
        !          1205:       binfo = basetype_path;
        !          1206:       type = BINFO_TYPE (binfo);
        !          1207: 
        !          1208:       /* See if we can find NAME in TYPE.  If RVAL is nonzero,
        !          1209:         and we do find NAME in TYPE, verify that such a second
        !          1210:         sighting is in fact legal.  */
        !          1211: 
        !          1212:       nval = lookup_field_1 (type, name);
        !          1213: 
        !          1214:       if (nval || lookup_fnfields_here (type, name)>=0)
        !          1215:        {
        !          1216:          if (nval && nval == rval && SHARED_MEMBER_P (nval))
        !          1217:            {
        !          1218:              /* This is ok, the member found is the same [class.ambig] */
        !          1219:            }
        !          1220:          else if (rval_binfo && hides (rval_binfo_h, binfo_h))
        !          1221:            {
        !          1222:              /* This is ok, the member found is in rval_binfo, not
        !          1223:                 here (binfo). */
        !          1224:            }
        !          1225:          else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h))
        !          1226:            {
        !          1227:              /* This is ok, the member found is here (binfo), not in
        !          1228:                 rval_binfo. */
        !          1229:              if (nval)
        !          1230:                {
        !          1231:                  rval = nval;
        !          1232:                  if (entry || protect)
        !          1233:                    this_v = compute_access (basetype_path, rval);
        !          1234:                  /* These may look ambiguous, but they really are not.  */
        !          1235:                  if (vbase_name_p)
        !          1236:                    break;
        !          1237:                }
        !          1238:              else
        !          1239:                {
        !          1240:                  /* Undo finding it before, as something else hides it. */
        !          1241:                  rval = NULL_TREE;
        !          1242:                }
        !          1243:              rval_binfo = binfo;
        !          1244:              rval_binfo_h = binfo_h;
        !          1245:            }
        !          1246:          else
        !          1247:            {
        !          1248:              /* This is ambiguous. */
        !          1249:              errstr = "request for member `%D' is ambiguous";
        !          1250:              protect = 2;
        !          1251:              break;
        !          1252:            }
        !          1253:        }
        !          1254:     }
        !          1255:   {
        !          1256:     tree *tp = search_stack->first;
        !          1257:     tree *search_tail = tp + tail;
        !          1258: 
        !          1259:     if (entry)
        !          1260:       TREE_VALUE (entry) = rval;
        !          1261: 
        !          1262:     if (want_type && (rval == NULL_TREE || TREE_CODE (rval) != TYPE_DECL))
        !          1263:       {
        !          1264:        rval = NULL_TREE;
        !          1265:        errstr = 0;
        !          1266:       }
        !          1267: 
        !          1268:     /* If this FIELD_DECL defines its own access level, deal with that.  */
        !          1269:     if (rval && errstr == 0
        !          1270:        && ((protect&1) || entry)
        !          1271:        && DECL_LANG_SPECIFIC (rval)
        !          1272:        && DECL_ACCESS (rval))
        !          1273:       {
        !          1274:        while (tp < search_tail)
        !          1275:          {
        !          1276:            /* If is possible for one of the derived types on the path to
        !          1277:               have defined special access for this field.  Look for such
        !          1278:               declarations and report an error if a conflict is found.  */
        !          1279:            enum access_type new_v;
        !          1280: 
        !          1281:            if (this_v != access_default)
        !          1282:              new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval);
        !          1283:            if (this_v != access_default && new_v != this_v)
        !          1284:              {
        !          1285:                errstr = "conflicting access to member `%D'";
        !          1286:                this_v = access_default;
        !          1287:              }
        !          1288:            own_access = new_v;
        !          1289:            CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
        !          1290:            tp += 1;
        !          1291:          }
        !          1292:       }
        !          1293:     else
        !          1294:       {
        !          1295:        while (tp < search_tail)
        !          1296:          {
        !          1297:            CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
        !          1298:            tp += 1;
        !          1299:          }
        !          1300:       }
        !          1301:   }
        !          1302:   search_stack = pop_search_level (search_stack);
        !          1303: 
        !          1304:   if (errstr == 0)
        !          1305:     {
        !          1306:       if (own_access == access_private)
        !          1307:        errstr = "member `%D' declared private";
        !          1308:       else if (own_access == access_protected)
        !          1309:        errstr = "member `%D' declared protected";
        !          1310:       else if (this_v == access_private)
        !          1311:        errstr = TREE_PRIVATE (rval)
        !          1312:          ? "member `%D' is private"
        !          1313:            : "member `%D' is from private base class";
        !          1314:       else if (this_v == access_protected)
        !          1315:        errstr = TREE_PROTECTED (rval)
        !          1316:          ? "member `%D' is protected"
        !          1317:            : "member `%D' is from protected base class";
        !          1318:     }
        !          1319: 
        !          1320:   if (entry)
        !          1321:     {
        !          1322:       if (errstr)
        !          1323:        {
        !          1324:          tree error_string = my_build_string (errstr);
        !          1325:          /* Save error message with entry.  */
        !          1326:          TREE_TYPE (entry) = error_string;
        !          1327:        }
        !          1328:       else
        !          1329:        {
        !          1330:          /* Mark entry as having no error string.  */
        !          1331:          TREE_TYPE (entry) = NULL_TREE;
        !          1332:        }
        !          1333:     }
        !          1334: 
        !          1335:   if (errstr && protect)
        !          1336:     {
        !          1337:       cp_error (errstr, name, type);
        !          1338:       rval = error_mark_node;
        !          1339:     }
        !          1340:   return rval;
        !          1341: }
        !          1342: 
        !          1343: /* Try to find NAME inside a nested class.  */
        !          1344: tree
        !          1345: lookup_nested_field (name, complain)
        !          1346:      tree name;
        !          1347:      int complain;
        !          1348: {
        !          1349:   register tree t;
        !          1350: 
        !          1351:   tree id = NULL_TREE;
        !          1352:   if (TREE_CHAIN (current_class_type))
        !          1353:     {
        !          1354:       /* Climb our way up the nested ladder, seeing if we're trying to
        !          1355:         modify a field in an enclosing class.  If so, we should only
        !          1356:         be able to modify if it's static.  */
        !          1357:       for (t = TREE_CHAIN (current_class_type);
        !          1358:           t && DECL_CONTEXT (t);
        !          1359:           t = TREE_CHAIN (DECL_CONTEXT (t)))
        !          1360:        {
        !          1361:          if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE)
        !          1362:            break;
        !          1363: 
        !          1364:          /* N.B.: lookup_field will do the access checking for us */
        !          1365:          id = lookup_field (DECL_CONTEXT (t), name, complain, 0);
        !          1366:          if (id == error_mark_node)
        !          1367:            {
        !          1368:              id = NULL_TREE;
        !          1369:              continue;
        !          1370:            }
        !          1371: 
        !          1372:          if (id != NULL_TREE)
        !          1373:            {
        !          1374:              if (TREE_CODE (id) == FIELD_DECL
        !          1375:                  && ! TREE_STATIC (id)
        !          1376:                  && TREE_TYPE (id) != error_mark_node)
        !          1377:                {
        !          1378:                  if (complain)
        !          1379:                    {
        !          1380:                      /* At parse time, we don't want to give this error, since
        !          1381:                         we won't have enough state to make this kind of
        !          1382:                         decision properly.  But there are times (e.g., with
        !          1383:                         enums in nested classes) when we do need to call
        !          1384:                         this fn at parse time.  So, in those cases, we pass
        !          1385:                         complain as a 0 and just return a NULL_TREE.  */
        !          1386:                      error ("assignment to non-static member `%s' of enclosing class `%s'",
        !          1387:                             lang_printable_name (id),
        !          1388:                             IDENTIFIER_POINTER (TYPE_IDENTIFIER
        !          1389:                                                 (DECL_CONTEXT (t))));
        !          1390:                      /* Mark this for do_identifier().  It would otherwise
        !          1391:                         claim that the variable was undeclared.  */
        !          1392:                      TREE_TYPE (id) = error_mark_node;
        !          1393:                    }
        !          1394:                  else
        !          1395:                    {
        !          1396:                      id = NULL_TREE;
        !          1397:                      continue;
        !          1398:                    }
        !          1399:                }
        !          1400:              break;
        !          1401:            }
        !          1402:        }
        !          1403:     }
        !          1404: 
        !          1405:   return id;
        !          1406: }
        !          1407: 
        !          1408: /* TYPE is a class type. Return the index of the fields within
        !          1409:    the method vector with name NAME, or -1 is no such field exists.  */
        !          1410: static int
        !          1411: lookup_fnfields_1 (type, name)
        !          1412:      tree type, name;
        !          1413: {
        !          1414:   register tree method_vec = CLASSTYPE_METHOD_VEC (type);
        !          1415: 
        !          1416:   if (method_vec != 0)
        !          1417:     {
        !          1418:       register tree *methods = &TREE_VEC_ELT (method_vec, 0);
        !          1419:       register tree *end = TREE_VEC_END (method_vec);
        !          1420: 
        !          1421: #ifdef GATHER_STATISTICS
        !          1422:       n_calls_lookup_fnfields_1++;
        !          1423: #endif
        !          1424:       if (*methods && name == constructor_name (type))
        !          1425:        return 0;
        !          1426: 
        !          1427:       while (++methods != end)
        !          1428:        {
        !          1429: #ifdef GATHER_STATISTICS
        !          1430:          n_outer_fields_searched++;
        !          1431: #endif
        !          1432:          if (DECL_NAME (*methods) == name)
        !          1433:            break;
        !          1434:        }
        !          1435:       if (methods != end)
        !          1436:        return methods - &TREE_VEC_ELT (method_vec, 0);
        !          1437:     }
        !          1438: 
        !          1439:   return -1;
        !          1440: }
        !          1441: 
        !          1442: /* Starting from BASETYPE, return a TREE_BASELINK-like object
        !          1443:    which gives the following information (in a list):
        !          1444: 
        !          1445:    TREE_TYPE: list of basetypes needed to get to...
        !          1446:    TREE_VALUE: list of all functions in of given type
        !          1447:    which have name NAME.
        !          1448: 
        !          1449:    No access information is computed by this function,
        !          1450:    other then to adorn the list of basetypes with
        !          1451:    TREE_VIA_PUBLIC.
        !          1452: 
        !          1453:    If there are two ways to find a name (two members), if COMPLAIN is
        !          1454:    non-zero, then error_mark_node is returned, and an error message is
        !          1455:    printed, otherwise, just an error_mark_node is returned.
        !          1456: 
        !          1457:    As a special case, is COMPLAIN is -1, we don't complain, and we
        !          1458:    don't return error_mark_node, but rather the complete list of
        !          1459:    virtuals.  This is used by get_virtuals_named_this.  */
        !          1460: tree
        !          1461: lookup_fnfields (basetype_path, name, complain)
        !          1462:      tree basetype_path, name;
        !          1463:      int complain;
        !          1464: {
        !          1465:   int head = 0, tail = 0;
        !          1466:   tree type, rval, rval_binfo = NULL_TREE, rvals = NULL_TREE, rval_binfo_h;
        !          1467:   tree entry, binfo, basetype_chain, binfo_h;
        !          1468:   int find_all = 0;
        !          1469: 
        !          1470:   /* rval_binfo is the binfo associated with the found member, note,
        !          1471:      this can be set with useful information, even when rval is not
        !          1472:      set, because it must deal with ALL members, not just function
        !          1473:      members.  It is used for ambiguity checking and the hidden
        !          1474:      checks.  Whereas rval is only set if a proper (not hidden)
        !          1475:      function member is found.  */
        !          1476: 
        !          1477:   /* rval_binfo_h and binfo_h are binfo values used when we perform the
        !          1478:      hiding checks, as virtual base classes may not be shared.  The strategy
        !          1479:      is we always go into the the binfo hierarchy owned by TYPE_BINFO of
        !          1480:      virtual base classes, as we cross virtual base class lines.  This way
        !          1481:      we know that binfo of a virtual base class will always == itself when
        !          1482:      found along any line.  (mrs)  */
        !          1483: 
        !          1484:   /* For now, don't try this.  */
        !          1485:   int protect = complain;
        !          1486: 
        !          1487:   char *errstr = 0;
        !          1488: 
        !          1489:   /* Set this to nonzero if we don't know how to compute
        !          1490:      accurate error messages for access control.  */
        !          1491:   int index = MEMOIZED_HASH_FN (name);
        !          1492: 
        !          1493:   if (complain == -1)
        !          1494:     {
        !          1495:       find_all = 1;
        !          1496:       protect = complain = 0;
        !          1497:     }
        !          1498: 
        !          1499:   /* If we are looking for a constructor in a templated type, use the
        !          1500:      unspecialized name, as that is how we store it.  */
        !          1501:   if (IDENTIFIER_TEMPLATE (name))
        !          1502:     name = constructor_name (name);
        !          1503: 
        !          1504:   binfo = basetype_path;
        !          1505:   binfo_h = binfo;
        !          1506:   type = BINFO_TYPE (basetype_path);
        !          1507: 
        !          1508:   /* The memoization code is in need of maintenance. */
        !          1509:   if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
        !          1510:     {
        !          1511:       tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
        !          1512: 
        !          1513:       while (tem && TREE_PURPOSE (tem) != name)
        !          1514:        {
        !          1515:          memoized_fields_searched[1]++;
        !          1516:          tem = TREE_CHAIN (tem);
        !          1517:        }
        !          1518:       if (tem)
        !          1519:        {
        !          1520:          if (protect && TREE_TYPE (tem))
        !          1521:            {
        !          1522:              error (TREE_STRING_POINTER (TREE_TYPE (tem)),
        !          1523:                     IDENTIFIER_POINTER (name),
        !          1524:                     TYPE_NAME_STRING (DECL_CLASS_CONTEXT (TREE_VALUE (TREE_VALUE (tem)))));
        !          1525:              return error_mark_node;
        !          1526:            }
        !          1527:          if (TREE_VALUE (tem) == NULL_TREE)
        !          1528:            {
        !          1529:              memoized_fast_rejects[1] += 1;
        !          1530:              return NULL_TREE;
        !          1531:            }
        !          1532:          else
        !          1533:            {
        !          1534:              /* Want to return this, but we must make sure
        !          1535:                 that access information is consistent.  */
        !          1536:              tree baselink = TREE_VALUE (tem);
        !          1537:              tree memoized_basetypes = TREE_PURPOSE (baselink);
        !          1538:              tree these_basetypes = basetype_path;
        !          1539:              while (memoized_basetypes && these_basetypes)
        !          1540:                {
        !          1541:                  memoized_fields_searched[1]++;
        !          1542:                  if (TREE_VALUE (memoized_basetypes) != these_basetypes)
        !          1543:                    break;
        !          1544:                  memoized_basetypes = TREE_CHAIN (memoized_basetypes);
        !          1545:                  these_basetypes = BINFO_INHERITANCE_CHAIN (these_basetypes);
        !          1546:                }
        !          1547:              /* The following statement is true only when both are NULL.  */
        !          1548:              if (memoized_basetypes == these_basetypes)
        !          1549:                {
        !          1550:                  memoized_fast_finds[1] += 1;
        !          1551:                  return TREE_VALUE (tem);
        !          1552:                }
        !          1553:              /* else, we must re-find this field by hand.  */
        !          1554:              baselink = tree_cons (basetype_path, TREE_VALUE (baselink), TREE_CHAIN (baselink));
        !          1555:              return baselink;
        !          1556:            }
        !          1557:        }
        !          1558:     }
        !          1559: 
        !          1560: #ifdef GATHER_STATISTICS
        !          1561:   n_calls_lookup_fnfields++;
        !          1562: #endif
        !          1563:   if (protect && flag_memoize_lookups && ! global_bindings_p ())
        !          1564:     entry = make_memoized_table_entry (type, name, 1);
        !          1565:   else
        !          1566:     entry = 0;
        !          1567: 
        !          1568:   index = lookup_fnfields_here (type, name);
        !          1569:   if (index >= 0 || lookup_field_1 (type, name))
        !          1570:     {
        !          1571:       rval_binfo = basetype_path;
        !          1572:       rval_binfo_h = rval_binfo;
        !          1573:     }
        !          1574: 
        !          1575:   if (index >= 0)
        !          1576:     {
        !          1577:       rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
        !          1578:       rvals = my_tree_cons (basetype_path, rval, rvals);
        !          1579:       if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type))
        !          1580:        TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
        !          1581: 
        !          1582:       if (entry)
        !          1583:        {
        !          1584:          TREE_VALUE (entry) = rvals;
        !          1585:          TREE_TYPE (entry) = NULL_TREE;
        !          1586:        }
        !          1587: 
        !          1588:       return rvals;
        !          1589:     }
        !          1590:   rval = NULL_TREE;
        !          1591: 
        !          1592:   if (basetype_path == TYPE_BINFO (type))
        !          1593:     {
        !          1594:       basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
        !          1595:       TREE_VIA_PUBLIC (basetype_chain) = 1;
        !          1596:       BINFO_VIA_PUBLIC (basetype_path) = 1;
        !          1597:       BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
        !          1598:     }
        !          1599:   else
        !          1600:     {
        !          1601:       basetype_chain = build_tree_list (NULL_TREE, basetype_path);
        !          1602:       TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
        !          1603:       TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
        !          1604:       TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
        !          1605:     }
        !          1606: 
        !          1607:   /* The ambiguity check relies upon breadth first searching. */
        !          1608: 
        !          1609:   search_stack = push_search_level (search_stack, &search_obstack);
        !          1610:   binfo = basetype_path;
        !          1611:   binfo_h = binfo;
        !          1612: 
        !          1613:   while (1)
        !          1614:     {
        !          1615:       tree binfos = BINFO_BASETYPES (binfo);
        !          1616:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          1617:       int index;
        !          1618: 
        !          1619:       /* Process and/or queue base types.  */
        !          1620:       for (i = 0; i < n_baselinks; i++)
        !          1621:        {
        !          1622:          tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          1623:          if (BINFO_FIELDS_MARKED (base_binfo) == 0)
        !          1624:            {
        !          1625:              tree btypes;
        !          1626: 
        !          1627:              SET_BINFO_FIELDS_MARKED (base_binfo);
        !          1628:              btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
        !          1629:              TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
        !          1630:              TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
        !          1631:              TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
        !          1632:              if (TREE_VIA_VIRTUAL (base_binfo))
        !          1633:                btypes = tree_cons (NULL_TREE,
        !          1634:                                    TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
        !          1635:                                    btypes);
        !          1636:              else
        !          1637:                btypes = tree_cons (NULL_TREE,
        !          1638:                                    TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
        !          1639:                                    btypes);
        !          1640:              obstack_ptr_grow (&search_obstack, btypes);
        !          1641:              tail += 1;
        !          1642:              if (tail >= search_stack->limit)
        !          1643:                my_friendly_abort (99);
        !          1644:            }
        !          1645:        }
        !          1646: 
        !          1647:       /* Process head of queue, if one exists.  */
        !          1648:       if (head >= tail)
        !          1649:        break;
        !          1650: 
        !          1651:       basetype_chain = search_stack->first[head++];
        !          1652:       binfo_h = TREE_VALUE (basetype_chain);
        !          1653:       basetype_chain = TREE_CHAIN (basetype_chain);
        !          1654:       basetype_path = TREE_VALUE (basetype_chain);
        !          1655:       if (TREE_CHAIN (basetype_chain))
        !          1656:        BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
        !          1657:       else
        !          1658:        BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
        !          1659: 
        !          1660:       binfo = basetype_path;
        !          1661:       type = BINFO_TYPE (binfo);
        !          1662: 
        !          1663:       /* See if we can find NAME in TYPE.  If RVAL is nonzero,
        !          1664:         and we do find NAME in TYPE, verify that such a second
        !          1665:         sighting is in fact legal.  */
        !          1666: 
        !          1667:       index = lookup_fnfields_here (type, name);
        !          1668: 
        !          1669:       if (index >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
        !          1670:        {
        !          1671:          if (rval_binfo && !find_all && hides (rval_binfo_h, binfo_h))
        !          1672:            {
        !          1673:              /* This is ok, the member found is in rval_binfo, not
        !          1674:                 here (binfo). */
        !          1675:            }
        !          1676:          else if (rval_binfo==NULL_TREE || find_all || hides (binfo_h, rval_binfo_h))
        !          1677:            {
        !          1678:              /* This is ok, the member found is here (binfo), not in
        !          1679:                 rval_binfo. */
        !          1680:              if (index >= 0)
        !          1681:                {
        !          1682:                  rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
        !          1683:                  /* Note, rvals can only be previously set if find_all is
        !          1684:                     true.  */
        !          1685:                  rvals = my_tree_cons (basetype_path, rval, rvals);
        !          1686:                  if (TYPE_BINFO_BASETYPES (type)
        !          1687:                      && CLASSTYPE_BASELINK_VEC (type))
        !          1688:                    TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
        !          1689:                }
        !          1690:              else
        !          1691:                {
        !          1692:                  /* Undo finding it before, as something else hides it. */
        !          1693:                  rval = NULL_TREE;
        !          1694:                  rvals = NULL_TREE;
        !          1695:                }
        !          1696:              rval_binfo = binfo;
        !          1697:              rval_binfo_h = binfo_h;
        !          1698:            }
        !          1699:          else
        !          1700:            {
        !          1701:              /* This is ambiguous. */
        !          1702:              errstr = "request for method `%D' is ambiguous";
        !          1703:              rvals = error_mark_node;
        !          1704:              break;
        !          1705:            }
        !          1706:        }
        !          1707:     }
        !          1708:   {
        !          1709:     tree *tp = search_stack->first;
        !          1710:     tree *search_tail = tp + tail;
        !          1711: 
        !          1712:     while (tp < search_tail)
        !          1713:       {
        !          1714:        CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
        !          1715:        tp += 1;
        !          1716:       }
        !          1717:   }
        !          1718:   search_stack = pop_search_level (search_stack);
        !          1719: 
        !          1720:   if (entry)
        !          1721:     {
        !          1722:       if (errstr)
        !          1723:        {
        !          1724:          tree error_string = my_build_string (errstr);
        !          1725:          /* Save error message with entry.  */
        !          1726:          TREE_TYPE (entry) = error_string;
        !          1727:        }
        !          1728:       else
        !          1729:        {
        !          1730:          /* Mark entry as having no error string.  */
        !          1731:          TREE_TYPE (entry) = NULL_TREE;
        !          1732:          TREE_VALUE (entry) = rvals;
        !          1733:        }
        !          1734:     }
        !          1735: 
        !          1736:   if (errstr && protect)
        !          1737:     {
        !          1738:       cp_error (errstr, name);
        !          1739:       rvals = error_mark_node;
        !          1740:     }
        !          1741: 
        !          1742:   return rvals;
        !          1743: }
        !          1744: 
        !          1745: /* BREADTH-FIRST SEARCH ROUTINES.  */
        !          1746: 
        !          1747: /* Search a multiple inheritance hierarchy by breadth-first search.
        !          1748: 
        !          1749:    TYPE is an aggregate type, possibly in a multiple-inheritance hierarchy.
        !          1750:    TESTFN is a function, which, if true, means that our condition has been met,
        !          1751:    and its return value should be returned.
        !          1752:    QFN, if non-NULL, is a predicate dictating whether the type should
        !          1753:    even be queued.  */
        !          1754: 
        !          1755: HOST_WIDE_INT
        !          1756: breadth_first_search (binfo, testfn, qfn)
        !          1757:      tree binfo;
        !          1758:      int (*testfn)();
        !          1759:      int (*qfn)();
        !          1760: {
        !          1761:   int head = 0, tail = 0;
        !          1762:   int rval = 0;
        !          1763: 
        !          1764:   search_stack = push_search_level (search_stack, &search_obstack);
        !          1765: 
        !          1766:   while (1)
        !          1767:     {
        !          1768:       tree binfos = BINFO_BASETYPES (binfo);
        !          1769:       int n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          1770:       int i;
        !          1771: 
        !          1772:       /* Process and/or queue base types.  */
        !          1773:       for (i = 0; i < n_baselinks; i++)
        !          1774:        {
        !          1775:          tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          1776: 
        !          1777:          if (BINFO_MARKED (base_binfo) == 0
        !          1778:              && (qfn == 0 || (*qfn) (binfo, i)))
        !          1779:            {
        !          1780:              SET_BINFO_MARKED (base_binfo);
        !          1781:              obstack_ptr_grow (&search_obstack, binfo);
        !          1782:              obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) i);
        !          1783:              tail += 2;
        !          1784:              if (tail >= search_stack->limit)
        !          1785:                my_friendly_abort (100);
        !          1786:            }
        !          1787:        }
        !          1788:       /* Process head of queue, if one exists.  */
        !          1789:       if (head >= tail)
        !          1790:        {
        !          1791:          rval = 0;
        !          1792:          break;
        !          1793:        }
        !          1794: 
        !          1795:       binfo = search_stack->first[head++];
        !          1796:       i = (HOST_WIDE_INT) search_stack->first[head++];
        !          1797:       if (rval = (*testfn) (binfo, i))
        !          1798:        break;
        !          1799:       binfo = BINFO_BASETYPE (binfo, i);
        !          1800:     }
        !          1801:   {
        !          1802:     tree *tp = search_stack->first;
        !          1803:     tree *search_tail = tp + tail;
        !          1804:     while (tp < search_tail)
        !          1805:       {
        !          1806:        tree binfo = *tp++;
        !          1807:        int i = (HOST_WIDE_INT)(*tp++);
        !          1808:        CLEAR_BINFO_MARKED (BINFO_BASETYPE (binfo, i));
        !          1809:       }
        !          1810:   }
        !          1811: 
        !          1812:   search_stack = pop_search_level (search_stack);
        !          1813:   return rval;
        !          1814: }
        !          1815: 
        !          1816: /* Functions to use in breadth first searches.  */
        !          1817: typedef tree (*pft)();
        !          1818: typedef int (*pfi)();
        !          1819: 
        !          1820: int tree_needs_constructor_p (binfo, i)
        !          1821:      tree binfo;
        !          1822:      int i;
        !          1823: {
        !          1824:   tree basetype;
        !          1825:   my_friendly_assert (i != 0, 296);
        !          1826:   basetype = BINFO_TYPE (BINFO_BASETYPE (binfo, i));
        !          1827:   return TYPE_NEEDS_CONSTRUCTING (basetype);
        !          1828: }
        !          1829: 
        !          1830: static tree declarator;
        !          1831: 
        !          1832: static tree
        !          1833: get_virtuals_named_this (binfo)
        !          1834:      tree binfo;
        !          1835: {
        !          1836:   tree fields;
        !          1837: 
        !          1838:   fields = lookup_fnfields (binfo, declarator, -1);
        !          1839:   /* fields cannot be error_mark_node */
        !          1840: 
        !          1841:   if (fields == 0)
        !          1842:     return 0;
        !          1843: 
        !          1844:   /* Get to the function decls, and return the first virtual function
        !          1845:      with this name, if there is one.  */
        !          1846:   while (fields)
        !          1847:     {
        !          1848:       tree fndecl;
        !          1849: 
        !          1850:       for (fndecl = TREE_VALUE (fields); fndecl; fndecl = DECL_CHAIN (fndecl))
        !          1851:        if (DECL_VINDEX (fndecl))
        !          1852:          return fields;
        !          1853:       fields = next_baselink (fields);
        !          1854:     }
        !          1855:   return NULL_TREE;
        !          1856: }
        !          1857: 
        !          1858: static tree get_virtual_destructor (binfo, i)
        !          1859:      tree binfo;
        !          1860:      int i;
        !          1861: {
        !          1862:   tree type = BINFO_TYPE (binfo);
        !          1863:   if (i >= 0)
        !          1864:     type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
        !          1865:   if (TYPE_HAS_DESTRUCTOR (type)
        !          1866:       && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0)))
        !          1867:     return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
        !          1868:   return 0;
        !          1869: }
        !          1870: 
        !          1871: int tree_has_any_destructor_p (binfo, i)
        !          1872:      tree binfo;
        !          1873:      int i;
        !          1874: {
        !          1875:   tree type = BINFO_TYPE (binfo);
        !          1876:   if (i >= 0)
        !          1877:     type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
        !          1878:   return TYPE_NEEDS_DESTRUCTOR (type);
        !          1879: }
        !          1880: 
        !          1881: /* Given a class type TYPE, and a function decl FNDECL, look for a
        !          1882:    virtual function in TYPE's hierarchy which FNDECL could match as a
        !          1883:    virtual function.  It doesn't matter which one we find.
        !          1884: 
        !          1885:    DTORP is nonzero if we are looking for a destructor.  Destructors
        !          1886:    need special treatment because they do not match by name.  */
        !          1887: tree
        !          1888: get_matching_virtual (binfo, fndecl, dtorp)
        !          1889:      tree binfo, fndecl;
        !          1890:      int dtorp;
        !          1891: {
        !          1892:   tree tmp = NULL_TREE;
        !          1893: 
        !          1894:   /* Breadth first search routines start searching basetypes
        !          1895:      of TYPE, so we must perform first ply of search here.  */
        !          1896:   if (dtorp)
        !          1897:     {
        !          1898:       if (tree_has_any_destructor_p (binfo, -1))
        !          1899:        tmp = get_virtual_destructor (binfo, -1);
        !          1900: 
        !          1901:       if (tmp)
        !          1902:        return tmp;
        !          1903: 
        !          1904:       tmp = (tree) breadth_first_search (binfo,
        !          1905:                                         (pfi) get_virtual_destructor,
        !          1906:                                         tree_has_any_destructor_p);
        !          1907:       return tmp;
        !          1908:     }
        !          1909:   else
        !          1910:     {
        !          1911:       tree drettype, dtypes, btypes, instptr_type;
        !          1912:       tree basetype = DECL_CLASS_CONTEXT (fndecl);
        !          1913:       tree baselink, best = NULL_TREE;
        !          1914:       tree name = DECL_ASSEMBLER_NAME (fndecl);
        !          1915: 
        !          1916:       declarator = DECL_NAME (fndecl);
        !          1917:       if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
        !          1918:        return NULL_TREE;
        !          1919: 
        !          1920:       baselink = get_virtuals_named_this (binfo);
        !          1921:       if (baselink == NULL_TREE)
        !          1922:        return NULL_TREE;
        !          1923: 
        !          1924:       drettype = TREE_TYPE (TREE_TYPE (fndecl));
        !          1925:       dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
        !          1926:       if (DECL_STATIC_FUNCTION_P (fndecl))
        !          1927:        instptr_type = NULL_TREE;
        !          1928:       else
        !          1929:        instptr_type = TREE_TYPE (TREE_VALUE (dtypes));
        !          1930: 
        !          1931:       for (; baselink; baselink = next_baselink (baselink))
        !          1932:        {
        !          1933:          for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp))
        !          1934:            {
        !          1935:              if (! DECL_VINDEX (tmp))
        !          1936:                continue;
        !          1937: 
        !          1938:              btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp));
        !          1939:              if (instptr_type == NULL_TREE)
        !          1940:                {
        !          1941:                  if (compparms (TREE_CHAIN (btypes), dtypes, 3))
        !          1942:                    /* Caller knows to give error in this case.  */
        !          1943:                    return tmp;
        !          1944:                  return NULL_TREE;
        !          1945:                }
        !          1946: 
        !          1947:              if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes)))
        !          1948:                   == TYPE_READONLY (instptr_type))
        !          1949:                  && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
        !          1950:                {
        !          1951:                  if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
        !          1952:                      && ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
        !          1953:                    {
        !          1954:                      cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
        !          1955:                      cp_error_at ("overriding definition as `%#D'", tmp);
        !          1956:                      SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
        !          1957:                    }
        !          1958:                  break;
        !          1959:                }
        !          1960:            }
        !          1961:          if (tmp)
        !          1962:            {
        !          1963:              best = tmp;
        !          1964:              break;
        !          1965:            }
        !          1966:        }
        !          1967:       if (best == NULL_TREE && warn_overloaded_virtual)
        !          1968:        cp_warning_at ("conflicting specification deriving virtual function `%D'", fndecl);
        !          1969: 
        !          1970:       return best;
        !          1971:     }
        !          1972: }
        !          1973: 
        !          1974: /* Return the list of virtual functions which are abstract in type
        !          1975:    TYPE that come from non virtual base classes.  See
        !          1976:    expand_direct_vtbls_init for the style of search we do.  */
        !          1977: static tree
        !          1978: get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
        !          1979:      tree binfo, abstract_virtuals;
        !          1980:      int do_self;
        !          1981: {
        !          1982:   tree binfos = BINFO_BASETYPES (binfo);
        !          1983:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          1984: 
        !          1985:   for (i = 0; i < n_baselinks; i++)
        !          1986:     {
        !          1987:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          1988:       int is_not_base_vtable =
        !          1989:        i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
        !          1990:       if (! TREE_VIA_VIRTUAL (base_binfo))
        !          1991:        abstract_virtuals
        !          1992:          = get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
        !          1993:                                     abstract_virtuals);
        !          1994:     }
        !          1995:   /* Should we use something besides CLASSTYPE_VFIELDS? */
        !          1996:   if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
        !          1997:     {
        !          1998:       tree tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
        !          1999: 
        !          2000:       /* Get around dossier entry if there is one.  */
        !          2001:       if (flag_dossier)
        !          2002:        tmp = TREE_CHAIN (tmp);
        !          2003: 
        !          2004:       while (tmp)
        !          2005:        {
        !          2006:          tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
        !          2007:          tree base_fndecl = TREE_OPERAND (base_pfn, 0);
        !          2008:          if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
        !          2009:            abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
        !          2010:          tmp = TREE_CHAIN (tmp);
        !          2011:        }
        !          2012:     }
        !          2013:   return abstract_virtuals;
        !          2014: }
        !          2015: 
        !          2016: /* Return the list of virtual functions which are abstract in type TYPE.
        !          2017:    This information is cached, and so must be built on a
        !          2018:    non-temporary obstack.  */
        !          2019: tree
        !          2020: get_abstract_virtuals (type)
        !          2021:      tree type;
        !          2022: {
        !          2023:   tree vbases, tmp;
        !          2024:   tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
        !          2025: 
        !          2026:   /* First get all from non-virtual bases. */
        !          2027:   abstract_virtuals
        !          2028:     = get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
        !          2029:                                               
        !          2030:   for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
        !          2031:     {
        !          2032:       if (! BINFO_VIRTUALS (vbases))
        !          2033:        continue;
        !          2034: 
        !          2035:       tmp = TREE_CHAIN (BINFO_VIRTUALS (vbases));
        !          2036:       while (tmp)
        !          2037:        {
        !          2038:          tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
        !          2039:          tree base_fndecl = TREE_OPERAND (base_pfn, 0);
        !          2040:          if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
        !          2041:            abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
        !          2042:          tmp = TREE_CHAIN (tmp);
        !          2043:        }
        !          2044:     }
        !          2045:   return nreverse (abstract_virtuals);
        !          2046: }
        !          2047: 
        !          2048: /* For the type TYPE, return a list of member functions available from
        !          2049:    base classes with name NAME.  The TREE_VALUE of the list is a chain of
        !          2050:    member functions with name NAME.  The TREE_PURPOSE of the list is a
        !          2051:    basetype, or a list of base types (in reverse order) which were
        !          2052:    traversed to reach the chain of member functions.  If we reach a base
        !          2053:    type which provides a member function of name NAME, and which has at
        !          2054:    most one base type itself, then we can terminate the search.  */
        !          2055: 
        !          2056: tree
        !          2057: get_baselinks (type_as_binfo_list, type, name)
        !          2058:      tree type_as_binfo_list;
        !          2059:      tree type, name;
        !          2060: {
        !          2061:   int head = 0, tail = 0, index;
        !          2062:   tree rval = 0, nval = 0;
        !          2063:   tree basetypes = type_as_binfo_list;
        !          2064:   tree binfo = TYPE_BINFO (type);
        !          2065: 
        !          2066:   search_stack = push_search_level (search_stack, &search_obstack);
        !          2067: 
        !          2068:   while (1)
        !          2069:     {
        !          2070:       tree binfos = BINFO_BASETYPES (binfo);
        !          2071:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          2072: 
        !          2073:       /* Process and/or queue base types.  */
        !          2074:       for (i = 0; i < n_baselinks; i++)
        !          2075:        {
        !          2076:          tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          2077:          tree btypes;
        !          2078: 
        !          2079:          btypes = hash_tree_cons (TREE_VIA_PUBLIC (base_binfo),
        !          2080:                                   TREE_VIA_VIRTUAL (base_binfo),
        !          2081:                                   TREE_VIA_PROTECTED (base_binfo),
        !          2082:                                   NULL_TREE, base_binfo,
        !          2083:                                   basetypes);
        !          2084:          obstack_ptr_grow (&search_obstack, btypes);
        !          2085:          search_stack->first = (tree *)obstack_base (&search_obstack);
        !          2086:          tail += 1;
        !          2087:        }
        !          2088: 
        !          2089:     dont_queue:
        !          2090:       /* Process head of queue, if one exists.  */
        !          2091:       if (head >= tail)
        !          2092:        break;
        !          2093: 
        !          2094:       basetypes = search_stack->first[head++];
        !          2095:       binfo = TREE_VALUE (basetypes);
        !          2096:       type = BINFO_TYPE (binfo);
        !          2097:       index = lookup_fnfields_1 (type, name);
        !          2098:       if (index >= 0)
        !          2099:        {
        !          2100:          nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
        !          2101:          rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval);
        !          2102:          if (TYPE_BINFO_BASETYPES (type) == 0)
        !          2103:            goto dont_queue;
        !          2104:          else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1)
        !          2105:            {
        !          2106:              if (CLASSTYPE_BASELINK_VEC (type))
        !          2107:                TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
        !          2108:              goto dont_queue;
        !          2109:            }
        !          2110:        }
        !          2111:       nval = NULL_TREE;
        !          2112:     }
        !          2113: 
        !          2114:   search_stack = pop_search_level (search_stack);
        !          2115:   return rval;
        !          2116: }
        !          2117: 
        !          2118: tree
        !          2119: next_baselink (baselink)
        !          2120:      tree baselink;
        !          2121: {
        !          2122:   tree tmp = TREE_TYPE (baselink);
        !          2123:   baselink = TREE_CHAIN (baselink);
        !          2124:   while (tmp)
        !          2125:     {
        !          2126:       /* @@ does not yet add previous base types.  */
        !          2127:       baselink = tree_cons (TREE_PURPOSE (tmp), TREE_VALUE (tmp),
        !          2128:                            baselink);
        !          2129:       TREE_TYPE (baselink) = TREE_TYPE (tmp);
        !          2130:       tmp = TREE_CHAIN (tmp);
        !          2131:     }
        !          2132:   return baselink;
        !          2133: }
        !          2134: 
        !          2135: /* DEPTH-FIRST SEARCH ROUTINES.  */
        !          2136: 
        !          2137: /* Assign unique numbers to _CLASSTYPE members of the lattice
        !          2138:    specified by TYPE.  The root nodes are marked first; the nodes
        !          2139:    are marked depth-fisrt, left-right.  */
        !          2140: 
        !          2141: static int cid;
        !          2142: 
        !          2143: /* Matrix implementing a relation from CLASSTYPE X CLASSTYPE => INT.
        !          2144:    Relation yields 1 if C1 <= C2, 0 otherwise.  */
        !          2145: typedef char mi_boolean;
        !          2146: static mi_boolean *mi_matrix;
        !          2147: 
        !          2148: /* Type for which this matrix is defined.  */
        !          2149: static tree mi_type;
        !          2150: 
        !          2151: /* Size of the matrix for indexing purposes.  */
        !          2152: static int mi_size;
        !          2153: 
        !          2154: /* Return nonzero if class C2 derives from class C1.  */
        !          2155: #define BINFO_DERIVES_FROM(C1, C2)     \
        !          2156:   ((mi_matrix+mi_size*(BINFO_CID (C1)-1))[BINFO_CID (C2)-1])
        !          2157: #define TYPE_DERIVES_FROM(C1, C2)      \
        !          2158:   ((mi_matrix+mi_size*(CLASSTYPE_CID (C1)-1))[CLASSTYPE_CID (C2)-1])
        !          2159: #define BINFO_DERIVES_FROM_STAR(C)     \
        !          2160:   (mi_matrix+(BINFO_CID (C)-1))
        !          2161: 
        !          2162: /* This routine converts a pointer to be a pointer of an immediate
        !          2163:    base class.  The normal convert_pointer_to routine would diagnose
        !          2164:    the conversion as ambiguous, under MI code that has the base class
        !          2165:    as an ambiguous base class. */
        !          2166: static tree
        !          2167: convert_pointer_to_single_level (to_type, expr)
        !          2168:      tree to_type, expr;
        !          2169: {
        !          2170:   tree binfo_of_derived;
        !          2171:   tree last;
        !          2172: 
        !          2173:   binfo_of_derived = TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr)));
        !          2174:   last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0);
        !          2175:   BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived;
        !          2176:   BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE;
        !          2177:   return build_vbase_path (PLUS_EXPR, TYPE_POINTER_TO (to_type), expr, last, 1);
        !          2178: }
        !          2179: 
        !          2180: /* The main function which implements depth first search.
        !          2181: 
        !          2182:    This routine has to remember the path it walked up, when
        !          2183:    dfs_init_vbase_pointers is the work function, as otherwise there
        !          2184:    would be no record. */
        !          2185: static void
        !          2186: dfs_walk (binfo, fn, qfn)
        !          2187:      tree binfo;
        !          2188:      void (*fn)();
        !          2189:      int (*qfn)();
        !          2190: {
        !          2191:   tree binfos = BINFO_BASETYPES (binfo);
        !          2192:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          2193: 
        !          2194:   for (i = 0; i < n_baselinks; i++)
        !          2195:     {
        !          2196:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          2197: 
        !          2198:       if ((*qfn)(base_binfo))
        !          2199:        {
        !          2200:          if (fn == dfs_init_vbase_pointers)
        !          2201:            {
        !          2202:              /* When traversing an arbitrary MI hierarchy, we need to keep
        !          2203:                 a record of the path we took to get down to the final base
        !          2204:                 type, as otherwise there would be no record of it, and just
        !          2205:                 trying to blindly convert at the bottom would be ambiguous.
        !          2206: 
        !          2207:                 The easiest way is to do the conversions one step at a time,
        !          2208:                 as we know we want the immediate base class at each step.
        !          2209: 
        !          2210:                 The only special trick to converting one step at a time,
        !          2211:                 is that when we hit the last virtual base class, we must
        !          2212:                 use the SLOT value for it, and not use the normal convert
        !          2213:                 routine.  We use the last virtual base class, as in our
        !          2214:                 implementation, we have pointers to all virtual base
        !          2215:                 classes in the base object.  */
        !          2216: 
        !          2217:              tree saved_vbase_decl_ptr_intermediate
        !          2218:                = vbase_decl_ptr_intermediate;
        !          2219: 
        !          2220:              if (TREE_VIA_VIRTUAL (base_binfo))
        !          2221:                {
        !          2222:                  /* No need for the conversion here, as we know it is the
        !          2223:                     right type.  */
        !          2224:                  vbase_decl_ptr_intermediate
        !          2225:                    = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
        !          2226:                }
        !          2227:              else
        !          2228:                {
        !          2229:                  vbase_decl_ptr_intermediate
        !          2230:                    = convert_pointer_to_single_level (BINFO_TYPE (base_binfo),
        !          2231:                                                       vbase_decl_ptr_intermediate);
        !          2232:                }
        !          2233: 
        !          2234:              dfs_walk (base_binfo, fn, qfn);
        !          2235: 
        !          2236:              vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
        !          2237:            } else
        !          2238:              dfs_walk (base_binfo, fn, qfn);
        !          2239:        }
        !          2240:     }
        !          2241: 
        !          2242:   fn (binfo);
        !          2243: }
        !          2244: 
        !          2245: /* Predicate functions which serve for dfs_walk.  */
        !          2246: static int numberedp (binfo) tree binfo;
        !          2247: { return BINFO_CID (binfo); }
        !          2248: static int unnumberedp (binfo) tree binfo;
        !          2249: { return BINFO_CID (binfo) == 0; }
        !          2250: 
        !          2251: static int markedp (binfo) tree binfo;
        !          2252: { return BINFO_MARKED (binfo); }
        !          2253: static int bfs_markedp (binfo, i) tree binfo; int i;
        !          2254: { return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
        !          2255: static int unmarkedp (binfo) tree binfo;
        !          2256: { return BINFO_MARKED (binfo) == 0; }
        !          2257: static int bfs_unmarkedp (binfo, i) tree binfo; int i;
        !          2258: { return BINFO_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
        !          2259: static int marked_vtable_pathp (binfo) tree binfo;
        !          2260: { return BINFO_VTABLE_PATH_MARKED (binfo); }
        !          2261: static int bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
        !          2262: { return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
        !          2263: static int unmarked_vtable_pathp (binfo) tree binfo;
        !          2264: { return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
        !          2265: static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
        !          2266: { return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
        !          2267: static int marked_new_vtablep (binfo) tree binfo;
        !          2268: { return BINFO_NEW_VTABLE_MARKED (binfo); }
        !          2269: static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
        !          2270: { return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
        !          2271: static int unmarked_new_vtablep (binfo) tree binfo;
        !          2272: { return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
        !          2273: static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
        !          2274: { return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
        !          2275: 
        !          2276: static int dfs_search_slot_nonempty_p (binfo) tree binfo;
        !          2277: { return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
        !          2278: 
        !          2279: static int dfs_debug_unmarkedp (binfo) tree binfo;
        !          2280: { return CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) == 0; }
        !          2281: 
        !          2282: /* The worker functions for `dfs_walk'.  These do not need to
        !          2283:    test anything (vis a vis marking) if they are paired with
        !          2284:    a predicate function (above).  */
        !          2285: 
        !          2286: /* Assign each type within the lattice a number which is unique
        !          2287:    in the lattice.  The first number assigned is 1.  */
        !          2288: 
        !          2289: static void
        !          2290: dfs_number (binfo)
        !          2291:      tree binfo;
        !          2292: {
        !          2293:   BINFO_CID (binfo) = ++cid;
        !          2294: }
        !          2295: 
        !          2296: static void
        !          2297: dfs_unnumber (binfo)
        !          2298:      tree binfo;
        !          2299: {
        !          2300:   BINFO_CID (binfo) = 0;
        !          2301: }
        !          2302: 
        !          2303: static void
        !          2304: dfs_mark (binfo) tree binfo;
        !          2305: { SET_BINFO_MARKED (binfo); }
        !          2306: 
        !          2307: static void
        !          2308: dfs_unmark (binfo) tree binfo;
        !          2309: { CLEAR_BINFO_MARKED (binfo); }
        !          2310: 
        !          2311: static void
        !          2312: dfs_mark_vtable_path (binfo) tree binfo;
        !          2313: { SET_BINFO_VTABLE_PATH_MARKED (binfo); }
        !          2314: 
        !          2315: static void
        !          2316: dfs_unmark_vtable_path (binfo) tree binfo;
        !          2317: { CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); }
        !          2318: 
        !          2319: static void
        !          2320: dfs_mark_new_vtable (binfo) tree binfo;
        !          2321: { SET_BINFO_NEW_VTABLE_MARKED (binfo); }
        !          2322: 
        !          2323: static void
        !          2324: dfs_unmark_new_vtable (binfo) tree binfo;
        !          2325: { CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); }
        !          2326: 
        !          2327: static void
        !          2328: dfs_clear_search_slot (binfo) tree binfo;
        !          2329: { CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
        !          2330: 
        !          2331: static void
        !          2332: dfs_debug_mark (binfo)
        !          2333:      tree binfo;
        !          2334: {
        !          2335:   tree t = BINFO_TYPE (binfo);
        !          2336: 
        !          2337:   /* Use heuristic that if there are virtual functions,
        !          2338:      ignore until we see a non-inline virtual function.  */
        !          2339:   tree methods = CLASSTYPE_METHOD_VEC (t);
        !          2340: 
        !          2341:   CLASSTYPE_DEBUG_REQUESTED (t) = 1;
        !          2342: 
        !          2343:   /* If interface info is known, the value of (?@@?) is correct.  */
        !          2344:   if (methods == 0
        !          2345:       || CLASSTYPE_INTERFACE_KNOWN (t)
        !          2346:       || (write_virtuals == 2 && TYPE_VIRTUAL_P (t)))
        !          2347:     return;
        !          2348: 
        !          2349:   /* If debug info is requested from this context for this type, supply it.
        !          2350:      If debug info is requested from another context for this type,
        !          2351:      see if some third context can supply it.  */
        !          2352:   if (current_function_decl == NULL_TREE
        !          2353:       || DECL_CLASS_CONTEXT (current_function_decl) != t)
        !          2354:     {
        !          2355:       if (TREE_VEC_ELT (methods, 0))
        !          2356:        methods = TREE_VEC_ELT (methods, 0);
        !          2357:       else
        !          2358:        methods = TREE_VEC_ELT (methods, 1);
        !          2359:       while (methods)
        !          2360:        {
        !          2361:          if (DECL_VINDEX (methods)
        !          2362:              && DECL_SAVED_INSNS (methods) == 0
        !          2363:              && DECL_PENDING_INLINE_INFO (methods) == 0
        !          2364:              && DECL_ABSTRACT_VIRTUAL_P (methods) == 0)
        !          2365:            {
        !          2366:              /* Somebody, somewhere is going to have to define this
        !          2367:                 virtual function.  When they do, they will provide
        !          2368:                 the debugging info.  */
        !          2369:              return;
        !          2370:            }
        !          2371:          methods = TREE_CHAIN (methods);
        !          2372:        }
        !          2373:     }
        !          2374:   /* We cannot rely on some alien method to solve our problems,
        !          2375:      so we must write out the debug info ourselves.  */
        !          2376:   TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
        !          2377:   rest_of_type_compilation (t, global_bindings_p ());
        !          2378: }
        !          2379: 
        !          2380: /*  Attach to the type of the virtual base class, the pointer to the
        !          2381:     virtual base class, given the global pointer vbase_decl_ptr.
        !          2382: 
        !          2383:     We use the global vbase_types.  ICK!  */
        !          2384: static void
        !          2385: dfs_find_vbases (binfo)
        !          2386:      tree binfo;
        !          2387: {
        !          2388:   tree binfos = BINFO_BASETYPES (binfo);
        !          2389:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          2390: 
        !          2391:   for (i = n_baselinks-1; i >= 0; i--)
        !          2392:     {
        !          2393:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          2394: 
        !          2395:       if (TREE_VIA_VIRTUAL (base_binfo)
        !          2396:          && CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo)) == 0)
        !          2397:        {
        !          2398:          tree vbase = BINFO_TYPE (base_binfo);
        !          2399:          tree binfo = binfo_member (vbase, vbase_types);
        !          2400: 
        !          2401:          CLASSTYPE_SEARCH_SLOT (vbase)
        !          2402:            = (char *) build (PLUS_EXPR, TYPE_POINTER_TO (vbase),
        !          2403:                              vbase_decl_ptr, BINFO_OFFSET (binfo));
        !          2404:        }
        !          2405:     }
        !          2406:   SET_BINFO_VTABLE_PATH_MARKED (binfo);
        !          2407:   SET_BINFO_NEW_VTABLE_MARKED (binfo);
        !          2408: }
        !          2409: 
        !          2410: static void
        !          2411: dfs_init_vbase_pointers (binfo)
        !          2412:      tree binfo;
        !          2413: {
        !          2414:   tree type = BINFO_TYPE (binfo);
        !          2415:   tree fields = TYPE_FIELDS (type);
        !          2416:   tree this_vbase_ptr;
        !          2417: 
        !          2418:   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
        !          2419: 
        !          2420:   /* If there is a dossier, it is the first field, though perhaps from
        !          2421:      the base class.  Otherwise, the first fields are virtual base class
        !          2422:      pointer fields.  */
        !          2423:   if (CLASSTYPE_DOSSIER (type) && VFIELD_NAME_P (DECL_NAME (fields)))
        !          2424:     /* Get past vtable for the object.  */
        !          2425:     fields = TREE_CHAIN (fields);
        !          2426: 
        !          2427:   if (fields == NULL_TREE
        !          2428:       || DECL_NAME (fields) == NULL_TREE
        !          2429:       || ! VBASE_NAME_P (DECL_NAME (fields)))
        !          2430:     return;
        !          2431: 
        !          2432:   this_vbase_ptr = vbase_decl_ptr_intermediate;
        !          2433: 
        !          2434:   if (TYPE_POINTER_TO (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
        !          2435:     my_friendly_abort (125);
        !          2436: 
        !          2437:   while (fields && DECL_NAME (fields)
        !          2438:         && VBASE_NAME_P (DECL_NAME (fields)))
        !          2439:     {
        !          2440:       tree ref = build (COMPONENT_REF, TREE_TYPE (fields),
        !          2441:                        build_indirect_ref (this_vbase_ptr, NULL_PTR), fields);
        !          2442:       tree init = (tree)CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
        !          2443:       vbase_init_result = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
        !          2444:                                                   vbase_types),
        !          2445:                                     build_modify_expr (ref, NOP_EXPR, init),
        !          2446:                                     vbase_init_result);
        !          2447:       fields = TREE_CHAIN (fields);
        !          2448:     }
        !          2449: }
        !          2450: 
        !          2451: /* Sometimes this needs to clear both VTABLE_PATH and NEW_VTABLE.  Other
        !          2452:    times, just NEW_VTABLE, but optimizer should make both with equal
        !          2453:    efficiency (though it does not currently).  */
        !          2454: static void
        !          2455: dfs_clear_vbase_slots (binfo)
        !          2456:      tree binfo;
        !          2457: {
        !          2458:   tree type = BINFO_TYPE (binfo);
        !          2459:   CLASSTYPE_SEARCH_SLOT (type) = 0;
        !          2460:   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
        !          2461:   CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
        !          2462: }
        !          2463: 
        !          2464: tree
        !          2465: init_vbase_pointers (type, decl_ptr)
        !          2466:      tree type;
        !          2467:      tree decl_ptr;
        !          2468: {
        !          2469:   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
        !          2470:     {
        !          2471:       int old_flag = flag_this_is_variable;
        !          2472:       tree binfo = TYPE_BINFO (type);
        !          2473:       flag_this_is_variable = -2;
        !          2474:       vbase_types = CLASSTYPE_VBASECLASSES (type);
        !          2475:       vbase_decl_ptr = decl_ptr;
        !          2476:       vbase_decl = build_indirect_ref (decl_ptr, NULL_PTR);
        !          2477:       vbase_decl_ptr_intermediate = vbase_decl_ptr;
        !          2478:       vbase_init_result = NULL_TREE;
        !          2479:       dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp);
        !          2480:       dfs_walk (binfo, dfs_init_vbase_pointers, marked_vtable_pathp);
        !          2481:       dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
        !          2482:       flag_this_is_variable = old_flag;
        !          2483:       return vbase_init_result;
        !          2484:     }
        !          2485:   return 0;
        !          2486: }
        !          2487: 
        !          2488: /* Build a COMPOUND_EXPR which when expanded will generate the code
        !          2489:    needed to initialize all the virtual function table slots of all
        !          2490:    the virtual baseclasses.  MAIN_BINFO is the binfo which determines
        !          2491:    the virtual baseclasses to use; TYPE is the type of the object to
        !          2492:    which the initialization applies.  TRUE_EXP is the true object we
        !          2493:    are initializing, and DECL_PTR is the pointer to the sub-object we
        !          2494:    are initializing.
        !          2495: 
        !          2496:    When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
        !          2497:    object was laidout by a top-level contructor and the computed
        !          2498:    offsets are valid to store vtables.  When zero, we must store new
        !          2499:    vtables through virtual baseclass pointers.
        !          2500: 
        !          2501:    We setup and use the globals: vbase_decl, vbase_decl_ptr, vbase_types
        !          2502:    ICK!  */
        !          2503: 
        !          2504: void
        !          2505: expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
        !          2506:      tree binfo;
        !          2507:      tree true_exp, decl_ptr;
        !          2508:      int use_computed_offsets;
        !          2509: {
        !          2510:   tree type = BINFO_TYPE (binfo);
        !          2511:   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
        !          2512:     {
        !          2513:       int old_flag = flag_this_is_variable;
        !          2514:       tree vbases = CLASSTYPE_VBASECLASSES (type);
        !          2515:       vbase_types = vbases;
        !          2516:       vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
        !          2517:       vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, NULL_PTR);
        !          2518: 
        !          2519:       if (use_computed_offsets)
        !          2520:        {
        !          2521:          /* This is an object of type IN_TYPE,  */
        !          2522:          flag_this_is_variable = -2;
        !          2523:          dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
        !          2524:        }
        !          2525: 
        !          2526:       /* Initialized with vtables of type TYPE.  */
        !          2527:       for (; vbases; vbases = TREE_CHAIN (vbases))
        !          2528:        {
        !          2529:          tree addr;
        !          2530:          if (use_computed_offsets)
        !          2531:            addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
        !          2532:          else
        !          2533:            {
        !          2534:              tree vbinfo = get_binfo (TREE_TYPE (vbases),
        !          2535:                                       TREE_TYPE (vbase_decl),
        !          2536:                                       0);
        !          2537: 
        !          2538:              /* See is we can get lucky.  */
        !          2539:              if (TREE_VIA_VIRTUAL (vbinfo))
        !          2540:                addr = convert_pointer_to_real (vbinfo, vbase_decl_ptr);
        !          2541:              else
        !          2542:                {
        !          2543:                  /* We go through all these contortions to avoid this
        !          2544:                     call, as it will fail when the virtual base type
        !          2545:                     is ambiguous from here.  We don't yet have a way
        !          2546:                     to search for and find just an instance of the
        !          2547:                     virtual base class.  Searching for the binfo in
        !          2548:                     vbases won't work, as we don't have the vbase
        !          2549:                     pointer field, for all vbases in the main class,
        !          2550:                     only direct vbases.  */
        !          2551:                  addr = convert_pointer_to_real (TREE_TYPE (vbases),
        !          2552:                                                  vbase_decl_ptr);
        !          2553:                  if (addr == error_mark_node)
        !          2554:                    continue;
        !          2555:                }
        !          2556:            }
        !          2557: 
        !          2558:          /* Do all vtables from this virtual base. */
        !          2559:          /* This assumes that virtual bases can never serve as parent
        !          2560:             binfos.  (in the CLASSTPE_VFIELD_PARENT sense)  */
        !          2561:          expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
        !          2562:                                    1, 0, addr);
        !          2563:        }
        !          2564: 
        !          2565:       dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
        !          2566: 
        !          2567:       flag_this_is_variable = old_flag;
        !          2568:     }
        !          2569: }
        !          2570: 
        !          2571: void
        !          2572: clear_search_slots (type)
        !          2573:      tree type;
        !          2574: {
        !          2575:   dfs_walk (TYPE_BINFO (type),
        !          2576:            dfs_clear_search_slot, dfs_search_slot_nonempty_p);
        !          2577: }
        !          2578: 
        !          2579: /* get virtual base class types.
        !          2580:    This adds type to the vbase_types list in reverse dfs order.
        !          2581:    Ordering is very important, so don't change it.  */
        !          2582: 
        !          2583: static void
        !          2584: dfs_get_vbase_types (binfo)
        !          2585:      tree binfo;
        !          2586: {
        !          2587:   if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
        !          2588:     {
        !          2589:       vbase_types = make_binfo (integer_zero_node, binfo,
        !          2590:                                BINFO_VTABLE (binfo),
        !          2591:                                BINFO_VIRTUALS (binfo), vbase_types);
        !          2592:       TREE_VIA_VIRTUAL (vbase_types) = 1;
        !          2593:       SET_BINFO_VBASE_MARKED (binfo);
        !          2594:     }
        !          2595:   SET_BINFO_MARKED (binfo);
        !          2596: }
        !          2597: 
        !          2598: /* get a list of virtual base classes in dfs order.  */
        !          2599: tree
        !          2600: get_vbase_types (type)
        !          2601:      tree type;
        !          2602: {
        !          2603:   tree vbases;
        !          2604:   tree binfo;
        !          2605: 
        !          2606:   if (TREE_CODE (type) == TREE_VEC)
        !          2607:     binfo = type;
        !          2608:   else
        !          2609:     binfo = TYPE_BINFO (type);
        !          2610: 
        !          2611:   vbase_types = NULL_TREE;
        !          2612:   dfs_walk (binfo, dfs_get_vbase_types, unmarkedp);
        !          2613:   dfs_walk (binfo, dfs_unmark, markedp);
        !          2614:   /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
        !          2615:      reverse it so that we get normal dfs ordering.  */
        !          2616:   vbase_types = nreverse (vbase_types);
        !          2617: 
        !          2618:   /* unmark marked vbases */
        !          2619:   for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
        !          2620:     CLEAR_BINFO_VBASE_MARKED (vbases);
        !          2621: 
        !          2622:   return vbase_types;
        !          2623: }
        !          2624: 
        !          2625: static void
        !          2626: dfs_record_inheritance (binfo)
        !          2627:      tree binfo;
        !          2628: {
        !          2629:   tree binfos = BINFO_BASETYPES (binfo);
        !          2630:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          2631:   mi_boolean *derived_row = BINFO_DERIVES_FROM_STAR (binfo);
        !          2632: 
        !          2633:   for (i = n_baselinks-1; i >= 0; i--)
        !          2634:     {
        !          2635:       int j;
        !          2636:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          2637:       tree baseclass = BINFO_TYPE (base_binfo);
        !          2638:       mi_boolean *base_row = BINFO_DERIVES_FROM_STAR (base_binfo);
        !          2639: 
        !          2640:       /* Don't search if there's nothing there!  MI_SIZE can be
        !          2641:         zero as a result of parse errors.  */
        !          2642:       if (TYPE_BINFO_BASETYPES (baseclass) && mi_size > 0)
        !          2643:        for (j = mi_size*(CLASSTYPE_CID (baseclass)-1); j >= 0; j -= mi_size)
        !          2644:          derived_row[j] |= base_row[j];
        !          2645:       TYPE_DERIVES_FROM (baseclass, BINFO_TYPE (binfo)) = 1;
        !          2646:     }
        !          2647: 
        !          2648:   SET_BINFO_MARKED (binfo);
        !          2649: }
        !          2650: 
        !          2651: /* Given a _CLASSTYPE node in a multiple inheritance lattice,
        !          2652:    convert the lattice into a simple relation such that,
        !          2653:    given to CIDs, C1 and C2, one can determine if C1 <= C2
        !          2654:    or C2 <= C1 or C1 <> C2.
        !          2655: 
        !          2656:    Once constructed, we walk the lattice depth fisrt,
        !          2657:    applying various functions to elements as they are encountered.
        !          2658: 
        !          2659:    We use xmalloc here, in case we want to randomly free these tables.  */
        !          2660: 
        !          2661: #define SAVE_MI_MATRIX
        !          2662: 
        !          2663: void
        !          2664: build_mi_matrix (type)
        !          2665:      tree type;
        !          2666: {
        !          2667:   tree binfo = TYPE_BINFO (type);
        !          2668:   cid = 0;
        !          2669: 
        !          2670: #ifdef SAVE_MI_MATRIX
        !          2671:   if (CLASSTYPE_MI_MATRIX (type))
        !          2672:     {
        !          2673:       mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
        !          2674:       mi_matrix = CLASSTYPE_MI_MATRIX (type);
        !          2675:       mi_type = type;
        !          2676:       dfs_walk (binfo, dfs_number, unnumberedp);
        !          2677:       return;
        !          2678:     }
        !          2679: #endif
        !          2680: 
        !          2681:   mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
        !          2682:   mi_matrix = (char *)xmalloc ((mi_size + 1) * (mi_size + 1));
        !          2683:   mi_type = type;
        !          2684:   bzero (mi_matrix, (mi_size + 1) * (mi_size + 1));
        !          2685:   dfs_walk (binfo, dfs_number, unnumberedp);
        !          2686:   dfs_walk (binfo, dfs_record_inheritance, unmarkedp);
        !          2687:   dfs_walk (binfo, dfs_unmark, markedp);
        !          2688: }
        !          2689: 
        !          2690: void
        !          2691: free_mi_matrix ()
        !          2692: {
        !          2693:   dfs_walk (TYPE_BINFO (mi_type), dfs_unnumber, numberedp);
        !          2694: 
        !          2695: #ifdef SAVE_MI_MATRIX
        !          2696:   CLASSTYPE_MI_MATRIX (mi_type) = mi_matrix;
        !          2697: #else
        !          2698:   free (mi_matrix);
        !          2699:   mi_size = 0;
        !          2700:   cid = 0;
        !          2701: #endif
        !          2702: }
        !          2703: 
        !          2704: /* If we want debug info for a type TYPE, make sure all its base types
        !          2705:    are also marked as being potentially interesting.  This avoids
        !          2706:    the problem of not writing any debug info for intermediate basetypes
        !          2707:    that have abstract virtual functions.  Also mark member types.  */
        !          2708: 
        !          2709: void
        !          2710: note_debug_info_needed (type)
        !          2711:      tree type;
        !          2712: {
        !          2713:   tree field;
        !          2714:   dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
        !          2715:   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        !          2716:     {
        !          2717:       tree ttype;
        !          2718:       if (TREE_CODE (field) == FIELD_DECL
        !          2719:          && IS_AGGR_TYPE (ttype = target_type (TREE_TYPE (field)))
        !          2720:          && dfs_debug_unmarkedp (TYPE_BINFO (ttype)))
        !          2721:        note_debug_info_needed (ttype);
        !          2722:     }
        !          2723: }
        !          2724: 
        !          2725: /* Subroutines of push_class_decls ().  */
        !          2726: 
        !          2727: /* Add the instance variables which this class contributed to the
        !          2728:    current class binding contour.  When a redefinition occurs,
        !          2729:    if the redefinition is strictly within a single inheritance path,
        !          2730:    we just overwrite (in the case of a data field) or
        !          2731:    cons (in the case of a member function) the old declaration with
        !          2732:    the new.  If the fields are not within a single inheritance path,
        !          2733:    we must cons them in either case.
        !          2734: 
        !          2735:    In order to know what decls are new (stemming from the current
        !          2736:    invocation of push_class_decls) we enclose them in an "envelope",
        !          2737:    which is a TREE_LIST node where the TREE_PURPOSE slot contains the
        !          2738:    new decl (or possibly a list of competing ones), the TREE_VALUE slot
        !          2739:    points to the old value and the TREE_CHAIN slot chains together all
        !          2740:    envelopes which needs to be "opened" in push_class_decls.  Opening an
        !          2741:    envelope means: push the old value onto the class_shadowed list,
        !          2742:    install the new one and if it's a TYPE_DECL do the same to the
        !          2743:    IDENTIFIER_TYPE_VALUE.  Such an envelope is recognized by seeing that
        !          2744:    the TREE_PURPOSE slot is non-null, and that it is not an identifier.
        !          2745:    Because if it is, it could be a set of overloaded methods from an
        !          2746:    outer scope.  */
        !          2747: 
        !          2748: static void
        !          2749: dfs_pushdecls (binfo)
        !          2750:      tree binfo;
        !          2751: {
        !          2752:   tree type = BINFO_TYPE (binfo);
        !          2753:   tree fields, *methods, *end;
        !          2754:   tree method_vec;
        !          2755: 
        !          2756:   for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
        !          2757:     {
        !          2758:       /* Unmark so that if we are in a constructor, and then find that
        !          2759:         this field was initialized by a base initializer,
        !          2760:         we can emit an error message.  */
        !          2761:       if (TREE_CODE (fields) == FIELD_DECL)
        !          2762:        TREE_USED (fields) = 0;
        !          2763: 
        !          2764:       /* Recurse into anonymous unions.  */
        !          2765:       if (DECL_NAME (fields) == NULL_TREE
        !          2766:          && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
        !          2767:        {
        !          2768:          dfs_pushdecls (TYPE_BINFO (TREE_TYPE (fields)));
        !          2769:          continue;
        !          2770:        }
        !          2771: 
        !          2772: #if 0
        !          2773:       if (TREE_CODE (fields) != TYPE_DECL)
        !          2774:        {
        !          2775:          DECL_PUBLIC (fields) = 0;
        !          2776:          DECL_PROTECTED (fields) = 0;
        !          2777:          DECL_PRIVATE (fields) = 0;
        !          2778:        }
        !          2779: #endif
        !          2780: 
        !          2781:       if (DECL_NAME (fields))
        !          2782:        {
        !          2783:          tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (fields));
        !          2784: 
        !          2785:          /* If the class value is an envelope of the kind described in
        !          2786:             the comment above, we try to rule out possible ambiguities.
        !          2787:             If we can't do that, keep a TREE_LIST with possibly ambiguous
        !          2788:             decls in there.  */
        !          2789:          if (class_value && TREE_CODE (class_value) == TREE_LIST
        !          2790:              && TREE_PURPOSE (class_value) != NULL_TREE
        !          2791:              && (TREE_CODE (TREE_PURPOSE (class_value))
        !          2792:                  != IDENTIFIER_NODE))
        !          2793:            {
        !          2794:              tree value = TREE_PURPOSE (class_value);
        !          2795:              tree context;
        !          2796: 
        !          2797:              /* Possible ambiguity.  If its defining type(s)
        !          2798:                 is (are all) derived from us, no problem.  */
        !          2799:              if (TREE_CODE (value) != TREE_LIST)
        !          2800:                {
        !          2801:                  context = (TREE_CODE (value) == FUNCTION_DECL
        !          2802:                             && DECL_VIRTUAL_P (value))
        !          2803:                    ? DECL_CLASS_CONTEXT (value)
        !          2804:                      : DECL_CONTEXT (value);
        !          2805: 
        !          2806:                  if (context && (context == type
        !          2807:                                  || TYPE_DERIVES_FROM (context, type)))
        !          2808:                    value = fields;
        !          2809:                  else
        !          2810:                    value = tree_cons (NULL_TREE, fields,
        !          2811:                                       build_tree_list (NULL_TREE, value));
        !          2812:                }
        !          2813:              else
        !          2814:                {
        !          2815:                  /* All children may derive from us, in which case
        !          2816:                     there is no problem.  Otherwise, we have to
        !          2817:                     keep lists around of what the ambiguities might be.  */
        !          2818:                  tree values;
        !          2819:                  int problem = 0;
        !          2820: 
        !          2821:                  for (values = value; values; values = TREE_CHAIN (values))
        !          2822:                    {
        !          2823:                      tree sub_values = TREE_VALUE (values);
        !          2824: 
        !          2825:                      if (TREE_CODE (sub_values) == TREE_LIST)
        !          2826:                        {
        !          2827:                          for (; sub_values; sub_values = TREE_CHAIN (sub_values))
        !          2828:                            {
        !          2829:                              register tree list_mbr = TREE_VALUE (sub_values);
        !          2830: 
        !          2831:                              context = (TREE_CODE (list_mbr) == FUNCTION_DECL
        !          2832:                                         && DECL_VIRTUAL_P (list_mbr))
        !          2833:                                ? DECL_CLASS_CONTEXT (list_mbr)
        !          2834:                                  : DECL_CONTEXT (list_mbr);
        !          2835: 
        !          2836:                              if (! TYPE_DERIVES_FROM (context, type))
        !          2837:                                {
        !          2838:                                  value = tree_cons (NULL_TREE, TREE_VALUE (values), value);
        !          2839:                                  problem = 1;
        !          2840:                                  break;
        !          2841:                                }
        !          2842:                            }
        !          2843:                        }
        !          2844:                      else
        !          2845:                        {
        !          2846:                          context = (TREE_CODE (sub_values) == FUNCTION_DECL
        !          2847:                                     && DECL_VIRTUAL_P (sub_values))
        !          2848:                            ? DECL_CLASS_CONTEXT (sub_values)
        !          2849:                              : DECL_CONTEXT (sub_values);
        !          2850: 
        !          2851:                          if (context && ! TYPE_DERIVES_FROM (context, type))
        !          2852:                            {
        !          2853:                              value = tree_cons (NULL_TREE, values, value);
        !          2854:                              problem = 1;
        !          2855:                              break;
        !          2856:                            }
        !          2857:                        }
        !          2858:                    }
        !          2859:                  if (! problem) value = fields;
        !          2860:                }
        !          2861: 
        !          2862:              /* Mark this as a potentially ambiguous member.  */
        !          2863:              if (TREE_CODE (value) == TREE_LIST)
        !          2864:                {
        !          2865:                  /* Leaving TREE_TYPE blank is intentional.
        !          2866:                     We cannot use `error_mark_node' (lookup_name)
        !          2867:                     or `unknown_type_node' (all member functions use this).  */
        !          2868:                  TREE_NONLOCAL_FLAG (value) = 1;
        !          2869:                }
        !          2870: 
        !          2871:              /* Put the new contents in our envelope.  */
        !          2872:              TREE_PURPOSE (class_value) = value;
        !          2873:            }
        !          2874:          else
        !          2875:            {
        !          2876:              /* See comment above for a description of envelopes.  */
        !          2877:              tree envelope = tree_cons (fields, class_value,
        !          2878:                                         closed_envelopes);
        !          2879: 
        !          2880:              closed_envelopes = envelope;
        !          2881:              IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = envelope;
        !          2882:            }
        !          2883:        }
        !          2884:     }
        !          2885: 
        !          2886:   method_vec = CLASSTYPE_METHOD_VEC (type);
        !          2887:   if (method_vec != 0)
        !          2888:     {
        !          2889:       /* Farm out constructors and destructors.  */
        !          2890:       methods = &TREE_VEC_ELT (method_vec, 1);
        !          2891:       end = TREE_VEC_END (method_vec);
        !          2892: 
        !          2893:       /* This does not work for multiple inheritance yet.  */
        !          2894:       while (methods != end)
        !          2895:        {
        !          2896:          /* This will cause lookup_name to return a pointer
        !          2897:             to the tree_list of possible methods of this name.
        !          2898:             If the order is a problem, we can nreverse them.  */
        !          2899:          tree tmp;
        !          2900:          tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
        !          2901: 
        !          2902:          if (class_value && TREE_CODE (class_value) == TREE_LIST
        !          2903:              && TREE_PURPOSE (class_value) != NULL_TREE
        !          2904:              && TREE_CODE (TREE_PURPOSE (class_value)) != IDENTIFIER_NODE)
        !          2905:            {
        !          2906:              tree old = TREE_PURPOSE (class_value);
        !          2907: 
        !          2908:              maybe_push_cache_obstack ();
        !          2909:              if (TREE_CODE (old) == TREE_LIST)
        !          2910:                tmp = tree_cons (DECL_NAME (*methods), *methods, old);
        !          2911:              else
        !          2912:                {
        !          2913:                  /* Only complain if we shadow something we can access.  */
        !          2914:                  if (old
        !          2915:                      && warn_shadow
        !          2916:                      && ((DECL_LANG_SPECIFIC (old)
        !          2917:                           && DECL_CLASS_CONTEXT (old) == current_class_type)
        !          2918:                          || ! TREE_PRIVATE (old)))
        !          2919:                    /* Should figure out access control more accurately.  */
        !          2920:                    {
        !          2921:                      cp_warning_at ("member `%#D' is shadowed", old);
        !          2922:                      cp_warning_at ("by member function `%#D'", *methods);
        !          2923:                      warning ("in this context");
        !          2924:                    }
        !          2925:                  tmp = build_tree_list (DECL_NAME (*methods), *methods);
        !          2926:                }
        !          2927:              pop_obstacks ();
        !          2928: 
        !          2929:              TREE_TYPE (tmp) = unknown_type_node;
        !          2930: #if 0
        !          2931:              TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
        !          2932: #endif
        !          2933:              TREE_NONLOCAL_FLAG (tmp) = 1;
        !          2934:              
        !          2935:              /* Put the new contents in our envelope.  */
        !          2936:              TREE_PURPOSE (class_value) = tmp;
        !          2937:            }
        !          2938:          else
        !          2939:            {
        !          2940:              maybe_push_cache_obstack ();
        !          2941:              tmp = build_tree_list (DECL_NAME (*methods), *methods);
        !          2942:              pop_obstacks ();
        !          2943: 
        !          2944:              TREE_TYPE (tmp) = unknown_type_node;
        !          2945: #if 0
        !          2946:              TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
        !          2947: #endif
        !          2948:              TREE_NONLOCAL_FLAG (tmp) = 1;
        !          2949:              
        !          2950:              /* See comment above for a description of envelopes.  */
        !          2951:              closed_envelopes = tree_cons (tmp, class_value,
        !          2952:                                            closed_envelopes);
        !          2953:              IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = closed_envelopes;
        !          2954:            }
        !          2955: #if 0
        !          2956:          tmp = *methods;
        !          2957:          while (tmp != 0)
        !          2958:            {
        !          2959:              DECL_PUBLIC (tmp) = 0;
        !          2960:              DECL_PROTECTED (tmp) = 0;
        !          2961:              DECL_PRIVATE (tmp) = 0;
        !          2962:              tmp = DECL_CHAIN (tmp);
        !          2963:            }
        !          2964: #endif
        !          2965: 
        !          2966:          methods++;
        !          2967:        }
        !          2968:     }
        !          2969:   SET_BINFO_MARKED (binfo);
        !          2970: }
        !          2971: 
        !          2972: /* Consolidate unique (by name) member functions.  */
        !          2973: static void
        !          2974: dfs_compress_decls (binfo)
        !          2975:      tree binfo;
        !          2976: {
        !          2977:   tree type = BINFO_TYPE (binfo);
        !          2978:   tree method_vec = CLASSTYPE_METHOD_VEC (type);
        !          2979: 
        !          2980:   if (method_vec != 0)
        !          2981:     {
        !          2982:       /* Farm out constructors and destructors.  */
        !          2983:       tree *methods = &TREE_VEC_ELT (method_vec, 1);
        !          2984:       tree *end = TREE_VEC_END (method_vec);
        !          2985: 
        !          2986:       for (; methods != end; methods++)
        !          2987:        {
        !          2988:          /* This is known to be an envelope of the kind described before
        !          2989:             dfs_pushdecls.  */
        !          2990:          tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
        !          2991:          tree tmp = TREE_PURPOSE (class_value);
        !          2992: 
        !          2993:          /* This was replaced in scope by somebody else.  Just leave it
        !          2994:             alone.  */
        !          2995:          if (TREE_CODE (tmp) != TREE_LIST)
        !          2996:            continue;
        !          2997: 
        !          2998:          if (TREE_CHAIN (tmp) == NULL_TREE
        !          2999:              && TREE_VALUE (tmp)
        !          3000:              && DECL_CHAIN (TREE_VALUE (tmp)) == NULL_TREE)
        !          3001:            {
        !          3002:              TREE_PURPOSE (class_value) = TREE_VALUE (tmp);
        !          3003:            }
        !          3004:        }
        !          3005:     }
        !          3006:   CLEAR_BINFO_MARKED (binfo);
        !          3007: }
        !          3008: 
        !          3009: /* When entering the scope of a class, we cache all of the
        !          3010:    fields that that class provides within its inheritance
        !          3011:    lattice.  Where ambiguities result, we mark them
        !          3012:    with `error_mark_node' so that if they are encountered
        !          3013:    without explicit qualification, we can emit an error
        !          3014:    message.  */
        !          3015: void
        !          3016: push_class_decls (type)
        !          3017:      tree type;
        !          3018: {
        !          3019:   tree id;
        !          3020:   struct obstack *ambient_obstack = current_obstack;
        !          3021: 
        !          3022: #if 0
        !          3023:   tree tags = CLASSTYPE_TAGS (type);
        !          3024: 
        !          3025:   while (tags)
        !          3026:     {
        !          3027:       tree code_type_node;
        !          3028:       tree tag;
        !          3029: 
        !          3030:       switch (TREE_CODE (TREE_VALUE (tags)))
        !          3031:        {
        !          3032:        case ENUMERAL_TYPE:
        !          3033:          code_type_node = enum_type_node;
        !          3034:          break;
        !          3035:        case RECORD_TYPE:
        !          3036:          code_type_node = record_type_node;
        !          3037:          break;
        !          3038:        case CLASS_TYPE:
        !          3039:          code_type_node = class_type_node;
        !          3040:          break;
        !          3041:        case UNION_TYPE:
        !          3042:          code_type_node = union_type_node;
        !          3043:          break;
        !          3044:        default:
        !          3045:          my_friendly_abort (297);
        !          3046:        }
        !          3047:       tag = xref_tag (code_type_node, TREE_PURPOSE (tags),
        !          3048:                      TYPE_BINFO_BASETYPE (TREE_VALUE (tags), 0), 0);
        !          3049: #if 0 /* not yet, should get fixed properly later */
        !          3050:       pushdecl (make_type_decl (TREE_PURPOSE (tags), TREE_VALUE (tags)));
        !          3051: #else
        !          3052:       pushdecl (build_decl (TYPE_DECL, TREE_PURPOSE (tags), TREE_VALUE (tags)));
        !          3053: #endif
        !          3054:     }
        !          3055: #endif
        !          3056: 
        !          3057:   search_stack = push_search_level (search_stack, &search_obstack);
        !          3058: 
        !          3059:   id = TYPE_IDENTIFIER (type);
        !          3060: #if 0
        !          3061:   if (IDENTIFIER_TEMPLATE (id) != 0)
        !          3062:     {
        !          3063:       tree tmpl = IDENTIFIER_TEMPLATE (id);
        !          3064:       push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
        !          3065:                           TREE_VALUE (tmpl), 1);
        !          3066:       overload_template_name (id, 1);
        !          3067:     }
        !          3068: #endif
        !          3069: 
        !          3070:   /* Push class fields into CLASS_VALUE scope, and mark.  */
        !          3071:   dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
        !          3072: 
        !          3073:   /* Compress fields which have only a single entry
        !          3074:      by a given name, and unmark.  */
        !          3075:   dfs_walk (TYPE_BINFO (type), dfs_compress_decls, markedp);
        !          3076: 
        !          3077:   /* Open up all the closed envelopes and push the contained decls into
        !          3078:      class scope.  */
        !          3079:   while (closed_envelopes)
        !          3080:     {
        !          3081:       tree new = TREE_PURPOSE (closed_envelopes);
        !          3082:       tree id;
        !          3083: 
        !          3084:       /* This is messy because the class value may be a *_DECL, or a
        !          3085:         TREE_LIST of overloaded *_DECLs or even a TREE_LIST of ambiguous
        !          3086:         *_DECLs.  The name is stored at different places in these three
        !          3087:         cases.  */
        !          3088:       if (TREE_CODE (new) == TREE_LIST)
        !          3089:        {
        !          3090:          if (TREE_PURPOSE (new) != NULL_TREE)
        !          3091:            id = TREE_PURPOSE (new);
        !          3092:          else
        !          3093:            {
        !          3094:              tree node = TREE_VALUE (new);
        !          3095: 
        !          3096:              while (TREE_CODE (node) == TREE_LIST)
        !          3097:                node = TREE_VALUE (node);
        !          3098:              id = DECL_NAME (node);
        !          3099:            }
        !          3100:        }
        !          3101:       else
        !          3102:        id = DECL_NAME (new);
        !          3103: 
        !          3104:       /* Install the original class value in order to make
        !          3105:         pushdecl_class_level work correctly.  */
        !          3106:       IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes);
        !          3107:       if (TREE_CODE (new) == TREE_LIST)
        !          3108:        push_class_level_binding (id, new);
        !          3109:       else
        !          3110:        pushdecl_class_level (new);
        !          3111:       closed_envelopes = TREE_CHAIN (closed_envelopes);
        !          3112:     }
        !          3113:   current_obstack = ambient_obstack;
        !          3114: }
        !          3115: 
        !          3116: /* Here's a subroutine we need because C lacks lambdas.  */
        !          3117: static void
        !          3118: dfs_unuse_fields (binfo)
        !          3119:      tree binfo;
        !          3120: {
        !          3121:   tree type = TREE_TYPE (binfo);
        !          3122:   tree fields;
        !          3123: 
        !          3124:   for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
        !          3125:     {
        !          3126:       if (TREE_CODE (fields) != FIELD_DECL)
        !          3127:        continue;
        !          3128: 
        !          3129:       TREE_USED (fields) = 0;
        !          3130:       if (DECL_NAME (fields) == NULL_TREE
        !          3131:          && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
        !          3132:        unuse_fields (TREE_TYPE (fields));
        !          3133:     }
        !          3134: }
        !          3135: 
        !          3136: void
        !          3137: unuse_fields (type)
        !          3138:      tree type;
        !          3139: {
        !          3140:   dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp);
        !          3141: }
        !          3142: 
        !          3143: void
        !          3144: pop_class_decls (type)
        !          3145:      tree type;
        !          3146: {
        !          3147:   /* We haven't pushed a search level when dealing with cached classes,
        !          3148:      so we'd better not try to pop it.  */
        !          3149:   if (search_stack)
        !          3150:     search_stack = pop_search_level (search_stack);
        !          3151: }
        !          3152: 
        !          3153: void
        !          3154: print_search_statistics ()
        !          3155: {
        !          3156: #ifdef GATHER_STATISTICS
        !          3157:   if (flag_memoize_lookups)
        !          3158:     {
        !          3159:       fprintf (stderr, "%d memoized contexts saved\n",
        !          3160:               n_contexts_saved);
        !          3161:       fprintf (stderr, "%d local tree nodes made\n", my_tree_node_counter);
        !          3162:       fprintf (stderr, "%d local hash nodes made\n", my_memoized_entry_counter);
        !          3163:       fprintf (stderr, "fields statistics:\n");
        !          3164:       fprintf (stderr, "  memoized finds = %d; rejects = %d; (searches = %d)\n",
        !          3165:               memoized_fast_finds[0], memoized_fast_rejects[0],
        !          3166:               memoized_fields_searched[0]);
        !          3167:       fprintf (stderr, "  memoized_adds = %d\n", memoized_adds[0]);
        !          3168:       fprintf (stderr, "fnfields statistics:\n");
        !          3169:       fprintf (stderr, "  memoized finds = %d; rejects = %d; (searches = %d)\n",
        !          3170:               memoized_fast_finds[1], memoized_fast_rejects[1],
        !          3171:               memoized_fields_searched[1]);
        !          3172:       fprintf (stderr, "  memoized_adds = %d\n", memoized_adds[1]);
        !          3173:     }
        !          3174:   fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
        !          3175:           n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1);
        !          3176:   fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
        !          3177:           n_outer_fields_searched, n_calls_lookup_fnfields);
        !          3178:   fprintf (stderr, "%d calls to get_base_type\n", n_calls_get_base_type);
        !          3179: #else
        !          3180:   fprintf (stderr, "no search statistics\n");
        !          3181: #endif
        !          3182: }
        !          3183: 
        !          3184: void
        !          3185: init_search_processing ()
        !          3186: {
        !          3187:   gcc_obstack_init (&search_obstack);
        !          3188:   gcc_obstack_init (&type_obstack);
        !          3189:   gcc_obstack_init (&type_obstack_entries);
        !          3190: 
        !          3191:   /* This gives us room to build our chains of basetypes,
        !          3192:      whether or not we decide to memoize them.  */
        !          3193:   type_stack = push_type_level (0, &type_obstack);
        !          3194:   _vptr_name = get_identifier ("_vptr");
        !          3195: }
        !          3196: 
        !          3197: void
        !          3198: reinit_search_statistics ()
        !          3199: {
        !          3200:   my_memoized_entry_counter = 0;
        !          3201:   memoized_fast_finds[0] = 0;
        !          3202:   memoized_fast_finds[1] = 0;
        !          3203:   memoized_adds[0] = 0;
        !          3204:   memoized_adds[1] = 0;
        !          3205:   memoized_fast_rejects[0] = 0;
        !          3206:   memoized_fast_rejects[1] = 0;
        !          3207:   memoized_fields_searched[0] = 0;
        !          3208:   memoized_fields_searched[1] = 0;
        !          3209:   n_fields_searched = 0;
        !          3210:   n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
        !          3211:   n_calls_lookup_fnfields = 0, n_calls_lookup_fnfields_1 = 0;
        !          3212:   n_calls_get_base_type = 0;
        !          3213:   n_outer_fields_searched = 0;
        !          3214:   n_contexts_saved = 0;
        !          3215: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.