Annotation of gcc/cp-search.c, revision 1.1.1.4

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 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: 
1.1.1.4 ! root       22: #if 0
        !            23: /* Remove before release, should only appear for development and testing. */
        !            24: #define CHECK_convert_pointer_to_single_level
        !            25: #endif
1.1       root       26: 
                     27: /* High-level class interface. */
                     28: 
                     29: #include "config.h"
                     30: #include "tree.h"
                     31: #include <stdio.h>
                     32: #include "cp-tree.h"
                     33: #include "obstack.h"
                     34: #include "flags.h"
                     35: 
                     36: #define obstack_chunk_alloc xmalloc
                     37: #define obstack_chunk_free free
                     38: 
                     39: void init_search ();
                     40: extern struct obstack *current_obstack;
                     41: 
                     42: #include "stack.h"
                     43: 
                     44: /* Obstack used for remembering decision points of breadth-first.  */
                     45: static struct obstack search_obstack;
                     46: 
                     47: /* Obstack used to bridge from one function context to another.  */
                     48: static struct obstack bridge_obstack;
                     49: 
                     50: /* Methods for pushing and popping objects to and from obstacks.  */
                     51: 
                     52: struct stack_level *
                     53: push_stack_level (obstack, tp, size)
                     54:      struct obstack *obstack;
1.1.1.2   root       55:      char *tp;  /* Sony NewsOS 5.0 compiler doesn't like void * here.  */
1.1       root       56:      int size;
                     57: {
                     58:   struct stack_level *stack;
                     59:   /* FIXME.  Doesn't obstack_grow, in the case when the current chunk has
                     60:      insufficient space, move the base so that obstack_next_free is not
                     61:      valid?  Perhaps obstack_copy should be used rather than obstack_grow,
                     62:      and its returned value be used.  -- Raeburn
                     63:    */
                     64:   stack = (struct stack_level *) obstack_next_free (obstack);
                     65:   obstack_grow (obstack, tp, size);
                     66:   obstack_finish (obstack);
                     67:   stack->obstack = obstack;
                     68:   stack->first = (tree *) obstack_base (obstack);
                     69:   stack->limit = obstack_room (obstack) / sizeof (tree *);
                     70:   return stack;
                     71: }
                     72: 
                     73: struct stack_level *
                     74: pop_stack_level (stack)
                     75:      struct stack_level *stack;
                     76: {
                     77:   struct stack_level *tem = stack;
                     78:   struct obstack *obstack = tem->obstack;
                     79:   stack = tem->prev;
                     80:   obstack_free (obstack, tem);
                     81:   return stack;
                     82: }
                     83: 
                     84: #define search_level stack_level
                     85: static struct search_level *search_stack;
                     86: 
                     87: static tree lookup_field_1 ();
                     88: static int lookup_fnfields_1 ();
1.1.1.4 ! root       89: static void dfs_walk ();
        !            90: static int markedp ();
        !            91: static void dfs_unmark ();
        !            92: static void dfs_init_vbase_pointers ();
        !            93: 
        !            94: static tree vbase_types;
        !            95: static tree vbase_decl, vbase_decl_ptr;
        !            96: static tree vbase_decl_ptr_intermediate;
        !            97: static tree vbase_init_result;
        !            98: static int saw_first_vbase;
1.1       root       99: 
                    100: /* Allocate a level of searching.  */
                    101: static struct search_level *
                    102: push_search_level (stack, obstack)
                    103:      struct stack_level *stack;
                    104:      struct obstack *obstack;
                    105: {
                    106:   struct search_level tem;
                    107:   tem.prev = stack;
                    108: 
                    109:   return push_stack_level (obstack, &tem, sizeof (tem));
                    110: }
                    111: 
                    112: /* Discard a level of search allocation.  */
                    113: #define pop_search_level pop_stack_level
                    114: 
                    115: /* Search memoization.  */
                    116: struct type_level
                    117: {
                    118:   struct stack_level base;
                    119: 
                    120:   /* First object allocated in obstack of entries.  */
                    121:   char *entries;
                    122: 
                    123:   /* Number of types memoized in this context.  */
                    124:   int len;
                    125: 
                    126:   /* Type being memoized; save this if we are saving
                    127:      memoized contexts.  */
                    128:   tree type;
                    129: };
                    130: 
                    131: /* Obstack used for memoizing member and member function lookup.  */
                    132: 
                    133: static struct obstack type_obstack, type_obstack_entries;
                    134: static struct type_level *type_stack;
                    135: static tree _vptr_name;
                    136: 
                    137: /* Make things that look like tree nodes, but allocate them
                    138:    on type_obstack_entries.  */
                    139: static int my_tree_node_counter;
                    140: static tree my_tree_cons (), my_build_string ();
                    141: 
                    142: extern int flag_memoize_lookups, flag_save_memoized_contexts;
                    143: 
                    144: /* Variables for gathering statistics.  */
                    145: static int my_memoized_entry_counter;
                    146: static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];
                    147: static int memoized_fields_searched[2];
                    148: static int n_fields_searched;
                    149: static int n_calls_lookup_field, n_calls_lookup_field_1;
                    150: static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;
                    151: static int n_calls_get_base_type;
                    152: static int n_outer_fields_searched;
                    153: static int n_contexts_saved;
                    154: 
                    155: /* Local variables to help save memoization contexts.  */
                    156: static tree prev_type_memoized;
                    157: static struct type_level *prev_type_stack;
                    158: 
1.1.1.3   root      159: /* Allocate a level of type memoization context.  */
1.1       root      160: static struct type_level *
                    161: push_type_level (stack, obstack)
                    162:      struct stack_level *stack;
                    163:      struct obstack *obstack;
                    164: {
                    165:   struct type_level tem;
                    166: 
                    167:   tem.base.prev = stack;
                    168: 
                    169:   obstack_finish (&type_obstack_entries);
                    170:   tem.entries = (char *) obstack_base (&type_obstack_entries);
                    171:   tem.len = 0;
                    172:   tem.type = NULL_TREE;
                    173: 
                    174:   return (struct type_level *)push_stack_level (obstack, &tem, sizeof (tem));
                    175: }
                    176: 
1.1.1.3   root      177: /* Discard a level of type memoization context.  */
1.1       root      178: 
                    179: static struct type_level *
                    180: pop_type_level (stack)
                    181:      struct type_level *stack;
                    182: {
                    183:   obstack_free (&type_obstack_entries, stack->entries);
                    184:   return (struct type_level *)pop_stack_level ((struct stack_level *)stack);
                    185: }
                    186: 
                    187: /* Make something that looks like a TREE_LIST, but
                    188:    do it on the type_obstack_entries obstack.  */
                    189: static tree
                    190: my_tree_cons (purpose, value, chain)
                    191:      tree purpose, value, chain;
                    192: {
                    193:   tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_list));
                    194:   ++my_tree_node_counter;
                    195:   TREE_TYPE (p) = 0;
                    196:   ((int *)p)[3] = 0;
                    197:   TREE_SET_CODE (p, TREE_LIST);
                    198:   TREE_PURPOSE (p) = purpose;
                    199:   TREE_VALUE (p) = value;
                    200:   TREE_CHAIN (p) = chain;
                    201:   return p;
                    202: }
                    203: 
                    204: static tree
                    205: my_build_string (str)
                    206:      char *str;
                    207: {
                    208:   tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_string));
                    209:   ++my_tree_node_counter;
                    210:   TREE_TYPE (p) = 0;
                    211:   ((int *)p)[3] = 0;
                    212:   TREE_SET_CODE (p, STRING_CST);
                    213:   TREE_STRING_POINTER (p) = str;
                    214:   TREE_STRING_LENGTH (p) = strlen (str);
                    215:   return p;
                    216: }
                    217: 
                    218: /* Memoizing machinery to make searches for multiple inheritance
                    219:    reasonably efficient.  */
                    220: #define MEMOIZE_HASHSIZE 8
                    221: typedef struct memoized_entry
                    222: {
                    223:   struct memoized_entry *chain;
                    224:   int uid;
                    225:   tree data_members[MEMOIZE_HASHSIZE];
                    226:   tree function_members[MEMOIZE_HASHSIZE];
                    227: } *ME;
                    228: 
                    229: #define MEMOIZED_CHAIN(ENTRY) (((ME)ENTRY)->chain)
                    230: #define MEMOIZED_UID(ENTRY) (((ME)ENTRY)->uid)
                    231: #define MEMOIZED_FIELDS(ENTRY,INDEX) (((ME)ENTRY)->data_members[INDEX])
                    232: #define MEMOIZED_FNFIELDS(ENTRY,INDEX) (((ME)ENTRY)->function_members[INDEX])
                    233: /* The following is probably a lousy hash function.  */
                    234: #define MEMOIZED_HASH_FN(NODE) (((long)(NODE)>>4)&(MEMOIZE_HASHSIZE - 1))
                    235: 
                    236: static struct memoized_entry *
                    237: my_new_memoized_entry (chain)
                    238:      struct memoized_entry *chain;
                    239: {
                    240:   struct memoized_entry *p =
                    241:     (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
                    242:                                            sizeof (struct memoized_entry));
                    243:   bzero (p, sizeof (struct memoized_entry));
                    244:   MEMOIZED_CHAIN (p) = chain;
                    245:   MEMOIZED_UID (p) = ++my_memoized_entry_counter;
                    246:   return p;
                    247: }
                    248: 
                    249: /* Make an entry in the memoized table for type TYPE
                    250:    that the entry for NAME is FIELD.  */
                    251: 
                    252: tree
                    253: make_memoized_table_entry (type, name, function_p)
                    254:      tree type, name;
1.1.1.4 ! root      255:      int function_p;
1.1       root      256: {
                    257:   int index = MEMOIZED_HASH_FN (name);
                    258:   tree entry, *prev_entry;
                    259: 
                    260:   memoized_adds[function_p] += 1;
                    261:   if (CLASSTYPE_MTABLE_ENTRY (type) == 0)
                    262:     {
                    263:       obstack_ptr_grow (&type_obstack, type);
                    264:       obstack_blank (&type_obstack, sizeof (struct memoized_entry *));
                    265:       CLASSTYPE_MTABLE_ENTRY (type) = (char *)my_new_memoized_entry (0);
                    266:       type_stack->len++;
                    267:       if (type_stack->len * 2 >= type_stack->base.limit)
1.1.1.3   root      268:        my_friendly_abort (88);
1.1       root      269:     }
                    270:   if (function_p)
                    271:     prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
                    272:   else
                    273:     prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
                    274: 
                    275:   entry = my_tree_cons (name, 0, *prev_entry);
                    276:   *prev_entry = entry;
                    277: 
                    278:   /* Don't know the error message to give yet.  */
                    279:   TREE_TYPE (entry) = error_mark_node;
                    280: 
                    281:   return entry;
                    282: }
                    283: 
                    284: /* When a new function or class context is entered, we build
                    285:    a table of types which have been searched for members.
                    286:    The table is an array (obstack) of types.  When a type is
                    287:    entered into the obstack, its CLASSTYPE_MTABLE_ENTRY
                    288:    field is set to point to a new record, of type struct memoized_entry.
                    289: 
                    290:    A non-NULL TREE_TYPE of the entry contains a visibility error message.
                    291: 
                    292:    The slots for the data members are arrays of tree nodes.
                    293:    These tree nodes are lists, with the TREE_PURPOSE
                    294:    of this list the known member name, and the TREE_VALUE
                    295:    as the FIELD_DECL for the member.
                    296: 
                    297:    For member functions, the TREE_PURPOSE is again the
                    298:    name of the member functions for that class,
                    299:    and the TREE_VALUE of the list is a pairs
                    300:    whose TREE_PURPOSE is a member functions of this name,
                    301:    and whose TREE_VALUE is a list of known argument lists this
                    302:    member function has been called with.  The TREE_TYPE of the pair,
                    303:    if non-NULL, is an error message to print.  */
                    304: 
                    305: /* Tell search machinery that we are entering a new context, and
                    306:    to update tables appropriately.
                    307: 
                    308:    TYPE is the type of the context we are entering, which can
                    309:    be NULL_TREE if we are not in a class's scope.
                    310: 
                    311:    USE_OLD, if nonzero tries to use previous context.  */
                    312: void
                    313: push_memoized_context (type, use_old)
                    314:      tree type;
                    315:      int use_old;
                    316: {
                    317:   int len;
                    318:   tree *tem;
                    319: 
                    320:   if (prev_type_stack)
                    321:     {
                    322:       if (use_old && prev_type_memoized == type)
                    323:        {
                    324: #ifdef GATHER_STATISTICS
                    325:          n_contexts_saved++;
                    326: #endif
                    327:          type_stack = prev_type_stack;
                    328:          prev_type_stack = 0;
                    329: 
                    330:          tem = &type_stack->base.first[0];
                    331:          len = type_stack->len;
                    332:          while (len--)
                    333:            CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)tem[len*2+1];
                    334:          return;
                    335:        }
                    336:       /* Otherwise, need to pop old stack here.  */
                    337:       type_stack = pop_type_level (prev_type_stack);
                    338:       prev_type_memoized = 0;
                    339:       prev_type_stack = 0;
                    340:     }
                    341: 
                    342:   type_stack = push_type_level ((struct stack_level *)type_stack,
                    343:                                &type_obstack);
                    344:   type_stack->type = type;
                    345: }
                    346: 
                    347: /* Tell search machinery that we have left a context.
                    348:    We do not currently save these contexts for later use.
                    349:    If we wanted to, we could not use pop_search_level, since
                    350:    poping that level allows the data we have collected to
                    351:    be clobbered; a stack of obstacks would be needed.  */
                    352: void
                    353: pop_memoized_context (use_old)
                    354:      int use_old;
                    355: {
                    356:   int len;
                    357:   tree *tem = &type_stack->base.first[0];
                    358: 
                    359:   if (! flag_save_memoized_contexts)
                    360:     use_old = 0;
                    361:   else if (use_old)
                    362:     {
                    363:       len = type_stack->len;
                    364:       while (len--)
                    365:        tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]);
                    366: 
                    367:       prev_type_stack = type_stack;
                    368:       prev_type_memoized = type_stack->type;
                    369:     }
                    370: 
                    371:   if (flag_memoize_lookups)
                    372:     {
                    373:       len = type_stack->len;
                    374:       while (len--)
                    375:        CLASSTYPE_MTABLE_ENTRY (tem[len*2])
                    376:          = (char *)MEMOIZED_CHAIN (CLASSTYPE_MTABLE_ENTRY (tem[len*2]));
                    377:     }
                    378:   if (! use_old)
                    379:     type_stack = pop_type_level (type_stack);
                    380:   else
                    381:     type_stack = (struct type_level *)type_stack->base.prev;
                    382: }
                    383: 
                    384: /* Recursively search for a path from PARENT to BINFO.
                    385:    If RVAL is > 0 and we succeed, update the BINFO_NEXT_BINFO
                    386:    pointers.
                    387:    If we find a distinct basetype that's not the one from BINFO,
                    388:    return -2;
                    389:    If we don't find any path, return 0.
                    390: 
                    391:    If we encounter a virtual basetype on the path, return RVAL
                    392:    and don't change any pointers after that point.  */
                    393: static int
                    394: recursive_bounded_basetype_p (parent, binfo, rval, update_chain)
                    395:      tree parent, binfo;
                    396:      int rval;
                    397:      int update_chain;
                    398: {
                    399:   tree binfos;
                    400: 
                    401:   if (BINFO_TYPE (parent) == BINFO_TYPE (binfo))
                    402:     {
                    403:       if (tree_int_cst_equal (BINFO_OFFSET (parent), BINFO_OFFSET (binfo)))
                    404:        return rval;
                    405:       return -2;
                    406:     }
                    407: 
                    408:   if (TREE_VIA_VIRTUAL (binfo))
                    409:     update_chain = 0;
                    410: 
                    411:   if (binfos = BINFO_BASETYPES (binfo))
                    412:     {
                    413:       int i, nval;
                    414:       for (i = 0; i < TREE_VEC_LENGTH (binfos); i++)
                    415:        {
                    416:          nval = recursive_bounded_basetype_p (parent, TREE_VEC_ELT (binfos, i),
                    417:                                               rval, update_chain);
                    418:          if (nval < 0)
                    419:            return nval;
                    420:          if (nval > 0 && update_chain)
                    421:            BINFO_INHERITANCE_CHAIN (TREE_VEC_ELT (binfos, i)) = binfo;
                    422:        }
                    423:       return rval;
                    424:     }
                    425:   return 0;
                    426: }
                    427: 
