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

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

unix.superglobalmegacorp.com

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