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

unix.superglobalmegacorp.com

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