1.1.1.4 ! root      428: /* Check whether the type given in BINFO is derived from PARENT.  If
        !           429:    it isn't, return 0.  If it is, but the derivation is MI-ambiguous
        !           430:    AND protect != 0, emit an error message and return error_mark_node.
        !           431: 
        !           432:    Otherwise, if TYPE is derived from PARENT, return the actual base
        !           433:    information, unless a one of the protection violations below
        !           434:    occurs, in which case emit an error message and return error_mark_node.
        !           435: 
        !           436:    The below should be worded better.  It may not be exactly what the code
        !           437:    does, but there should be a lose correlation.  If you understand the code
        !           438:    well, please try and make the comments below more readable.
        !           439: 
        !           440:    If PROTECT is 1, then check if access to a public field of PARENT
        !           441:    would be private.
        !           442: 
        !           443:    If PROTECT is 2, then check if the given type is derived from
        !           444:    PARENT via private visibility rules.
        !           445: 
1.1       root      446:    If PROTECT is 3, then immediately private baseclass is ok,
1.1.1.4 ! root      447:    but deeper than that, check if private.  */
1.1       root      448: tree
                    449: get_binfo (parent, binfo, protect)
                    450:      register tree parent, binfo;
                    451: {
                    452:   tree xtype, type;
                    453:   tree otype;
                    454:   int head = 0, tail = 0;
                    455:   int is_private = 0;
                    456:   tree rval = NULL_TREE;
                    457:   int rval_private = 0;
                    458:   tree friends;
                    459: 
                    460: #ifdef GATHER_STATISTICS
                    461:   n_calls_get_base_type++;
                    462: #endif
                    463: 
                    464:   if (TREE_CODE (parent) == TREE_VEC)
                    465:     parent = BINFO_TYPE (parent);
1.1.1.4 ! root      466:   /* unions cannot participate in inheritance relationships */
        !           467:   else if (TREE_CODE (parent) == UNION_TYPE)
        !           468:     return 0;
1.1       root      469:   else if (TREE_CODE (parent) != RECORD_TYPE)
1.1.1.3   root      470:     my_friendly_abort (89);
1.1       root      471: 
                    472:   parent = TYPE_MAIN_VARIANT (parent);
                    473:   search_stack = push_search_level (search_stack, &search_obstack);
                    474: 
                    475:   if (TREE_CODE (binfo) == TREE_VEC)
                    476:     type = BINFO_TYPE (binfo);
                    477:   else if (TREE_CODE (binfo) == RECORD_TYPE)
                    478:     {
                    479:       type = binfo;
                    480:       binfo = TYPE_BINFO (type);
                    481:     }
1.1.1.3   root      482:   else my_friendly_abort (90);
1.1       root      483:   xtype = type;
                    484:   friends = current_class_type ? CLASSTYPE_FRIEND_CLASSES (type) : NULL_TREE;
                    485: 
                    486:   while (1)
                    487:     {
                    488:       tree binfos = BINFO_BASETYPES (binfo);
                    489:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                    490: 
                    491:       /* Process and/or queue base types.  */
                    492:       for (i = 0; i < n_baselinks; i++)
                    493:        {
1.1.1.4 ! root      494:          tree base_binfo = TREE_VEC_ELT (binfos, i);
1.1       root      495: 
1.1.1.4 ! root      496:          if (BINFO_MARKED (base_binfo) == 0)
1.1       root      497:            {
1.1.1.4 ! root      498:              int via_private = is_private || !TREE_VIA_PUBLIC (base_binfo);
        !           499: 
        !           500:              SET_BINFO_MARKED (base_binfo);
1.1       root      501: 
                    502:              if (via_private == 0)
                    503:                ;
                    504:              else if (protect == 0)
                    505:                via_private = 0;
                    506:              else if (protect == 1 && BINFO_TYPE (binfo) == current_class_type)
                    507:                /* The immediate base class of the class we are in
                    508:                   does let its public members through.  */
                    509:                via_private = 0;
                    510: #ifndef NOJJG
                    511:              else if (protect
                    512:                       && friends != NULL_TREE
                    513:                       && BINFO_TYPE (binfo) == xtype
                    514:                       && value_member (current_class_type, friends))
                    515:                /* Friend types of the most derived type have access
                    516:                   to its baseclass pointers.  */
                    517:                via_private = 0;
                    518: #endif
                    519: 
                    520:              otype = type;
1.1.1.4 ! root      521:              obstack_ptr_grow (&search_obstack, base_binfo);
1.1       root      522:              obstack_int_grow (&search_obstack, via_private);
                    523:              tail += 2;
                    524:              if (tail >= search_stack->limit)
1.1.1.3   root      525:                my_friendly_abort (91);
1.1       root      526:            }
1.1.1.4 ! root      527: #if 0
        !           528:          /* This code cannot possibly be right.  Ambiguities can only be
        !           529:             checked by traversing the whole tree, and seeing if it pops
        !           530:             up twice. */
        !           531:          else if (protect && ! TREE_VIA_VIRTUAL (base_binfo))
1.1       root      532:            {
                    533:              error_with_aggr_type (parent, "type `%s' is ambiguous base class for type `%s'",
                    534:                                    TYPE_NAME_STRING (xtype));
                    535:              error ("(base class for types `%s' and `%s')",
                    536:                     TYPE_NAME_STRING (BINFO_TYPE (binfo)),
                    537:                     TYPE_NAME_STRING (otype));
                    538:              rval = error_mark_node;
1.1.1.4 ! root      539:              goto cleanup;
1.1       root      540:            }
1.1.1.4 ! root      541: #endif
1.1       root      542:        }
                    543: 
                    544:     dont_queue:
                    545:       /* Process head of queue, if one exists.  */
                    546:       if (head >= tail)
                    547:        break;
                    548: 
                    549:       binfo = search_stack->first[head++];
1.1.1.4 ! root      550:       is_private = (HOST_WIDE_INT)search_stack->first[head++];
1.1       root      551:       if (BINFO_TYPE (binfo) == parent)
                    552:        {
                    553:          if (rval == 0)
                    554:            {
                    555:              rval = binfo;
                    556:              rval_private = is_private;
                    557:            }
1.1.1.4 ! root      558:          else
        !           559:            /* I believe it is the case that this error is only an error when
        !           560:               used by someone that wants error messages printed.  Routines that
        !           561:               call this one, that don't set protect want the first one found,
        !           562:               even if there are more.  */
        !           563:            if (protect)
        !           564:              {
        !           565:                /* Found two or more possible return values.  */
        !           566:                error_with_aggr_type (parent, "type `%s' is ambiguous base class for type `%s'",
        !           567:                                      TYPE_NAME_STRING (xtype));
        !           568:                rval = error_mark_node;
        !           569:                goto cleanup;
        !           570:              }
1.1       root      571:          goto dont_queue;
                    572:        }
                    573:     }
1.1.1.4 ! root      574: 
        !           575:  cleanup:
1.1       root      576:   {
                    577:     tree *tp = search_stack->first;
                    578:     tree *search_tail = tp + tail;
                    579: 
                    580:     while (tp < search_tail)
                    581:       {
                    582:        CLEAR_BINFO_MARKED (*tp);
                    583:        tp += 2;
                    584:       }
                    585:   }
                    586:   search_stack = pop_search_level (search_stack);
                    587: 
                    588:   if (rval == error_mark_node)
                    589:     return error_mark_node;
                    590: 
                    591:   if (rval && protect && rval_private)
                    592:     {
                    593:       if (protect == 3)
                    594:        {
                    595:          tree binfos = BINFO_BASETYPES (TYPE_BINFO (xtype));
                    596:          int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                    597: 
                    598:          for (i = 0; i < n_baselinks; i++)
                    599:            {
1.1.1.4 ! root      600:              tree base_binfo = TREE_VEC_ELT (binfos, i);
        !           601:              if (parent == BINFO_TYPE (base_binfo))
1.1.1.3   root      602:                /* It's ok, since it's immediate.  */
1.1       root      603:                return rval;
                    604:            }
                    605:        }
                    606:       error_with_aggr_type (xtype, "type `%s' is derived from private `%s'",
                    607:                            TYPE_NAME_STRING (parent));
                    608:       return error_mark_node;
                    609:     }
                    610: 
                    611:   return rval;
                    612: }
                    613: 
1.1.1.4 ! root      614: /* -------------------------------------------------- */
        !           615: /* These two routines are ONLY here to check for ambiguities for
        !           616:    get_base_distance, as it probably cannot check by itself for
        !           617:    all ambiguities.  When get_base_distance is sure to check for all,
        !           618:    these routines can go.  (mrs) */
        !           619: 
        !           620: tree
        !           621: get_binfo2_recursive (binfo, parent, type)
        !           622:      register tree binfo, parent;
        !           623:      tree type;
        !           624: {
        !           625:   tree rval = NULL_TREE;
        !           626:   tree nrval;
        !           627:   tree binfos = BINFO_BASETYPES (binfo);
        !           628:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !           629: 
        !           630:   if (BINFO_TYPE (binfo) == parent)
        !           631:     {
        !           632:       return binfo;
        !           633:     }
        !           634: 
        !           635:   /* Process base types.  */
        !           636:   for (i = 0; i < n_baselinks; i++)
        !           637:     {
        !           638:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !           639: 
        !           640:       if (BINFO_MARKED (base_binfo) == 0)
        !           641:        {
        !           642:          SET_BINFO_MARKED (base_binfo);
        !           643: 
        !           644:          nrval = get_binfo2_recursive (base_binfo, parent, type);
        !           645: 
        !           646:          if (nrval == error_mark_node)
        !           647:            return nrval;
        !           648:          if (nrval)
        !           649:            if (rval == 0)
        !           650:              {
        !           651:                rval = nrval;
        !           652:              }
        !           653:            else
        !           654:              return error_mark_node;
        !           655:        }
        !           656:     }
        !           657:   return rval;
        !           658: }
        !           659: 
        !           660: tree
        !           661: get_binfo2 (parent, binfo)
        !           662:      register tree parent, binfo;
        !           663: {
        !           664:   tree type;
        !           665:   tree rval = NULL_TREE;
        !           666: 
        !           667:   if (TREE_CODE (parent) == TREE_VEC)
        !           668:     parent = BINFO_TYPE (parent);
        !           669:   /* unions cannot participate in inheritance relationships */
        !           670:   else if (TREE_CODE (parent) == UNION_TYPE)
        !           671:     return 0;
        !           672:   else if (TREE_CODE (parent) != RECORD_TYPE)
        !           673:     my_friendly_abort (89);
        !           674: 
        !           675:   parent = TYPE_MAIN_VARIANT (parent);
        !           676: 
        !           677:   if (TREE_CODE (binfo) == TREE_VEC)
        !           678:     type = BINFO_TYPE (binfo);
        !           679:   else if (TREE_CODE (binfo) == RECORD_TYPE)
        !           680:     {
        !           681:       type = binfo;
        !           682:       binfo = TYPE_BINFO (type);
        !           683:     }
        !           684:   else my_friendly_abort (90);
        !           685: 
        !           686:   rval = get_binfo2_recursive (binfo, parent, type);
        !           687: 
        !           688:   dfs_walk (binfo, dfs_unmark, markedp);
        !           689: 
        !           690:   return rval;
        !           691: }
        !           692: 
        !           693: /* -------------------------------------------------- */
        !           694: 
        !           695: /* Return the number of levels between type PARENT and the type given
        !           696:    in BINFO, following the leftmost path to PARENT.  If PARENT is its
        !           697:    own main type variant, then if PARENT appears in different places
        !           698:    from TYPE's point of view, the leftmost PARENT will be the one
        !           699:    chosen.
        !           700: 
        !           701:    The term `leftmost' should be defined in g++int.texi and the
        !           702:    significance should be explained.  If it is, this message should be
        !           703:    deleted, if not, and you understand the term, please add
        !           704:    documentation for it in g++int.texi.  Also, the part about the
        !           705:    ``PARENT is its own main type variant'' should give reasons when
        !           706:    and why this happens, and why it is important, and a better
        !           707:    explaination of what this routine does both when that is true and
        !           708:    when it is not.
1.1       root      709: 
                    710:    Return -1 if TYPE is not derived from PARENT.
                    711:    Return -2 if PARENT is an ambiguous base class of TYPE.
                    712:    Return -3 if PARENT is private to TYPE, and protect is non-zero.
                    713: 
                    714:    If PATH_PTR is non-NULL, then also build the list of types
                    715:    from PARENT to TYPE, with TREE_VIA_VIRUAL and TREE_VIA_PUBLIC
1.1.1.4 ! root      716:    set.
        !           717: 
        !           718:    It is unclear whether or not the path should be built if -2 and/or
        !           719:    -3 is returned.  Maybe, maybe not.  I suspect that there is code
        !           720:    that relies upon it being built, such as prepare_fresh_vtable.
        !           721:    (mrs)
        !           722: 
        !           723:    Also, it would appear that we only sometimes want -2.  The question is
        !           724:    under what exact conditions do we want to see -2, and when do we not
        !           725:    want to see -2.  (mrs)
        !           726: 
        !           727:    It is also unlikely that this thing finds all ambiguties, as I
        !           728:    don't trust any deviation from the method used in get_binfo.  It
        !           729:    would be nice to use that method here, as it is simple and straight
        !           730:    forward.  The code here and in recursive_bounded_basetype_p is not.
        !           731:    For now, I shall include an extra call to find ambiguities.  (mrs)
        !           732:    */
        !           733: 
1.1       root      734: int
                    735: get_base_distance (parent, binfo, protect, path_ptr)
                    736:      register tree parent, binfo;
                    737:      int protect;
                    738:      tree *path_ptr;
                    739: {
                    740:   int head, tail;
                    741:   int is_private = 0;
1.1.1.4 ! root      742:   int rval = -1;
1.1       root      743:   int depth = 0;
                    744:   int rval_private = 0;
                    745:   tree type, basetype_path;
                    746:   tree friends;
                    747:   int use_leftmost;
                    748: 
                    749:   if (TYPE_READONLY (parent) || TYPE_VOLATILE (parent))
                    750:     parent = TYPE_MAIN_VARIANT (parent);
                    751:   use_leftmost = (parent == TYPE_MAIN_VARIANT (parent));
                    752: 
                    753:   if (TREE_CODE (binfo) == TREE_VEC)
                    754:     type = BINFO_TYPE (binfo);
                    755:   else if (TREE_CODE (binfo) == RECORD_TYPE)
                    756:     {
                    757:       type = binfo;
                    758:       binfo = TYPE_BINFO (type);
                    759:     }
1.1.1.3   root      760:   else my_friendly_abort (92);
1.1       root      761: 
                    762:   friends = current_class_type ? CLASSTYPE_FRIEND_CLASSES (type) : NULL_TREE;
                    763: 
                    764:   if (path_ptr)
                    765:     {
                    766:       basetype_path = TYPE_BINFO (type);
                    767:       BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
                    768:     }
                    769: 
                    770:   if (TYPE_MAIN_VARIANT (parent) == type)
                    771:     {
                    772:       /* If the distance is 0, then we don't really need
                    773:         a path pointer, but we shouldn't let garbage go back.  */
                    774:       if (path_ptr)
                    775:        *path_ptr = basetype_path;
                    776:       return 0;
                    777:     }
                    778: 
                    779:   search_stack = push_search_level (search_stack, &search_obstack);
                    780: 
                    781:   /* Keep space for TYPE.  */
                    782:   obstack_ptr_grow (&search_obstack, binfo);
                    783:   obstack_int_grow (&search_obstack, 0);
                    784:   obstack_int_grow (&search_obstack, 0);
                    785:   if (path_ptr)
                    786:     {
                    787:       obstack_ptr_grow (&search_obstack, 0);
                    788:       head = 4;
                    789:     }
                    790:   else head = 3;
                    791:   tail = head;
                    792: 
                    793:   while (1)
                    794:     {
                    795:       tree binfos = BINFO_BASETYPES (binfo);
                    796:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                    797: 
                    798:       /* Process and/or queue base types.  */
                    799:       for (i = 0; i < n_baselinks; i++)
                    800:        {
1.1.1.4 ! root      801:          tree base_binfo = TREE_VEC_ELT (binfos, i);
1.1       root      802: 
1.1.1.4 ! root      803:          if (BINFO_MARKED (base_binfo) == 0)
1.1       root      804:            {
1.1.1.4 ! root      805:              int via_private = is_private || !TREE_VIA_PUBLIC (base_binfo);
        !           806: 
        !           807:              SET_BINFO_MARKED (base_binfo);
1.1       root      808: 
                    809:              if (via_private == 0)
                    810:                ;
                    811:              else if (protect == 0)
                    812:                via_private = 0;
                    813: 
1.1.1.4 ! root      814:              obstack_ptr_grow (&search_obstack, base_binfo);
1.1       root      815:              obstack_int_grow (&search_obstack, depth);
                    816:              obstack_int_grow (&search_obstack, via_private);
1.1.1.4 ! root      817:              tail += 3;
1.1       root      818:              if (path_ptr)
                    819:                {
                    820:                  obstack_ptr_grow (&search_obstack, basetype_path);
                    821:                  tail += 1;
                    822:                }
                    823:              if (tail >= search_stack->limit)
1.1.1.3   root      824:                my_friendly_abort (93);
1.1       root      825:            }
1.1.1.4 ! root      826: #if 0
        !           827:          /* This code cannot possibly be right.  Ambiguities can only be
        !           828:             checked by traversing the whole tree, and seeing if it pops
        !           829:             up twice. */
        !           830:          else if (! TREE_VIA_VIRTUAL (base_binfo))
1.1       root      831:            {
                    832:              rval = -2;
                    833:              goto done;
                    834:            }
1.1.1.4 ! root      835: #endif
1.1       root      836:        }
                    837: 
                    838:       /* Process head of queue, if one exists.  */
                    839:       if (head >= tail)
1.1.1.4 ! root      840:        break;
1.1       root      841: 
                    842:       binfo = search_stack->first[head++];
1.1.1.4 ! root      843:       depth = (HOST_WIDE_INT)search_stack->first[head++] + 1;
        !           844:       is_private = (HOST_WIDE_INT)search_stack->first[head++];
1.1       root      845:       if (path_ptr)
                    846:        {
                    847:          basetype_path = search_stack->first[head++];
                    848:          BINFO_INHERITANCE_CHAIN (binfo) = basetype_path;
                    849:          basetype_path = binfo;
                    850:        }
                    851:       if (BINFO_TYPE (binfo) == parent)
                    852:        {
1.1.1.4 ! root      853:          /* It is wrong to set this and break, the proper thing to do
        !           854:             would be to set it only if it has not been set before,
        !           855:             and if is has been set, an ambiguity exists, and just
        !           856:             continue searching the tree for more of them as is done
        !           857:             in get_binfo.  But until the code below can cope, this
        !           858:             can't be done. Also, it is not clear what should happen if
        !           859:             use_leftmost is set.  */
1.1       root      860:          rval = depth;
                    861:          rval_private = is_private;
                    862:          break;
                    863:        }
                    864:     }
1.1.1.4 ! root      865: #if 0
        !           866:   /* Unneeded now, as we know the above code in the #if 0 is wrong.  */
1.1       root      867:  done:
1.1.1.4 ! root      868: #endif
1.1       root      869:   {
                    870:     int increment = path_ptr ? 4 : 3;
                    871:     tree *tp = search_stack->first;
                    872:     tree *search_tail = tp + tail;
                    873: 
                    874:     /* We can skip the first entry, since it wasn't marked.  */
                    875:     tp += increment;
                    876: 
                    877:     basetype_path = binfo;
                    878:     while (tp < search_tail)
                    879:       {
                    880:        CLEAR_BINFO_MARKED (*tp);
                    881:        tp += increment;
                    882:       }
                    883: 
                    884:     /* Now, guarantee that we are following the leftmost path in the
                    885:        chain.  Algorithm: the search stack holds tuples in BFS order.
                    886:        The last tuple on the search stack contains the tentative binfo
                    887:        for the basetype we are looking for.  We know that starting
                    888:        with FIRST, each tuple with only a single basetype must be on
                    889:        the leftmost path.  Each time we come to a split, we select
                    890:        the tuple for the leftmost basetype that can reach the ultimate
                    891:        basetype.  */
                    892: 
                    893:     if (use_leftmost
                    894:        && rval > 0
                    895:        && (! BINFO_OFFSET_ZEROP (binfo) || TREE_VIA_VIRTUAL (binfo)))
                    896:       {
                    897:        tree tp_binfos;
                    898: 
                    899:        /* Farm out the tuples with a single basetype.  */
                    900:        for (tp = search_stack->first; tp < search_tail; tp += increment)
                    901:          {
                    902:            tp_binfos = BINFO_BASETYPES (*tp);
                    903:            if (tp_binfos && TREE_VEC_LENGTH (tp_binfos) > 1)
                    904:              break;
                    905:          }
                    906: 
                    907:        if (tp < search_tail)
                    908:          {
                    909:            /* Pick the best path.  */
1.1.1.4 ! root      910:            tree base_binfo;
1.1       root      911:            int i;
                    912:            for (i = 0; i < TREE_VEC_LENGTH (tp_binfos); i++)
                    913:              {
1.1.1.4 ! root      914:                base_binfo = TREE_VEC_ELT (tp_binfos, i);
1.1       root      915:                if (tp+((i+1)*increment) < search_tail)
1.1.1.4 ! root      916:                  my_friendly_assert (base_binfo == tp[(i+1)*increment], 295);
        !           917:                if (rval = recursive_bounded_basetype_p (binfo, base_binfo, rval, 1))
1.1       root      918:                  break;
                    919:              }
                    920:            if (rval > 0)
1.1.1.4 ! root      921:              BINFO_INHERITANCE_CHAIN (base_binfo) = *tp;
1.1       root      922:          }
1.1.1.4 ! root      923: 
        !           924:        /* Because I don't trust recursive_bounded_basetype_p to find
        !           925:           all ambiguities, I will just make sure here.  When it is
        !           926:           sure that all ambiguities are found, the two routines and
        !           927:           this call can be removed.  Not toally sure this should be
        !           928:           here, but I think it should. (mrs) */
        !           929: 
        !           930:        if (get_binfo2 (parent, type) == error_mark_node && rval != -2)
        !           931:          {
        !           932: #if 1
        !           933:            /* This warning is here because the code over in
        !           934:               prepare_fresh_vtable relies on partial completion
        !           935:               offered by recursive_bounded_basetype_p I think, but
        !           936:               that behavior is not documented.  It needs to be.  I
        !           937:               don't think prepare_fresh_vtable is the only routine
        !           938:               that relies upon path_ptr being set to something in a
        !           939:               particular way when this routine returns -2.  (mrs) */
        !           940:            warning ("internal consistency check failed, please report, recovering.");
        !           941:            rval = -2;
        !           942: #endif
        !           943:          }
        !           944: 
1.1       root      945:        /* Visibilities don't count if we found an ambiguous basetype.  */
                    946:        if (rval == -2)
                    947:          rval_private = 0;
                    948:       }
                    949:   }
                    950:   search_stack = pop_search_level (search_stack);
                    951: 
                    952:   if (rval && protect && rval_private)
                    953:     return -3;
                    954: 
                    955:   if (path_ptr)
                    956:     *path_ptr = binfo;
                    957:   return rval;
                    958: }
                    959: 
                    960: /* Search for a member with name NAME in a multiple inheritance lattice
                    961:    specified by TYPE.  If it does not exist, return NULL_TREE.
                    962:    If the member is ambiguously referenced, return `error_mark_node'.
                    963:    Otherwise, return the FIELD_DECL.  */
                    964: 
                    965: /* Do a 1-level search for NAME as a member of TYPE.  The caller
                    966:    must figure out whether it has a visible path to this field.
                    967:    (Since it is only one level, this is reasonable.)  */
                    968: static tree
                    969: lookup_field_1 (type, name)
                    970:      tree type, name;
                    971: {
                    972:   register tree field = TYPE_FIELDS (type);
                    973: 
                    974: #ifdef GATHER_STATISTICS
                    975:   n_calls_lookup_field_1++;
                    976: #endif
                    977:   while (field)
                    978:     {
                    979: #ifdef GATHER_STATISTICS
                    980:       n_fields_searched++;
                    981: #endif
                    982:       if (DECL_NAME (field) == NULL_TREE
                    983:          && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
                    984:        {
                    985:          tree temp = lookup_field_1 (TREE_TYPE (field), name);
                    986:          if (temp)
                    987:            return temp;
                    988:        }
                    989:       if (DECL_NAME (field) == name)
                    990:        {
                    991:          if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL)
                    992:              && DECL_ASSEMBLER_NAME (field) != NULL)
                    993:            GNU_xref_ref(current_function_decl,
                    994:                         IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (field)));
                    995:          return field;
                    996:        }
                    997:       field = TREE_CHAIN (field);
                    998:     }
                    999:   /* Not found.  */
                   1000:   if (name == _vptr_name)
                   1001:     {
                   1002:       /* Give the user what s/he thinks s/he wants.  */
                   1003:       if (TYPE_VIRTUAL_P (type))
                   1004:        return CLASSTYPE_VFIELD (type);
                   1005:     }
                   1006:   return NULL_TREE;
                   1007: }
                   1008: 
                   1009: /* Compute the visibility of FIELD.  This is done by computing
                   1010:    the visibility available to each type in BASETYPES (which comes
                   1011:    as a list of [via_public/basetype] in reverse order, namely base
                   1012:    class before derived class).  The first one which defines a
                   1013:    visibility defines the visibility for the field.  Otherwise, the
                   1014:    visibility of the field is that which occurs normally.
                   1015: 
                   1016:    Uses global variables CURRENT_CLASS_TYPE and
                   1017:    CURRENT_FUNCTION_DECL to use friend relationships
                   1018:    if necessary.
                   1019: 
                   1020:    This will be static when lookup_fnfield comes into this file.  */
                   1021: 
                   1022: #define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), visibility_public
                   1023: #define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), visibility_protected
                   1024: #define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), visibility_private
                   1025: 
                   1026: enum visibility_type
                   1027: compute_visibility (basetype_path, field)
                   1028:      tree basetype_path, field;
                   1029: {
                   1030:   enum visibility_type visibility = visibility_public;
                   1031:   tree types;
                   1032:   tree context = DECL_CLASS_CONTEXT (field);
                   1033: 
                   1034:   /* Virtual function tables are never private.
                   1035:      But we should know that we are looking for this,
                   1036:      and not even try to hide it.  */
                   1037:   if (DECL_NAME (field) && VFIELD_NAME_P (DECL_NAME (field)) == 1)
                   1038:     return visibility_public;
                   1039: 
                   1040:   /* Make these special cases fast.  */
                   1041:   if (BINFO_TYPE (basetype_path) == current_class_type)
                   1042:     {
                   1043:       if (DECL_PUBLIC (field))
                   1044:        return visibility_public;
                   1045:       if (DECL_PROTECTED (field))
                   1046:        return visibility_protected;
                   1047:       if (DECL_PRIVATE (field))
                   1048:        return visibility_private;
                   1049:     }
                   1050: 
                   1051:   /* Member function manipulating its own members.  */
                   1052:   if (current_class_type == context)
                   1053:     PUBLIC_RETURN;
                   1054: 
                   1055:   /* Member found immediately within object.  */
                   1056:   if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE)
                   1057:     {
                   1058:       /* At object's top level, public members are public.  */
                   1059:       if (TREE_PROTECTED (field) == 0 && TREE_PRIVATE (field) == 0)
                   1060:        PUBLIC_RETURN;
                   1061: 
                   1062:       /* Friend function manipulating members it gets (for being a friend).  */
                   1063:       if (is_friend (context, current_function_decl))
                   1064:        PUBLIC_RETURN;
                   1065: 
                   1066:       /* Inner than that, without special visibility,
                   1067: 
                   1068:           protected members are ok if type of object is current_class_type
                   1069:           is derived therefrom.  This means that if the type of the object
                   1070:           is a base type for our current class type, we cannot access
                   1071:           protected members.
                   1072: 
                   1073:           private members are not ok.  */
                   1074:       if (current_class_type && DECL_VISIBILITY (field) == NULL_TREE)
                   1075:        {
                   1076:          if (TREE_PRIVATE (field))
                   1077:            PRIVATE_RETURN;
                   1078: 
                   1079:          if (TREE_PROTECTED (field))
                   1080:            {
                   1081:              if (context == current_class_type
1.1.1.4 ! root     1082:                  || UNIQUELY_DERIVED_FROM_P (context, current_class_type))
1.1       root     1083:                PUBLIC_RETURN;
                   1084:              else
                   1085:                PROTECTED_RETURN;
                   1086:            }
1.1.1.3   root     1087:          else my_friendly_abort (94);
1.1       root     1088:        }
                   1089:     }
                   1090:   /* Friend function manipulating members it gets (for being a friend).  */
                   1091:   if (is_friend (context, current_function_decl))
                   1092:     PUBLIC_RETURN;
                   1093: 
                   1094:   /* must reverse more than one element */
                   1095:   basetype_path = reverse_path (basetype_path);
                   1096:   types = basetype_path;
                   1097: 
                   1098:   while (types)
                   1099:     {
                   1100:       tree member;
                   1101:       tree binfo = types;
                   1102:       tree type = BINFO_TYPE (binfo);
                   1103: 
                   1104:       member = purpose_member (type, DECL_VISIBILITY (field));
                   1105:       if (member)
                   1106:        {
                   1107:          visibility = (enum visibility_type)TREE_VALUE (member);
                   1108:          if (visibility == visibility_public
                   1109:              || is_friend (type, current_function_decl)
                   1110:              || (visibility == visibility_protected
                   1111:                  && current_class_type
1.1.1.4 ! root     1112:                  && UNIQUELY_DERIVED_FROM_P (context, current_class_type)))
1.1       root     1113:            visibility = visibility_public;
                   1114:          goto ret;
                   1115:        }
                   1116: 
                   1117:       /* Friends inherit the visibility of the class they inherit from.  */
                   1118:       if (is_friend (type, current_function_decl))
                   1119:        {
                   1120:          if (type == context)
                   1121:            {
                   1122:              visibility = visibility_public;
                   1123:              goto ret;
                   1124:            }
                   1125:          if (TREE_PROTECTED (field))
                   1126:            {
                   1127:              visibility = visibility_public;
                   1128:              goto ret;
                   1129:            }
                   1130: #if 0
                   1131:          /* This short-cut is too short.  */
                   1132:          if (visibility == visibility_public)
                   1133:            goto ret;
                   1134: #endif
                   1135:          /* else, may be a friend of a deeper base class */
                   1136:        }
                   1137: 
                   1138:       if (type == context)
                   1139:        break;
                   1140: 
                   1141:       types = BINFO_INHERITANCE_CHAIN (types);
                   1142:       /* If the next type was not VIA_PUBLIC, then fields of all
                   1143:         remaining class past that one are private.  */
1.1.1.4 ! root     1144:       if (types)
        !          1145:        {
        !          1146:          if (TREE_VIA_PROTECTED (types))
        !          1147:            visibility = visibility_protected;
        !          1148:          else if (! TREE_VIA_PUBLIC (types))
        !          1149:            visibility = visibility_private;
        !          1150:        }
1.1       root     1151:     }
                   1152: 
                   1153:   /* No special visibilities apply.  Use normal rules.
                   1154:      No assignment needed for BASETYPEs here from the nreverse.
                   1155:      This is because we use it only for information about the
                   1156:      path to the base.  The code earlier dealt with what
                   1157:      happens when we are at the base level.  */
                   1158: 
                   1159:   if (visibility == visibility_public)
                   1160:     {
                   1161:       basetype_path = reverse_path (basetype_path);
                   1162:       if (TREE_PRIVATE (field))
                   1163:        PRIVATE_RETURN;
                   1164:       if (TREE_PROTECTED (field))
                   1165:        {
                   1166:          /* Used to check if the current class type was derived from
                   1167:             the type that contains the field.  This is wrong for
                   1168:             multiple inheritance because is gives one class reference
                   1169:             to protected members via another classes protected path.
                   1170:             I.e., if A; B1 : A; B2 : A;  Then B1 and B2 can access
                   1171:             their own members which are protected in A, but not
                   1172:             those same members in one another.  */
                   1173:          if (current_class_type
1.1.1.4 ! root     1174:              && UNIQUELY_DERIVED_FROM_P (context, current_class_type))
1.1       root     1175:            PUBLIC_RETURN;
                   1176:          PROTECTED_RETURN;
                   1177:        }
                   1178:       PUBLIC_RETURN;
                   1179:     }
                   1180: 
