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

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

unix.superglobalmegacorp.com

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