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

1.1     ! root        1: /* Language-dependent node constructors for parse phase of GNU compiler.
        !             2:    Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
        !             3:    Hacked by Michael Tiemann ([email protected])
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 2, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: #include "config.h"
        !            22: #include <stdio.h>
        !            23: #include "obstack.h"
        !            24: #include "tree.h"
        !            25: #include "cp-tree.h"
        !            26: #include "flags.h"
        !            27: #include "assert.h"
        !            28: 
        !            29: #define CEIL(x,y) (((x) + (y) - 1) / (y))
        !            30: 
        !            31: /* Return nonzero if REF is an lvalue valid for this language.
        !            32:    Lvalues can be assigned, unless they have TREE_READONLY.
        !            33:    Lvalues can have their address taken, unless they have TREE_REGDECL.  */
        !            34: 
        !            35: int
        !            36: lvalue_p (ref)
        !            37:      tree ref;
        !            38: {
        !            39:   register enum tree_code code = TREE_CODE (ref);
        !            40: 
        !            41:   if (language_lvalue_valid (ref))
        !            42:     switch (code)
        !            43:       {
        !            44:       case COMPONENT_REF:
        !            45:        return lvalue_p (TREE_OPERAND (ref, 0));
        !            46: 
        !            47:       case STRING_CST:
        !            48:        return 1;
        !            49: 
        !            50:       case VAR_DECL:
        !            51:        if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
        !            52:            && DECL_LANG_SPECIFIC (ref)
        !            53:            && DECL_IN_AGGR_P (ref))
        !            54:          return 0;
        !            55:       case INDIRECT_REF:
        !            56:       case ARRAY_REF:
        !            57:       case PARM_DECL:
        !            58:       case RESULT_DECL:
        !            59:       case ERROR_MARK:
        !            60:        if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
        !            61:            && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
        !            62:          return 1;
        !            63:        break;
        !            64: 
        !            65:       case TARGET_EXPR:
        !            66:       case WITH_CLEANUP_EXPR:
        !            67:        return 1;
        !            68: 
        !            69:       case CALL_EXPR:
        !            70:        if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE
        !            71:            /* unary_complex_lvalue knows how to deal with this case.  */
        !            72:            || TREE_ADDRESSABLE (TREE_TYPE (ref)))
        !            73:          return 1;
        !            74:        break;
        !            75: 
        !            76:        /* A currently unresolved scope ref.  */
        !            77:       case SCOPE_REF:
        !            78:        abort ();
        !            79:       case OFFSET_REF:
        !            80:        if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
        !            81:          return 1;
        !            82:        if (TREE_CODE (TREE_OPERAND (ref, 1)) == VAR_DECL)
        !            83:          if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
        !            84:              && DECL_LANG_SPECIFIC (ref)
        !            85:              && DECL_IN_AGGR_P (ref))
        !            86:            return 0;
        !            87:          else
        !            88:            return 1;
        !            89:        break;
        !            90:       }
        !            91:   return 0;
        !            92: }
        !            93: 
        !            94: /* Return nonzero if REF is an lvalue valid for this language;
        !            95:    otherwise, print an error message and return zero.  */
        !            96: 
        !            97: int
        !            98: lvalue_or_else (ref, string)
        !            99:      tree ref;
        !           100:      char *string;
        !           101: {
        !           102:   int win = lvalue_p (ref);
        !           103:   if (! win)
        !           104:     error ("invalid lvalue in %s", string);
        !           105:   return win;
        !           106: }
        !           107: 
        !           108: /* INIT is a CALL_EXPR which needs info about its target.
        !           109:    TYPE is the type that this initialization should appear to have.
        !           110: 
        !           111:    Build an encapsulation of the initialization to perform
        !           112:    and return it so that it can be processed by language-independent
        !           113:    and language-specific expression expanders.
        !           114: 
        !           115:    If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression.
        !           116:    Otherwise, cleanups are not built here.  For example, when building
        !           117:    an initialization for a stack slot, since the called function handles
        !           118:    the cleanup, we would not want to do it here.  */
        !           119: tree
        !           120: build_cplus_new (type, init, with_cleanup_p)
        !           121:      tree type;
        !           122:      tree init;
        !           123:      int with_cleanup_p;
        !           124: {
        !           125:   tree slot = build (VAR_DECL, type);
        !           126:   tree rval = build (NEW_EXPR, type,
        !           127:                     TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
        !           128:   TREE_ADDRESSABLE (rval) = 1;
        !           129:   rval = build (TARGET_EXPR, type, slot, rval, 0);
        !           130:   TREE_SIDE_EFFECTS (rval) = 1;
        !           131:   TREE_ADDRESSABLE (rval) = 1;
        !           132: 
        !           133:   if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type))
        !           134:     rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
        !           135:                  build_delete (TYPE_POINTER_TO (type),
        !           136:                                build_unary_op (ADDR_EXPR, slot, 0),
        !           137:                                integer_two_node,
        !           138:                                LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0));
        !           139:   TREE_SIDE_EFFECTS (rval) = 1;
        !           140:   return rval;
        !           141: }
        !           142: 
        !           143: tree
        !           144: break_out_cleanups (exp)
        !           145:      tree exp;
        !           146: {
        !           147:   tree tmp = exp;
        !           148: 
        !           149:   if (TREE_CODE (tmp) == CALL_EXPR
        !           150:       && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))
        !           151:     return build_cplus_new (TREE_TYPE (tmp), tmp, 1);
        !           152: 
        !           153:   while (TREE_CODE (tmp) == NOP_EXPR
        !           154:         || TREE_CODE (tmp) == CONVERT_EXPR
        !           155:         || TREE_CODE (tmp) == NON_LVALUE_EXPR)
        !           156:     {
        !           157:       if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR
        !           158:          && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
        !           159:        {
        !           160:          TREE_OPERAND (tmp, 0)
        !           161:            = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
        !           162:                               TREE_OPERAND (tmp, 0), 1);
        !           163:          break;
        !           164:        }
        !           165:       else
        !           166:        tmp = TREE_OPERAND (tmp, 0);
        !           167:     }
        !           168:   return exp;
        !           169: }
        !           170: 
        !           171: extern struct obstack *current_obstack;
        !           172: extern struct obstack permanent_obstack, class_obstack;
        !           173: extern struct obstack *saveable_obstack;
        !           174: 
        !           175: /* Here is how primitive or already-canonicalized types' hash
        !           176:    codes are made.  MUST BE CONSISTENT WITH tree.c !!! */
        !           177: #define TYPE_HASH(TYPE) ((int) (TYPE) & 0777777)
        !           178: 
        !           179: /* Construct, lay out and return the type of methods belonging to class
        !           180:    BASETYPE and whose arguments and values are described by TYPE.
        !           181:    If that type exists already, reuse it.
        !           182:    TYPE must be a FUNCTION_TYPE node.  */
        !           183: 
        !           184: tree
        !           185: build_cplus_method_type (basetype, rettype, argtypes)
        !           186:      tree basetype, rettype, argtypes;
        !           187: {
        !           188:   register tree t;
        !           189:   tree ptype = build_pointer_type (basetype);
        !           190:   int hashcode;
        !           191: 
        !           192:   /* Make a node of the sort we want.  */
        !           193:   t = make_node (METHOD_TYPE);
        !           194: 
        !           195:   TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
        !           196:   TREE_TYPE (t) = rettype;
        !           197:   ptype = build_type_variant (ptype, !flag_this_is_variable, 0);
        !           198: 
        !           199:   /* The actual arglist for this function includes a "hidden" argument
        !           200:      which is "this".  Put it into the list of argument types.  */
        !           201: 
        !           202:   TYPE_ARG_TYPES (t) = tree_cons (NULL, ptype, argtypes);
        !           203: 
        !           204:   /* If we already have such a type, use the old one and free this one.
        !           205:      Note that it also frees up the above cons cell if found.  */
        !           206:   hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
        !           207:   t = type_hash_canon (hashcode, t);
        !           208: 
        !           209:   if (TYPE_SIZE (t) == 0)
        !           210:     layout_type (t);
        !           211: 
        !           212:   return t;
        !           213: }
        !           214: 
        !           215: tree
        !           216: build_cplus_staticfn_type (basetype, rettype, argtypes)
        !           217:      tree basetype, rettype, argtypes;
        !           218: {
        !           219:   register tree t;
        !           220:   tree ptype = build_pointer_type (basetype);
        !           221:   int hashcode;
        !           222: 
        !           223:   /* Make a node of the sort we want.  */
        !           224:   t = make_node (FUNCTION_TYPE);
        !           225: 
        !           226:   TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
        !           227:   TREE_TYPE (t) = rettype;
        !           228: 
        !           229:   /* The actual arglist for this function includes a "hidden" argument
        !           230:      which is "this".  Put it into the list of argument types.  */
        !           231: 
        !           232:   TYPE_ARG_TYPES (t) = argtypes;
        !           233: 
        !           234:   /* If we already have such a type, use the old one and free this one.
        !           235:      Note that it also frees up the above cons cell if found.  */
        !           236:   hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
        !           237:   t = type_hash_canon (hashcode, t);
        !           238: 
        !           239:   if (TYPE_SIZE (t) == 0)
        !           240:     layout_type (t);
        !           241: 
        !           242:   return t;
        !           243: }
        !           244: 
        !           245: tree
        !           246: build_cplus_array_type (elt_type, index_type)
        !           247:      tree elt_type;
        !           248:      tree index_type;
        !           249: {
        !           250:   register struct obstack *ambient_obstack = current_obstack;
        !           251:   register struct obstack *ambient_saveable_obstack = saveable_obstack;
        !           252:   tree t;
        !           253: 
        !           254:   /* We need a new one.  If both ELT_TYPE and INDEX_TYPE are permanent,
        !           255:      make this permanent too.  */
        !           256:   if (TREE_PERMANENT (elt_type)
        !           257:       && (index_type == 0 || TREE_PERMANENT (index_type)))
        !           258:     {
        !           259:       current_obstack = &permanent_obstack;
        !           260:       saveable_obstack = &permanent_obstack;
        !           261:     }
        !           262: 
        !           263:   t = build_array_type (elt_type, index_type);
        !           264: 
        !           265:   /* Push these needs up so that initialization takes place
        !           266:      more easily.  */
        !           267:   TYPE_NEEDS_CONSTRUCTING (t) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
        !           268:   TYPE_NEEDS_DESTRUCTOR (t) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
        !           269:   current_obstack = ambient_obstack;
        !           270:   saveable_obstack = ambient_saveable_obstack;
        !           271:   return t;
        !           272: }
        !           273: 
        !           274: /* This is temporary until later.  */
        !           275: /* Construct, lay out and return the type of objects which are of type TYPE
        !           276:    as members of type BASETYPE.  If that type exists already, reuse it.  */
        !           277: tree
        !           278: build_member_type (basetype, type)
        !           279:      tree basetype, type;
        !           280: {
        !           281:   register tree t;
        !           282:   int hashcode;
        !           283: 
        !           284:   assert (TREE_CODE (type) != FUNCTION_TYPE);
        !           285: 
        !           286:   /* Make a node of the sort we want.  */
        !           287:   t = make_node (OFFSET_TYPE);
        !           288:   TYPE_OFFSET_BASETYPE (t) = basetype;
        !           289:   TREE_TYPE (t) = type;
        !           290:   hashcode = TYPE_HASH (basetype) + TYPE_HASH (type);
        !           291:   t = type_hash_canon (hashcode, t);
        !           292: 
        !           293:   return t;
        !           294: }
        !           295: 
        !           296: /* Add OFFSET to all child types of T.
        !           297: 
        !           298:    OFFSET, which is a type offset, is number of bytes.
        !           299: 
        !           300:    Note that we don't have to worry about having two paths to the
        !           301:    same base type, since this type owns its association list.  */
        !           302: void
        !           303: propagate_binfo_offsets (binfo, offset)
        !           304:      tree binfo;
        !           305:      tree offset;
        !           306: {
        !           307:   tree t = BINFO_TYPE (binfo);
        !           308:   tree binfos = BINFO_BASETYPES (binfo);
        !           309:   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !           310: 
        !           311:   for (i = 0; i < n_baselinks; /* note increment is done in the loop.  */)
        !           312:     {
        !           313:       tree child = TREE_VEC_ELT (binfos, i);
        !           314: 
        !           315:       if (TREE_VIA_VIRTUAL (child))
        !           316:        i += 1;
        !           317:       else
        !           318:        {
        !           319:          int j;
        !           320:          tree child_binfos = BINFO_BASETYPES (child);
        !           321:          tree basetype = BINFO_TYPE (child);
        !           322:          tree delta;
        !           323: 
        !           324:          for (j = i+1; j < n_baselinks; j++)
        !           325:            if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j)))
        !           326:              {
        !           327:                /* The next basetype offset must take into account the space
        !           328:                   between the classes, not just the size of each class.  */
        !           329:                delta = size_binop (MINUS_EXPR,
        !           330:                                    BINFO_OFFSET (TREE_VEC_ELT (binfos, j)),
        !           331:                                    BINFO_OFFSET (child));
        !           332:                break;
        !           333:              }
        !           334: 
        !           335: #if 0
        !           336:          if (BINFO_OFFSET_ZEROP (child))
        !           337:            BINFO_OFFSET (child) = offset;
        !           338:          else
        !           339:            BINFO_OFFSET (child)
        !           340:              = size_binop (PLUS_EXPR, BINFO_OFFSET (child), offset);
        !           341: #else
        !           342:          BINFO_OFFSET (child) = offset;
        !           343: #endif
        !           344:          if (child_binfos)
        !           345:            {
        !           346:              int k;
        !           347:              tree chain = NULL_TREE;
        !           348: 
        !           349:              /* Now unshare the structure beneath CHILD.  */
        !           350:              for (k = TREE_VEC_LENGTH (child_binfos)-1;
        !           351:                   k >= 0; k--)
        !           352:                {
        !           353:                  tree child_child = TREE_VEC_ELT (child_binfos, k);
        !           354:                  if (! TREE_VIA_VIRTUAL (child_child))
        !           355:                    TREE_VEC_ELT (child_binfos, k)
        !           356:                      = make_binfo (BINFO_OFFSET (child_child),
        !           357:                                    BINFO_TYPE (child_child),
        !           358:                                    BINFO_VTABLE (child_child),
        !           359:                                    BINFO_VIRTUALS (child_child),
        !           360:                                    chain);
        !           361:                  chain = TREE_VEC_ELT (child_binfos, k);
        !           362:                  TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (child_child);
        !           363:                }
        !           364:              /* Now propagate the offset to the children.  */
        !           365:              propagate_binfo_offsets (child, offset);
        !           366:            }
        !           367: 
        !           368:          /* Go to our next class that counts for offset propagation.  */
        !           369:          i = j;
        !           370:          if (i < n_baselinks)
        !           371:            offset = size_binop (PLUS_EXPR, offset, delta);
        !           372:        }
        !           373:     }
        !           374: }
        !           375: 
        !           376: /* Compute the actual offsets that our virtual base classes
        !           377:    will have *for this type*.  This must be performed after
        !           378:    the fields are laid out, since virtual baseclasses must
        !           379:    lay down at the end of the record.
        !           380: 
        !           381:    Returns the maximum number of virtual functions any of the virtual
        !           382:    baseclasses provide.  */
        !           383: int
        !           384: layout_vbasetypes (rec, max)
        !           385:      tree rec;
        !           386:      int max;
        !           387: {
        !           388:   /* Get all the virtual base types that this type uses.
        !           389:      The TREE_VALUE slot holds the virtual baseclass type.  */
        !           390:   tree vbase_types = get_vbase_types (rec);
        !           391: 
        !           392: #ifdef STRUCTURE_SIZE_BOUNDARY
        !           393:   unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));
        !           394: #else
        !           395:   unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
        !           396: #endif
        !           397: 
        !           398:   /* Record size so far is CONST_SIZE + VAR_SIZE bits,
        !           399:      where CONST_SIZE is an integer
        !           400:      and VAR_SIZE is a tree expression.
        !           401:      If VAR_SIZE is null, the size is just CONST_SIZE.
        !           402:      Naturally we try to avoid using VAR_SIZE.  */
        !           403:   register unsigned const_size = 0;
        !           404:   register tree var_size = 0;
        !           405:   int nonvirtual_const_size;
        !           406:   tree nonvirtual_var_size;
        !           407: 
        !           408:   CLASSTYPE_VBASECLASSES (rec) = vbase_types;
        !           409: 
        !           410:   if (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST)
        !           411:     const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
        !           412:   else
        !           413:     var_size = TYPE_SIZE (rec);
        !           414: 
        !           415:   nonvirtual_const_size = const_size;
        !           416:   nonvirtual_var_size = var_size;
        !           417: 
        !           418:   while (vbase_types)
        !           419:     {
        !           420:       tree basetype = BINFO_TYPE (vbase_types);
        !           421:       tree offset;
        !           422: 
        !           423:       if (const_size == 0)
        !           424:        offset = integer_zero_node;
        !           425:       else
        !           426:        offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
        !           427: 
        !           428:       if (CLASSTYPE_VSIZE (basetype) > max)
        !           429:        max = CLASSTYPE_VSIZE (basetype);
        !           430:       BINFO_OFFSET (vbase_types) = offset;
        !           431: 
        !           432:       if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
        !           433:        const_size += MAX (record_align,
        !           434:                           TREE_INT_CST_LOW (TYPE_SIZE (basetype))
        !           435:                           - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
        !           436:       else if (var_size == 0)
        !           437:        var_size = TYPE_SIZE (basetype);
        !           438:       else
        !           439:        var_size = size_binop (PLUS_EXPR, var_size, TYPE_SIZE (basetype));
        !           440: 
        !           441:       vbase_types = TREE_CHAIN (vbase_types);
        !           442:     }
        !           443: 
        !           444:   if (const_size != nonvirtual_const_size)
        !           445:     {
        !           446:       CLASSTYPE_VBASE_SIZE (rec)
        !           447:        = size_int (const_size - nonvirtual_const_size);
        !           448:       TYPE_SIZE (rec) = size_int (const_size);
        !           449:     }
        !           450: 
        !           451:   /* Now propagate offset information throughout the lattice
        !           452:      under the vbase type.  */
        !           453:   for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;
        !           454:        vbase_types = TREE_CHAIN (vbase_types))
        !           455:     {
        !           456:       tree child_binfos = BINFO_BASETYPES (vbase_types);
        !           457: 
        !           458:       if (child_binfos)
        !           459:        {
        !           460:          tree chain = NULL_TREE;
        !           461:          int j;
        !           462:          /* Now unshare the structure beneath CHILD.  */
        !           463: 
        !           464:          for (j = TREE_VEC_LENGTH (child_binfos)-1;
        !           465:               j >= 0; j--)
        !           466:            {
        !           467:              tree child_child = TREE_VEC_ELT (child_binfos, j);
        !           468:              if (! TREE_VIA_VIRTUAL (child_child))
        !           469:                TREE_VEC_ELT (child_binfos, j)
        !           470:                  = make_binfo (BINFO_OFFSET (child_child),
        !           471:                                BINFO_TYPE (child_child),
        !           472:                                BINFO_VTABLE (child_child),
        !           473:                                BINFO_VIRTUALS (child_child),
        !           474:                                chain);
        !           475:              chain = TREE_VEC_ELT (child_binfos, j);
        !           476:              TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (child_child);
        !           477:            }
        !           478: 
        !           479:          propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
        !           480:        }
        !           481:     }
        !           482: 
        !           483:   return max;
        !           484: }
        !           485: 
        !           486: /* Lay out the base types of a record type, REC.
        !           487:    Tentatively set the size and alignment of REC
        !           488:    according to the base types alone.
        !           489: 
        !           490:    Offsets for immediate nonvirtual baseclasses are also computed here.
        !           491: 
        !           492:    Returns list of virtual base classes in a FIELD_DECL chain.  */
        !           493: tree
        !           494: layout_basetypes (rec, binfos)
        !           495:      tree rec, binfos;
        !           496: {
        !           497:   /* Chain to hold all the new FIELD_DECLs which point at virtual
        !           498:      base classes.  */
        !           499:   tree vbase_decls = NULL_TREE;
        !           500: 
        !           501: #ifdef STRUCTURE_SIZE_BOUNDARY
        !           502:   int record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));
        !           503: #else
        !           504:   int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
        !           505: #endif
        !           506: 
        !           507:   /* Record size so far is CONST_SIZE + VAR_SIZE bits,
        !           508:      where CONST_SIZE is an integer
        !           509:      and VAR_SIZE is a tree expression.
        !           510:      If VAR_SIZE is null, the size is just CONST_SIZE.
        !           511:      Naturally we try to avoid using VAR_SIZE.  */
        !           512:   register int const_size = 0;
        !           513:   register tree var_size = 0;
        !           514:   int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !           515: 
        !           516:   /* Handle basetypes almost like fields, but record their
        !           517:      offsets differently.  */
        !           518: 
        !           519:   for (i = 0; i < n_baseclasses; i++)
        !           520:     {
        !           521:       int inc, desired_align, int_vbase_size;
        !           522:       register tree child = TREE_VEC_ELT (binfos, i);
        !           523:       register tree basetype = BINFO_TYPE (child);
        !           524:       tree decl, offset;
        !           525: 
        !           526:       if (TYPE_SIZE (basetype) == 0)
        !           527:        {
        !           528:          error_with_aggr_type (child, "base class `%s' has incomplete type");
        !           529:          TREE_VIA_PUBLIC (child) = 1;
        !           530:          TREE_VIA_VIRTUAL (child) = 0;
        !           531:          continue;
        !           532:        }
        !           533: 
        !           534:       /* All basetypes are recorded in the association list of the
        !           535:         derived type.  */
        !           536: 
        !           537:       if (TREE_VIA_VIRTUAL (child))
        !           538:        {
        !           539:          tree binfo;
        !           540:          int j;
        !           541:          char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype)
        !           542:                                       + sizeof (VBASE_NAME) + 1);
        !           543: 
        !           544:          /* The offset for a virtual base class is only used in computing
        !           545:             virtual function tables and for initializing virtual base
        !           546:             pointers.  It is built once `get_vbase_types' is called.  */
        !           547: 
        !           548:          /* If this basetype can come from another vbase pointer
        !           549:             without an additional indirection, we will share
        !           550:             that pointer.  If an indirection is involved, we
        !           551:             make our own pointer.  */
        !           552:          for (j = 0; j < n_baseclasses; j++)
        !           553:            {
        !           554:              tree other_child = TREE_VEC_ELT (binfos, j);
        !           555:              if (! TREE_VIA_VIRTUAL (other_child)
        !           556:                  && binfo_member (basetype,
        !           557:                                   CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_child))))
        !           558:                goto got_it;
        !           559:            }
        !           560:          sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
        !           561:          decl = build_lang_decl (FIELD_DECL, get_identifier (name),
        !           562:                                  build_pointer_type (basetype));
        !           563:          DECL_ASSEMBLER_NAME (decl) = get_identifier ("$vb");
        !           564:          DECL_VIRTUAL_P (decl) = 1;
        !           565:          DECL_FIELD_CONTEXT (decl) = rec;
        !           566:          DECL_CLASS_CONTEXT (decl) = rec;
        !           567:          DECL_FCONTEXT (decl) = basetype;
        !           568:          TREE_CHAIN (decl) = vbase_decls;
        !           569:          vbase_decls = decl;
        !           570: 
        !           571:          if (TYPE_HAS_DESTRUCTOR (basetype)
        !           572:              && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
        !           573:            {
        !           574:              warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
        !           575:                                 "destructor `%s' non-virtual");
        !           576:              warning ("in inheritance relationship `%s: virtual %s'",
        !           577:                       TYPE_NAME_STRING (rec),
        !           578:                       TYPE_NAME_STRING (basetype));
        !           579:            }
        !           580:        got_it:
        !           581:          /* The space this decl occupies has already been accounted for.  */
        !           582:          continue;
        !           583:        }
        !           584: 
        !           585:       if (const_size == 0)
        !           586:        offset = integer_zero_node;
        !           587:       else
        !           588:        {
        !           589:          /* Give each base type the alignment it wants.  */
        !           590:          const_size = CEIL (const_size, TYPE_ALIGN (basetype))
        !           591:            * TYPE_ALIGN (basetype);
        !           592:          offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
        !           593: 
        !           594:          if (TYPE_HAS_DESTRUCTOR (basetype)
        !           595:              && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
        !           596:            {
        !           597:              warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
        !           598:                                 "destructor `%s' non-virtual");
        !           599:              warning ("in inheritance relationship `%s: virtual %s'",
        !           600:                       TYPE_NAME_STRING (rec),
        !           601:                       TYPE_NAME_STRING (basetype));
        !           602:            }
        !           603:        }
        !           604:       BINFO_OFFSET (child) = offset;
        !           605:       if (CLASSTYPE_VSIZE (basetype))
        !           606:        {
        !           607:          BINFO_VTABLE (child) = TYPE_BINFO_VTABLE (basetype);
        !           608:          BINFO_VIRTUALS (child) = TYPE_BINFO_VIRTUALS (basetype);
        !           609:        }
        !           610:       TREE_CHAIN (child) = TYPE_BINFO (rec);
        !           611:       TYPE_BINFO (rec) = child;
        !           612: 
        !           613:       /* Add only the amount of storage not present in
        !           614:         the virtual baseclasses.  */
        !           615: 
        !           616:       int_vbase_size = TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype));
        !           617:       if (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) > int_vbase_size)
        !           618:        {
        !           619:          inc = MAX (record_align,
        !           620:                     (TREE_INT_CST_LOW (TYPE_SIZE (basetype))
        !           621:                      - int_vbase_size));
        !           622: 
        !           623:          /* Record must have at least as much alignment as any field.  */
        !           624:          desired_align = TYPE_ALIGN (basetype);
        !           625:          record_align = MAX (record_align, desired_align);
        !           626: 
        !           627:          const_size += inc;
        !           628:        }
        !           629:     }
        !           630: 
        !           631:   if (const_size)
        !           632:     CLASSTYPE_SIZE (rec) = size_int (const_size);
        !           633:   else
        !           634:     CLASSTYPE_SIZE (rec) = integer_zero_node;
        !           635:   CLASSTYPE_ALIGN (rec) = record_align;
        !           636: 
        !           637:   return vbase_decls;
        !           638: }
        !           639: 
        !           640: /* Hashing of lists so that we don't make duplicates.
        !           641:    The entry point is `list_hash_canon'.  */
        !           642: 
        !           643: /* Each hash table slot is a bucket containing a chain
        !           644:    of these structures.  */
        !           645: 
        !           646: struct list_hash
        !           647: {
        !           648:   struct list_hash *next;      /* Next structure in the bucket.  */
        !           649:   int hashcode;                        /* Hash code of this list.  */
        !           650:   tree list;                   /* The list recorded here.  */
        !           651: };
        !           652: 
        !           653: /* Now here is the hash table.  When recording a list, it is added
        !           654:    to the slot whose index is the hash code mod the table size.
        !           655:    Note that the hash table is used for several kinds of lists.
        !           656:    While all these live in the same table, they are completely independent,
        !           657:    and the hash code is computed differently for each of these.  */
        !           658: 
        !           659: #define TYPE_HASH_SIZE 59
        !           660: struct list_hash *list_hash_table[TYPE_HASH_SIZE];
        !           661: 
        !           662: /* Compute a hash code for a list (chain of TREE_LIST nodes
        !           663:    with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the
        !           664:    TREE_COMMON slots), by adding the hash codes of the individual entries.  */
        !           665: 
        !           666: int
        !           667: list_hash (list)
        !           668:      tree list;
        !           669: {
        !           670:   register int hashcode = 0;
        !           671: 
        !           672:   if (TREE_CHAIN (list))
        !           673:     hashcode += TYPE_HASH (TREE_CHAIN (list));
        !           674: 
        !           675:   if (TREE_VALUE (list))
        !           676:     hashcode += TYPE_HASH (TREE_VALUE (list));
        !           677:   else
        !           678:     hashcode += 1007;
        !           679:   if (TREE_PURPOSE (list))
        !           680:     hashcode += TYPE_HASH (TREE_PURPOSE (list));
        !           681:   else
        !           682:     hashcode += 1009;
        !           683:   return hashcode;
        !           684: }
        !           685: 
        !           686: /* Look in the type hash table for a type isomorphic to TYPE.
        !           687:    If one is found, return it.  Otherwise return 0.  */
        !           688: 
        !           689: tree
        !           690: list_hash_lookup (hashcode, list)
        !           691:      int hashcode;
        !           692:      tree list;
        !           693: {
        !           694:   register struct list_hash *h;
        !           695:   for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
        !           696:     if (h->hashcode == hashcode
        !           697:        && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list)
        !           698:        && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list)
        !           699:        && TREE_PURPOSE (h->list) == TREE_PURPOSE (list)
        !           700:        && TREE_VALUE (h->list) == TREE_VALUE (list)
        !           701:        && TREE_CHAIN (h->list) == TREE_CHAIN (list))
        !           702:       {
        !           703:        assert (TREE_TYPE (h->list) == TREE_TYPE (list));
        !           704:        return h->list;
        !           705:       }
        !           706:   return 0;
        !           707: }
        !           708: 
        !           709: /* Add an entry to the list-hash-table
        !           710:    for a list TYPE whose hash code is HASHCODE.  */
        !           711: 
        !           712: void
        !           713: list_hash_add (hashcode, list)
        !           714:      int hashcode;
        !           715:      tree list;
        !           716: {
        !           717:   register struct list_hash *h;
        !           718: 
        !           719:   h = (struct list_hash *) obstack_alloc (&class_obstack, sizeof (struct list_hash));
        !           720:   h->hashcode = hashcode;
        !           721:   h->list = list;
        !           722:   h->next = list_hash_table[hashcode % TYPE_HASH_SIZE];
        !           723:   list_hash_table[hashcode % TYPE_HASH_SIZE] = h;
        !           724: }
        !           725: 
        !           726: /* Given TYPE, and HASHCODE its hash code, return the canonical
        !           727:    object for an identical list if one already exists.
        !           728:    Otherwise, return TYPE, and record it as the canonical object
        !           729:    if it is a permanent object.
        !           730: 
        !           731:    To use this function, first create a list of the sort you want.
        !           732:    Then compute its hash code from the fields of the list that
        !           733:    make it different from other similar lists.
        !           734:    Then call this function and use the value.
        !           735:    This function frees the list you pass in if it is a duplicate.  */
        !           736: 
        !           737: /* Set to 1 to debug without canonicalization.  Never set by program.  */
        !           738: int debug_no_list_hash = 0;
        !           739: 
        !           740: tree
        !           741: list_hash_canon (hashcode, list)
        !           742:      int hashcode;
        !           743:      tree list;
        !           744: {
        !           745:   tree t1;
        !           746: 
        !           747:   if (debug_no_list_hash)
        !           748:     return list;
        !           749: 
        !           750:   t1 = list_hash_lookup (hashcode, list);
        !           751:   if (t1 != 0)
        !           752:     {
        !           753:       obstack_free (&class_obstack, list);
        !           754:       return t1;
        !           755:     }
        !           756: 
        !           757:   /* If this is a new list, record it for later reuse.  */
        !           758:   list_hash_add (hashcode, list);
        !           759: 
        !           760:   return list;
        !           761: }
        !           762: 
        !           763: tree
        !           764: hash_tree_cons (via_public, via_virtual, purpose, value, chain)
        !           765:      int via_public, via_virtual;
        !           766:      tree purpose, value, chain;
        !           767: {
        !           768:   struct obstack *ambient_obstack = current_obstack;
        !           769:   tree t;
        !           770:   int hashcode;
        !           771: 
        !           772:   current_obstack = &class_obstack;
        !           773:   t = tree_cons (purpose, value, chain);
        !           774:   TREE_VIA_PUBLIC (t) = via_public;
        !           775:   TREE_VIA_VIRTUAL (t) = via_virtual;
        !           776:   hashcode = list_hash (t);
        !           777:   t = list_hash_canon (hashcode, t);
        !           778:   current_obstack = ambient_obstack;
        !           779:   return t;
        !           780: }
        !           781: 
        !           782: /* Constructor for hashed lists.  */
        !           783: tree
        !           784: hash_tree_chain (value, chain)
        !           785:      tree value, chain;
        !           786: {
        !           787:   struct obstack *ambient_obstack = current_obstack;
        !           788:   tree t;
        !           789:   int hashcode;
        !           790: 
        !           791:   current_obstack = &class_obstack;
        !           792:   t = tree_cons (NULL_TREE, value, chain);
        !           793:   hashcode = list_hash (t);
        !           794:   t = list_hash_canon (hashcode, t);
        !           795:   current_obstack = ambient_obstack;
        !           796:   return t;
        !           797: }
        !           798: 
        !           799: /* Similar, but used for concatenating two lists.  */
        !           800: tree
        !           801: hash_chainon (list1, list2)
        !           802:      tree list1, list2;
        !           803: {
        !           804:   if (list2 == 0)
        !           805:     return list1;
        !           806:   if (list1 == 0)
        !           807:     return list2;
        !           808:   if (TREE_CHAIN (list1) == NULL_TREE)
        !           809:     return hash_tree_chain (TREE_VALUE (list1), list2);
        !           810:   return hash_tree_chain (TREE_VALUE (list1),
        !           811:                          hash_chainon (TREE_CHAIN (list1), list2));
        !           812: }
        !           813: 
        !           814: tree
        !           815: get_decl_list (value)
        !           816:      tree value;
        !           817: {
        !           818:   tree list = NULL_TREE;
        !           819: 
        !           820:   if (TREE_CODE (value) == IDENTIFIER_NODE)
        !           821:     {
        !           822:       list = IDENTIFIER_AS_LIST (value);
        !           823:       if (list != NULL_TREE
        !           824:          && (TREE_CODE (list) != TREE_LIST
        !           825:              || TREE_VALUE (list) != value))
        !           826:        list = NULL_TREE;
        !           827:       else if (IDENTIFIER_HAS_TYPE_VALUE (value)
        !           828:               && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
        !           829:        {
        !           830:          tree type = IDENTIFIER_TYPE_VALUE (value);
        !           831:          if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
        !           832:            CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value, NULL_TREE);
        !           833:          list = CLASSTYPE_ID_AS_LIST (type);
        !           834:        }
        !           835:     }
        !           836:   else if (TREE_CODE (value) == RECORD_TYPE
        !           837:           && TYPE_LANG_SPECIFIC (value))
        !           838:     list = CLASSTYPE_AS_LIST (value);
        !           839: 
        !           840:   if (list != NULL_TREE)
        !           841:     {
        !           842:       assert (TREE_CHAIN (list) == NULL_TREE);
        !           843:       return list;
        !           844:     }
        !           845: 
        !           846:   return build_decl_list (NULL_TREE, value);
        !           847: }
        !           848: 
        !           849: /* Look in the type hash table for a type isomorphic to
        !           850:    `build_tree_list (NULL_TREE, VALUE)'.
        !           851:    If one is found, return it.  Otherwise return 0.  */
        !           852: 
        !           853: tree
        !           854: list_hash_lookup_or_cons (value)
        !           855:      tree value;
        !           856: {
        !           857:   register int hashcode = TYPE_HASH (value);
        !           858:   register struct list_hash *h;
        !           859:   struct obstack *ambient_obstack;
        !           860:   tree list = NULL_TREE;
        !           861: 
        !           862:   if (TREE_CODE (value) == IDENTIFIER_NODE)
        !           863:     {
        !           864:       list = IDENTIFIER_AS_LIST (value);
        !           865:       if (list != NULL_TREE
        !           866:          && (TREE_CODE (list) != TREE_LIST
        !           867:              || TREE_VALUE (list) != value))
        !           868:        list = NULL_TREE;
        !           869:       else if (IDENTIFIER_HAS_TYPE_VALUE (value)
        !           870:               && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
        !           871:        {
        !           872:          /* If the type name and constructor name are different, don't
        !           873:             write constructor name into type.  */
        !           874:          extern tree constructor_name ();
        !           875:          if (IDENTIFIER_TYPEDECL_VALUE (value)
        !           876:              && IDENTIFIER_TYPEDECL_VALUE (value) != constructor_name (value))
        !           877:            list = tree_cons (NULL_TREE, value, NULL_TREE);
        !           878:          else
        !           879:            {
        !           880:              tree type = IDENTIFIER_TYPE_VALUE (value);
        !           881:              if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
        !           882:                CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value,
        !           883:                                                              NULL_TREE);
        !           884:              list = CLASSTYPE_ID_AS_LIST (type);
        !           885:            }
        !           886:        }
        !           887:     }
        !           888:   else if (TREE_CODE (value) == TYPE_DECL
        !           889:           && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
        !           890:           && TYPE_LANG_SPECIFIC (TREE_TYPE (value)))
        !           891:     list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value));
        !           892:   else if (TREE_CODE (value) == RECORD_TYPE
        !           893:           && TYPE_LANG_SPECIFIC (value))
        !           894:     list = CLASSTYPE_AS_LIST (value);
        !           895: 
        !           896:   if (list != NULL_TREE)
        !           897:     {
        !           898:       assert (TREE_CHAIN (list) == NULL_TREE);
        !           899:       return list;
        !           900:     }
        !           901: 
        !           902:   if (debug_no_list_hash)
        !           903:     return hash_tree_chain (value, NULL_TREE);
        !           904: 
        !           905:   for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
        !           906:     if (h->hashcode == hashcode
        !           907:        && TREE_VIA_VIRTUAL (h->list) == 0
        !           908:        && TREE_VIA_PUBLIC (h->list) == 0
        !           909:        && TREE_PURPOSE (h->list) == 0
        !           910:        && TREE_VALUE (h->list) == value)
        !           911:       {
        !           912:        assert (TREE_TYPE (h->list) == 0);
        !           913:        assert (TREE_CHAIN (h->list) == 0);
        !           914:        return h->list;
        !           915:       }
        !           916: 
        !           917:   ambient_obstack = current_obstack;
        !           918:   current_obstack = &class_obstack;
        !           919:   list = build_tree_list (NULL_TREE, value);
        !           920:   list_hash_add (hashcode, list);
        !           921:   current_obstack = ambient_obstack;
        !           922:   return list;
        !           923: }
        !           924: 
        !           925: /* Build an association between TYPE and some parameters:
        !           926: 
        !           927:    OFFSET is the offset added to `this' to convert it to a pointer
        !           928:    of type `TYPE *'
        !           929: 
        !           930:    VTABLE is the virtual function table with which to initialize
        !           931:    sub-objects of type TYPE.
        !           932: 
        !           933:    VIRTUALS are the virtual functions sitting in VTABLE.
        !           934: 
        !           935:    CHAIN are more associations we must retain.  */
        !           936: 
        !           937: tree
        !           938: make_binfo (offset, type, vtable, virtuals, chain)
        !           939:      tree offset, type;
        !           940:      tree vtable, virtuals;
        !           941:      tree chain;
        !           942: {
        !           943:   tree binfo = make_tree_vec (5);
        !           944:   tree old_binfo = TYPE_BINFO (type);
        !           945:   tree last;
        !           946: 
        !           947:   TREE_CHAIN (binfo) = chain;
        !           948:   if (chain)
        !           949:     TREE_USED (binfo) = TREE_USED (chain);
        !           950: 
        !           951:   TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type);
        !           952:   TREE_VEC_ELT (binfo, 1) = offset;
        !           953:   TREE_VEC_ELT (binfo, 2) = vtable;
        !           954:   TREE_VEC_ELT (binfo, 3) = virtuals;
        !           955: 
        !           956:   last = binfo;
        !           957:   if (old_binfo != NULL_TREE
        !           958:       && BINFO_BASETYPES (old_binfo) != NULL_TREE)
        !           959:     {
        !           960:       int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
        !           961:       tree binfos = TYPE_BINFO_BASETYPES (type);
        !           962: 
        !           963:       BINFO_BASETYPES (binfo) = make_tree_vec (n_baseclasses);
        !           964:       for (i = 0; i < n_baseclasses; i++)
        !           965:        {
        !           966:          tree child = TREE_VEC_ELT (binfos, i);
        !           967:          tree old_child = old_binfo ? BINFO_BASETYPE (old_binfo, i) : 0;
        !           968:          BINFO_BASETYPE (binfo, i) = child;
        !           969:          if (old_binfo)
        !           970:            {
        !           971:              TREE_VIA_PUBLIC (child) = TREE_VIA_PUBLIC (old_child);
        !           972:              TREE_VIA_VIRTUAL (child) = TREE_VIA_VIRTUAL (old_child);
        !           973:            }
        !           974:        }
        !           975:     }
        !           976:   return binfo;
        !           977: }
        !           978: 
        !           979: tree
        !           980: copy_binfo (list)
        !           981:      tree list;
        !           982: {
        !           983:   tree binfo = copy_list (list);
        !           984:   tree rval = binfo;
        !           985:   while (binfo)
        !           986:     {
        !           987:       TREE_USED (binfo) = 0;
        !           988:       if (BINFO_BASETYPES (binfo))
        !           989:        BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo));
        !           990:       binfo = TREE_CHAIN (binfo);
        !           991:     }
        !           992:   return rval;
        !           993: }
        !           994: 
        !           995: /* Return the binfo value for ELEM in TYPE.  Due to structure
        !           996:    sharing, we may find ELEM only in the association list
        !           997:    belonging to a basetype of TYPE.
        !           998: 
        !           999:    COPYING is 0 if we just want an binfo value without needing
        !          1000:    to modify it.
        !          1001:    COPYING is 1 if we want the binfo value in order to modify it.
        !          1002:    In this case, if we don't find ELEM immediately in the binfo
        !          1003:    values of TYPE, we return a copy.
        !          1004:    COPYING is -1 if we are called recursively and need a copy.
        !          1005:    In this case we return a copy of ELEM at the point we find it.  */
        !          1006: tree
        !          1007: binfo_value (elem, type, copying)
        !          1008:      tree elem;
        !          1009:      tree type;
        !          1010:      int copying;
        !          1011: {
        !          1012:   tree binfo = TYPE_BINFO (type);
        !          1013:   tree last;
        !          1014:   tree rval = NULL_TREE;
        !          1015: 
        !          1016:   /* Dispose quickly of degenerate case.  */
        !          1017:   if (elem == type)
        !          1018:     return copying < 0 ? copy_binfo (binfo) : binfo;
        !          1019: 
        !          1020:   /* Look for ELEM in two passes.  First pass checks the entire binfo list.
        !          1021:      Second pass recursively searches the binfo lists of binfos.  */
        !          1022:   while (binfo)
        !          1023:     {
        !          1024:       if (elem == BINFO_TYPE (binfo))
        !          1025:        /* If we find it on the main spine, then
        !          1026:           there can be no ambiguity.  */
        !          1027:        return copying < 0 ? copy_binfo (binfo) : binfo;
        !          1028:       last = binfo;
        !          1029:       binfo = TREE_CHAIN (binfo);
        !          1030:     }
        !          1031: 
        !          1032:   for (binfo = TYPE_BINFO (type);
        !          1033:        binfo != TREE_CHAIN (last);
        !          1034:        binfo = TREE_CHAIN (binfo))
        !          1035:     {
        !          1036:       /* ??? Should this condition instead test
        !          1037:         BINFO_TYPE (binfo) != TYPE_MAIN_VARIANT (type) ???  */
        !          1038:       if (BINFO_TYPE (binfo) != TYPE_MAIN_VARIANT (type))
        !          1039:        {
        !          1040:          tree nval = binfo_value (elem, BINFO_TYPE (binfo), copying ? -1 : 0);
        !          1041: 
        !          1042:          if (nval)
        !          1043:            {
        !          1044:              if (copying && rval == NULL_TREE)
        !          1045:                chainon (TYPE_BINFO (type), nval);
        !          1046: 
        !          1047:              if (rval && BINFO_TYPE (rval) != BINFO_TYPE (nval))
        !          1048:                /* If we find it underneath, we must make sure that
        !          1049:                   there are no two ways to do it.  */
        !          1050:                compiler_error ("base class `%s' ambiguous in binfo_value",
        !          1051:                                TYPE_NAME_STRING (elem));
        !          1052:              else
        !          1053:                rval = nval;
        !          1054:            }
        !          1055:        }
        !          1056:     }
        !          1057:   return rval;
        !          1058: }
        !          1059: 
        !          1060: tree
        !          1061: reverse_path (path)
        !          1062:      tree path;
        !          1063: {
        !          1064:   register tree prev = 0, tmp, next;
        !          1065:   for (tmp = path; tmp; tmp = next)
        !          1066:     {
        !          1067:       next = BINFO_INHERITANCE_CHAIN (tmp);
        !          1068:       BINFO_INHERITANCE_CHAIN (tmp) = prev;
        !          1069:       prev = tmp;
        !          1070:     }
        !          1071:   return prev;
        !          1072: }
        !          1073: 
        !          1074: tree
        !          1075: virtual_member (elem, list)
        !          1076:      tree elem;
        !          1077:      tree list;
        !          1078: {
        !          1079:   tree t;
        !          1080:   tree rval, nval;
        !          1081: 
        !          1082:   for (t = list; t; t = TREE_CHAIN (t))
        !          1083:     if (elem == BINFO_TYPE (t))
        !          1084:       return t;
        !          1085:   rval = 0;
        !          1086:   for (t = list; t; t = TREE_CHAIN (t))
        !          1087:     {
        !          1088:       tree binfos = BINFO_BASETYPES (t);
        !          1089:       int i;
        !          1090: 
        !          1091:       if (binfos != NULL_TREE)
        !          1092:        for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
        !          1093:          {
        !          1094:            nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0);
        !          1095:            if (nval)
        !          1096:              {
        !          1097:                if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
        !          1098:                  abort ();
        !          1099:                rval = nval;
        !          1100:              }
        !          1101:          }
        !          1102:     }
        !          1103:   return rval;
        !          1104: }
        !          1105: 
        !          1106: /* Return the offset (as an INTEGER_CST) for ELEM in LIST.
        !          1107:    INITIAL_OFFSET is the value to add to the offset that ELEM's
        !          1108:    binfo entry in LIST provides.
        !          1109: 
        !          1110:    Returns NULL if ELEM does not have an binfo value in LIST.  */
        !          1111: 
        !          1112: tree
        !          1113: virtual_offset (elem, list, initial_offset)
        !          1114:      tree elem;
        !          1115:      tree list;
        !          1116:      tree initial_offset;
        !          1117: {
        !          1118:   tree vb, offset;
        !          1119:   tree rval, nval;
        !          1120: 
        !          1121:   for (vb = list; vb; vb = TREE_CHAIN (vb))
        !          1122:     if (elem == BINFO_TYPE (vb))
        !          1123:       return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb));
        !          1124:   rval = 0;
        !          1125:   for (vb = list; vb; vb = TREE_CHAIN (vb))
        !          1126:     {
        !          1127:       tree binfos = BINFO_BASETYPES (vb);
        !          1128:       int i;
        !          1129: 
        !          1130:       if (binfos == NULL_TREE)
        !          1131:        continue;
        !          1132: 
        !          1133:       for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
        !          1134:        {
        !          1135:          nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0);
        !          1136:          if (nval)
        !          1137:            {
        !          1138:              if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
        !          1139:                abort ();
        !          1140:              offset = BINFO_OFFSET (vb);
        !          1141:              rval = nval;
        !          1142:            }
        !          1143:        }
        !          1144:     }
        !          1145:   if (rval == NULL_TREE)
        !          1146:     return rval;
        !          1147:   return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval));
        !          1148: }
        !          1149: 
        !          1150: void
        !          1151: debug_binfo (elem)
        !          1152:      tree elem;
        !          1153: {
        !          1154:   int i;
        !          1155:   tree virtuals;
        !          1156: 
        !          1157:   fprintf (stderr, "type \"%s\"; offset = %d\n",
        !          1158:           TYPE_NAME_STRING (BINFO_TYPE (elem)),
        !          1159:           TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
        !          1160:   fprintf (stderr, "vtable type:\n");
        !          1161:   debug_tree (BINFO_TYPE (elem));
        !          1162:   if (BINFO_VTABLE (elem))
        !          1163:     fprintf (stderr, "vtable decl \"%s\"\n", IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem))));
        !          1164:   else
        !          1165:     fprintf (stderr, "no vtable decl yet\n");
        !          1166:   fprintf (stderr, "virtuals:\n");
        !          1167:   virtuals = BINFO_VIRTUALS (elem);
        !          1168:   if (virtuals != 0)
        !          1169:     {
        !          1170:       virtuals = TREE_CHAIN (virtuals);
        !          1171:       if (flag_dossier)
        !          1172:        virtuals = TREE_CHAIN (virtuals);
        !          1173:     }
        !          1174:   i = 1;
        !          1175:   while (virtuals)
        !          1176:     {
        !          1177:       tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
        !          1178:       fprintf (stderr, "%s [%d =? %d]\n",
        !          1179:               IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
        !          1180:               i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
        !          1181:       virtuals = TREE_CHAIN (virtuals);
        !          1182:       i += 1;
        !          1183:     }
        !          1184: }
        !          1185: 
        !          1186: /* Return the length of a chain of nodes chained through DECL_CHAIN.
        !          1187:    We expect a null pointer to mark the end of the chain.
        !          1188:    This is the Lisp primitive `length'.  */
        !          1189: 
        !          1190: int
        !          1191: decl_list_length (t)
        !          1192:      tree t;
        !          1193: {
        !          1194:   register tree tail;
        !          1195:   register int len = 0;
        !          1196: 
        !          1197:   assert (TREE_CODE (t) == FUNCTION_DECL);
        !          1198:   for (tail = t; tail; tail = DECL_CHAIN (tail))
        !          1199:     len++;
        !          1200: 
        !          1201:   return len;
        !          1202: }
        !          1203: 
        !          1204: tree
        !          1205: fnaddr_from_vtable_entry (entry)
        !          1206:      tree entry;
        !          1207: {
        !          1208:   return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
        !          1209: }
        !          1210: 
        !          1211: void
        !          1212: set_fnaddr_from_vtable_entry (entry, value)
        !          1213:      tree entry, value;
        !          1214: {
        !          1215:   TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value;
        !          1216: }
        !          1217: 
        !          1218: tree
        !          1219: function_arg_chain (t)
        !          1220:      tree t;
        !          1221: {
        !          1222:   return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t)));
        !          1223: }
        !          1224: 
        !          1225: int
        !          1226: promotes_to_aggr_type (t, code)
        !          1227:      tree t;
        !          1228:      enum tree_code code;
        !          1229: {
        !          1230:   if (TREE_CODE (t) == code)
        !          1231:     t = TREE_TYPE (t);
        !          1232:   return IS_AGGR_TYPE (t);
        !          1233: }
        !          1234: 
        !          1235: int
        !          1236: is_aggr_type_2 (t1, t2)
        !          1237:      tree t1, t2;
        !          1238: {
        !          1239:   if (TREE_CODE (t1) != TREE_CODE (t2))
        !          1240:     return 0;
        !          1241:   return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
        !          1242: }
        !          1243: 
        !          1244: /* Give message using types TYPE1 and TYPE2 as arguments.
        !          1245:    PFN is the function which will print the message;
        !          1246:    S is the format string for PFN to use.  */
        !          1247: void
        !          1248: message_2_types (pfn, s, type1, type2)
        !          1249:      void (*pfn) ();
        !          1250:      char *s;
        !          1251:      tree type1, type2;
        !          1252: {
        !          1253:   tree name1 = TYPE_NAME (type1);
        !          1254:   tree name2 = TYPE_NAME (type2);
        !          1255:   if (TREE_CODE (name1) == TYPE_DECL)
        !          1256:     name1 = DECL_NAME (name1);
        !          1257:   if (TREE_CODE (name2) == TYPE_DECL)
        !          1258:     name2 = DECL_NAME (name2);
        !          1259:   (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));
        !          1260: }
        !          1261: 
        !          1262: #define PRINT_RING_SIZE 4
        !          1263: 
        !          1264: char *
        !          1265: lang_printable_name (decl)
        !          1266:      tree decl;
        !          1267: {
        !          1268:   static tree decl_ring[PRINT_RING_SIZE];
        !          1269:   static char *print_ring[PRINT_RING_SIZE];
        !          1270:   static int ring_counter;
        !          1271:   int i;
        !          1272: 
        !          1273:   if (TREE_CODE (decl) != FUNCTION_DECL
        !          1274:       || DECL_LANG_SPECIFIC (decl) == 0)
        !          1275:     {
        !          1276:       if (DECL_NAME (decl))
        !          1277:        {
        !          1278:          if (THIS_NAME_P (DECL_NAME (decl)))
        !          1279:            return "this";
        !          1280:          return IDENTIFIER_POINTER (DECL_NAME (decl));
        !          1281:        }
        !          1282:       return "((anonymous))";
        !          1283:     }
        !          1284: 
        !          1285:   /* See if this print name is lying around.  */
        !          1286:   for (i = 0; i < PRINT_RING_SIZE; i++)
        !          1287:     if (decl_ring[i] == decl)
        !          1288:       /* yes, so return it.  */
        !          1289:       return print_ring[i];
        !          1290: 
        !          1291:   if (++ring_counter == PRINT_RING_SIZE)
        !          1292:     ring_counter = 0;
        !          1293: 
        !          1294:   if (current_function_decl != NULL_TREE)
        !          1295:     {
        !          1296:       if (decl_ring[ring_counter] == current_function_decl)
        !          1297:        ring_counter += 1;
        !          1298:       if (ring_counter == PRINT_RING_SIZE)
        !          1299:        ring_counter = 0;
        !          1300:       if (decl_ring[ring_counter] == current_function_decl)
        !          1301:        abort ();
        !          1302:     }
        !          1303: 
        !          1304:   if (print_ring[ring_counter])
        !          1305:     free (print_ring[ring_counter]);
        !          1306: 
        !          1307:   {
        !          1308:     int print_ret_type_p
        !          1309:       = (!DECL_CONSTRUCTOR_P (decl)
        !          1310:         && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
        !          1311: 
        !          1312:     char *name = (char *)fndecl_as_string (0, decl, print_ret_type_p);
        !          1313:     print_ring[ring_counter] = (char *)malloc (strlen (name) + 1);
        !          1314:     strcpy (print_ring[ring_counter], name);
        !          1315:     decl_ring[ring_counter] = decl;
        !          1316:   }
        !          1317:   return print_ring[ring_counter];
        !          1318: }
        !          1319: 
        !          1320: /* Comparison function for sorting identifiers in RAISES lists.
        !          1321:    Note that because IDENTIFIER_NODEs are unique, we can sort
        !          1322:    them by address, saving an indirection.  */
        !          1323: static int
        !          1324: id_cmp (p1, p2)
        !          1325:      tree *p1, *p2;
        !          1326: {
        !          1327:   return (int)TREE_VALUE (*p1) - (int)TREE_VALUE (*p2);
        !          1328: }
        !          1329: 
        !          1330: /* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions
        !          1331:    listed in RAISES.  */
        !          1332: tree
        !          1333: build_exception_variant (ctype, type, raises)
        !          1334:      tree ctype, type;
        !          1335:      tree raises;
        !          1336: {
        !          1337:   int i;
        !          1338:   tree v = TYPE_MAIN_VARIANT (type);
        !          1339:   tree t, t2, cname;
        !          1340:   tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree));
        !          1341:   int constp = TYPE_READONLY (type);
        !          1342:   int volatilep = TYPE_VOLATILE (type);
        !          1343: 
        !          1344:   if (raises && TREE_CHAIN (raises))
        !          1345:     {
        !          1346:       for (i = 0, t = raises; t; t = TREE_CHAIN (t), i++)
        !          1347:        a[i] = t;
        !          1348:       /* NULL terminator for list.  */
        !          1349:       a[i] = NULL_TREE;
        !          1350:       qsort (a, i, sizeof (tree), id_cmp);
        !          1351:       while (i--)
        !          1352:        TREE_CHAIN (a[i]) = a[i+1];
        !          1353:       raises = a[0];
        !          1354:     }
        !          1355:   else if (raises)
        !          1356:     /* do nothing.  */;
        !          1357:   else
        !          1358:     return build_type_variant (v, constp, volatilep);
        !          1359: 
        !          1360:   if (ctype)
        !          1361:     {
        !          1362:       cname = TYPE_NAME (ctype);
        !          1363:       if (TREE_CODE (cname) == TYPE_DECL)
        !          1364:        cname = DECL_NAME (cname);
        !          1365:     }
        !          1366:   else
        !          1367:     cname = NULL_TREE;
        !          1368: 
        !          1369:   for (t = raises; t; t = TREE_CHAIN (t))
        !          1370:     {
        !          1371:       /* See that all the exceptions we are thinking about
        !          1372:         raising have been declared.  */
        !          1373:       tree this_cname = lookup_exception_cname (ctype, cname, t);
        !          1374:       tree decl = lookup_exception_object (this_cname, TREE_VALUE (t), 1);
        !          1375: 
        !          1376:       if (decl == NULL_TREE)
        !          1377:        decl = lookup_exception_object (this_cname, TREE_VALUE (t), 0);
        !          1378:       /* Place canonical exception decl into TREE_TYPE of RAISES list.  */
        !          1379:       TREE_TYPE (t) = decl;
        !          1380:     }
        !          1381: 
        !          1382:   for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
        !          1383:     {
        !          1384:       if (TYPE_READONLY (v) != constp
        !          1385:          || TYPE_VOLATILE (v) != volatilep)
        !          1386:        continue;
        !          1387: 
        !          1388:       t = raises;
        !          1389:       t2 = TYPE_RAISES_EXCEPTIONS (v);
        !          1390:       while (t && t2)
        !          1391:        {
        !          1392:          if (TREE_TYPE (t) == TREE_TYPE (t2))
        !          1393:            {
        !          1394:              t = TREE_CHAIN (t);
        !          1395:              t2 = TREE_CHAIN (t2);
        !          1396:            }
        !          1397:          else break;
        !          1398:        }
        !          1399:       if (t || t2)
        !          1400:        continue;
        !          1401:       /* List of exceptions raised matches previously found list.
        !          1402: 
        !          1403:          @@ Nice to free up storage used in consing up the
        !          1404:         @@ list of exceptions raised.  */
        !          1405:       return v;
        !          1406:     }
        !          1407: 
        !          1408:   /* Need to build a new variant.  */
        !          1409:   v = copy_node (type);
        !          1410:   TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
        !          1411:   TYPE_NEXT_VARIANT (type) = v;
        !          1412:   if (raises && ! TREE_PERMANENT (raises))
        !          1413:     {
        !          1414:       push_obstacks_nochange ();
        !          1415:       end_temporary_allocation ();
        !          1416:       raises = copy_list (raises);
        !          1417:       pop_obstacks ();
        !          1418:     }
        !          1419:   TYPE_RAISES_EXCEPTIONS (v) = raises;
        !          1420:   return v;
        !          1421: }
        !          1422: 
        !          1423: /* Subroutine of make_permanent_node.
        !          1424: 
        !          1425:    Assuming T is a node build bottom-up, make it all exist on
        !          1426:    permanent obstack, if it is not permanent already.  */
        !          1427: static tree
        !          1428: make_deep_copy (t)
        !          1429:      tree t;
        !          1430: {
        !          1431:   enum tree_code code;
        !          1432: 
        !          1433:   if (t == NULL_TREE || TREE_PERMANENT (t))
        !          1434:     return t;
        !          1435: 
        !          1436:   switch (code = TREE_CODE (t))
        !          1437:     {
        !          1438:     case ERROR_MARK:
        !          1439:       return error_mark_node;
        !          1440: 
        !          1441:     case VAR_DECL:
        !          1442:     case FUNCTION_DECL:
        !          1443:     case CONST_DECL:
        !          1444:       break;
        !          1445: 
        !          1446:     case PARM_DECL:
        !          1447:       {
        !          1448:        tree chain = TREE_CHAIN (t);
        !          1449:        t = copy_node (t);
        !          1450:        TREE_CHAIN (t) = make_deep_copy (chain);
        !          1451:        TREE_TYPE (t) = make_deep_copy (TREE_TYPE (t));
        !          1452:        DECL_INITIAL (t) = make_deep_copy (DECL_INITIAL (t));
        !          1453:        DECL_SIZE (t) = make_deep_copy (DECL_SIZE (t));
        !          1454:        return t;
        !          1455:       }
        !          1456: 
        !          1457:     case TREE_LIST:
        !          1458:       {
        !          1459:        tree chain = TREE_CHAIN (t);
        !          1460:        t = copy_node (t);
        !          1461:        TREE_PURPOSE (t) = make_deep_copy (TREE_PURPOSE (t));
        !          1462:        TREE_VALUE (t) = make_deep_copy (TREE_VALUE (t));
        !          1463:        TREE_CHAIN (t) = make_deep_copy (chain);
        !          1464:        return t;
        !          1465:       }
        !          1466: 
        !          1467:     case TREE_VEC:
        !          1468:       {
        !          1469:        int len = TREE_VEC_LENGTH (t);
        !          1470: 
        !          1471:        t = copy_node (t);
        !          1472:        while (len--)
        !          1473:          TREE_VEC_ELT (t, len) = make_deep_copy (TREE_VEC_ELT (t, len));
        !          1474:        return t;
        !          1475:       }
        !          1476: 
        !          1477:     case INTEGER_CST:
        !          1478:     case REAL_CST:
        !          1479:     case STRING_CST:
        !          1480:       return copy_node (t);
        !          1481: 
        !          1482:     case COND_EXPR:
        !          1483:     case TARGET_EXPR:
        !          1484:     case NEW_EXPR:
        !          1485:       t = copy_node (t);
        !          1486:       TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
        !          1487:       TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1));
        !          1488:       TREE_OPERAND (t, 2) = make_deep_copy (TREE_OPERAND (t, 2));
        !          1489:       return t;
        !          1490: 
        !          1491:     case SAVE_EXPR:
        !          1492:       t = copy_node (t);
        !          1493:       TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
        !          1494:       return t;
        !          1495: 
        !          1496:     case MODIFY_EXPR:
        !          1497:     case PLUS_EXPR:
        !          1498:     case MINUS_EXPR:
        !          1499:     case MULT_EXPR:
        !          1500:     case TRUNC_DIV_EXPR:
        !          1501:     case TRUNC_MOD_EXPR:
        !          1502:     case MIN_EXPR:
        !          1503:     case MAX_EXPR:
        !          1504:     case LSHIFT_EXPR:
        !          1505:     case RSHIFT_EXPR:
        !          1506:     case BIT_IOR_EXPR:
        !          1507:     case BIT_XOR_EXPR:
        !          1508:     case BIT_AND_EXPR:
        !          1509:     case BIT_ANDTC_EXPR:
        !          1510:     case TRUTH_ANDIF_EXPR:
        !          1511:     case TRUTH_ORIF_EXPR:
        !          1512:     case LT_EXPR:
        !          1513:     case LE_EXPR:
        !          1514:     case GT_EXPR:
        !          1515:     case GE_EXPR:
        !          1516:     case EQ_EXPR:
        !          1517:     case NE_EXPR:
        !          1518:     case CEIL_DIV_EXPR:
        !          1519:     case FLOOR_DIV_EXPR:
        !          1520:     case ROUND_DIV_EXPR:
        !          1521:     case CEIL_MOD_EXPR:
        !          1522:     case FLOOR_MOD_EXPR:
        !          1523:     case ROUND_MOD_EXPR:
        !          1524:     case COMPOUND_EXPR:
        !          1525:     case PREDECREMENT_EXPR:
        !          1526:     case PREINCREMENT_EXPR:
        !          1527:     case POSTDECREMENT_EXPR:
        !          1528:     case POSTINCREMENT_EXPR:
        !          1529:     case CALL_EXPR:
        !          1530:       t = copy_node (t);
        !          1531:       TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
        !          1532:       TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1));
        !          1533:       return t;
        !          1534: 
        !          1535:     case CONVERT_EXPR:
        !          1536:     case ADDR_EXPR:
        !          1537:     case INDIRECT_REF:
        !          1538:     case NEGATE_EXPR:
        !          1539:     case BIT_NOT_EXPR:
        !          1540:     case TRUTH_NOT_EXPR:
        !          1541:     case NOP_EXPR:
        !          1542:     case COMPONENT_REF:
        !          1543:       t = copy_node (t);
        !          1544:       TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
        !          1545:       return t;
        !          1546: 
        !          1547:       /*  This list is incomplete, but should suffice for now.
        !          1548:          It is very important that `sorry' does not call
        !          1549:          `report_error_function'.  That could cause an infinite loop.  */
        !          1550:     default:
        !          1551:       sorry ("initializer contains unrecognized tree code");
        !          1552:       return error_mark_node;
        !          1553: 
        !          1554:     }
        !          1555:   abort ();
        !          1556:   /* NOTREACHED */
        !          1557:   return NULL_TREE;
        !          1558: }
        !          1559: 
        !          1560: /* Assuming T is a node built bottom-up, make it all exist on
        !          1561:    permanent obstack, if it is not permanent already.  */
        !          1562: tree
        !          1563: copy_to_permanent (t)
        !          1564:      tree t;
        !          1565: {
        !          1566:   register struct obstack *ambient_obstack = current_obstack;
        !          1567:   register struct obstack *ambient_saveable_obstack = saveable_obstack;
        !          1568: 
        !          1569:   if (t == NULL_TREE || TREE_PERMANENT (t))
        !          1570:     return t;
        !          1571: 
        !          1572:   saveable_obstack = &permanent_obstack;
        !          1573:   current_obstack = saveable_obstack;
        !          1574: 
        !          1575:   t = make_deep_copy (t);
        !          1576: 
        !          1577:   current_obstack = ambient_obstack;
        !          1578:   saveable_obstack = ambient_saveable_obstack;
        !          1579: 
        !          1580:   return t;
        !          1581: }
        !          1582: 
        !          1583: int
        !          1584: lang_simple_cst_equal (t1, t2)
        !          1585:      tree t1, t2;
        !          1586: {
        !          1587:   register enum tree_code code1, code2;
        !          1588:   int cmp;
        !          1589: 
        !          1590:   if (t1 == t2)
        !          1591:     return 1;
        !          1592:   if (t1 == 0 || t2 == 0)
        !          1593:     return 0;
        !          1594: 
        !          1595:   code1 = TREE_CODE (t1);
        !          1596:   code2 = TREE_CODE (t2);
        !          1597: 
        !          1598:   switch (code1)
        !          1599:     {
        !          1600:     case NEW_EXPR:
        !          1601:       cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
        !          1602:       if (cmp <= 0)
        !          1603:        return cmp;
        !          1604:       return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
        !          1605: 
        !          1606:     default:
        !          1607:       return -1;
        !          1608:     }
        !          1609: }
        !          1610: 
        !          1611: void
        !          1612: print_lang_statistics ()
        !          1613: {
        !          1614:   extern struct obstack maybepermanent_obstack;
        !          1615:   print_obstack_statistics ("class_obstack", &class_obstack);
        !          1616:   print_obstack_statistics ("permanent_obstack", &permanent_obstack);
        !          1617:   print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
        !          1618:   print_search_statistics ();
        !          1619:   print_class_statistics ();
        !          1620: }
        !          1621: 
        !          1622: /* This is used by the `assert' macro.  It is provided in libgcc.a,
        !          1623:    which `cc' doesn't know how to link.  */
        !          1624: void
        !          1625: __eprintf (string, expression, line, filename)
        !          1626: #ifdef __STDC__
        !          1627:      const char *string;
        !          1628:      const char *expression;
        !          1629:      int line;
        !          1630:      const char *filename;
        !          1631: #else
        !          1632:      char *string;
        !          1633:      char *expression;
        !          1634:      int line;
        !          1635:      char *filename;
        !          1636: #endif
        !          1637: {
        !          1638:   fprintf (stderr, string, expression, line, filename);
        !          1639:   fflush (stderr);
        !          1640:   abort ();
        !          1641: }

unix.superglobalmegacorp.com

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