1.1.1.4 ! root     1181:   if (visibility == visibility_protected)
        !          1182:     {
        !          1183:       /* reverse_path? */
        !          1184:       if (TREE_PRIVATE (field))
        !          1185:        PRIVATE_RETURN;
        !          1186:       /* We want to make sure that all non-private members in
        !          1187:         the current class (as derived) are accessible.  */
        !          1188:       if (current_class_type
        !          1189:          && UNIQUELY_DERIVED_FROM_P (context, current_class_type))
        !          1190:        PUBLIC_RETURN;
        !          1191:       PROTECTED_RETURN;
        !          1192:     }
        !          1193: 
1.1       root     1194:   if (visibility == visibility_private
                   1195:       && current_class_type != NULL_TREE)
                   1196:     {
                   1197:       if (TREE_PRIVATE (field))
                   1198:        {
                   1199:          reverse_path (basetype_path);
                   1200:          PRIVATE_RETURN;
                   1201:        }
                   1202: 
                   1203:       /* See if the field isn't protected.  */
                   1204:       if (TREE_PROTECTED (field))
                   1205:        {
                   1206:          tree test = basetype_path;
                   1207:          while (test)
                   1208:            {
                   1209:              if (BINFO_TYPE (test) == current_class_type)
                   1210:                break;
                   1211:              test = BINFO_INHERITANCE_CHAIN (test);
                   1212:            }
                   1213:          reverse_path (basetype_path);
                   1214:          if (test)
                   1215:            PUBLIC_RETURN;
                   1216:          PROTECTED_RETURN;
                   1217:        }
                   1218: 
                   1219:       /* See if the field isn't a public member of
                   1220:         a private base class.  */
                   1221: 
                   1222:       visibility = visibility_public;
                   1223:       types = BINFO_INHERITANCE_CHAIN (basetype_path);
                   1224:       while (types)
                   1225:        {
                   1226:          if (! TREE_VIA_PUBLIC (types))
                   1227:            {
                   1228:              if (visibility == visibility_private)
                   1229:                {
                   1230:                  visibility = visibility_private;
                   1231:                  goto ret;
                   1232:                }
                   1233:              visibility = visibility_private;
                   1234:            }
                   1235:          if (BINFO_TYPE (types) == context)
                   1236:            {
                   1237:              visibility = visibility_public;
                   1238:              goto ret;
                   1239:            }
                   1240:          types = BINFO_INHERITANCE_CHAIN (types);
                   1241:        }
1.1.1.3   root     1242:       my_friendly_abort (95);
1.1       root     1243:     }
                   1244: 
                   1245:  ret:
                   1246:   reverse_path (basetype_path);
                   1247: 
                   1248:   if (visibility == visibility_public)
                   1249:     DECL_PUBLIC (field) = 1;
                   1250:   else if (visibility == visibility_protected)
                   1251:     DECL_PROTECTED (field) = 1;
                   1252:   else if (visibility == visibility_private)
                   1253:     DECL_PRIVATE (field) = 1;
1.1.1.3   root     1254:   else my_friendly_abort (96);
1.1       root     1255:   return visibility;
                   1256: }
                   1257: 
                   1258: /* Look for a field named NAME in an inheritance lattice dominated by
                   1259:    XBASETYPE.  PROTECT is zero if we can avoid computing visibility
1.1.1.4 ! root     1260:    information, otherwise it is 1.  WANT_TYPE is 1 when we should only
        !          1261:    return TYPE_DECLs, if no TYPE_DECL can be found return NULL.  */
1.1       root     1262: tree
1.1.1.4 ! root     1263: lookup_field (xbasetype, name, protect, want_type)
1.1       root     1264:      register tree xbasetype, name;
1.1.1.4 ! root     1265:      int protect, want_type;
1.1       root     1266: {
                   1267:   int head = 0, tail = 0;
                   1268:   tree rval;
                   1269:   tree type, basetype_chain, basetype_path;
                   1270:   enum visibility_type this_v = visibility_default;
                   1271:   tree entry, binfo;
                   1272:   enum visibility_type own_visibility = visibility_default;
                   1273:   int vbase_name_p = VBASE_NAME_P (name);
                   1274: 
                   1275:   /* Things for memoization.  */
                   1276:   char *errstr = 0;
                   1277: 
                   1278:   /* Set this to nonzero if we don't know how to compute
                   1279:      accurate error messages for visibility.  */
                   1280:   int index = MEMOIZED_HASH_FN (name);
                   1281: 
                   1282:   if (TREE_CODE (xbasetype) == TREE_VEC)
                   1283:     basetype_path = xbasetype, type = BINFO_TYPE (xbasetype);
                   1284:   else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
                   1285:     basetype_path = TYPE_BINFO (xbasetype), type = xbasetype;
1.1.1.3   root     1286:   else my_friendly_abort (97);
1.1       root     1287: 
                   1288:   if (CLASSTYPE_MTABLE_ENTRY (type))
                   1289:     {
                   1290:       tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
                   1291: 
                   1292:       while (tem && TREE_PURPOSE (tem) != name)
                   1293:        {
                   1294:          memoized_fields_searched[0]++;
                   1295:          tem = TREE_CHAIN (tem);
                   1296:        }
                   1297:       if (tem)
                   1298:        {
                   1299:          if (protect && TREE_TYPE (tem))
                   1300:            {
                   1301:              error (TREE_STRING_POINTER (TREE_TYPE (tem)),
                   1302:                     IDENTIFIER_POINTER (name),
                   1303:                     TYPE_NAME_STRING (DECL_FIELD_CONTEXT (TREE_VALUE (tem))));
                   1304:              return error_mark_node;
                   1305:            }
                   1306:          if (TREE_VALUE (tem) == NULL_TREE)
                   1307:            memoized_fast_rejects[0] += 1;
                   1308:          else
                   1309:            memoized_fast_finds[0] += 1;
                   1310:          return TREE_VALUE (tem);
                   1311:        }
                   1312:     }
                   1313: 
                   1314: #ifdef GATHER_STATISTICS
                   1315:   n_calls_lookup_field++;
                   1316: #endif
                   1317:   if (protect && flag_memoize_lookups && ! global_bindings_p ())
                   1318:     entry = make_memoized_table_entry (type, name, 0);
                   1319:   else
                   1320:     entry = 0;
                   1321: 
                   1322:   rval = lookup_field_1 (type, name);
                   1323: 
1.1.1.4 ! root     1324:   if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
        !          1325:     rval = NULL_TREE;
        !          1326: 
1.1       root     1327:   if (rval)
                   1328:     {
                   1329:       if (protect)
                   1330:        {
                   1331:          if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
                   1332:            this_v = compute_visibility (basetype_path, rval);
                   1333:          if (TREE_CODE (rval) == CONST_DECL)
                   1334:            {
                   1335:              if (this_v == visibility_private)
                   1336:                errstr = "enum `%s' is a private value of class `%s'";
                   1337:              else if (this_v == visibility_protected)
                   1338:                errstr = "enum `%s' is a protected value of class `%s'";
                   1339:            }
                   1340:          else
                   1341:            {
                   1342:              if (this_v == visibility_private)
                   1343:                errstr = "member `%s' is a private member of class `%s'";
                   1344:              else if (this_v == visibility_protected)
                   1345:                errstr = "member `%s' is a protected member of class `%s'";
                   1346:            }
                   1347:        }
                   1348: 
                   1349:       if (entry)
                   1350:        {
                   1351:          if (errstr)
                   1352:            {
                   1353:              /* This depends on behavior of lookup_field_1!  */
                   1354:              tree error_string = my_build_string (errstr);
                   1355:              TREE_TYPE (entry) = error_string;
                   1356:            }
                   1357:          else
                   1358:            {
                   1359:              /* Let entry know there is no problem with this access.  */
                   1360:              TREE_TYPE (entry) = NULL_TREE;
                   1361:            }
                   1362:          TREE_VALUE (entry) = rval;
                   1363:        }
                   1364: 
                   1365:       if (errstr && protect)
                   1366:        {
                   1367:          error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
                   1368:          return error_mark_node;
                   1369:        }
                   1370:       return rval;
                   1371:     }
                   1372: 
                   1373:   basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
                   1374:   TREE_VIA_PUBLIC (basetype_chain) = 1;
                   1375: 
                   1376:   search_stack = push_search_level (search_stack, &search_obstack);
                   1377:   BINFO_VIA_PUBLIC (basetype_path) = 1;
                   1378:   BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
                   1379:   binfo = basetype_path;
                   1380: 
                   1381:   while (1)
                   1382:     {
                   1383:       tree binfos = BINFO_BASETYPES (binfo);
                   1384:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                   1385: 
                   1386:       /* Process and/or queue base types.  */
                   1387:       for (i = 0; i < n_baselinks; i++)
                   1388:        {
1.1.1.4 ! root     1389:          tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          1390:          if (BINFO_FIELDS_MARKED (base_binfo) == 0)
1.1       root     1391:            {
                   1392:              tree btypes;
                   1393: 
1.1.1.4 ! root     1394:              SET_BINFO_FIELDS_MARKED (base_binfo);
        !          1395:              btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
        !          1396:              TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
        !          1397:              TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
        !          1398:              TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
1.1       root     1399:              obstack_ptr_grow (&search_obstack, btypes);
                   1400:              tail += 1;
                   1401:              if (tail >= search_stack->limit)
1.1.1.3   root     1402:                my_friendly_abort (98);
1.1       root     1403:            }
                   1404:        }
                   1405: 
                   1406:       /* Process head of queue, if one exists.  */
                   1407:       if (head >= tail)
                   1408:        break;
                   1409: 
                   1410:       basetype_chain = search_stack->first[head++];
                   1411:       basetype_path = TREE_VALUE (basetype_chain);
                   1412:       if (TREE_CHAIN (basetype_chain))
                   1413:        BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
                   1414:       else
                   1415:        BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
                   1416: 
                   1417:       binfo = basetype_path;
                   1418:       type = BINFO_TYPE (binfo);
                   1419: 
                   1420:       /* See if we can find NAME in TYPE.  If RVAL is nonzero,
                   1421:         and we do find NAME in TYPE, verify that such a second
                   1422:         sighting is in fact legal.  */
                   1423: 
                   1424:       if (rval)
                   1425:        {
                   1426:          tree context = DECL_FIELD_CONTEXT (rval);
                   1427:          /* Just another way of finding the same member.  */
                   1428:          if (TYPE_BINFO (context) == binfo)
                   1429:            {
                   1430:              enum visibility_type new_v
                   1431:                = compute_visibility (basetype_path, rval);
                   1432:              if (this_v != new_v)
                   1433:                errstr = "conflicting visibilities to member `%s'";
                   1434:            }
                   1435:          /* Same baseclass, maybe different places in the lattice.  */
                   1436:          else if (context == type)
                   1437:            {
                   1438:              errstr = "member `%s' belongs to distinct base classes `%s'";
                   1439:              protect = 2;
                   1440:            }
                   1441:          else
                   1442:            {
                   1443:              tree nval = lookup_field_1 (type, name);
                   1444: 
1.1.1.4 ! root     1445:              if (nval && TREE_CODE (nval) != TYPE_DECL && want_type)
        !          1446:                nval = NULL_TREE;
        !          1447: 
        !          1448: 
1.1       root     1449:              if (nval
                   1450:                  && binfo != get_binfo (type, DECL_FIELD_CONTEXT (rval), 0))
                   1451:                {
                   1452:                  /* We found it in other than a baseclass of RVAL's.  */
                   1453:                  errstr = "request for member `%s' is ambiguous";
                   1454:                  protect = 2;
                   1455:                }
                   1456:            }
                   1457:          if (errstr && entry)
                   1458:            {
                   1459:              tree error_string = my_build_string (errstr);
                   1460:              TREE_TYPE (entry) = error_string;
                   1461:            }
                   1462:          if (errstr && protect)
                   1463:            break;
                   1464:        }
                   1465:       else
                   1466:        {
                   1467:          rval = lookup_field_1 (type, name);
1.1.1.4 ! root     1468: 
        !          1469:          if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
        !          1470:            rval = NULL_TREE;
        !          1471: 
1.1       root     1472:          if (rval)
                   1473:            {
                   1474:              if (entry || protect)
                   1475:                this_v = compute_visibility (basetype_path, rval);
                   1476:              if (entry)
                   1477:                TREE_VALUE (entry) = rval;
                   1478: 
                   1479:              /* These may look ambiguous, but they really are not.  */
                   1480:              if (vbase_name_p)
                   1481:                break;
                   1482:            }
                   1483:        }
                   1484:     }
                   1485:   {
                   1486:     tree *tp = search_stack->first;
                   1487:     tree *search_tail = tp + tail;
                   1488: 
                   1489:     /* If this FIELD_DECL defines its own visibility, deal with that.  */
                   1490:     if (rval && errstr == 0
                   1491:        && ((protect&1) || entry)
                   1492:        && DECL_LANG_SPECIFIC (rval)
                   1493:        && DECL_VISIBILITY (rval))
                   1494:       {
                   1495:        while (tp < search_tail)
                   1496:          {
                   1497:            /* If is possible for one of the derived types on the
                   1498:               path to have defined special visibility for this
                   1499:               field.  Look for such declarations and report an
                   1500:               error if a conflict is found.  */
                   1501:            enum visibility_type new_v;
                   1502: 
                   1503:            if (this_v != visibility_default)
                   1504:              new_v = compute_visibility (TREE_VALUE (*tp), rval);
                   1505:            if (this_v != visibility_default && new_v != this_v)
                   1506:              {
                   1507:                errstr = "conflicting visibilities to member `%s'";
                   1508:                this_v = visibility_default;
                   1509:              }
                   1510:            own_visibility = new_v;
                   1511:            CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (*tp));
                   1512:            tp += 1;
                   1513:          }
                   1514:       }
                   1515:     else
                   1516:       {
                   1517:        while (tp < search_tail)
                   1518:          {
                   1519:            CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (*tp));
                   1520:            tp += 1;
                   1521:          }
                   1522:       }
                   1523:   }
                   1524:   search_stack = pop_search_level (search_stack);
                   1525: 
                   1526:   if (errstr == 0)
                   1527:     {
                   1528:       if (own_visibility == visibility_private)
                   1529:        errstr = "member `%s' declared private";
                   1530:       else if (own_visibility == visibility_protected)
                   1531:        errstr = "member `%s' declared protected";
                   1532:       else if (this_v == visibility_private)
1.1.1.4 ! root     1533:        errstr = TREE_PRIVATE (rval)
        !          1534:          ? "member `%s' is private"
        !          1535:            : "member `%s' is from private base class";
1.1       root     1536:       else if (this_v == visibility_protected)
1.1.1.4 ! root     1537:        errstr = TREE_PROTECTED (rval)
        !          1538:          ? "member `%s' is protected"
        !          1539:            : "member `%s' is from protected base class";
1.1       root     1540:     }
                   1541: 
                   1542:   if (entry)
                   1543:     {
                   1544:       if (errstr)
                   1545:        {
                   1546:          tree error_string = my_build_string (errstr);
                   1547:          /* Save error message with entry.  */
                   1548:          TREE_TYPE (entry) = error_string;
                   1549:        }
                   1550:       else
                   1551:        {
                   1552:          /* Mark entry as having no error string.  */
                   1553:          TREE_TYPE (entry) = NULL_TREE;
                   1554:        }
                   1555:     }
                   1556: 
                   1557:   if (errstr && protect)
                   1558:     {
                   1559:       error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
                   1560:       rval = error_mark_node;
                   1561:     }
                   1562:   return rval;
                   1563: }
                   1564: 
