Annotation of GNUtools/cc/cp-search.c, revision 1.1

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

unix.superglobalmegacorp.com

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