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

1.1     ! root        1: /* Breadth-first and depth-first routines for
        !             2:    searching multiple-inheritance lattice for GNU C++.
        !             3:    Copyright (C) 1987, 1989, 1992 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.