1.1.1.4 ! root     1565: /* Try to find NAME inside a nested class.  */
        !          1566: tree
        !          1567: lookup_nested_field (name)
        !          1568:      tree name;
        !          1569: {
        !          1570:   register tree t;
        !          1571: 
        !          1572:   tree id = NULL_TREE;
        !          1573:   if (TREE_CHAIN (current_class_type))
        !          1574:     {
        !          1575:       /* Climb our way up the nested ladder, seeing if we're trying to
        !          1576:         modify a field in an enclosing class.  If so, we should only
        !          1577:         be able to modify if it's static.  */
        !          1578:       for (t = TREE_CHAIN (current_class_type);
        !          1579:           t && DECL_CONTEXT (t);
        !          1580:           t = TREE_CHAIN (DECL_CONTEXT (t)))
        !          1581:        {
        !          1582:          if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE)
        !          1583:            break;
        !          1584: 
        !          1585:          /* N.B.: lookup_field will do the visibility checking for us */
        !          1586:          id = lookup_field (DECL_CONTEXT (t), name, 1, 0);
        !          1587:          if (id == error_mark_node)
        !          1588:            continue;
        !          1589:          if (id != NULL_TREE)
        !          1590:            {
        !          1591:              if (TREE_CODE (id) == FIELD_DECL
        !          1592:                  && ! TREE_STATIC (id)
        !          1593:                  && TREE_TYPE (id) != error_mark_node)
        !          1594:                {
        !          1595:                  error ("assignment to non-static member `%s' of enclosing class `%s'",
        !          1596:                         lang_printable_name (id),
        !          1597:                         IDENTIFIER_POINTER (TYPE_IDENTIFIER
        !          1598:                                             (DECL_CONTEXT (t))));
        !          1599:                  /* Mark this for do_identifier().  It would otherwise
        !          1600:                     claim that the variable was undeclared.  */
        !          1601:                  TREE_TYPE (id) = error_mark_node;
        !          1602:                }
        !          1603:              break;
        !          1604:            }
        !          1605:        }
        !          1606:     }
        !          1607: 
        !          1608:   return id;
        !          1609: }
        !          1610: 
1.1       root     1611: /* TYPE is a class type. Return the index of the fields within
                   1612:    the method vector with name NAME, or -1 is no such field exists.  */
                   1613: static int
                   1614: lookup_fnfields_1 (type, name)
                   1615:      tree type, name;
                   1616: {
                   1617:   register tree method_vec = CLASSTYPE_METHOD_VEC (type);
                   1618: 
                   1619:   if (method_vec != 0)
                   1620:     {
                   1621:       register tree *methods = &TREE_VEC_ELT (method_vec, 0);
                   1622:       register tree *end = TREE_VEC_END (method_vec);
                   1623: 
                   1624: #ifdef GATHER_STATISTICS
                   1625:       n_calls_lookup_fnfields_1++;
                   1626: #endif
                   1627:       if (*methods && name == constructor_name (type))
                   1628:        return 0;
                   1629: 
                   1630:       while (++methods != end)
                   1631:        {
                   1632: #ifdef GATHER_STATISTICS
1.1.1.4 ! root     1633:          n_outer_fields_searched++;
1.1       root     1634: #endif
                   1635:          if (DECL_NAME (*methods) == name)
                   1636:            break;
                   1637:        }
                   1638:       if (methods != end)
                   1639:        return methods - &TREE_VEC_ELT (method_vec, 0);
                   1640:     }
                   1641: 
                   1642:   return -1;
                   1643: }
                   1644: 
                   1645: /* Starting from BASETYPE, return a TREE_BASELINK-like object
                   1646:    which gives the following information (in a list):
                   1647: 
                   1648:    TREE_TYPE: list of basetypes needed to get to...
                   1649:    TREE_VALUE: list of all functions in of given type
                   1650:    which have name NAME.
                   1651: 
                   1652:    No visibility information is computed by this function,
                   1653:    other then to adorn the list of basetypes with
                   1654:    TREE_VIA_PUBLIC.
                   1655: 
                   1656:    If FIND_AMBIGUOUS is non-zero, then if we find two ways to get
                   1657:    to the same member function, both those ways are found,
                   1658:    and the caller must know what to do about this.  */
                   1659: tree
                   1660: lookup_fnfields (basetype_path, name, find_ambiguous)
                   1661:      tree basetype_path, name;
                   1662:      int find_ambiguous;
                   1663: {
                   1664:   int head = 0, tail = 0;
                   1665:   tree type, rval, rvals = NULL_TREE;
                   1666:   tree entry, binfo, basetype_chain;
                   1667: 
                   1668:   /* For now, don't try this.  */
                   1669:   int protect = find_ambiguous;
                   1670: 
                   1671:   /* Things for memoization.  */
                   1672:   char *errstr = 0;
                   1673: 
                   1674:   /* Set this to nonzero if we don't know how to compute
                   1675:      accurate error messages for visibility.  */
                   1676:   int index = MEMOIZED_HASH_FN (name);
                   1677: 
                   1678:   binfo = basetype_path;
                   1679:   type = BINFO_TYPE (basetype_path);
                   1680: 
                   1681:   if (CLASSTYPE_MTABLE_ENTRY (type))
                   1682:     {
                   1683:       tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
                   1684: 
                   1685:       while (tem && TREE_PURPOSE (tem) != name)
                   1686:        {
                   1687:          memoized_fields_searched[1]++;
                   1688:          tem = TREE_CHAIN (tem);
                   1689:        }
                   1690:       if (tem)
                   1691:        {
                   1692:          if (protect && TREE_TYPE (tem))
                   1693:            {
                   1694:              error (TREE_STRING_POINTER (TREE_TYPE (tem)),
                   1695:                     IDENTIFIER_POINTER (name),
                   1696:                     TYPE_NAME_STRING (DECL_CLASS_CONTEXT (TREE_VALUE (TREE_VALUE (tem)))));
                   1697:              return error_mark_node;
                   1698:            }
                   1699:          if (TREE_VALUE (tem) == NULL_TREE)
                   1700:            {
                   1701:              memoized_fast_rejects[1] += 1;
                   1702:              return NULL_TREE;
                   1703:            }
                   1704:          else
                   1705:            {
                   1706:              /* Want to return this, but we must make sure
                   1707:                 that visibility information is consistent.  */
                   1708:              tree baselink = TREE_VALUE (tem);
                   1709:              tree memoized_basetypes = TREE_PURPOSE (baselink);
                   1710:              tree these_basetypes = basetype_path;
                   1711:              while (memoized_basetypes && these_basetypes)
                   1712:                {
                   1713:                  memoized_fields_searched[1]++;
                   1714:                  if (TREE_VALUE (memoized_basetypes) != these_basetypes)
                   1715:                    break;
                   1716:                  memoized_basetypes = TREE_CHAIN (memoized_basetypes);
                   1717:                  these_basetypes = BINFO_INHERITANCE_CHAIN (these_basetypes);
                   1718:                }
                   1719:              /* The following statement is true only when both are NULL.  */
                   1720:              if (memoized_basetypes == these_basetypes)
                   1721:                {
                   1722:                  memoized_fast_finds[1] += 1;
                   1723:                  return TREE_VALUE (tem);
                   1724:                }
                   1725:              /* else, we must re-find this field by hand.  */
                   1726:              baselink = tree_cons (basetype_path, TREE_VALUE (baselink), TREE_CHAIN (baselink));
                   1727:              return baselink;
                   1728:            }
                   1729:        }
                   1730:     }
                   1731: 
                   1732: #ifdef GATHER_STATISTICS
                   1733:   n_calls_lookup_fnfields++;
                   1734: #endif
                   1735:   if (protect && flag_memoize_lookups && ! global_bindings_p ())
                   1736:     entry = make_memoized_table_entry (type, name, 1);
                   1737:   else
                   1738:     entry = 0;
                   1739: 
                   1740:   index = lookup_fnfields_1 (type, name);
                   1741: 
                   1742:   if (index >= 0)
                   1743:     {
                   1744:       rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
                   1745:       rvals = my_tree_cons (basetype_path, rval, NULL_TREE);
                   1746:       if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type))
                   1747:        TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
                   1748: 
                   1749:       if (entry)
                   1750:        {
                   1751:          TREE_VALUE (entry) = rvals;
                   1752:          TREE_TYPE (entry) = NULL_TREE;
                   1753:        }
                   1754: 
                   1755:       if (errstr && protect)
                   1756:        {
                   1757:          error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
                   1758:          return error_mark_node;
                   1759:        }
                   1760:       return rvals;
                   1761:     }
                   1762:   rval = NULL_TREE;
                   1763: 
                   1764:   basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
                   1765:   TREE_VIA_PUBLIC (basetype_chain) = 1;
                   1766: 
                   1767:   search_stack = push_search_level (search_stack, &search_obstack);
                   1768:   BINFO_VIA_PUBLIC (basetype_path) = 1;
                   1769:   BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
                   1770:   binfo = basetype_path;
                   1771: 
                   1772:   while (1)
                   1773:     {
                   1774:       tree binfos = BINFO_BASETYPES (binfo);
                   1775:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                   1776: 
                   1777:       /* Process and/or queue base types.  */
                   1778:       for (i = 0; i < n_baselinks; i++)
                   1779:        {
1.1.1.4 ! root     1780:          tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          1781:          if (BINFO_FIELDS_MARKED (base_binfo) == 0)
1.1       root     1782:            {
                   1783:              tree btypes;
                   1784: 
1.1.1.4 ! root     1785:              SET_BINFO_FIELDS_MARKED (base_binfo);
        !          1786:              btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
        !          1787:              TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
        !          1788:              TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
        !          1789:              TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
1.1       root     1790:              obstack_ptr_grow (&search_obstack, btypes);
                   1791:              tail += 1;
                   1792:              if (tail >= search_stack->limit)
1.1.1.3   root     1793:                my_friendly_abort (99);
1.1       root     1794:            }
                   1795:        }
                   1796: 
                   1797:       /* Process head of queue, if one exists.  */
                   1798:       if (head >= tail)
                   1799:        break;
                   1800: 
                   1801:       basetype_chain = search_stack->first[head++];
                   1802:       basetype_path = TREE_VALUE (basetype_chain);
                   1803:       if (TREE_CHAIN (basetype_chain))
                   1804:        BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
                   1805:       else
                   1806:        BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
                   1807: 
                   1808:       binfo = basetype_path;
                   1809:       type = BINFO_TYPE (binfo);
                   1810: 
                   1811:       /* See if we can find NAME in TYPE.  If RVAL is nonzero,
                   1812:         and we do find NAME in TYPE, verify that such a second
                   1813:         sighting is in fact legal.  */
                   1814: 
                   1815:       if (rval)
                   1816:        {
                   1817:          tree context = DECL_CLASS_CONTEXT (rval);
                   1818:          /* Just another way of finding the same member.  */
                   1819:          if (TYPE_BINFO (context) == binfo)
                   1820:            ;
                   1821:          /* Same baseclass, maybe different places in the lattice.  */
                   1822:          else if (context == type)
                   1823:            {
                   1824:              if (TREE_VIA_VIRTUAL (TREE_PURPOSE (rvals)))
                   1825:                if (TREE_VIA_VIRTUAL (binfo))
                   1826:                  ;
                   1827:                else
                   1828:                  errstr = "member `%s' belongs to virtual and non-virtual baseclasses `%s'";
                   1829:              else if (TREE_VIA_VIRTUAL (binfo))
                   1830:                errstr = "member `%s' belongs to virtual and non-virtual baseclasses `%s'";
                   1831:              else
                   1832:                errstr = "member `%s' belongs to MI-distinct base classes `%s'";
                   1833:            }
                   1834:          else
                   1835:            {
                   1836:              int index = lookup_fnfields_1 (type, name);
                   1837: 
1.1.1.2   root     1838:              /* ??? This code is broken.  If CONTEXT is not the leftmost
                   1839:                 baseclass, it makes all of its baseclasses appear to be
                   1840:                 unrelated.  */
1.1       root     1841:              if (index >= 0 && binfo != get_binfo (type, context, 0))
                   1842:                {
                   1843:                  /* We found it in other than a baseclass of RVAL's.  */
                   1844:                  rvals = my_tree_cons (basetype_path, TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index), rvals);
                   1845:                  if (CLASSTYPE_BASELINK_VEC (type))
                   1846:                    TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
                   1847:                }
                   1848:            }
                   1849:          if (errstr && entry)
                   1850:            {
                   1851:              tree error_string = my_build_string (errstr);
                   1852:              TREE_TYPE (entry) = error_string;
                   1853:            }
                   1854:          if (errstr && find_ambiguous)
                   1855:            {
                   1856:              rvals = error_mark_node;
                   1857:              break;
                   1858:            }
                   1859:        }
                   1860:       else
                   1861:        {
                   1862:          int index = lookup_fnfields_1 (type, name);
                   1863:          if (index >= 0)
                   1864:            {
                   1865:              rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
                   1866:              rvals = my_tree_cons (basetype_path, rval, NULL_TREE);
                   1867:              if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type))
                   1868:                TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
                   1869:              if (entry)
                   1870:                TREE_VALUE (entry) = rvals;
                   1871:            }
                   1872:          else
                   1873:            rval = NULL_TREE;
                   1874:        }
                   1875:     }
                   1876:   {
                   1877:     tree *tp = search_stack->first;
                   1878:     tree *search_tail = tp + tail;
                   1879: 
                   1880:     while (tp < search_tail)
                   1881:       {
                   1882:        CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (*tp));
                   1883:        tp += 1;
                   1884:       }
                   1885:   }
                   1886:   search_stack = pop_search_level (search_stack);
                   1887: 
                   1888:   if (entry)
                   1889:     {
                   1890:       if (errstr)
                   1891:        {
                   1892:          tree error_string = my_build_string (errstr);
                   1893:          /* Save error message with entry.  */
                   1894:          TREE_TYPE (entry) = error_string;
                   1895:        }
                   1896:       else
                   1897:        {
                   1898:          /* Mark entry as having no error string.  */
                   1899:          TREE_TYPE (entry) = NULL_TREE;
                   1900:        }
                   1901:     }
                   1902: 
                   1903:   if (errstr && protect)
                   1904:     {
                   1905:       error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
                   1906:       rvals = error_mark_node;
                   1907:     }
                   1908: 
                   1909:   return rvals;
                   1910: }
                   1911: 
                   1912: /* BREADTH-FIRST SEARCH ROUTINES.  */
                   1913: 
                   1914: /* Search a multiple inheritance hierarchy by breadth-first search.
                   1915: 
                   1916:    TYPE is an aggregate type, possibly in a multiple-inheritance hierarchy.
                   1917:    TESTFN is a function, which, if true, means that our condition has been met,
                   1918:    and its return value should be returned.
                   1919:    QFN, if non-NULL, is a predicate dictating whether the type should
                   1920:    even be queued.  */
                   1921: 
1.1.1.4 ! root     1922: HOST_WIDE_INT
1.1       root     1923: breadth_first_search (binfo, testfn, qfn)
                   1924:      tree binfo;
                   1925:      int (*testfn)();
                   1926:      int (*qfn)();
                   1927: {
                   1928:   int head = 0, tail = 0;
                   1929:   int rval = 0;
                   1930: 
                   1931:   search_stack = push_search_level (search_stack, &search_obstack);
                   1932: 
                   1933:   while (1)
                   1934:     {
                   1935:       tree binfos = BINFO_BASETYPES (binfo);
                   1936:       int n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                   1937:       int i;
                   1938: 
                   1939:       /* Process and/or queue base types.  */
                   1940:       for (i = 0; i < n_baselinks; i++)
                   1941:        {
1.1.1.4 ! root     1942:          tree base_binfo = TREE_VEC_ELT (binfos, i);
1.1       root     1943: 
1.1.1.4 ! root     1944:          if (BINFO_MARKED (base_binfo) == 0
1.1       root     1945:              && (qfn == 0 || (*qfn) (binfo, i)))
                   1946:            {
1.1.1.4 ! root     1947:              SET_BINFO_MARKED (base_binfo);
1.1       root     1948:              obstack_ptr_grow (&search_obstack, binfo);
                   1949:              obstack_int_grow (&search_obstack, i);
                   1950:              tail += 2;
                   1951:              if (tail >= search_stack->limit)
1.1.1.3   root     1952:                my_friendly_abort (100);
1.1       root     1953:            }
                   1954:        }
                   1955:       /* Process head of queue, if one exists.  */
                   1956:       if (head >= tail)
                   1957:        {
                   1958:          rval = 0;
                   1959:          break;
                   1960:        }
                   1961: 
                   1962:       binfo = search_stack->first[head++];
1.1.1.4 ! root     1963:       i = (HOST_WIDE_INT)search_stack->first[head++];
1.1       root     1964:       if (rval = (*testfn) (binfo, i))
                   1965:        break;
                   1966:       binfo = BINFO_BASETYPE (binfo, i);
                   1967:     }
                   1968:   {
                   1969:     tree *tp = search_stack->first;
                   1970:     tree *search_tail = tp + tail;
                   1971:     while (tp < search_tail)
                   1972:       {
                   1973:        tree binfo = *tp++;
1.1.1.4 ! root     1974:        int i = (HOST_WIDE_INT)(*tp++);
1.1       root     1975:        CLEAR_BINFO_MARKED (BINFO_BASETYPE (binfo, i));
                   1976:       }
                   1977:   }
                   1978: 
                   1979:   search_stack = pop_search_level (search_stack);
                   1980:   return rval;
                   1981: }
                   1982: 
                   1983: /* Functions to use in breadth first searches.  */
                   1984: typedef tree (*pft)();
                   1985: typedef int (*pfi)();
                   1986: 
                   1987: int tree_needs_constructor_p (binfo, i)
                   1988:      tree binfo;
