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

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

unix.superglobalmegacorp.com

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