1.1.1.4 ! root     1989:      int i;
1.1       root     1990: {
                   1991:   tree basetype;
1.1.1.4 ! root     1992:   my_friendly_assert (i != 0, 296);
1.1       root     1993:   basetype = BINFO_TYPE (BINFO_BASETYPE (binfo, i));
                   1994:   return TYPE_NEEDS_CONSTRUCTOR (basetype);
                   1995: }
                   1996: 
                   1997: static tree declarator;
                   1998: 
                   1999: static tree
                   2000: get_virtuals_named_this (binfo, i)
                   2001:      tree binfo;
                   2002:      int i;
                   2003: {
                   2004:   tree fields;
                   2005:   tree type = BINFO_TYPE (binfo);
                   2006: 
                   2007:   if (i >= 0)
                   2008:     type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
                   2009:   fields = lookup_fnfields (binfo, declarator, 0);
                   2010: 
                   2011:   if (fields == 0 || fields == error_mark_node)
                   2012:     return 0;
                   2013: 
                   2014:   /* Get to the function decls, and return the first virtual function
                   2015:      with this name, if there is one.  */
                   2016:   while (fields)
                   2017:     {
                   2018:       tree fndecl;
                   2019: 
                   2020:       for (fndecl = TREE_VALUE (fields); fndecl; fndecl = DECL_CHAIN (fndecl))
                   2021:        if (DECL_VINDEX (fndecl))
                   2022:          return fields;
                   2023:       fields = next_baselink (fields);
                   2024:     }
                   2025:   return NULL_TREE;
                   2026: }
                   2027: 
                   2028: static tree get_virtual_destructor (binfo, i)
                   2029:      tree binfo;
                   2030:      int i;
                   2031: {
                   2032:   tree type = BINFO_TYPE (binfo);
                   2033:   if (i >= 0)
                   2034:     type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
                   2035:   if (TYPE_HAS_DESTRUCTOR (type)
                   2036:       && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0)))
                   2037:     return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
                   2038:   return 0;
                   2039: }
                   2040: 
                   2041: int tree_has_any_destructor_p (binfo, i)
                   2042:      tree binfo;
                   2043:      int i;
                   2044: {
                   2045:   tree type = BINFO_TYPE (binfo);
                   2046:   if (i >= 0)
                   2047:     type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
                   2048:   return TYPE_NEEDS_DESTRUCTOR (type);
                   2049: }
                   2050: 
                   2051: /* Given a class type TYPE, and a function decl FNDECL,
1.1.1.3   root     2052:    look for the first function the TYPE's hierarchy which
1.1       root     2053:    FNDECL could match as a virtual function.
                   2054: 
                   2055:    DTORP is nonzero if we are looking for a destructor.  Destructors
                   2056:    need special treatment because they do not match by name.  */
                   2057: tree
                   2058: get_first_matching_virtual (binfo, fndecl, dtorp)
                   2059:      tree binfo, fndecl;
                   2060:      int dtorp;
                   2061: {
                   2062:   tree tmp = NULL_TREE;
                   2063: 
                   2064:   /* Breadth first search routines start searching basetypes
                   2065:      of TYPE, so we must perform first ply of search here.  */
                   2066:   if (dtorp)
                   2067:     {
                   2068:       if (tree_has_any_destructor_p (binfo, -1))
                   2069:        tmp = get_virtual_destructor (binfo, -1);
                   2070: 
                   2071:       if (tmp)
                   2072:        {
1.1.1.2   root     2073:          if (get_base_distance (DECL_CONTEXT (tmp),
                   2074:                                 DECL_CONTEXT (fndecl), 0, 0) > 0)
                   2075:            DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
1.1       root     2076:          return tmp;
                   2077:        }
                   2078: 
                   2079:       tmp = (tree) breadth_first_search (binfo,
                   2080:                                         (pfi) get_virtual_destructor,
                   2081:                                         tree_has_any_destructor_p);
                   2082:       if (tmp)
                   2083:        DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
                   2084:       return tmp;
                   2085:     }
                   2086:   else
                   2087:     {
                   2088:       tree drettype, dtypes, btypes, instptr_type;
                   2089:       tree basetype = DECL_CLASS_CONTEXT (fndecl);
                   2090:       tree baselink, best = NULL_TREE;
                   2091:       tree name = DECL_ASSEMBLER_NAME (fndecl);
                   2092: 
                   2093:       declarator = DECL_NAME (fndecl);
                   2094:       if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
                   2095:        return 0;
                   2096: 
                   2097:       drettype = TREE_TYPE (TREE_TYPE (fndecl));
                   2098:       dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
                   2099:       if (DECL_STATIC_FUNCTION_P (fndecl))
                   2100:        instptr_type = NULL_TREE;
                   2101:       else
                   2102:        instptr_type = TREE_TYPE (TREE_VALUE (dtypes));
                   2103: 
                   2104:       for (baselink = get_virtuals_named_this (binfo, -1);
                   2105:           baselink; baselink = next_baselink (baselink))
                   2106:        {
                   2107:          for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp))
                   2108:            {
                   2109:              if (! DECL_VINDEX (tmp))
                   2110:                continue;
                   2111: 
                   2112:              btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp));
1.1.1.4 ! root     2113:              if (instptr_type == NULL_TREE)
        !          2114:                {
        !          2115:                  if (compparms (TREE_CHAIN (btypes), dtypes, 3))
        !          2116:                    /* Caller knows to give error in this case.  */
        !          2117:                    return tmp;
        !          2118:                  return NULL_TREE;
        !          2119:                }
1.1       root     2120: 
                   2121:              if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes)))
                   2122:                   == TYPE_READONLY (instptr_type))
                   2123:                  && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
                   2124:                {
                   2125:                  if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
                   2126:                      && ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
                   2127:                    {
                   2128:                      error_with_decl (fndecl, "conflicting return type specified for virtual function `%s'");
                   2129:                      SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
                   2130:                    }
                   2131:                  break;
                   2132:                }
                   2133:            }
                   2134:          if (tmp)
                   2135:            {
                   2136:              /* If this is ambiguous, we will warn about it later.  */
                   2137:              if (best)
                   2138:                {
                   2139:                  if (get_base_distance (DECL_CLASS_CONTEXT (best),
                   2140:                                         DECL_CLASS_CONTEXT (tmp), 0, 0) > 0)
                   2141:                    best = tmp;
                   2142:                }
                   2143:              else
                   2144:                best = tmp;
                   2145:            }
                   2146:        }
                   2147:       if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
                   2148:          && best == NULL_TREE && warn_overloaded_virtual)
                   2149:        {
1.1.1.2   root     2150:          error_with_decl (fndecl, "conflicting specification deriving virtual function `%s'");
1.1       root     2151:          SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
                   2152:        }
                   2153:       if (best)
                   2154:        {
                   2155:          DECL_CONTEXT (fndecl) = DECL_CONTEXT (best);
                   2156:        }
                   2157:       return best;
                   2158:     }
                   2159: }
                   2160: 
                   2161: /* Return the list of virtual functions which are abstract in type TYPE.
                   2162:    This information is cached, and so must be built on a
                   2163:    non-temporary obstack.  */
                   2164: tree
                   2165: get_abstract_virtuals (type)
                   2166:      tree type;
                   2167: {
                   2168:   /* For each layer of base class (i.e., the first base class, and each
                   2169:      virtual base class from that one), modify the virtual function table
                   2170:      of the derived class to contain the new virtual function.
                   2171:      A class has as many vfields as it has virtual base classes (total).  */
                   2172:   tree vfields, vbases, base, tmp;
                   2173:   tree vfield = CLASSTYPE_VFIELD (type);
                   2174:   tree fcontext = vfield ? DECL_FCONTEXT (vfield) : NULL_TREE;
                   2175:   tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
                   2176: 
                   2177:   for (vfields = CLASSTYPE_VFIELDS (type); vfields; vfields = TREE_CHAIN (vfields))
                   2178:     {
                   2179:       int normal;
                   2180: 
                   2181:       /* Find the right base class for this derived class, call it BASE.  */
                   2182:       base = VF_BASETYPE_VALUE (vfields);
                   2183:       if (base == type)
                   2184:        continue;
                   2185: 
                   2186:       /* We call this case NORMAL iff this virtual function table
                   2187:         pointer field has its storage reserved in this class.
                   2188:         This is normally the case without virtual baseclasses
                   2189:         or off-center multiple baseclasses.  */
                   2190:       normal = (base == fcontext
                   2191:                && (VF_BINFO_VALUE (vfields) == NULL_TREE
                   2192:                    || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));
                   2193: 
                   2194:       if (normal)
                   2195:        tmp = TREE_CHAIN (TYPE_BINFO_VIRTUALS (type));
                   2196:       else
                   2197:        {
                   2198:          /* n.b.: VF_BASETYPE_VALUE (vfields) is the first basetype
                   2199:             that provides the virtual function table, whereas
                   2200:             VF_DERIVED_VALUE (vfields) is an immediate base type of TYPE
                   2201:             that dominates VF_BASETYPE_VALUE (vfields).  The list of
                   2202:             vfields we want lies between these two values.  */
                   2203:          tree binfo = get_binfo (VF_NORMAL_VALUE (vfields), type, 0);
                   2204:          tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
                   2205:        }
                   2206: 
                   2207:       /* Get around dossier entry if there is one.  */
                   2208:       if (flag_dossier)
                   2209:        tmp = TREE_CHAIN (tmp);
                   2210: 
                   2211:       while (tmp)
                   2212:        {
                   2213:          tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
                   2214:          tree base_fndecl = TREE_OPERAND (base_pfn, 0);
                   2215:          if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
                   2216:            abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
                   2217:          tmp = TREE_CHAIN (tmp);
                   2218:        }
                   2219:     }
                   2220:   for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
                   2221:     {
                   2222:       if (! BINFO_VIRTUALS (vbases))
                   2223:        continue;
                   2224: 
                   2225:       tmp = TREE_CHAIN (BINFO_VIRTUALS (vbases));
                   2226:       while (tmp)
                   2227:        {
                   2228:          tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
                   2229:          tree base_fndecl = TREE_OPERAND (base_pfn, 0);
                   2230:          if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
                   2231:            abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
                   2232:          tmp = TREE_CHAIN (tmp);
                   2233:        }
                   2234:     }
                   2235:   return nreverse (abstract_virtuals);
                   2236: }
                   2237: 
                   2238: /* For the type TYPE, return a list of member functions available from
                   2239:    base classes with name NAME.  The TREE_VALUE of the list is a chain of
                   2240:    member functions with name NAME.  The TREE_PURPOSE of the list is a
                   2241:    basetype, or a list of base types (in reverse order) which were
                   2242:    traversed to reach the chain of member functions.  If we reach a base
                   2243:    type which provides a member function of name NAME, and which has at
                   2244:    most one base type itself, then we can terminate the search.  */
                   2245: 
                   2246: tree
                   2247: get_baselinks (type_as_binfo_list, type, name)
                   2248:      tree type_as_binfo_list;
                   2249:      tree type, name;
                   2250: {
                   2251:   tree hash_tree_cons ();
                   2252:   int head = 0, tail = 0, index;
                   2253:   tree rval = 0, nval = 0;
                   2254:   tree basetypes = type_as_binfo_list;
                   2255:   tree binfo = TYPE_BINFO (type);
                   2256: 
                   2257:   search_stack = push_search_level (search_stack, &search_obstack);
                   2258: 
                   2259:   while (1)
                   2260:     {
                   2261:       tree binfos = BINFO_BASETYPES (binfo);
                   2262:       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                   2263: 
                   2264:       /* Process and/or queue base types.  */
                   2265:       for (i = 0; i < n_baselinks; i++)
                   2266:        {
1.1.1.4 ! root     2267:          tree base_binfo = TREE_VEC_ELT (binfos, i);
1.1       root     2268:          tree btypes;
                   2269: 
1.1.1.4 ! root     2270:          btypes = hash_tree_cons (TREE_VIA_PUBLIC (base_binfo),
        !          2271:                                   TREE_VIA_VIRTUAL (base_binfo),
        !          2272:                                   TREE_VIA_PROTECTED (base_binfo),
        !          2273:                                   NULL_TREE, base_binfo,
1.1       root     2274:                                   basetypes);
                   2275:          obstack_ptr_grow (&search_obstack, btypes);
                   2276:          search_stack->first = (tree *)obstack_base (&search_obstack);
                   2277:          tail += 1;
                   2278:        }
                   2279: 
                   2280:     dont_queue:
                   2281:       /* Process head of queue, if one exists.  */
                   2282:       if (head >= tail)
                   2283:        break;
                   2284: 
                   2285:       basetypes = search_stack->first[head++];
                   2286:       binfo = TREE_VALUE (basetypes);
                   2287:       type = BINFO_TYPE (binfo);
                   2288:       index = lookup_fnfields_1 (type, name);
                   2289:       if (index >= 0)
                   2290:        {
                   2291:          nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
1.1.1.4 ! root     2292:          rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval);
1.1       root     2293:          if (TYPE_BINFO_BASETYPES (type) == 0)
                   2294:            goto dont_queue;
                   2295:          else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1)
                   2296:            {
                   2297:              if (CLASSTYPE_BASELINK_VEC (type))
                   2298:                TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
                   2299:              goto dont_queue;
                   2300:            }
                   2301:        }
                   2302:       nval = NULL_TREE;
                   2303:     }
                   2304: 
                   2305:   search_stack = pop_search_level (search_stack);
                   2306:   return rval;
                   2307: }
                   2308: 
                   2309: tree
                   2310: next_baselink (baselink)
                   2311:      tree baselink;
                   2312: {
                   2313:   tree tmp = TREE_TYPE (baselink);
                   2314:   baselink = TREE_CHAIN (baselink);
                   2315:   while (tmp)
                   2316:     {
                   2317:       /* @@ does not yet add previous base types.  */
                   2318:       baselink = tree_cons (TREE_PURPOSE (tmp), TREE_VALUE (tmp),
                   2319:                            baselink);
                   2320:       TREE_TYPE (baselink) = TREE_TYPE (tmp);
                   2321:       tmp = TREE_CHAIN (tmp);
                   2322:     }
                   2323:   return baselink;
                   2324: }
                   2325: 
                   2326: /* DEPTH-FIRST SEARCH ROUTINES.  */
                   2327: 
                   2328: /* Assign unique numbers to _CLASSTYPE members of the lattice
                   2329:    specified by TYPE.  The root nodes are marked first; the nodes
                   2330:    are marked depth-fisrt, left-right.  */
                   2331: 
                   2332: static int cid;
                   2333: 
                   2334: /* Matrix implementing a relation from CLASSTYPE X CLASSTYPE => INT.
                   2335:    Relation yields 1 if C1 <= C2, 0 otherwise.  */
                   2336: typedef char mi_boolean;
                   2337: static mi_boolean *mi_matrix;
                   2338: 
                   2339: /* Type for which this matrix is defined.  */
                   2340: static tree mi_type;
                   2341: 
                   2342: /* Size of the matrix for indexing purposes.  */
                   2343: static int mi_size;
                   2344: 
                   2345: /* Return nonzero if class C2 derives from class C1.  */
                   2346: #define BINFO_DERIVES_FROM(C1, C2)     \
                   2347:   ((mi_matrix+mi_size*(BINFO_CID (C1)-1))[BINFO_CID (C2)-1])
                   2348: #define TYPE_DERIVES_FROM(C1, C2)      \
                   2349:   ((mi_matrix+mi_size*(CLASSTYPE_CID (C1)-1))[CLASSTYPE_CID (C2)-1])
                   2350: #define BINFO_DERIVES_FROM_STAR(C)     \
                   2351:   (mi_matrix+(BINFO_CID (C)-1))
                   2352: 
1.1.1.4 ! root     2353: /* This routine converts a pointer to be a pointer of an immediate
        !          2354:    base class.  The normal convert_pointer_to routine would diagnose
        !          2355:    the conversion as ambiguous, under MI code that has the base class
        !          2356:    as an ambiguous base class. */
        !          2357: static tree
        !          2358: convert_pointer_to_single_level (to_type, expr)
        !          2359:      tree to_type, expr;
        !          2360: {
        !          2361:   tree binfo_of_derived;
        !          2362:   tree last;
        !          2363: 
        !          2364:   binfo_of_derived = TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr)));
        !          2365:   last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0);
        !          2366:   BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived;
        !          2367:   BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE;
        !          2368:   return build_vbase_path (PLUS_EXPR, TYPE_POINTER_TO (to_type), expr, last, 1);
        !          2369: }
        !          2370: 
        !          2371: /* The main function which implements depth first search.
        !          2372: 
        !          2373:    This routine has to remember the path it walked up, when
        !          2374:    dfs_init_vbase_pointers is the work function, as otherwise there
        !          2375:    would be no record. */
1.1       root     2376: static void
                   2377: dfs_walk (binfo, fn, qfn)
                   2378:      tree binfo;
                   2379:      void (*fn)();
                   2380:      int (*qfn)();
                   2381: {
                   2382:   tree binfos = BINFO_BASETYPES (binfo);
                   2383:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                   2384: 
                   2385:   for (i = 0; i < n_baselinks; i++)
                   2386:     {
1.1.1.4 ! root     2387:       tree base_binfo = TREE_VEC_ELT (binfos, i);
1.1       root     2388: 
1.1.1.4 ! root     2389:       if ((*qfn)(base_binfo))
1.1       root     2390:        {
1.1.1.4 ! root     2391:          if (fn == dfs_init_vbase_pointers)
        !          2392:            {
        !          2393:              /* When traversing an arbitrary MI hierarchy, we need to keep
        !          2394:                 a record of the path we took to get down to the final base
        !          2395:                 type, as otherwise there would be no record of it, and just
        !          2396:                 trying to blindly convert at the bottom would be ambiguous.
        !          2397: 
        !          2398:                 The easiest way is to do the conversions one step at a time,
        !          2399:                 as we know we want the immediate base class at each step.
        !          2400: 
        !          2401:                 The only special trick to converting one step at a time,
        !          2402:                 is that when we hit the first virtual base class, we must
        !          2403:                 use the SLOT value for it, and not use the normal convert
        !          2404:                 routine.
        !          2405:                 */
        !          2406:              tree saved_vbase_decl_ptr_intermediate
        !          2407:                = vbase_decl_ptr_intermediate;
        !          2408:              int save_saw_first_vbase = saw_first_vbase;
        !          2409: 
        !          2410:              if (!saw_first_vbase && TREE_VIA_VIRTUAL (base_binfo))
        !          2411:                {
        !          2412:                  saw_first_vbase = 1;
        !          2413:                  /* No need for the conversion here, as we know it is the
        !          2414:                     right type.  */
        !          2415:                  vbase_decl_ptr_intermediate =
        !          2416:                    (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
        !          2417:                }
        !          2418:              else
        !          2419:                {
        !          2420: #ifdef CHECK_convert_pointer_to_single_level
        !          2421:                  /* This code here introduces a little software fault
        !          2422:                     tolerance It should be that case that the second
        !          2423:                     one always gets the same valid answer that the
        !          2424:                     first one gives, if the first one gives a valid
        !          2425:                     answer.
        !          2426: 
        !          2427:                     If it doesn't, the second algorithm is at fault
        !          2428:                     and needs to be fixed.
        !          2429: 
        !          2430:                     The first one is known to be bad and produce
        !          2431:                     error_mark_node when dealing with MI base
        !          2432:                     classes.  It is the only problem supposed to be
        !          2433:                     fixed by the second. */
        !          2434: #endif
        !          2435:                  tree vdpi1, vdpi2;
        !          2436:                  
        !          2437: #ifdef CHECK_convert_pointer_to_single_level
        !          2438:                  vdpi1 = convert_pointer_to (BINFO_TYPE (base_binfo),
        !          2439:                                              vbase_decl_ptr_intermediate);
        !          2440: #endif
        !          2441:                  vdpi2 = convert_pointer_to_single_level (BINFO_TYPE (base_binfo),
        !          2442:                                                           vbase_decl_ptr_intermediate);
        !          2443:                  vbase_decl_ptr_intermediate = vdpi2;
        !          2444: #ifdef CHECK_convert_pointer_to_single_level
        !          2445:                  if (vdpi1 == error_mark_node && vdpi2 != vdpi1)
        !          2446:                    {
        !          2447:                      extern int errorcount;
        !          2448:                      errorcount -=2;
        !          2449:                      warning ("internal: Don't worry, be happy, I can fix tangs man.  (ignore above error)");
        !          2450:                    }
        !          2451:                  else if (simple_cst_equal (vdpi1, vdpi2) != 1) {
        !          2452:                    if (simple_cst_equal (vdpi1, vdpi2) == 0)
        !          2453:                      warning ("internal: convert_pointer_to_single_level: They are not the same, going with old algorithm");
        !          2454:                    else
        !          2455:                      warning ("internal: convert_pointer_to_single_level: They might not be the same, going with old algorithm");
        !          2456:                    vbase_decl_ptr_intermediate = vdpi1;
        !          2457:                  }
        !          2458: #endif
        !          2459:                }
        !          2460: 
        !          2461:              dfs_walk (base_binfo, fn, qfn);
        !          2462: 
        !          2463:              vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
        !          2464:              saw_first_vbase = save_saw_first_vbase;
        !          2465:            } else
        !          2466:              dfs_walk (base_binfo, fn, qfn);
1.1       root     2467:        }
                   2468:     }
                   2469: 
                   2470:   fn (binfo);
                   2471: }
                   2472: 
                   2473: /* Predicate functions which serve for dfs_walk.  */
                   2474: static int numberedp (binfo) tree binfo;
                   2475: { return BINFO_CID (binfo); }
                   2476: static int unnumberedp (binfo) tree binfo;
                   2477: { return BINFO_CID (binfo) == 0; }
                   2478: 
                   2479: static int markedp (binfo) tree binfo;
                   2480: { return BINFO_MARKED (binfo); }
                   2481: static int bfs_markedp (binfo, i) tree binfo; int i;
                   2482: { return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
                   2483: static int unmarkedp (binfo) tree binfo;
                   2484: { return BINFO_MARKED (binfo) == 0; }
                   2485: static int bfs_unmarkedp (binfo, i) tree binfo; int i;
                   2486: { return BINFO_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
1.1.1.4 ! root     2487: static int marked_vtable_pathp (binfo) tree binfo;
1.1       root     2488: { return BINFO_VTABLE_PATH_MARKED (binfo); }
1.1.1.4 ! root     2489: static int bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
1.1       root     2490: { return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
1.1.1.4 ! root     2491: static int unmarked_vtable_pathp (binfo) tree binfo;
1.1       root     2492: { return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
1.1.1.4 ! root     2493: static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
1.1       root     2494: { return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
1.1.1.4 ! root     2495: static int marked_new_vtablep (binfo) tree binfo;
1.1       root     2496: { return BINFO_NEW_VTABLE_MARKED (binfo); }
1.1.1.4 ! root     2497: static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
1.1       root     2498: { return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
1.1.1.4 ! root     2499: static int unmarked_new_vtablep (binfo) tree binfo;
1.1       root     2500: { return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
1.1.1.4 ! root     2501: static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
1.1       root     2502: { return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
                   2503: 
                   2504: static int dfs_search_slot_nonempty_p (binfo) tree binfo;
                   2505: { return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
                   2506: 
                   2507: static int dfs_debug_unmarkedp (binfo) tree binfo;
                   2508: { return CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) == 0; }
                   2509: 
                   2510: /* The worker functions for `dfs_walk'.  These do not need to
                   2511:    test anything (vis a vis marking) if they are paired with
                   2512:    a predicate function (above).  */
                   2513: 
                   2514: /* Assign each type within the lattice a number which is unique
                   2515:    in the lattice.  The first number assigned is 1.  */
                   2516: 
                   2517: static void
                   2518: dfs_number (binfo)
                   2519:      tree binfo;
                   2520: {
                   2521:   BINFO_CID (binfo) = ++cid;
                   2522: }
                   2523: 
                   2524: static void
                   2525: dfs_unnumber (binfo)
                   2526:      tree binfo;
                   2527: {
                   2528:   BINFO_CID (binfo) = 0;
                   2529: }
                   2530: 
                   2531: static void
                   2532: dfs_mark (binfo) tree binfo;
                   2533: { SET_BINFO_MARKED (binfo); }
                   2534: 
                   2535: static void
                   2536: dfs_unmark (binfo) tree binfo;
                   2537: { CLEAR_BINFO_MARKED (binfo); }
                   2538: 
                   2539: static void
1.1.1.4 ! root     2540: dfs_mark_vtable_path (binfo) tree binfo;
1.1       root     2541: { SET_BINFO_VTABLE_PATH_MARKED (binfo); }
                   2542: 
                   2543: static void
1.1.1.4 ! root     2544: dfs_unmark_vtable_path (binfo) tree binfo;
1.1       root     2545: { CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); }
                   2546: 
                   2547: static void
1.1.1.4 ! root     2548: dfs_mark_new_vtable (binfo) tree binfo;
1.1       root     2549: { SET_BINFO_NEW_VTABLE_MARKED (binfo); }
                   2550: 
                   2551: static void
1.1.1.4 ! root     2552: dfs_unmark_new_vtable (binfo) tree binfo;
1.1       root     2553: { CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); }
                   2554: 
                   2555: static void
                   2556: dfs_clear_search_slot (binfo) tree binfo;
                   2557: { CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
                   2558: 
                   2559: static void
                   2560: dfs_debug_mark (binfo)
                   2561:      tree binfo;
                   2562: {
                   2563:   tree t = BINFO_TYPE (binfo);
                   2564: 
                   2565:   /* Use heuristic that if there are virtual functions,
                   2566:      ignore until we see a non-inline virtual function.  */
                   2567:   tree methods = CLASSTYPE_METHOD_VEC (t);
                   2568: 
                   2569:   CLASSTYPE_DEBUG_REQUESTED (t) = 1;
                   2570: 
1.1.1.4 ! root     2571:   /* If interface info is known, the value of (?@@?) is correct.  */
1.1       root     2572:   if (methods == 0
                   2573:       || ! CLASSTYPE_INTERFACE_UNKNOWN (t)
                   2574:       || (write_virtuals == 2 && TYPE_VIRTUAL_P (t)))
                   2575:     return;
                   2576: 
                   2577:   /* If debug info is requested from this context for this type, supply it.
                   2578:      If debug info is requested from another context for this type,
                   2579:      see if some third context can supply it.  */
                   2580:   if (current_function_decl == NULL_TREE
                   2581:       || DECL_CLASS_CONTEXT (current_function_decl) != t)
                   2582:     {
                   2583:       if (TREE_VEC_ELT (methods, 0))
                   2584:        methods = TREE_VEC_ELT (methods, 0);
                   2585:       else
                   2586:        methods = TREE_VEC_ELT (methods, 1);
                   2587:       while (methods)
                   2588:        {
                   2589:          if (DECL_VINDEX (methods)
                   2590:              && DECL_SAVED_INSNS (methods) == 0
                   2591:              && DECL_PENDING_INLINE_INFO (methods) == 0
                   2592:              && DECL_ABSTRACT_VIRTUAL_P (methods) == 0)
                   2593:            {
                   2594:              /* Somebody, somewhere is going to have to define this
                   2595:                 virtual function.  When they do, they will provide
                   2596:                 the debugging info.  */
                   2597:              return;
                   2598:            }
                   2599:          methods = TREE_CHAIN (methods);
                   2600:        }
                   2601:     }
                   2602:   /* We cannot rely on some alien method to solve our problems,
                   2603:      so we must write out the debug info ourselves.  */
                   2604:   DECL_IGNORED_P (TYPE_NAME (t)) = 0;
                   2605:   if (! TREE_ASM_WRITTEN (TYPE_NAME (t)))
                   2606:     rest_of_type_compilation (t, global_bindings_p ());
                   2607: }
                   2608: 
1.1.1.4 ! root     2609: /*  Attach to the type of the virtual base class, the pointer to the
        !          2610:     virtual base class, given the global pointer vbase_decl_ptr.  */
1.1       root     2611: static void
                   2612: dfs_find_vbases (binfo)
                   2613:      tree binfo;
                   2614: {
                   2615:   tree binfos = BINFO_BASETYPES (binfo);
                   2616:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                   2617: 
                   2618:   for (i = n_baselinks-1; i >= 0; i--)
                   2619:     {
1.1.1.4 ! root     2620:       tree base_binfo = TREE_VEC_ELT (binfos, i);
1.1       root     2621: 
1.1.1.4 ! root     2622:       if (TREE_VIA_VIRTUAL (base_binfo)
        !          2623:          && CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo)) == 0)
1.1       root     2624:        {
1.1.1.4 ! root     2625:          tree vbase = BINFO_TYPE (base_binfo);
1.1       root     2626:          tree binfo = binfo_member (vbase, vbase_types);
                   2627: 
                   2628:          CLASSTYPE_SEARCH_SLOT (vbase)
                   2629:            = (char *) build (PLUS_EXPR, TYPE_POINTER_TO (vbase),
                   2630:                              vbase_decl_ptr, BINFO_OFFSET (binfo));
                   2631:        }
                   2632:     }
                   2633:   SET_BINFO_VTABLE_PATH_MARKED (binfo);
                   2634:   SET_BINFO_NEW_VTABLE_MARKED (binfo);
                   2635: }
                   2636: 
                   2637: static void
                   2638: dfs_init_vbase_pointers (binfo)
                   2639:      tree binfo;
                   2640: {
                   2641:   tree type = BINFO_TYPE (binfo);
                   2642:   tree fields = TYPE_FIELDS (type);
                   2643:   tree path, this_vbase_ptr;
                   2644:   int distance;
                   2645: 
                   2646:   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
                   2647: 
                   2648:   /* If there is a dossier, it is the first field, though perhaps from
                   2649:      the base class.  Otherwise, the first fields are virtual base class
                   2650:      pointer fields.  */
                   2651:   if (CLASSTYPE_DOSSIER (type) && VFIELD_NAME_P (DECL_NAME (fields)))
                   2652:     /* Get past vtable for the object.  */
                   2653:     fields = TREE_CHAIN (fields);
                   2654: 
                   2655:   if (fields == NULL_TREE
                   2656:       || DECL_NAME (fields) == NULL_TREE
                   2657:       || ! VBASE_NAME_P (DECL_NAME (fields)))
                   2658:     return;
                   2659: 
1.1.1.4 ! root     2660:   this_vbase_ptr = vbase_decl_ptr_intermediate;
        !          2661: 
        !          2662:   if (TYPE_POINTER_TO (type) != TREE_TYPE (this_vbase_ptr))
        !          2663:     my_friendly_abort (125);
        !          2664: 
        !          2665: #if 0
1.1       root     2666:   distance = get_base_distance (type, TREE_TYPE (vbase_decl), 0, &path);
1.1.1.4 ! root     2667:   if (distance == -2)
        !          2668:     {
        !          2669:       error ("inheritance lattice too complex below");
        !          2670:     }
1.1       root     2671:   while (path)
                   2672:     {
                   2673:       if (TREE_VIA_VIRTUAL (path))
                   2674:        break;
                   2675:       distance -= 1;
                   2676:       path = BINFO_INHERITANCE_CHAIN (path);
                   2677:     }
                   2678: 
                   2679:   if (distance > 0)
1.1.1.4 ! root     2680:     this_vbase_ptr = convert_pointer_to (type, (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (path)));
1.1       root     2681:   else
                   2682:     this_vbase_ptr = convert_pointer_to (type, vbase_decl_ptr);
                   2683: 
1.1.1.4 ! root     2684:   /* This happens when it is ambiguous. */
        !          2685:   if (this_vbase_ptr == error_mark_node)
        !          2686:     return;
        !          2687: #endif
        !          2688: 
1.1       root     2689:   while (fields && DECL_NAME (fields)
                   2690:         && VBASE_NAME_P (DECL_NAME (fields)))
                   2691:     {
                   2692:       tree ref = build (COMPONENT_REF, TREE_TYPE (fields),
                   2693:                        build_indirect_ref (this_vbase_ptr, 0), fields);
                   2694:       tree init = (tree)CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
                   2695:       vbase_init_result = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
                   2696:                                                   vbase_types),
                   2697:                                     build_modify_expr (ref, NOP_EXPR, init),
                   2698:                                     vbase_init_result);
                   2699:       fields = TREE_CHAIN (fields);
                   2700:     }
                   2701: }
                   2702: 
1.1.1.4 ! root     2703: /* Sometimes this needs to clear both VTABLE_PATH and NEW_VTABLE.  Other
        !          2704:    times, just NEW_VTABLE, but optimizer should make both with equal
        !          2705:    efficiency (though it does not currently).  */
1.1       root     2706: static void
                   2707: dfs_clear_vbase_slots (binfo)
                   2708:      tree binfo;
                   2709: {
                   2710:   tree type = BINFO_TYPE (binfo);
                   2711:   CLASSTYPE_SEARCH_SLOT (type) = 0;
                   2712:   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
                   2713:   CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
                   2714: }
                   2715: 
                   2716: tree
                   2717: init_vbase_pointers (type, decl_ptr)
                   2718:      tree type;
                   2719:      tree decl_ptr;
                   2720: {
                   2721:   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
                   2722:     {
                   2723:       int old_flag = flag_this_is_variable;
                   2724:       tree binfo = TYPE_BINFO (type);
1.1.1.2   root     2725:       flag_this_is_variable = -2;
1.1       root     2726:       vbase_types = CLASSTYPE_VBASECLASSES (type);
                   2727:       vbase_decl_ptr = decl_ptr;
                   2728:       vbase_decl = build_indirect_ref (decl_ptr, 0);
1.1.1.4 ! root     2729:       vbase_decl_ptr_intermediate = vbase_decl_ptr;
        !          2730:       saw_first_vbase = 0;
1.1       root     2731:       vbase_init_result = NULL_TREE;
1.1.1.4 ! root     2732:       dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp);
        !          2733:       dfs_walk (binfo, dfs_init_vbase_pointers, marked_vtable_pathp);
        !          2734:       dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
1.1       root     2735:       flag_this_is_variable = old_flag;
                   2736:       return vbase_init_result;
                   2737:     }
                   2738:   return 0;
                   2739: }
                   2740: 
                   2741: /* Build a COMPOUND_EXPR which when expanded will generate the code
                   2742:    needed to initialize all the virtual function table slots of all
                   2743:    the virtual baseclasses.  FOR_TYPE is the type which determines the
                   2744:    virtual baseclasses to use; TYPE is the type of the object to which
                   2745:    the initialization applies.  TRUE_EXP is the true object we are
                   2746:    initializing, and DECL_PTR is the pointer to the sub-object we
                   2747:    are initializing.
                   2748: 
                   2749:    CTOR_P is non-zero if the caller of this function is a top-level
                   2750:    constructor.  It is zero when called from a destructor.  When
                   2751:    non-zero, we can use computed offsets to store the vtables.  When
                   2752:    zero, we must store new vtables through virtual baseclass pointers.  */
                   2753: 
                   2754: tree
                   2755: build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr, ctor_p)
                   2756:      tree main_binfo, binfo;
                   2757:      tree true_exp, decl_ptr;
                   2758:      int ctor_p;
                   2759: {
                   2760:   tree for_type = BINFO_TYPE (main_binfo);
                   2761:   tree type = BINFO_TYPE (binfo);
                   2762:   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
                   2763:     {
                   2764:       int old_flag = flag_this_is_variable;
                   2765:       tree vtable_init_result = NULL_TREE;
                   2766:       tree vbases = CLASSTYPE_VBASECLASSES (type);
                   2767: 
                   2768:       vbase_types = CLASSTYPE_VBASECLASSES (for_type);
                   2769:       vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
                   2770:       vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, 0);
                   2771: 
                   2772:       if (ctor_p)
1.1.1.3   root     2773:        {
                   2774:          /* This is an object of type IN_TYPE,  */
                   2775:          flag_this_is_variable = -2;
1.1.1.4 ! root     2776:          dfs_walk (main_binfo, dfs_find_vbases, unmarked_new_vtablep);
1.1.1.3   root     2777:        }
1.1       root     2778: 
                   2779:       /* Initialized with vtables of type TYPE.  */
                   2780:       while (vbases)
                   2781:        {
                   2782:          /* This time through, not every class's vtable
                   2783:             is going to be initialized.  That is, we only initialize
                   2784:             the "last" vtable pointer.  */
                   2785: 
                   2786:          if (CLASSTYPE_VSIZE (BINFO_TYPE (vbases)))
                   2787:            {
                   2788:              tree addr;
                   2789:              tree vtbl = BINFO_VTABLE (vbases);
                   2790:              tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
1.1.1.4 ! root     2791:              assemble_external (vtbl);
1.1       root     2792:              TREE_USED (vtbl) = 1;
                   2793: 
                   2794:              if (ctor_p == 0)
                   2795:                addr = convert_pointer_to (vbases, vbase_decl_ptr);
                   2796:              else
                   2797:                addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
                   2798: 
                   2799:              if (addr)
                   2800:                {
                   2801:                  tree ref = build_vfield_ref (build_indirect_ref (addr, 0),
                   2802:                                               BINFO_TYPE (vbases));
                   2803:                  init = convert_force (TREE_TYPE (ref), init);
                   2804:                  vtable_init_result = tree_cons (NULL_TREE, build_modify_expr (ref, NOP_EXPR, init),
                   2805:                                                  vtable_init_result);
                   2806:                }
                   2807:            }
                   2808:          vbases = TREE_CHAIN (vbases);
                   2809:        }
                   2810: 
1.1.1.4 ! root     2811:       dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
1.1       root     2812: 
                   2813:       flag_this_is_variable = old_flag;
                   2814:       if (vtable_init_result)
                   2815:        return build_compound_expr (vtable_init_result);
                   2816:     }
                   2817:   return error_mark_node;
                   2818: }
                   2819: 
                   2820: void
                   2821: clear_search_slots (type)
                   2822:      tree type;
                   2823: {
                   2824:   dfs_walk (TYPE_BINFO (type),
                   2825:            dfs_clear_search_slot, dfs_search_slot_nonempty_p);
                   2826: }
                   2827: 
                   2828: static void
                   2829: dfs_get_vbase_types (binfo)
                   2830:      tree binfo;
                   2831: {
                   2832:   int i;
                   2833:   tree binfos = BINFO_BASETYPES (binfo);
                   2834:   tree type = BINFO_TYPE (binfo);
                   2835:   tree these_vbase_types = CLASSTYPE_VBASECLASSES (type);
                   2836: 
                   2837:   if (these_vbase_types)
                   2838:     {
                   2839:       while (these_vbase_types)
                   2840:        {
                   2841:          tree this_type = BINFO_TYPE (these_vbase_types);
                   2842: 
                   2843:          /* We really need to start from a fresh copy of this
                   2844:             virtual basetype!  CLASSTYPE_MARKED2 is the shortcut
                   2845:             for BINFO_VBASE_MARKED.  */
                   2846:          if (! CLASSTYPE_MARKED2 (this_type))
                   2847:            {
                   2848:              vbase_types = make_binfo (integer_zero_node,
                   2849:                                        this_type,
                   2850:                                        TYPE_BINFO_VTABLE (this_type),
                   2851:                                        TYPE_BINFO_VIRTUALS (this_type),
                   2852:                                        vbase_types);
                   2853:              TREE_VIA_VIRTUAL (vbase_types) = 1;
                   2854:              SET_CLASSTYPE_MARKED2 (this_type);
                   2855:            }
                   2856:          these_vbase_types = TREE_CHAIN (these_vbase_types);
                   2857:        }
                   2858:     }
                   2859:   else for (i = binfos ? TREE_VEC_LENGTH (binfos)-1 : -1; i >= 0; i--)
                   2860:     {
1.1.1.4 ! root     2861:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          2862:       if (TREE_VIA_VIRTUAL (base_binfo) && ! BINFO_VBASE_MARKED (base_binfo))
1.1       root     2863:        {
1.1.1.4 ! root     2864:          vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (base_binfo),
        !          2865:                                    BINFO_VTABLE (base_binfo),
        !          2866:                                    BINFO_VIRTUALS (base_binfo), vbase_types);
1.1       root     2867:          TREE_VIA_VIRTUAL (vbase_types) = 1;
1.1.1.4 ! root     2868:          SET_BINFO_VBASE_MARKED (base_binfo);
1.1       root     2869:        }
                   2870:     }
                   2871:   SET_BINFO_MARKED (binfo);
                   2872: }
                   2873: 
                   2874: /* Some virtual baseclasses might be virtual baseclasses for
                   2875:    other virtual baseclasses.  We sort the virtual baseclasses
                   2876:    topologically: in the list returned, the first virtual base
                   2877:    classes have no virtual baseclasses themselves, and any entry
                   2878:    on the list has no dependency on virtual base classes later in the
                   2879:    list.  */
                   2880: tree
                   2881: get_vbase_types (type)
                   2882:      tree type;
                   2883: {
                   2884:   tree ordered_vbase_types = NULL_TREE, prev, next;
                   2885:   tree vbases;
                   2886: 
                   2887:   vbase_types = NULL_TREE;
                   2888:   dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp);
                   2889:   dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
                   2890: 
                   2891:   while (vbase_types)
                   2892:     {
                   2893:       /* Now sort these types.  This is essentially a bubble merge.  */
                   2894: 
                   2895:       /* Farm out virtual baseclasses which have no marked ancestors.  */
                   2896:       for (vbases = vbase_types, prev = NULL_TREE;
                   2897:           vbases; vbases = next)
                   2898:        {
                   2899:          next = TREE_CHAIN (vbases);
                   2900:          /* If VBASES does not have any vbases itself, or it's
                   2901:             topologically safe, it goes into the sorted list.  */
                   2902:          if (! CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases))
                   2903:              || BINFO_VBASE_MARKED (vbases) == 0)
                   2904:            {
                   2905:              if (prev)
                   2906:                TREE_CHAIN (prev) = TREE_CHAIN (vbases);
                   2907:              else
                   2908:                vbase_types = TREE_CHAIN (vbases);
                   2909:              TREE_CHAIN (vbases) = NULL_TREE;
                   2910:              ordered_vbase_types = chainon (ordered_vbase_types, vbases);
                   2911:              CLEAR_BINFO_VBASE_MARKED (vbases);
                   2912:            }
                   2913:          else
                   2914:            prev = vbases;
                   2915:        }
                   2916: 
                   2917:       /* Now unmark types all of whose ancestors are now on the
                   2918:         `ordered_vbase_types' list.  */
                   2919:       for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
                   2920:        {
                   2921:          /* If all our virtual baseclasses are unmarked, ok.  */
                   2922:          tree t = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases));
                   2923:          while (t && (BINFO_VBASE_MARKED (t) == 0
                   2924:                       || ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (t))))
                   2925:            t = TREE_CHAIN (t);
                   2926:          if (t == NULL_TREE)
                   2927:            CLEAR_BINFO_VBASE_MARKED (vbases);
                   2928:        }
                   2929:     }
                   2930: 
                   2931:   return ordered_vbase_types;
                   2932: }
                   2933: 
                   2934: static void
                   2935: dfs_record_inheritance (binfo)
                   2936:      tree binfo;
                   2937: {
                   2938:   tree binfos = BINFO_BASETYPES (binfo);
                   2939:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
                   2940:   mi_boolean *derived_row = BINFO_DERIVES_FROM_STAR (binfo);
                   2941: 
                   2942:   for (i = n_baselinks-1; i >= 0; i--)
                   2943:     {
                   2944:       int j;
1.1.1.4 ! root     2945:       tree base_binfo = TREE_VEC_ELT (binfos, i);
        !          2946:       tree baseclass = BINFO_TYPE (base_binfo);
        !          2947:       mi_boolean *base_row = BINFO_DERIVES_FROM_STAR (base_binfo);
1.1       root     2948: 
                   2949:       /* Don't search if there's nothing there!  MI_SIZE can be
                   2950:         zero as a result of parse errors.  */
                   2951:       if (TYPE_BINFO_BASETYPES (baseclass) && mi_size > 0)
                   2952:        for (j = mi_size*(CLASSTYPE_CID (baseclass)-1); j >= 0; j -= mi_size)
                   2953:          derived_row[j] |= base_row[j];
                   2954:       TYPE_DERIVES_FROM (baseclass, BINFO_TYPE (binfo)) = 1;
                   2955:     }
                   2956: 
                   2957:   SET_BINFO_MARKED (binfo);
                   2958: }
                   2959: 
                   2960: /* Given a _CLASSTYPE node in a multiple inheritance lattice,
                   2961:    convert the lattice into a simple relation such that,
                   2962:    given to CIDs, C1 and C2, one can determine if C1 <= C2
                   2963:    or C2 <= C1 or C1 <> C2.
                   2964: 
                   2965:    Once constructed, we walk the lattice depth fisrt,
                   2966:    applying various functions to elements as they are encountered.
                   2967: 
                   2968:    We use xmalloc here, in case we want to randomly free these tables.  */
                   2969: 
                   2970: #define SAVE_MI_MATRIX
                   2971: 
                   2972: void
                   2973: build_mi_matrix (type)
                   2974:      tree type;
                   2975: {
                   2976:   tree binfo = TYPE_BINFO (type);
                   2977:   cid = 0;
                   2978: 
                   2979: #ifdef SAVE_MI_MATRIX
                   2980:   if (CLASSTYPE_MI_MATRIX (type))
                   2981:     {
                   2982:       mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
                   2983:       mi_matrix = CLASSTYPE_MI_MATRIX (type);
                   2984:       mi_type = type;
                   2985:       dfs_walk (binfo, dfs_number, unnumberedp);
                   2986:       return;
                   2987:     }
                   2988: #endif
                   2989: 
                   2990:   mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
                   2991:   mi_matrix = (char *)xmalloc ((mi_size+1) * (mi_size+1));
                   2992:   mi_type = type;
                   2993:   bzero (mi_matrix, mi_size * mi_size);
                   2994:   dfs_walk (binfo, dfs_number, unnumberedp);
                   2995:   dfs_walk (binfo, dfs_record_inheritance, unmarkedp);
                   2996:   dfs_walk (binfo, dfs_unmark, markedp);
                   2997: }
                   2998: 
                   2999: void
                   3000: free_mi_matrix ()
                   3001: {
                   3002:   dfs_walk (TYPE_BINFO (mi_type), dfs_unnumber, numberedp);
                   3003: 
                   3004: #ifdef SAVE_MI_MATRIX
                   3005:   CLASSTYPE_MI_MATRIX (mi_type) = mi_matrix;
                   3006: #else
                   3007:   free (mi_matrix);
                   3008:   mi_size = 0;
                   3009:   cid = 0;
                   3010: #endif
                   3011: }
                   3012: 
                   3013: /* Local variables for detecting ambiguities of virtual functions
                   3014:    when two or more classes are joined at a multiple inheritance
                   3015:    seam.  */
                   3016: typedef tree mi_ventry[3];
                   3017: static mi_ventry *mi_vmatrix;
                   3018: static int *mi_vmax;
                   3019: static int mi_vrows, mi_vcols;
                   3020: #define MI_VMATRIX(ROW,COL) ((mi_vmatrix + (ROW)*mi_vcols)[COL])
                   3021: 
                   3022: /* Build a table of virtual functions for a multiple-inheritance
                   3023:    structure.  Here, there are N base classes, and at most
                   3024:    M entries per class.
                   3025: 
                   3026:    This function does nothing if N is 0 or 1.  */
                   3027: void
                   3028: build_mi_virtuals (rows, cols)
                   3029:      int rows, cols;
                   3030: {
                   3031:   if (rows < 2 || cols == 0)
                   3032:     return;
                   3033:   mi_vrows = rows;
                   3034:   mi_vcols = cols;
                   3035:   mi_vmatrix = (mi_ventry *)xmalloc ((rows+1) * cols * sizeof (mi_ventry));
                   3036:   mi_vmax = (int *)xmalloc ((rows+1) * sizeof (int));
                   3037: 
                   3038:   bzero (mi_vmax, rows * sizeof (int));
                   3039: 
1.1.1.3   root     3040:   /* Row indices start at 1, so adjust this.  */
1.1       root     3041:   mi_vmatrix -= cols;
                   3042:   mi_vmax -= 1;
                   3043: }
                   3044: 
                   3045: /* Comparison function for ordering virtual function table entries.  */
                   3046: static int
                   3047: rank_mi_virtuals (v1, v2)
                   3048:      mi_ventry *v1, *v2;
                   3049: {
                   3050:   tree p1, p2;
                   3051:   int i;
                   3052: 
                   3053:   i = ((long) (DECL_NAME ((*v1)[0])) - (long) (DECL_NAME ((*v2)[0])));
                   3054:   if (i)
                   3055:     return i;
                   3056:   p1 = (*v1)[1];
                   3057:   p2 = (*v2)[1];
                   3058: 
                   3059:   if (p1 == p2)
                   3060:     return 0;
                   3061: 
                   3062:   while (p1 && p2)
                   3063:     {
                   3064:       i = ((long) (TREE_VALUE (p1)) - (long) (TREE_VALUE (p2)));
                   3065:       if (i)
                   3066:        return i;
                   3067: 
                   3068:       if (TREE_CHAIN (p1))
                   3069:        {
                   3070:          if (! TREE_CHAIN (p2))
                   3071:            return 1;
                   3072:          p1 = TREE_CHAIN (p1);
                   3073:          p2 = TREE_CHAIN (p2);
                   3074:        }
                   3075:       else if (TREE_CHAIN (p2))
                   3076:        return -1;
                   3077:       else
                   3078:        {
                   3079:          /* When matches of argument lists occur, pick lowest
                   3080:             address to keep searching time to a minimum on
                   3081:             later passes--like hashing, only different.
                   3082:             *MUST BE STABLE*.  */
                   3083:          if ((long) ((*v2)[1]) < (long) ((*v1)[1]))
                   3084:            (*v1)[1] = (*v2)[1];
                   3085:          else
                   3086:            (*v2)[1] = (*v1)[1];
                   3087:          return 0;
                   3088:        }
                   3089:     }
                   3090:   return 0;
                   3091: }
                   3092: 
                   3093: /* Install the virtuals functions got from the initializer VIRTUALS to
                   3094:    the table at index ROW.  */
                   3095: void
                   3096: add_mi_virtuals (row, virtuals)
                   3097:      int row;
                   3098:      tree virtuals;
                   3099: {
                   3100:   int col = 0;
                   3101: 
                   3102:   if (mi_vmatrix == 0)
                   3103:     return;
                   3104:   while (virtuals)
                   3105:     {
                   3106:       tree decl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
                   3107:       MI_VMATRIX (row, col)[0] = decl;
                   3108:       MI_VMATRIX (row, col)[1] = FUNCTION_ARG_CHAIN (decl);
                   3109:       MI_VMATRIX (row, col)[2] = TREE_VALUE (virtuals);
                   3110:       virtuals = TREE_CHAIN (virtuals);
                   3111:       col += 1;
                   3112:     }
                   3113:   mi_vmax[row] = col;
                   3114: 
                   3115:   qsort (mi_vmatrix + row * mi_vcols,
                   3116:         col,
                   3117:         sizeof (mi_ventry),
                   3118:         rank_mi_virtuals);
                   3119: }
                   3120: 
                   3121: /* If joining two types results in an ambiguity in the virtual
                   3122:    function table, report such here.  */
                   3123: void
                   3124: report_ambiguous_mi_virtuals (rows, type)
                   3125:      int rows;
                   3126:      tree type;
                   3127: {
                   3128:   int *mi_vmin;
                   3129:   int row1, col1, row, col;
                   3130: 
                   3131:   if (mi_vmatrix == 0)
                   3132:     return;
                   3133: 
                   3134:   /* Now virtuals are all sorted, so we merge to find ambiguous cases.  */
                   3135:   mi_vmin = (int *)alloca ((rows+1) * sizeof (int));
                   3136:   bzero (mi_vmin, rows * sizeof (int));
                   3137: 
                   3138:   /* adjust.  */
                   3139:   mi_vmin -= 1;
                   3140: 
                   3141:   /* For each base class with virtual functions (and this includes views
                   3142:      of the virtual baseclasses from different base classes), see that
                   3143:      each virtual function in that base class has a unique meet.
                   3144: 
                   3145:      When the column loop is finished, THIS_DECL is in fact the meet.
                   3146:      If that value does not appear in the virtual function table for
                   3147:      the row, install it.  This happens when that virtual function comes
                   3148:      from a virtual baseclass, or a non-leftmost baseclass.  */
1.1.1.4 ! root     3149: 
1.1       root     3150:   for (row1 = 1; row1 < rows; row1++)
                   3151:     {
                   3152:       tree this_decl = 0;
                   3153: 
                   3154:       for (col1 = mi_vmax[row1]-1; col1 >= mi_vmin[row1]; col1--)
                   3155:        {
                   3156:          tree these_args = MI_VMATRIX (row1, col1)[1];
                   3157:          tree this_context;
                   3158: 
                   3159:          this_decl = MI_VMATRIX (row1, col1)[0];
                   3160:          if (this_decl == 0)
                   3161:            continue;
                   3162:          this_context = TYPE_BINFO (DECL_CLASS_CONTEXT (this_decl));
                   3163: 
                   3164:          if (this_context != TYPE_BINFO (type))
                   3165:            this_context = get_binfo (this_context, type, 0);
                   3166: 
                   3167:          for (row = row1+1; row <= rows; row++)
                   3168:            for (col = mi_vmax[row]-1; col >= mi_vmin[row]; col--)
                   3169:              {
                   3170:                mi_ventry this_entry;
                   3171: 
                   3172:                if (MI_VMATRIX (row, col)[0] == 0)
                   3173:                  continue;
                   3174: 
                   3175:                this_entry[0] = this_decl;
                   3176:                this_entry[1] = these_args;
                   3177:                this_entry[2] = MI_VMATRIX (row1, col1)[2];
                   3178:                if (rank_mi_virtuals (this_entry, MI_VMATRIX (row, col)) == 0)
                   3179:                  {
                   3180:                    /* They are equal.  There are four possibilities:
1.1.1.4 ! root     3181: 
1.1       root     3182:                       (1) Derived class is defining this virtual function.
                   3183:                       (2) Two paths to the same virtual function in the
                   3184:                       same base class.
                   3185:                       (3) A path to a virtual function declared in one base
                   3186:                       class, and another path to a virtual function in a
                   3187:                       base class of the base class.
                   3188:                       (4) Two paths to the same virtual function in different
                   3189:                       base classes.
1.1.1.4 ! root     3190: 
1.1       root     3191:                       The first three cases are ok (non-ambiguous).  */
                   3192: 
                   3193:                    tree that_context, tmp;
                   3194:                    int this_before_that;
                   3195: 
                   3196:                    if (type == BINFO_TYPE (this_context))
                   3197:                      /* case 1.  */
                   3198:                      goto ok;
                   3199:                    that_context = get_binfo (DECL_CLASS_CONTEXT (MI_VMATRIX (row, col)[0]), type, 0);
                   3200:                    if (that_context == this_context)
                   3201:                      /* case 2.  */
                   3202:                      goto ok;
                   3203:                    if (that_context != NULL_TREE)
                   3204:                      {
                   3205:                        tmp = get_binfo (that_context, this_context, 0);
                   3206:                        this_before_that = (that_context != tmp);
                   3207:                        if (this_before_that == 0)
                   3208:                          /* case 3a.  */
                   3209:                          goto ok;
                   3210:                        tmp = get_binfo (this_context, that_context, 0);
                   3211:                        this_before_that = (this_context == tmp);
                   3212:                        if (this_before_that != 0)
                   3213:                          /* case 3b.  */
                   3214:                          goto ok;
                   3215: 
                   3216:                        /* case 4.  */
                   3217:                        error_with_decl (MI_VMATRIX (row, col)[0], "ambiguous virtual function `%s'");
                   3218:                        error_with_decl (this_decl, "ambiguating function `%s' (joined by type `%s')", IDENTIFIER_POINTER (current_class_name));
                   3219:                      }
                   3220:                  ok:
                   3221:                    MI_VMATRIX (row, col)[0] = 0;
                   3222: 
                   3223:                    /* Let zeros propagate.  */
                   3224:                    if (col == mi_vmax[row]-1)
                   3225:                      {
                   3226:                        int i = col;
                   3227:                        while (i >= mi_vmin[row]
                   3228:                               && MI_VMATRIX (row, i)[0] == 0)
                   3229:                          i--;
                   3230:                        mi_vmax[row] = i+1;
                   3231:                      }
                   3232:                    else if (col == mi_vmin[row])
                   3233:                      {
                   3234:                        int i = col;
                   3235:                        while (i < mi_vmax[row]
                   3236:                               && MI_VMATRIX (row, i)[0] == 0)
                   3237:                          i++;
                   3238:                        mi_vmin[row] = i;
                   3239:                      }
                   3240:                  }
                   3241:              }
                   3242:        }
                   3243:     }
                   3244:   free (mi_vmatrix + mi_vcols);
                   3245:   mi_vmatrix = 0;
                   3246:   free (mi_vmax + 1);
                   3247:   mi_vmax = 0;
                   3248: }
                   3249: 
                   3250: /* If we want debug info for a type TYPE, make sure all its base types
                   3251:    are also marked as being potentially interesting.  This avoids
                   3252:    the problem of not writing any debug info for intermediate basetypes
                   3253:    that have abstract virtual functions.  */
                   3254: 
                   3255: void
                   3256: note_debug_info_needed (type)
                   3257:      tree type;
                   3258: {
                   3259:   dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
                   3260: }
                   3261: 
                   3262: /* Subroutines of push_class_decls ().  */
                   3263: 
                   3264: /* Add the instance variables which this class contributed to the
                   3265:    current class binding contour.  When a redefinition occurs,
                   3266:    if the redefinition is strictly within a single inheritance path,
                   3267:    we just overwrite (in the case of a data field) or
                   3268:    cons (in the case of a member function) the old declaration with
                   3269:    the new.  If the fields are not within a single inheritance path,
                   3270:    we must cons them in either case.  */
                   3271: 
                   3272: static void
                   3273: dfs_pushdecls (binfo)
                   3274:      tree binfo;
                   3275: {
                   3276:   tree type = BINFO_TYPE (binfo);
                   3277:   tree fields, *methods, *end;
                   3278:   tree method_vec;
                   3279: 
                   3280:   for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
                   3281:     {
                   3282:       /* Unmark so that if we are in a constructor, and then find that
                   3283:         this field was initialized by a base initializer,
                   3284:         we can emit an error message.  */
                   3285:       if (TREE_CODE (fields) == FIELD_DECL)
                   3286:        TREE_USED (fields) = 0;
                   3287: 
                   3288:       if (DECL_NAME (fields) == NULL_TREE
                   3289:          && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
                   3290:        {
                   3291:          dfs_pushdecls (TYPE_BINFO (TREE_TYPE (fields)));
                   3292:          continue;
                   3293:        }
                   3294:       if (TREE_CODE (fields) != TYPE_DECL)
                   3295:        {
                   3296:          DECL_PUBLIC (fields) = 0;
                   3297:          DECL_PROTECTED (fields) = 0;
                   3298:          DECL_PRIVATE (fields) = 0;
                   3299:        }
                   3300: 
                   3301:       if (DECL_NAME (fields))
                   3302:        {
                   3303:          tree value = IDENTIFIER_CLASS_VALUE (DECL_NAME (fields));
                   3304:          if (value)
                   3305:            {
                   3306:              tree context;
                   3307: 
                   3308:              /* Possible ambiguity.  If its defining type(s)
                   3309:                 is (are all) derived from us, no problem.  */
                   3310: 
                   3311:              if (TREE_CODE (value) != TREE_LIST)
                   3312:                {
                   3313:                  context = DECL_CLASS_CONTEXT (value);
                   3314: 
1.1.1.4 ! root     3315:                  if (context && (context == type
        !          3316:                                  || TYPE_DERIVES_FROM (context, type)))
1.1       root     3317:                    value = fields;
                   3318:                  else
                   3319:                    value = tree_cons (NULL_TREE, fields,
                   3320:                                       build_tree_list (NULL_TREE, value));
                   3321:                }
                   3322:              else
                   3323:                {
                   3324:                  /* All children may derive from us, in which case
                   3325:                     there is no problem.  Otherwise, we have to
                   3326:                     keep lists around of what the ambiguities might be.  */
                   3327:                  tree values;
                   3328:                  int problem = 0;
                   3329: 
                   3330:                  for (values = value; values; values = TREE_CHAIN (values))
                   3331:                    {
                   3332:                      tree sub_values = TREE_VALUE (values);
                   3333: 
                   3334:                      if (TREE_CODE (sub_values) == TREE_LIST)
                   3335:                        {
                   3336:                          for (; sub_values; sub_values = TREE_CHAIN (sub_values))
                   3337:                            {
                   3338:                              context = DECL_CLASS_CONTEXT (TREE_VALUE (sub_values));
                   3339: 
                   3340:                              if (! TYPE_DERIVES_FROM (context, type))
                   3341:                                {
                   3342:                                  value = tree_cons (NULL_TREE, TREE_VALUE (values), value);
                   3343:                                  problem = 1;
                   3344:                                  break;
                   3345:                                }
                   3346:                            }
                   3347:                        }
                   3348:                      else
                   3349:                        {
                   3350:                          context = DECL_CLASS_CONTEXT (sub_values);
                   3351: 
                   3352:                          if (! TYPE_DERIVES_FROM (context, type))
                   3353:                            {
                   3354:                              value = tree_cons (NULL_TREE, values, value);
                   3355:                              problem = 1;
                   3356:                              break;
                   3357:                            }
                   3358:                        }
                   3359:                    }
                   3360:                  if (! problem) value = fields;
                   3361:                }
                   3362: 
                   3363:              /* Mark this as a potentially ambiguous member.  */
                   3364:              if (TREE_CODE (value) == TREE_LIST)
                   3365:                {
                   3366:                  /* Leaving TREE_TYPE blank is intentional.
                   3367:                     We cannot use `error_mark_node' (lookup_name)
                   3368:                     or `unknown_type_node' (all member functions use this).  */
                   3369:                  TREE_NONLOCAL_FLAG (value) = 1;
                   3370:                }
                   3371: 
                   3372:              IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = value;
                   3373:            }
                   3374:          else IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = fields;
                   3375:        }
                   3376:     }
                   3377: 
                   3378:   method_vec = CLASSTYPE_METHOD_VEC (type);
                   3379:   if (method_vec != 0)
                   3380:     {
                   3381:       /* Farm out constructors and destructors.  */
                   3382:       methods = &TREE_VEC_ELT (method_vec, 1);
                   3383:       end = TREE_VEC_END (method_vec);
                   3384: 
                   3385:       /* This does not work for multiple inheritance yet.  */
                   3386:       while (methods != end)
                   3387:        {
                   3388:          /* This will cause lookup_name to return a pointer
                   3389:             to the tree_list of possible methods of this name.
                   3390:             If the order is a problem, we can nreverse them.  */
                   3391:          tree tmp;
                   3392:          tree old = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
                   3393: 
                   3394:          if (old && TREE_CODE (old) == TREE_LIST)
                   3395:            tmp = tree_cons (DECL_NAME (*methods), *methods, old);
                   3396:          else
                   3397:            {
                   3398:              /* Only complain if we shadow something we can access.  */
                   3399:              if (old && (DECL_CLASS_CONTEXT (old) == current_class_type
                   3400:                          || ! TREE_PRIVATE (old)))
                   3401:                /* Should figure out visibility more accurately.  */
                   3402:                warning ("shadowing member `%s' with member function",
                   3403:                         IDENTIFIER_POINTER (DECL_NAME (*methods)));
                   3404:              tmp = build_tree_list (DECL_NAME (*methods), *methods);
                   3405:            }
                   3406: 
                   3407:          TREE_TYPE (tmp) = unknown_type_node;
                   3408: #if 0
                   3409:          TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
                   3410: #endif
                   3411:          TREE_NONLOCAL_FLAG (tmp) = 1;
                   3412:          IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = tmp;
                   3413: 
                   3414:          tmp = *methods;
                   3415:          while (tmp != 0)
                   3416:            {
                   3417:              DECL_PUBLIC (tmp) = 0;
                   3418:              DECL_PROTECTED (tmp) = 0;
                   3419:              DECL_PRIVATE (tmp) = 0;
                   3420:              tmp = DECL_CHAIN (tmp);
                   3421:            }
                   3422: 
                   3423:          methods++;
                   3424:        }
                   3425:     }
                   3426:   SET_BINFO_MARKED (binfo);
                   3427: }
                   3428: 
                   3429: /* Consolidate unique (by name) member functions.  */
                   3430: static void
                   3431: dfs_compress_decls (binfo)
                   3432:      tree binfo;
                   3433: {
                   3434:   tree type = BINFO_TYPE (binfo);
                   3435:   tree method_vec = CLASSTYPE_METHOD_VEC (type);
                   3436: 
                   3437:   if (method_vec != 0)
                   3438:     {
                   3439:       /* Farm out constructors and destructors.  */
                   3440:       tree *methods = &TREE_VEC_ELT (method_vec, 1);
                   3441:       tree *end = TREE_VEC_END (method_vec);
                   3442: 
                   3443:       for (; methods != end; methods++)
                   3444:        {
                   3445:          tree tmp = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
                   3446: 
                   3447:          /* This was replaced in scope by somebody else.  Just leave it
                   3448:             alone.  */
                   3449:          if (TREE_CODE (tmp) != TREE_LIST)
                   3450:            continue;
                   3451: 
                   3452:          if (TREE_CHAIN (tmp) == NULL_TREE
                   3453:              && TREE_VALUE (tmp)
                   3454:              && DECL_CHAIN (TREE_VALUE (tmp)) == NULL_TREE)
                   3455:            {
                   3456:              IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = TREE_VALUE (tmp);
                   3457:            }
                   3458:        }
                   3459:     }
                   3460:   CLEAR_BINFO_MARKED (binfo);
                   3461: }
                   3462: 
                   3463: /* When entering the scope of a class, we cache all of the
                   3464:    fields that that class provides within its inheritance
                   3465:    lattice.  Where ambiguities result, we mark them
                   3466:    with `error_mark_node' so that if they are encountered
                   3467:    without explicit qualification, we can emit an error
                   3468:    message.  */
                   3469: void
                   3470: push_class_decls (type)
                   3471:      tree type;
                   3472: {
                   3473:   tree id;
                   3474:   struct obstack *ambient_obstack = current_obstack;
                   3475: 
                   3476: #if 0
                   3477:   tree tags = CLASSTYPE_TAGS (type);
                   3478: 
                   3479:   while (tags)
                   3480:     {
                   3481:       tree code_type_node;
                   3482:       tree tag;
                   3483: 
                   3484:       switch (TREE_CODE (TREE_VALUE (tags)))
                   3485:        {
                   3486:        case ENUMERAL_TYPE:
                   3487:          code_type_node = enum_type_node;
                   3488:          break;
                   3489:        case RECORD_TYPE:
                   3490:          code_type_node = record_type_node;
                   3491:          break;
                   3492:        case CLASS_TYPE:
                   3493:          code_type_node = class_type_node;
                   3494:          break;
                   3495:        case UNION_TYPE:
                   3496:          code_type_node = union_type_node;
                   3497:          break;
                   3498:        default:
1.1.1.4 ! root     3499:          my_friendly_assert (0, 297);
1.1       root     3500:        }
                   3501:       tag = xref_tag (code_type_node, TREE_PURPOSE (tags),
                   3502:                      TYPE_BINFO_BASETYPE (TREE_VALUE (tags), 0));
1.1.1.2   root     3503: #if 0 /* not yet, should get fixed properly later */
                   3504:       pushdecl (make_type_decl (TREE_PURPOSE (tags), TREE_VALUE (tags)));
                   3505: #else
1.1       root     3506:       pushdecl (build_decl (TYPE_DECL, TREE_PURPOSE (tags), TREE_VALUE (tags)));
1.1.1.2   root     3507: #endif
1.1       root     3508:     }
                   3509: #endif
                   3510: 
                   3511:   current_obstack = &bridge_obstack;
                   3512:   search_stack = push_search_level (search_stack, &bridge_obstack);
                   3513: 
1.1.1.3   root     3514:   id = TYPE_IDENTIFIER (type);
1.1       root     3515:   if (IDENTIFIER_TEMPLATE (id) != 0)
                   3516:     {
                   3517: #if 0
                   3518:       tree tmpl = IDENTIFIER_TEMPLATE (id);
                   3519:       push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
                   3520:                           TREE_VALUE (tmpl), 1);
                   3521: #endif
                   3522:       overload_template_name (id, 0);
                   3523:     }
                   3524: 
                   3525:   /* Push class fields into CLASS_VALUE scope, and mark.  */
                   3526:   dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
                   3527: 
                   3528:   /* Compress fields which have only a single entry
                   3529:      by a given name, and unmark.  */
                   3530:   dfs_walk (TYPE_BINFO (type), dfs_compress_decls, markedp);
                   3531:   current_obstack = ambient_obstack;
                   3532: }
                   3533: 
                   3534: static void
                   3535: dfs_popdecls (binfo)
                   3536:      tree binfo;
                   3537: {
                   3538:   tree type = BINFO_TYPE (binfo);
                   3539:   tree fields = TYPE_FIELDS (type);
                   3540:   tree method_vec = CLASSTYPE_METHOD_VEC (type);
                   3541: 
                   3542:   while (fields)
                   3543:     {
                   3544:       if (DECL_NAME (fields) == NULL_TREE
                   3545:          && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
                   3546:        {
                   3547:          dfs_popdecls (TYPE_BINFO (TREE_TYPE (fields)));
                   3548:        }
                   3549:       else if (DECL_NAME (fields))
                   3550:        IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = NULL_TREE;
                   3551:       fields = TREE_CHAIN (fields);
                   3552:     }
                   3553:   if (method_vec != 0)
                   3554:     {
                   3555:       tree *methods = &TREE_VEC_ELT (method_vec, 0);
                   3556:       tree *end = TREE_VEC_END (method_vec);
                   3557: 
                   3558:       /* Clear out ctors and dtors.  */
                   3559:       if (*methods)
1.1.1.3   root     3560:        IDENTIFIER_CLASS_VALUE (TYPE_IDENTIFIER (type)) = NULL_TREE;
1.1       root     3561: 
                   3562:       for (methods += 1; methods != end; methods++)
                   3563:        IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = NULL_TREE;
                   3564:     }
                   3565: 
                   3566:   SET_BINFO_MARKED (binfo);
                   3567: }
                   3568: 
                   3569: void
                   3570: pop_class_decls (type)
                   3571:      tree type;
                   3572: {
                   3573:   tree binfo = TYPE_BINFO (type);
                   3574: 
                   3575:   /* Clear out the IDENTIFIER_CLASS_VALUE which this
                   3576:      class may have occupied, and mark.  */
                   3577:   dfs_walk (binfo, dfs_popdecls, unmarkedp);
                   3578: 
                   3579:   /* Unmark.  */
                   3580:   dfs_walk (binfo, dfs_unmark, markedp);
                   3581: 
                   3582: #if 0
1.1.1.3   root     3583:   tmpl = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type));
1.1       root     3584:   if (tmpl != 0)
                   3585:     pop_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
                   3586:                        TREE_VALUE (tmpl), 1);
                   3587: #endif
                   3588: 
                   3589:   search_stack = pop_search_level (search_stack);
                   3590: }
                   3591: 
                   3592: /* Given a base type PARENT, and a derived type TYPE, build
                   3593:    a name which distinguishes exactly the PARENT member of TYPE's type.
                   3594: 
                   3595:    FORMAT is a string which controls how sprintf formats the name
                   3596:    we have generated.
                   3597: 
                   3598:    For example, given
                   3599: 
                   3600:        class A; class B; class C : A, B;
                   3601: 
                   3602:    it is possible to distinguish "A" from "C's A".  And given
                   3603: 
                   3604:        class L;
                   3605:        class A : L; class B : L; class C : A, B;
                   3606: 
                   3607:    it is possible to distinguish "L" from "A's L", and also from
1.1.1.4 ! root     3608:    "C's L from A".
        !          3609: 
        !          3610:    Make sure to use the DECL_ASSEMBLER_NAME of the TYPE_NAME of the
        !          3611:    type, as template have DECL_NAMEs like: X<int>, whereas the
        !          3612:    DECL_ASSEMBLER_NAME is set to be something the assembler can handle.
        !          3613:   */
1.1       root     3614: tree
                   3615: build_type_pathname (format, parent, type)
                   3616:      char *format;
                   3617:      tree parent, type;
                   3618: {
                   3619:   extern struct obstack temporary_obstack;
                   3620:   char *first, *base, *name;
                   3621:   int i;
                   3622:   tree id;
                   3623: 
                   3624:   parent = TYPE_MAIN_VARIANT (parent);
                   3625: 
                   3626:   /* Remember where to cut the obstack to.  */
                   3627:   first = obstack_base (&temporary_obstack);
                   3628: 
                   3629:   /* Put on TYPE+PARENT.  */
                   3630:   obstack_grow (&temporary_obstack,
1.1.1.4 ! root     3631:                TYPE_ASSEMBLER_NAME_STRING (type),
        !          3632:                TYPE_ASSEMBLER_NAME_LENGTH (type));
1.1       root     3633:   obstack_1grow (&temporary_obstack, JOINER);
                   3634:   obstack_grow0 (&temporary_obstack,
1.1.1.4 ! root     3635:                 TYPE_ASSEMBLER_NAME_STRING (parent),
        !          3636:                 TYPE_ASSEMBLER_NAME_LENGTH (parent));
1.1       root     3637:   i = obstack_object_size (&temporary_obstack);
                   3638:   base = obstack_base (&temporary_obstack);
                   3639:   obstack_finish (&temporary_obstack);
                   3640: 
                   3641:   /* Put on FORMAT+TYPE+PARENT.  */
                   3642:   obstack_blank (&temporary_obstack, strlen (format) + i + 1);
                   3643:   name = obstack_base (&temporary_obstack);
                   3644:   sprintf (name, format, base);
                   3645:   id = get_identifier (name);
                   3646:   obstack_free (&temporary_obstack, first);
                   3647: 
                   3648:   return id;
                   3649: }
                   3650: 
                   3651: static int
                   3652: bfs_unmark_finished_struct (binfo, i)
                   3653:      tree binfo;
                   3654:      int i;
                   3655: {
                   3656:   if (i >= 0)
                   3657:     binfo = BINFO_BASETYPE (binfo, i);
                   3658: 
                   3659:   if (BINFO_NEW_VTABLE_MARKED (binfo))
                   3660:     {
                   3661:       tree decl, context;
                   3662: 
                   3663:       if (TREE_VIA_VIRTUAL (binfo))
                   3664:        binfo = binfo_member (BINFO_TYPE (binfo),
                   3665:                              CLASSTYPE_VBASECLASSES (current_class_type));
                   3666: 
                   3667:       decl = BINFO_VTABLE (binfo);
                   3668:       context = DECL_CONTEXT (decl);
                   3669:       DECL_CONTEXT (decl) = 0;
                   3670:       if (write_virtuals >= 0
                   3671:          && DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
                   3672:        DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
                   3673:                                        BINFO_VIRTUALS (binfo));
                   3674:       finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
                   3675:       DECL_CONTEXT (decl) = context;
                   3676:     }
                   3677:   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
                   3678:   CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
                   3679:   return 0;
                   3680: }
                   3681: 
                   3682: void
                   3683: unmark_finished_struct (type)
                   3684:      tree type;
                   3685: {
                   3686:   tree binfo = TYPE_BINFO (type);
                   3687:   bfs_unmark_finished_struct (binfo, -1);
1.1.1.4 ! root     3688:   breadth_first_search (binfo, bfs_unmark_finished_struct, bfs_marked_vtable_pathp);
1.1       root     3689: }
                   3690: 
                   3691: void
                   3692: print_search_statistics ()
                   3693: {
                   3694: #ifdef GATHER_STATISTICS
                   3695:   if (flag_memoize_lookups)
                   3696:     {
                   3697:       fprintf (stderr, "%d memoized contexts saved\n",
                   3698:               n_contexts_saved);
                   3699:       fprintf (stderr, "%d local tree nodes made\n", my_tree_node_counter);
                   3700:       fprintf (stderr, "%d local hash nodes made\n", my_memoized_entry_counter);
                   3701:       fprintf (stderr, "fields statistics:\n");
                   3702:       fprintf (stderr, "  memoized finds = %d; rejects = %d; (searches = %d)\n",
                   3703:               memoized_fast_finds[0], memoized_fast_rejects[0],
                   3704:               memoized_fields_searched[0]);
                   3705:       fprintf (stderr, "  memoized_adds = %d\n", memoized_adds[0]);
                   3706:       fprintf (stderr, "fnfields statistics:\n");
                   3707:       fprintf (stderr, "  memoized finds = %d; rejects = %d; (searches = %d)\n",
                   3708:               memoized_fast_finds[1], memoized_fast_rejects[1],
                   3709:               memoized_fields_searched[1]);
                   3710:       fprintf (stderr, "  memoized_adds = %d\n", memoized_adds[1]);
                   3711:     }
                   3712:   fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
                   3713:           n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1);
                   3714:   fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
                   3715:           n_outer_fields_searched, n_calls_lookup_fnfields);
                   3716:   fprintf (stderr, "%d calls to get_base_type\n", n_calls_get_base_type);
                   3717: #else
                   3718:   fprintf (stderr, "no search statistics\n");
                   3719: #endif
                   3720: }
                   3721: 
                   3722: void
                   3723: init_search_processing ()
                   3724: {
                   3725:   gcc_obstack_init (&search_obstack);
                   3726:   gcc_obstack_init (&type_obstack);
                   3727:   gcc_obstack_init (&type_obstack_entries);
                   3728:   gcc_obstack_init (&bridge_obstack);
                   3729: 
                   3730:   /* This gives us room to build our chains of basetypes,
                   3731:      whether or not we decide to memoize them.  */
                   3732:   type_stack = push_type_level (0, &type_obstack);
                   3733:   _vptr_name = get_identifier ("_vptr");
                   3734: }
                   3735: 
                   3736: void
                   3737: reinit_search_statistics ()
                   3738: {
                   3739:   my_memoized_entry_counter = 0;
                   3740:   memoized_fast_finds[0] = 0;
                   3741:   memoized_fast_finds[1] = 0;
                   3742:   memoized_adds[0] = 0;
                   3743:   memoized_adds[1] = 0;
                   3744:   memoized_fast_rejects[0] = 0;
                   3745:   memoized_fast_rejects[1] = 0;
                   3746:   memoized_fields_searched[0] = 0;
                   3747:   memoized_fields_searched[1] = 0;
                   3748:   n_fields_searched = 0;
                   3749:   n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
                   3750:   n_calls_lookup_fnfields = 0, n_calls_lookup_fnfields_1 = 0;
                   3751:   n_calls_get_base_type = 0;
                   3752:   n_outer_fields_searched = 0;
                   3753:   n_contexts_saved = 0;
                   3754: }

unix.superglobalmegacorp.com

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