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

1.1     ! root        1: /* Handle initialization things in C++.
        !             2:    Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
        !             3:    Contributed 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: 
        !            22: /* High-level class interface. */
        !            23: 
        !            24: #include "config.h"
        !            25: #include "tree.h"
        !            26: #include "cp-tree.h"
        !            27: #include "flags.h"
        !            28: #include "assert.h"
        !            29: 
        !            30: #define NULL 0
        !            31: 
        !            32: /* In C++, structures with well-defined constructors are initialized by
        !            33:    those constructors, unasked.  CURRENT_BASE_INIT_LIST
        !            34:    holds a list of stmts for a BASE_INIT term in the grammar.
        !            35:    This list has one element for each base class which must be
        !            36:    initialized.  The list elements are [basename, init], with
        !            37:    type basetype.  This allows the possibly anachronistic form
        !            38:    (assuming d : a, b, c) "d (int a) : c(a+5), b (a-4), a (a+3)"
        !            39:    where each successive term can be handed down the constructor
        !            40:    line.  Perhaps this was not intended.  */
        !            41: tree current_base_init_list, current_member_init_list;
        !            42: 
        !            43: void init_init_processing ();
        !            44: void emit_base_init ();
        !            45: void check_base_init ();
        !            46: static void expand_aggr_vbase_init ();
        !            47: void expand_member_init ();
        !            48: void expand_aggr_init ();
        !            49: tree build_virtual_init ();
        !            50: tree build_vbase_delete ();
        !            51: 
        !            52: static void expand_aggr_init_1 ();
        !            53: static void expand_recursive_init_1 ();
        !            54: static void expand_recursive_init ();
        !            55: tree expand_vec_init ();
        !            56: tree build_vec_delete ();
        !            57: 
        !            58: static void add_friend (), add_friends ();
        !            59: 
        !            60: int is_aggr_typedef ();
        !            61: /* Cache _builtin_new and _builtin_delete exprs.  */
        !            62: static tree BIN, BID;
        !            63: 
        !            64: #ifdef SOS
        !            65: tree get_linktable_name (), get_dtable_name (), get_sos_dtable ();
        !            66: static tree __sosFindCode, __sosLookup, __sosImport;
        !            67: static tree build_dynamic_new ();
        !            68: #endif
        !            69: static tree minus_one;
        !            70: 
        !            71: extern struct rtx_def *start_sequence (), *get_insns (), *get_last_insn ();
        !            72: extern struct rtx_def *const0_rtx;
        !            73: 
        !            74: /* Set up local variable for this file.  MUST BE CALLED AFTER
        !            75:    INIT_DECL_PROCESSING.  */
        !            76: 
        !            77: tree BI_header_type, BI_header_size;
        !            78: 
        !            79: void init_init_processing ()
        !            80: {
        !            81:   tree op_id;
        !            82:   tree fields[2];
        !            83: 
        !            84:   BIN = default_conversion (TREE_VALUE (lookup_name (get_identifier ("__builtin_new"), 0)));
        !            85:   TREE_USED (TREE_OPERAND (BIN, 0)) = 0;
        !            86:   BID = default_conversion (TREE_VALUE (lookup_name (get_identifier ("__builtin_delete"), 0)));
        !            87:   TREE_USED (TREE_OPERAND (BID, 0)) = 0;
        !            88:   minus_one = build_int_2 (-1, -1);
        !            89: 
        !            90:   op_id = ansi_opname[NEW_EXPR];
        !            91:   IDENTIFIER_GLOBAL_VALUE (op_id) = BIN;
        !            92:   op_id = ansi_opname[DELETE_EXPR];
        !            93:   IDENTIFIER_GLOBAL_VALUE (op_id) = BID;
        !            94: 
        !            95: #ifdef SOS
        !            96:   if (flag_all_virtual == 2)
        !            97:     {
        !            98:       __sosFindCode = default_conversion (lookup_name (get_identifier ("sosFindCode"), 0));
        !            99:       __sosLookup = default_conversion (lookup_name (get_identifier ("sosLookup"), 0));
        !           100:       __sosImport = default_conversion (lookup_name (get_identifier ("sosImport"), 0));
        !           101:     }
        !           102: #endif
        !           103: 
        !           104:   /* Define the structure that holds header information for
        !           105:      arrays allocated via operator new.  */
        !           106:   BI_header_type = make_lang_type (RECORD_TYPE);
        !           107:   fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("nelts"),
        !           108:                                     sizetype);
        !           109:   fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("ptr_2comp"),
        !           110:                                     ptr_type_node);
        !           111:   finish_builtin_type (BI_header_type, "__new_cookie", fields, 1, double_type_node);
        !           112:   BI_header_size = size_in_bytes (BI_header_type);
        !           113: }
        !           114: 
        !           115: /* Recursive subroutine of emit_base_init.  For main type T,
        !           116:    recursively initialize the vfields of the base type PARENT.
        !           117:    RECURSE is non-zero when this function is being called
        !           118:    recursively.  */
        !           119: 
        !           120: static void
        !           121: init_vfields (t, parent, recurse)
        !           122:      tree t, parent;
        !           123:      int recurse;
        !           124: {
        !           125:   tree vfields;
        !           126: 
        !           127:   /* Initialize all the virtual function table fields that
        !           128:      do not come from virtual base classes.  */
        !           129:   vfields = CLASSTYPE_VFIELDS (parent);
        !           130:   while (vfields)
        !           131:     {
        !           132:       tree basetype = VF_DERIVED_VALUE (vfields)
        !           133:        ? TYPE_MAIN_VARIANT (VF_DERIVED_VALUE (vfields))
        !           134:          : VF_BASETYPE_VALUE (vfields);
        !           135: 
        !           136:       /* If the vtable installed by the constructor was not
        !           137:         the right one, fix that here.  */
        !           138:       if (TREE_ADDRESSABLE (vfields)
        !           139:          && CLASSTYPE_NEEDS_VIRTUAL_REINIT (basetype)
        !           140:          && (recurse > 0
        !           141:              || TYPE_HAS_CONSTRUCTOR (basetype)
        !           142:              /* BASE_INIT_LIST has already initialized the immediate basetypes.  */
        !           143:              || get_base_distance (basetype, t, 0, 0) > 1))
        !           144:        {
        !           145:          tree binfo = binfo_value (basetype, t, 0);
        !           146:          if ((recurse != 0 && (binfo != binfo_value (basetype, parent, 0)))
        !           147:              || (recurse == 0
        !           148:                  && BINFO_VTABLE (binfo) != TYPE_BINFO_VTABLE (basetype)))
        !           149:            {
        !           150:              tree ptr = convert_pointer_to (binfo, current_class_decl);
        !           151:              expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), binfo, ptr));
        !           152:            }
        !           153:          init_vfields (t, basetype, recurse+1);
        !           154:        }
        !           155:       vfields = TREE_CHAIN (vfields);
        !           156:     }
        !           157: }
        !           158: 
        !           159: /* Perform whatever initialization have yet to be done on the
        !           160:    base class of the class variable.  These actions are in
        !           161:    the global variable CURRENT_BASE_INIT_LIST.  Such an
        !           162:    action could be NULL_TREE, meaning that the user has explicitly
        !           163:    called the base class constructor with no arguments.
        !           164: 
        !           165:    If there is a need for a call to a constructor, we
        !           166:    must surround that call with a pushlevel/poplevel pair,
        !           167:    since we are technically at the PARM level of scope.
        !           168: 
        !           169:    Argument ASSIGNS_THIS_P is nonzero if the current function assigns
        !           170:    `this' explicitly.  We cannot get this value by checking
        !           171:    `current_function_assigns_this', since it is set up after this
        !           172:    function is called.  (although I don't know if its really
        !           173:    necessary to wait until afterward to do that.)
        !           174: 
        !           175:    Note that emit_base_init does *not* initialize virtual
        !           176:    base classes.  That is done specially, elsewhere.  */
        !           177:    
        !           178: void
        !           179: emit_base_init (t, immediately)
        !           180:      tree t;
        !           181:      int immediately;
        !           182: {
        !           183:   extern tree in_charge_identifier;
        !           184: 
        !           185:   tree member, decl, vbases;
        !           186:   tree init_list;
        !           187:   int pass, start;
        !           188:   tree t_binfo = TYPE_BINFO (t);
        !           189:   tree binfos = BINFO_BASETYPES (t_binfo);
        !           190:   int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !           191:   tree fields_to_unmark = NULL_TREE;
        !           192: 
        !           193:   if (! immediately)
        !           194:     {
        !           195:       do_pending_stack_adjust ();
        !           196:       start_sequence ();
        !           197:       /* As a matter of principle, `start_sequence' should do this.  */
        !           198:       emit_note (0, -1);
        !           199:     }
        !           200: 
        !           201:   /* In this case, we always need IN_CHARGE_NODE, because we have
        !           202:      to know whether to deallocate or not before exiting.  */
        !           203:   if (flag_handle_exceptions == 2
        !           204:       && lookup_name (in_charge_identifier, 0) == NULL_TREE)
        !           205:     {
        !           206:       tree in_charge_node = pushdecl (build_decl (VAR_DECL, in_charge_identifier,
        !           207:                                                  integer_type_node));
        !           208:       store_init_value (in_charge_node, build (EQ_EXPR, integer_type_node,
        !           209:                                               current_class_decl,
        !           210:                                               integer_zero_node));
        !           211:       expand_decl (in_charge_node);
        !           212:       expand_decl_init (in_charge_node);
        !           213:     }
        !           214: 
        !           215:   start = ! TYPE_USES_VIRTUAL_BASECLASSES (t);
        !           216:   for (pass = start; pass < 2; pass++)
        !           217:     {
        !           218:       tree vbase_init_list = NULL_TREE;
        !           219: 
        !           220:       for (init_list = current_base_init_list; init_list;
        !           221:           init_list = TREE_CHAIN (init_list))
        !           222:        {
        !           223:          tree basename = TREE_PURPOSE (init_list);
        !           224:          tree binfo;
        !           225:          tree init = TREE_VALUE (init_list);
        !           226: 
        !           227:          if (basename == NULL_TREE)
        !           228:            {
        !           229:              /* Initializer for single base class.  Must not
        !           230:                 use multiple inheritance or this is ambiguous.  */
        !           231:              switch (n_baseclasses)
        !           232:                {
        !           233:                case 0:
        !           234:                  error ("type `%s' does not have a base class to initialize",
        !           235:                         IDENTIFIER_POINTER (current_class_name));
        !           236:                  return;
        !           237:                case 1:
        !           238:                  break;
        !           239:                default:
        !           240:                  error ("unnamed initializer ambiguous for type `%s' which uses multiple inheritance", IDENTIFIER_POINTER (current_class_name));
        !           241:                  return;
        !           242:                }
        !           243:              binfo = TREE_VEC_ELT (binfos, 0);
        !           244:            }
        !           245:          else if (is_aggr_typedef (basename, 1))
        !           246:            {
        !           247:              binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
        !           248:              if (binfo == NULL_TREE)
        !           249:                continue;
        !           250: 
        !           251:              /* Virtual base classes are special cases.  Their initializers
        !           252:                 are recorded with this constructor, and they are used when
        !           253:                 this constructor is the top-level constructor called.  */
        !           254:              if (! TREE_VIA_VIRTUAL (binfo) || pedantic)
        !           255:                {
        !           256:                  /* Otherwise, if it is not an immediate base class, complain.  */
        !           257:                  for (i = n_baseclasses-1; i >= 0; i--)
        !           258:                    if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
        !           259:                      break;
        !           260:                  if (i < 0)
        !           261:                    {
        !           262:                      error ("type `%s' is not an immediate base class of type `%s'",
        !           263:                             IDENTIFIER_POINTER (basename),
        !           264:                             IDENTIFIER_POINTER (current_class_name));
        !           265:                      continue;
        !           266:                    }
        !           267:                }
        !           268:            }
        !           269:          else
        !           270:            continue;
        !           271: 
        !           272:          /* The base initialization list goes up to the first
        !           273:             base class which can actually use it.  */
        !           274: 
        !           275:          if (pass == start)
        !           276:            {
        !           277:              char *msgp = (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
        !           278:                ? "cannot pass initialization up to class `%s'" : 0;
        !           279: 
        !           280:              while (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo))
        !           281:                     && BINFO_BASETYPES (binfo) != NULL_TREE
        !           282:                     && TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 1)
        !           283:                binfo = BINFO_BASETYPE (binfo, 0);
        !           284: 
        !           285:              if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
        !           286:                {
        !           287:                  if (msgp)
        !           288:                    {
        !           289:                      if (pedantic)
        !           290:                        error_with_aggr_type (binfo, msgp);
        !           291:                      else
        !           292:                        msgp = 0;
        !           293:                    }
        !           294:                }
        !           295:              else
        !           296:                {
        !           297:                  msgp = "no constructor found for initialization of `%s'";
        !           298:                  error (msgp, IDENTIFIER_POINTER (basename));
        !           299:                }
        !           300: 
        !           301:              if (BINFO_BASEINIT_MARKED (binfo))
        !           302:                {
        !           303:                  msgp = "class `%s' initializer already specified";
        !           304:                  error (msgp, IDENTIFIER_POINTER (basename));
        !           305:                }
        !           306:              if (msgp)
        !           307:                continue;
        !           308: 
        !           309:              SET_BINFO_BASEINIT_MARKED (binfo);
        !           310:              if (TREE_VIA_VIRTUAL (binfo))
        !           311:                {
        !           312:                  vbase_init_list = tree_cons (init, BINFO_TYPE (binfo),
        !           313:                                               vbase_init_list);
        !           314:                  continue;
        !           315:                }
        !           316:              if (pass == 0)
        !           317:                continue;
        !           318:            }
        !           319:          else if (TREE_VIA_VIRTUAL (binfo))
        !           320:            continue;
        !           321: 
        !           322:          member = convert_pointer_to (binfo, current_class_decl);
        !           323:          expand_aggr_init_1 (t_binfo, 0,
        !           324:                              build_indirect_ref (member, 0), init,
        !           325:                              BINFO_OFFSET_ZEROP (binfo),
        !           326:                              LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);
        !           327:          if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
        !           328:            {
        !           329:              cplus_expand_start_try (1);
        !           330:              push_exception_cleanup (member);
        !           331:            }
        !           332:        }
        !           333: 
        !           334:       if (pass == 0)
        !           335:        {
        !           336:          tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
        !           337:          tree vbases;
        !           338: 
        !           339:          if (DECL_NAME (current_function_decl) == NULL_TREE
        !           340:              && TREE_CHAIN (first_arg) != NULL_TREE)
        !           341:            {
        !           342:              /* If there are virtual baseclasses without initialization
        !           343:                 specified, and this is a default X(X&) construcotr,
        !           344:                 build the initialization list so that each virtual baseclass
        !           345:                 of the new object is initialized from the virtual baseclass
        !           346:                 of the incoming arg.  */
        !           347:              tree init_arg = build_unary_op (ADDR_EXPR, TREE_CHAIN (first_arg), 0);
        !           348:              for (vbases = CLASSTYPE_VBASECLASSES (t);
        !           349:                   vbases; vbases = TREE_CHAIN (vbases))
        !           350:                {
        !           351:                  if (BINFO_BASEINIT_MARKED (vbases) == 0)
        !           352:                    {
        !           353:                      member = convert_pointer_to (vbases, init_arg);
        !           354:                      if (member == init_arg)
        !           355:                        member = TREE_CHAIN (first_arg);
        !           356:                      else
        !           357:                        TREE_TYPE (member) = build_reference_type (BINFO_TYPE (vbases));
        !           358:                      vbase_init_list = tree_cons (convert_from_reference (member),
        !           359:                                                   vbases, vbase_init_list);
        !           360:                      SET_BINFO_BASEINIT_MARKED (vbases);
        !           361:                    }
        !           362:                }
        !           363:            }
        !           364:          expand_start_cond (first_arg, 0);
        !           365:          expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
        !           366:                                  vbase_init_list);
        !           367:          expand_expr_stmt (build_vbase_vtables_init (t_binfo, t_binfo,
        !           368:                                                      C_C_D, current_class_decl, 1));
        !           369:          expand_end_cond ();
        !           370:        }
        !           371:     }
        !           372:   current_base_init_list = NULL_TREE;
        !           373: 
        !           374:   /* Now, perform default initialization of all base classes which
        !           375:      have not yet been initialized, and unmark baseclasses which
        !           376:      have been initialized.  */
        !           377:   for (i = 0; i < n_baseclasses; i++)
        !           378:     {
        !           379:       tree base = current_class_decl;
        !           380:       tree child = TREE_VEC_ELT (binfos, i);
        !           381: 
        !           382:       if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (child)))
        !           383:        {
        !           384:          if (! TREE_VIA_VIRTUAL (child)
        !           385:              && ! BINFO_BASEINIT_MARKED (child))
        !           386:            {
        !           387:              tree ref;
        !           388: 
        !           389:              if (BINFO_OFFSET_ZEROP (child))
        !           390:                base = build1 (NOP_EXPR, TYPE_POINTER_TO (BINFO_TYPE (child)), current_class_decl);
        !           391:              else
        !           392:                base = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (child)), current_class_decl, BINFO_OFFSET (child));
        !           393: 
        !           394:              ref = build_indirect_ref (base, 0);
        !           395:              expand_aggr_init_1 (t_binfo, 0, ref, NULL_TREE,
        !           396:                                  BINFO_OFFSET_ZEROP (child),
        !           397:                                  LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);
        !           398:              if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (child)))
        !           399:                {
        !           400:                  cplus_expand_start_try (1);
        !           401:                  push_exception_cleanup (base);
        !           402:                }
        !           403:            }
        !           404:        }
        !           405:       CLEAR_BINFO_BASEINIT_MARKED (child);
        !           406:     }
        !           407:   for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
        !           408:     CLEAR_BINFO_BASEINIT_MARKED (vbases);
        !           409: 
        !           410:   /* Initialize all the virtual function table fields that
        !           411:      do not come from virtual base classes.  */
        !           412:   init_vfields (t, t, 0);
        !           413: 
        !           414:   if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t)
        !           415: #ifdef SOS
        !           416:        || TYPE_DYNAMIC (t)
        !           417: #endif
        !           418:        )
        !           419:     expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), t,
        !           420:                                          current_class_decl));
        !           421: 
        !           422:   /* Members we through expand_member_init.  We initialize all the members
        !           423:      needing initialization that did not get it so far.  */
        !           424:   for (; current_member_init_list;
        !           425:        current_member_init_list = TREE_CHAIN (current_member_init_list))
        !           426:     {
        !           427:       tree name = TREE_PURPOSE (current_member_init_list);
        !           428:       tree init = TREE_VALUE (current_member_init_list);
        !           429:       tree field = (TREE_CODE (name) == COMPONENT_REF
        !           430:                    ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name));
        !           431:       tree type;
        !           432:       
        !           433:       /* If one member shadows another, get the outermost one.  */
        !           434:       if (TREE_CODE (field) == TREE_LIST)
        !           435:        {
        !           436:          field = TREE_VALUE (field);
        !           437:          if (decl_type_context (field) != current_class_type)
        !           438:            error ("field `%s' not in immediate context");
        !           439:        }
        !           440: 
        !           441:       type = TREE_TYPE (field);
        !           442: 
        !           443:       if (TREE_STATIC (field))
        !           444:        {
        !           445:          error_with_aggr_type (DECL_FIELD_CONTEXT (field),
        !           446:                                "field `%s::%s' is static; only point of initialization is its declaration", IDENTIFIER_POINTER (name));
        !           447:          continue;
        !           448:        }
        !           449: 
        !           450:       if (DECL_NAME (field))
        !           451:        {
        !           452:          if (TREE_HAS_CONSTRUCTOR (field))
        !           453:            error ("multiple initializations given for member `%s'",
        !           454:                   IDENTIFIER_POINTER (DECL_NAME (field)));
        !           455:        }
        !           456: 
        !           457:       /* Mark this node as having been initialized.  */
        !           458:       TREE_HAS_CONSTRUCTOR (field) = 1;
        !           459:       if (DECL_FIELD_CONTEXT (field) != t)
        !           460:        fields_to_unmark = tree_cons (NULL_TREE, field, fields_to_unmark);
        !           461: 
        !           462:       if (TREE_CODE (name) == COMPONENT_REF)
        !           463:        {
        !           464:          /* Initialization of anonymous union.  */
        !           465:          expand_assignment (name, init, 0, 0);
        !           466:          continue;
        !           467:        }
        !           468:       decl = build_component_ref (C_C_D, name, 0, 1);
        !           469: 
        !           470:       if (TYPE_NEEDS_CONSTRUCTING (type))
        !           471:        {
        !           472:          if (TREE_CODE (type) == ARRAY_TYPE
        !           473:              && TREE_CHAIN (init) == NULL_TREE
        !           474:              && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
        !           475:            {
        !           476:              /* Initialization of one array from another.  */
        !           477:              expand_vec_init (TREE_OPERAND (decl, 1), decl,
        !           478:                               array_type_nelts (type), TREE_VALUE (init), 1);
        !           479:            }
        !           480:          else
        !           481:            expand_aggr_init (decl, init, 0);
        !           482:        }
        !           483:       else
        !           484:        {
        !           485:          if (init == NULL_TREE)
        !           486:            {
        !           487:              error ("types without constructors must have complete initializers");
        !           488:              init = error_mark_node;
        !           489:            }
        !           490:          else if (TREE_CHAIN (init))
        !           491:            {
        !           492:              warning ("initializer list treated as compound expression");
        !           493:              init = build_compound_expr (init);
        !           494:            }
        !           495:          else
        !           496:            init = TREE_VALUE (init);
        !           497: 
        !           498:          expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
        !           499:        }
        !           500:       if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type))
        !           501:        {
        !           502:          cplus_expand_start_try (1);
        !           503:          push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));
        !           504:        }
        !           505:     }
        !           506: 
        !           507:   for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
        !           508:     {
        !           509:       /* All we care about is this unique member.  It contains
        !           510:         all the information we need to know, and that right early.  */
        !           511:       tree type = TREE_TYPE (member);
        !           512:       tree init = TREE_HAS_CONSTRUCTOR (member)
        !           513:        ? error_mark_node : DECL_INITIAL (member);
        !           514: 
        !           515:       /* Unmark this field.  If it is from an anonymous union,
        !           516:          then unmark the field recursively.  */
        !           517:       TREE_HAS_CONSTRUCTOR (member) = 0;
        !           518:       if (TREE_ANON_UNION_ELEM (member))
        !           519:        emit_base_init (TREE_TYPE (member), 1);
        !           520: 
        !           521:       /* Member had explicit initializer.  */
        !           522:       if (init == error_mark_node)
        !           523:        continue;
        !           524: 
        !           525:       if (TREE_CODE (member) != FIELD_DECL)
        !           526:        continue;
        !           527: 
        !           528:       if (type == error_mark_node)
        !           529:        continue;
        !           530: 
        !           531:       if (TYPE_NEEDS_CONSTRUCTING (type))
        !           532:        {
        !           533:          if (init)
        !           534:            init = build_tree_list (NULL_TREE, init);
        !           535:          decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0);
        !           536:          expand_aggr_init (decl, init, 0);
        !           537:        }
        !           538:       else
        !           539:        {
        !           540:          if (init)
        !           541:            {
        !           542:              decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0);
        !           543:              expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
        !           544:            }
        !           545:          else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE)
        !           546:            warning ("uninitialized reference member `%s'",
        !           547:                     IDENTIFIER_POINTER (DECL_NAME (member)));
        !           548:        }
        !           549:       if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type))
        !           550:        {
        !           551:          cplus_expand_start_try (1);
        !           552:          push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));
        !           553:        }
        !           554:     }
        !           555:   /* Unmark fields which are initialized for the base class.  */
        !           556:   while (fields_to_unmark)
        !           557:     {
        !           558:       TREE_HAS_CONSTRUCTOR (TREE_VALUE (fields_to_unmark)) = 0;
        !           559:       fields_to_unmark = TREE_CHAIN (fields_to_unmark);
        !           560:     }
        !           561: 
        !           562:   /* It is possible for the initializers to need cleanups.
        !           563:      Expand those cleanups now that all the initialization
        !           564:      has been done.  */
        !           565:   expand_cleanups_to (NULL_TREE);
        !           566: 
        !           567:   if (! immediately)
        !           568:     {
        !           569:       extern struct rtx_def *base_init_insns;
        !           570: 
        !           571:       do_pending_stack_adjust ();
        !           572:       assert (base_init_insns == 0);
        !           573:       base_init_insns = get_insns ();
        !           574:       end_sequence ();
        !           575:     }
        !           576: 
        !           577:   /* All the implicit try blocks we built up will be zapped
        !           578:      when we come to a real binding contour boundary.  */
        !           579: }
        !           580: 
        !           581: /* Check that all fields are properly initialized after
        !           582:    an assignment to `this'.  */
        !           583: void
        !           584: check_base_init (t)
        !           585:      tree t;
        !           586: {
        !           587:   tree member;
        !           588:   for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
        !           589:     if (DECL_NAME (member) && TREE_USED (member))
        !           590:       error ("field `%s' used before initialized (after assignment to `this')",
        !           591:             IDENTIFIER_POINTER (DECL_NAME (member)));
        !           592: }
        !           593: 
        !           594: /* This code sets up the virtual function tables appropriate for
        !           595:    the pointer DECL.  It is a one-ply initialization.
        !           596: 
        !           597:    TYPE is the exact type that DECL is supposed to be.  In
        !           598:    muliple inheritance, this might mean "C's A" if C : A, B.  */
        !           599: tree
        !           600: build_virtual_init (main_binfo, binfo, decl)
        !           601:      tree main_binfo, binfo;
        !           602:      tree decl;
        !           603: {
        !           604:   tree type;
        !           605:   tree vtbl, vtbl_ptr;
        !           606:   tree vtype;
        !           607: 
        !           608:   if (TREE_CODE (binfo) == TREE_VEC)
        !           609:     type = BINFO_TYPE (binfo);
        !           610:   else if (TREE_CODE (binfo) == RECORD_TYPE)
        !           611:     {
        !           612:       type = binfo;
        !           613:       binfo = TYPE_BINFO (type);
        !           614:     }
        !           615:   else abort ();
        !           616: 
        !           617: #ifdef SOS
        !           618:   if (TYPE_DYNAMIC (type))
        !           619:     vtbl = build1 (NOP_EXPR, ptr_type_node, lookup_name (get_identifier (AUTO_VTABLE_NAME), 0));
        !           620:   else
        !           621: #endif
        !           622:     {
        !           623: #if 1
        !           624:       vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)),
        !           625:                                        BINFO_TYPE (main_binfo), 0));
        !           626: #else
        !           627:       assert (BINFO_TYPE (main_binfo) == BINFO_TYPE (binfo));
        !           628:       vtbl = BINFO_VTABLE (main_binfo);
        !           629: #endif /* 1 */
        !           630:       if (TREE_USED (vtbl) == 0)
        !           631:        {
        !           632:          if (TREE_EXTERNAL (vtbl))
        !           633:            assemble_external (vtbl);
        !           634:          TREE_USED (vtbl) = 1;
        !           635:        }
        !           636:       vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
        !           637:     }
        !           638:   vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
        !           639:   decl = convert_pointer_to (vtype, decl);
        !           640:   vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, 0), vtype);
        !           641:   if (vtbl_ptr == error_mark_node)
        !           642:     return error_mark_node;
        !           643: 
        !           644:   /* Have to convert VTBL since array sizes may be different.  */
        !           645:   return build_modify_expr (vtbl_ptr, NOP_EXPR,
        !           646:                            convert (TREE_TYPE (vtbl_ptr), vtbl));
        !           647: }
        !           648: 
        !           649: /* Subroutine of `expand_aggr_vbase_init'.
        !           650:    BINFO is the binfo of the type that is being initialized.
        !           651:    INIT_LIST is the list of initializers for the virtual baseclass.  */
        !           652: static void
        !           653: expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
        !           654:      tree binfo, exp, addr, init_list;
        !           655: {
        !           656:   tree init = value_member (BINFO_TYPE (binfo), init_list);
        !           657:   tree ref = build_indirect_ref (addr, 0);
        !           658:   if (init)
        !           659:     init = TREE_PURPOSE (init);
        !           660:   /* Call constructors, but don't set up vtables.  */
        !           661:   expand_aggr_init_1 (binfo, exp, ref, init, 0,
        !           662:                      LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY);
        !           663:   CLEAR_BINFO_VBASE_INIT_MARKED (binfo);
        !           664: }
        !           665: 
        !           666: /* Initialize this object's virtual base class pointers.  This must be
        !           667:    done only at the top-level of the object being constructed.
        !           668: 
        !           669:    INIT_LIST is list of initialization for constructor to perform.  */
        !           670: static void
        !           671: expand_aggr_vbase_init (binfo, exp, addr, init_list)
        !           672:      tree binfo;
        !           673:      tree exp;
        !           674:      tree addr;
        !           675:      tree init_list;
        !           676: {
        !           677:   tree type = BINFO_TYPE (binfo);
        !           678: 
        !           679:   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
        !           680:     {
        !           681:       tree result = init_vbase_pointers (type, addr);
        !           682:       tree vbases;
        !           683: 
        !           684:       if (result)
        !           685:        expand_expr_stmt (build_compound_expr (result));
        !           686: 
        !           687:       /* Mark everything as having an initializer
        !           688:         (either explicit or default).  */
        !           689:       for (vbases = CLASSTYPE_VBASECLASSES (type);
        !           690:           vbases; vbases = TREE_CHAIN (vbases))
        !           691:        SET_BINFO_VBASE_INIT_MARKED (vbases);
        !           692: 
        !           693:       /* First, initialize baseclasses which could be baseclasses
        !           694:         for other virtual baseclasses.  */
        !           695:       for (vbases = CLASSTYPE_VBASECLASSES (type);
        !           696:           vbases; vbases = TREE_CHAIN (vbases))
        !           697:        /* Don't initialize twice.  */
        !           698:        if (BINFO_VBASE_INIT_MARKED (vbases))
        !           699:          {
        !           700:            tree tmp = result;
        !           701: 
        !           702:            while (BINFO_TYPE (vbases) != BINFO_TYPE (TREE_PURPOSE (tmp)))
        !           703:              tmp = TREE_CHAIN (tmp);
        !           704:            expand_aggr_vbase_init_1 (vbases, exp,
        !           705:                                      TREE_OPERAND (TREE_VALUE (tmp), 0),
        !           706:                                      init_list);
        !           707:          }
        !           708: 
        !           709:       /* Now initialize the baseclasses which don't have virtual baseclasses.  */
        !           710:       for (; result; result = TREE_CHAIN (result))
        !           711:        /* Don't initialize twice.  */
        !           712:        if (BINFO_VBASE_INIT_MARKED (TREE_PURPOSE (result)))
        !           713:          {
        !           714:            abort ();
        !           715:            expand_aggr_vbase_init_1 (TREE_PURPOSE (result), exp,
        !           716:                                      TREE_OPERAND (TREE_VALUE (result), 0),
        !           717:                                      init_list);
        !           718:          }
        !           719:     }
        !           720: }
        !           721: 
        !           722: /* Subroutine to perform parser actions for member initialization.
        !           723:    S_ID is the scoped identifier.
        !           724:    NAME is the name of the member.
        !           725:    INIT is the initializer, or `void_type_node' if none.  */
        !           726: void
        !           727: do_member_init (s_id, name, init)
        !           728:      tree s_id, name, init;
        !           729: {
        !           730:   tree binfo, base;
        !           731: 
        !           732:   if (current_class_type == NULL_TREE
        !           733:       || ! is_aggr_typedef (s_id, 1))
        !           734:     return;
        !           735:   binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),
        !           736:                          current_class_type, 1);
        !           737:   if (binfo == error_mark_node)
        !           738:     return;
        !           739:   if (binfo == 0)
        !           740:     {
        !           741:       error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);
        !           742:       return;
        !           743:     }
        !           744: 
        !           745:   base = convert_pointer_to (binfo, current_class_decl);
        !           746:   expand_member_init (build_indirect_ref (base), name, init);
        !           747: }
        !           748: 
        !           749: /* Function to give error message if member initialization specification
        !           750:    is erroneous.  FIELD is the member we decided to initialize.
        !           751:    TYPE is the type for which the initialization is being performed.
        !           752:    FIELD must be a member of TYPE, or the base type from which FIELD
        !           753:    comes must not need a constructor.
        !           754:    
        !           755:    MEMBER_NAME is the name of the member.  */
        !           756: 
        !           757: static int
        !           758: member_init_ok_or_else (field, type, member_name)
        !           759:      tree field;
        !           760:      tree type;
        !           761:      char *member_name;
        !           762: {
        !           763:   if (field == error_mark_node) return 0;
        !           764:   if (field == NULL_TREE)
        !           765:     {
        !           766:       error_with_aggr_type (type, "class `%s' does not have any field named `%s'",
        !           767:                            member_name);
        !           768:       return 0;
        !           769:     }
        !           770:   if (DECL_CONTEXT (field) != type
        !           771:       && TYPE_NEEDS_CONSTRUCTOR (DECL_CONTEXT (field)))
        !           772:     {
        !           773:       error ("member `%s' comes from base class needing constructor", member_name);
        !           774:       return 0;
        !           775:     }
        !           776:   return 1;
        !           777: }
        !           778: 
        !           779: /* If NAME is a viable field name for the aggregate DECL,
        !           780:    and PARMS is a viable parameter list, then expand an _EXPR
        !           781:    which describes this initialization.
        !           782: 
        !           783:    Note that we do not need to chase through the class's base classes
        !           784:    to look for NAME, because if it's in that list, it will be handled
        !           785:    by the constructor for that base class.
        !           786: 
        !           787:    We do not yet have a fixed-point finder to instantiate types
        !           788:    being fed to overloaded constructors.  If there is a unique
        !           789:    constructor, then argument types can be got from that one.
        !           790: 
        !           791:    If INIT is non-NULL, then it the initialization should
        !           792:    be placed in `current_base_init_list', where it will be processed
        !           793:    by `emit_base_init'.  */
        !           794: void
        !           795: expand_member_init (exp, name, init)
        !           796:      tree exp, name, init;
        !           797: {
        !           798:   extern tree ptr_type_node;   /* should be in tree.h */
        !           799: 
        !           800:   tree basetype = NULL_TREE, field;
        !           801:   tree parm;
        !           802:   tree rval, type;
        !           803:   tree actual_name;
        !           804: 
        !           805:   if (exp == NULL_TREE)
        !           806:     return;                    /* complain about this later */
        !           807: 
        !           808:   type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
        !           809: 
        !           810:   if (name == NULL_TREE && IS_AGGR_TYPE (type))
        !           811:     switch (CLASSTYPE_N_BASECLASSES (type))
        !           812:       {
        !           813:       case 0:
        !           814:        error ("base class initializer specified, but no base class to initialize");
        !           815:        return;
        !           816:       case 1:
        !           817:        basetype = TYPE_BINFO_BASETYPE (type, 0);
        !           818:        break;
        !           819:       default:
        !           820:        error ("initializer for unnamed base class ambiguous");
        !           821:        error_with_aggr_type (type, "(type `%s' uses multiple inheritance)");
        !           822:        return;
        !           823:       }
        !           824: 
        !           825:   if (init)
        !           826:     {
        !           827:       /* The grammar should not allow fields which have names
        !           828:         that are TYPENAMEs.  Therefore, if the field has
        !           829:         a non-NULL TREE_TYPE, we may assume that this is an
        !           830:         attempt to initialize a base class member of the current
        !           831:         type.  Otherwise, it is an attempt to initialize a
        !           832:         member field.  */
        !           833: 
        !           834:       if (init == void_type_node)
        !           835:        init = NULL_TREE;
        !           836: 
        !           837:       if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name))
        !           838:        {
        !           839:          tree base_init;
        !           840: 
        !           841:          if (name == NULL_TREE)
        !           842:            if (basetype)
        !           843:              name = TYPE_IDENTIFIER (basetype);
        !           844:            else
        !           845:              {
        !           846:                error ("no base class to initialize");
        !           847:                return;
        !           848:              }
        !           849:          else
        !           850:            {
        !           851:              basetype = IDENTIFIER_TYPE_VALUE (name);
        !           852:              if (basetype != type
        !           853:                  && ! binfo_member (basetype, TYPE_BINFO (type))
        !           854:                  && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
        !           855:                {
        !           856:                  if (IDENTIFIER_CLASS_VALUE (name))
        !           857:                    goto try_member;
        !           858:                  if (TYPE_USES_VIRTUAL_BASECLASSES (type))
        !           859:                    error ("type `%s' is not an immediate or virtual basetype for `%s'",
        !           860:                           IDENTIFIER_POINTER (name),
        !           861:                           TYPE_NAME_STRING (type));
        !           862:                  else
        !           863:                    error ("type `%s' is not an immediate basetype for `%s'",
        !           864:                           IDENTIFIER_POINTER (name),
        !           865:                           TYPE_NAME_STRING (type));
        !           866:                  return;
        !           867:                }
        !           868:            }
        !           869: 
        !           870:          if (purpose_member (name, current_base_init_list))
        !           871:            {
        !           872:              error ("base class `%s' already initialized",
        !           873:                     IDENTIFIER_POINTER (name));
        !           874:              return;
        !           875:            }
        !           876: 
        !           877:          base_init = build_tree_list (name, init);
        !           878:          TREE_TYPE (base_init) = basetype;
        !           879:          current_base_init_list = chainon (current_base_init_list, base_init);
        !           880:        }
        !           881:       else
        !           882:        {
        !           883:          tree member_init;
        !           884: 
        !           885:        try_member:
        !           886:          field = lookup_field (type, name, 1);
        !           887: 
        !           888:          if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
        !           889:            return;
        !           890: 
        !           891:          if (purpose_member (name, current_member_init_list))
        !           892:            {
        !           893:              error ("field `%s' already initialized", IDENTIFIER_POINTER (name));
        !           894:              return;
        !           895:            }
        !           896: 
        !           897:          member_init = build_tree_list (name, init);
        !           898:          TREE_TYPE (member_init) = TREE_TYPE (field);
        !           899:          current_member_init_list = chainon (current_member_init_list, member_init);
        !           900:        }
        !           901:       return;
        !           902:     }
        !           903:   else if (name == NULL_TREE)
        !           904:     {
        !           905:       compiler_error ("expand_member_init: name == NULL_TREE");
        !           906:       return;
        !           907:     }
        !           908: 
        !           909:   basetype = type;
        !           910:   field = lookup_field (basetype, name, 0);
        !           911: 
        !           912:   if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))
        !           913:     return;
        !           914: 
        !           915:   /* now see if there is a constructor for this type
        !           916:      which will take these args. */
        !           917: 
        !           918:   if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
        !           919:     {
        !           920:       tree parmtypes, fndecl;
        !           921: 
        !           922:       if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
        !           923:        {
        !           924:          /* just know that we've seen something for this node */
        !           925:          DECL_INITIAL (exp) = error_mark_node;
        !           926:          TREE_USED (exp) = 1;
        !           927:        }
        !           928:       type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
        !           929:       actual_name = TYPE_IDENTIFIER (type);
        !           930:       parm = build_component_ref (exp, name, 0, 0);
        !           931: 
        !           932:       /* Now get to the constructor.  */
        !           933:       fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
        !           934:       /* Get past destructor, if any.  */
        !           935:       if (TYPE_HAS_DESTRUCTOR (type))
        !           936:        fndecl = DECL_CHAIN (fndecl);
        !           937: 
        !           938:       if (fndecl)
        !           939:        assert (TREE_CODE (fndecl) == FUNCTION_DECL);
        !           940: 
        !           941:       /* If the field is unique, we can use the parameter
        !           942:         types to guide possible type instantiation.  */
        !           943:       if (DECL_CHAIN (fndecl) == NULL_TREE)
        !           944:        {
        !           945:          /* There was a confusion here between
        !           946:             FIELD and FNDECL.  The following code
        !           947:             should be correct, but abort is here
        !           948:             to make sure.  */
        !           949:          abort ();
        !           950:          parmtypes = FUNCTION_ARG_CHAIN (fndecl);
        !           951:        }
        !           952:       else
        !           953:        {
        !           954:          parmtypes = NULL_TREE;
        !           955:          fndecl = NULL_TREE;
        !           956:        }
        !           957: 
        !           958:       init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);
        !           959:       if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)
        !           960:        rval = build_method_call (NULL_TREE, actual_name, init, NULL_TREE, LOOKUP_NORMAL);
        !           961:       else
        !           962:        return;
        !           963: 
        !           964:       if (rval != error_mark_node)
        !           965:        {
        !           966:          /* Now, fill in the first parm with our guy */
        !           967:          TREE_VALUE (TREE_OPERAND (rval, 1))
        !           968:            = build_unary_op (ADDR_EXPR, parm, 0);
        !           969:          TREE_TYPE (rval) = ptr_type_node;
        !           970:          TREE_SIDE_EFFECTS (rval) = 1;
        !           971:        }
        !           972:     }
        !           973:   else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
        !           974:     {
        !           975:       parm = build_component_ref (exp, name, 0, 0);
        !           976:       expand_aggr_init (parm, NULL_TREE, 0);
        !           977:       rval = error_mark_node;
        !           978:     }
        !           979: 
        !           980:   /* Now initialize the member.  It does not have to
        !           981:      be of aggregate type to receive initialization.  */
        !           982:   if (rval != error_mark_node)
        !           983:     expand_expr_stmt (rval);
        !           984: }
        !           985: 
        !           986: /* This is like `expand_member_init', only it stores one aggregate
        !           987:    value into another.
        !           988: 
        !           989:    INIT comes in two flavors: it is either a value which
        !           990:    is to be stored in EXP, or it is a parameter list
        !           991:    to go to a constructor, which will operate on EXP.
        !           992:    If `init' is a CONSTRUCTOR, then we emit a warning message,
        !           993:    explaining that such initializaitions are illegal.
        !           994: 
        !           995:    ALIAS_THIS is nonzero iff we are initializing something which is
        !           996:    essentially an alias for C_C_D.  In this case, the base constructor
        !           997:    may move it on us, and we must keep track of such deviations.
        !           998: 
        !           999:    If INIT resolves to a CALL_EXPR which happens to return
        !          1000:    something of the type we are looking for, then we know
        !          1001:    that we can safely use that call to perform the
        !          1002:    initialization.
        !          1003: 
        !          1004:    The virtual function table pointer cannot be set up here, because
        !          1005:    we do not really know its type.
        !          1006: 
        !          1007:    Virtual baseclass pointers are also set up here.
        !          1008: 
        !          1009:    This never calls operator=().
        !          1010: 
        !          1011:    When initializing, nothing is CONST.  */
        !          1012: 
        !          1013: void
        !          1014: expand_aggr_init (exp, init, alias_this)
        !          1015:      tree exp, init;
        !          1016:      int alias_this;
        !          1017: {
        !          1018:   tree type = TREE_TYPE (exp);
        !          1019:   int was_const = TREE_READONLY (exp);
        !          1020: 
        !          1021:   if (init == error_mark_node)
        !          1022:     return;
        !          1023: 
        !          1024:   TREE_READONLY (exp) = 0;
        !          1025: 
        !          1026:   if (TREE_CODE (type) == ARRAY_TYPE)
        !          1027:     {
        !          1028:       /* Must arrange to initialize each element of EXP
        !          1029:         from elements of INIT.  */
        !          1030:       int was_const_elts = TYPE_READONLY (TREE_TYPE (type));
        !          1031:       tree itype = init ? TREE_TYPE (init) : NULL_TREE;
        !          1032:       if (was_const_elts)
        !          1033:        {
        !          1034:          tree atype = build_cplus_array_type (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
        !          1035:                                               TYPE_DOMAIN (type));
        !          1036:          if (TREE_TYPE (exp) == TREE_TYPE (init))
        !          1037:            TREE_TYPE (init) = atype;
        !          1038:          TREE_TYPE (exp) = atype;
        !          1039:        }
        !          1040:       expand_vec_init (exp, exp, array_type_nelts (type), init,
        !          1041:                       init && TREE_TYPE (init) == TREE_TYPE (exp));
        !          1042:       TREE_READONLY (exp) = was_const;
        !          1043:       TREE_TYPE (exp) = type;
        !          1044:       if (init) TREE_TYPE (init) = itype;
        !          1045:       return;
        !          1046:     }
        !          1047: 
        !          1048:   if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
        !          1049:     /* just know that we've seen something for this node */
        !          1050:     TREE_USED (exp) = 1;
        !          1051: 
        !          1052:   /* If initializing from a GNU C CONSTRUCTOR, consider the elts in the
        !          1053:      constructor as parameters to an implicit GNU C++ constructor.  */
        !          1054:   if (init && TREE_CODE (init) == CONSTRUCTOR
        !          1055:       && TYPE_HAS_CONSTRUCTOR (type)
        !          1056:       && TREE_TYPE (init) == type)
        !          1057:     init = CONSTRUCTOR_ELTS (init);
        !          1058:   expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
        !          1059:                      init, alias_this, LOOKUP_NORMAL);
        !          1060:   TREE_READONLY (exp) = was_const;
        !          1061: }
        !          1062: 
        !          1063: /* This function is responsible for initializing EXP with INIT
        !          1064:    (if any).
        !          1065: 
        !          1066:    BINFO is the binfo of the type for who we are performing the
        !          1067:    initialization.  For example, if W is a virtual base class of A and B,
        !          1068:    and C : A, B.
        !          1069:    If we are initializing B, then W must contain B's W vtable, whereas
        !          1070:    were we initializing C, W must contain C's W vtable.
        !          1071: 
        !          1072:    TRUE_EXP is nonzero if it is the true expression being initialized.
        !          1073:    In this case, it may be EXP, or may just contain EXP.  The reason we
        !          1074:    need this is because if EXP is a base element of TRUE_EXP, we
        !          1075:    don't necessarily know by looking at EXP where its virtual
        !          1076:    baseclass fields should really be pointing.  But we do know
        !          1077:    from TRUE_EXP.  In constructors, we don't know anything about
        !          1078:    the value being initialized.
        !          1079: 
        !          1080:    ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
        !          1081: 
        !          1082:    FLAGS is just passes to `build_method_call'.  See that function for
        !          1083:    its description.  */
        !          1084: 
        !          1085: static void
        !          1086: expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
        !          1087:      tree binfo;
        !          1088:      tree true_exp, exp;
        !          1089:      tree init;
        !          1090:      int alias_this;
        !          1091:      int flags;
        !          1092: {
        !          1093:   tree type = TREE_TYPE (exp);
        !          1094:   tree init_type = NULL_TREE;
        !          1095:   tree rval;
        !          1096: 
        !          1097:   assert (init != error_mark_node && type != error_mark_node);
        !          1098: 
        !          1099:   /* Use a function returning the desired type to initialize EXP for us.
        !          1100:      If the function is a constructor, and its first argument is
        !          1101:      NULL_TREE, know that it was meant for us--just slide exp on
        !          1102:      in and expand the constructor.  Constructors now come
        !          1103:      as TARGET_EXPRs.  */
        !          1104:   if (init)
        !          1105:     {
        !          1106:       tree init_list = NULL_TREE;
        !          1107: 
        !          1108:       if (TREE_CODE (init) == TREE_LIST)
        !          1109:        {
        !          1110:          init_list = init;
        !          1111:          if (TREE_CHAIN (init) == NULL_TREE)
        !          1112:            init = TREE_VALUE (init);
        !          1113:        }
        !          1114: 
        !          1115:       init_type = TREE_TYPE (init);
        !          1116: 
        !          1117:       if (TREE_CODE (init) != TREE_LIST)
        !          1118:        {
        !          1119:          if (TREE_CODE (init_type) == ERROR_MARK)
        !          1120:            return;
        !          1121: 
        !          1122: #if 0
        !          1123:          /* These lines are found troublesome 5/11/89.  */
        !          1124:          if (TREE_CODE (init_type) == REFERENCE_TYPE)
        !          1125:            init_type = TREE_TYPE (init_type);
        !          1126: #endif
        !          1127: 
        !          1128:          /* This happens when we use C++'s functional cast notation.
        !          1129:             If the types match, then just use the TARGET_EXPR
        !          1130:             directly.  Otherwise, we need to create the initializer
        !          1131:             separately from the object being initialized.  */
        !          1132:          if (TREE_CODE (init) == TARGET_EXPR)
        !          1133:            {
        !          1134:              if (init_type == type)
        !          1135:                {
        !          1136:                  if (TREE_CODE (exp) == VAR_DECL
        !          1137:                      || TREE_CODE (exp) == RESULT_DECL)
        !          1138:                    /* Unify the initialization targets.  */
        !          1139:                    DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
        !          1140:                  else
        !          1141:                    DECL_RTL (TREE_OPERAND (init, 0))
        !          1142:                      = (struct rtx_def *)expand_expr (exp, 0, 0, 0);
        !          1143: 
        !          1144:                  expand_expr_stmt (init);
        !          1145:                  return;
        !          1146:                }
        !          1147:              else
        !          1148:                {
        !          1149:                  init = TREE_OPERAND (init, 1);
        !          1150:                  init = build (CALL_EXPR, init_type,
        !          1151:                                TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
        !          1152:                  TREE_SIDE_EFFECTS (init) = 1;
        !          1153: #if 0
        !          1154:                  TREE_RAISES (init) = ??
        !          1155: #endif
        !          1156:                    if (init_list)
        !          1157:                      TREE_VALUE (init_list) = init;
        !          1158:                }
        !          1159:            }
        !          1160: 
        !          1161:          if (init_type == type && TREE_CODE (init) == CALL_EXPR
        !          1162: #if 0
        !          1163:              /* It is legal to directly initialize from a CALL_EXPR
        !          1164:                 without going through X(X&), apparently.  */
        !          1165:              && ! TYPE_GETS_INIT_REF (type)
        !          1166: #endif
        !          1167:              )
        !          1168:            {
        !          1169:              /* A CALL_EXPR is a legitmate form of initialization, so
        !          1170:                 we should not print this warning message.  */
        !          1171: #if 0
        !          1172:              /* Should have gone away due to 5/11/89 change.  */
        !          1173:              if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
        !          1174:                init = convert_from_reference (init);
        !          1175: #endif
        !          1176:              expand_assignment (exp, init, 0, 0);
        !          1177:              if (exp == DECL_RESULT (current_function_decl))
        !          1178:                {
        !          1179:                  /* Failing this assertion means that the return value
        !          1180:                     from receives multiple initializations.  */
        !          1181:                  assert (DECL_INITIAL (exp) == NULL_TREE || DECL_INITIAL (exp) == error_mark_node);
        !          1182:                  DECL_INITIAL (exp) = init;
        !          1183:                }
        !          1184:              return;
        !          1185:            }
        !          1186:          else if (init_type == type
        !          1187:                   && TREE_CODE (init) == COND_EXPR)
        !          1188:            {
        !          1189:              /* Push value to be initialized into the cond, where possible.
        !          1190:                 Avoid spurious warning messages when initializing the
        !          1191:                 result of this function.  */
        !          1192:              TREE_OPERAND (init, 1)
        !          1193:                = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));
        !          1194:              if (exp == DECL_RESULT (current_function_decl))
        !          1195:                DECL_INITIAL (exp) = NULL_TREE;
        !          1196:              TREE_OPERAND (init, 2)
        !          1197:                = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));
        !          1198:              if (exp == DECL_RESULT (current_function_decl))
        !          1199:                DECL_INITIAL (exp) = init;
        !          1200:              expand_expr (init, const0_rtx, VOIDmode, 0);
        !          1201:              free_temp_slots ();
        !          1202:              return;
        !          1203:            }
        !          1204:        }
        !          1205: 
        !          1206:       /* We did not know what we were initializing before.  Now we do.  */
        !          1207:       if (TREE_CODE (init) == TARGET_EXPR)
        !          1208:        {
        !          1209:          tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
        !          1210: 
        !          1211:          if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
        !          1212:              && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)
        !          1213:            {
        !          1214:              /* In order for this to work for RESULT_DECLs, if their
        !          1215:                 type has a constructor, then they must be BLKmode
        !          1216:                 so that they will be meaningfully addressable.  */
        !          1217:              tree arg = build_unary_op (ADDR_EXPR, exp, 0);
        !          1218:              init = TREE_OPERAND (init, 1);
        !          1219:              init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
        !          1220:                            TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
        !          1221:              TREE_SIDE_EFFECTS (init) = 1;
        !          1222: #if 0
        !          1223:              TREE_RAISES (init) = ??
        !          1224: #endif
        !          1225:              TREE_VALUE (TREE_OPERAND (init, 1))
        !          1226:                = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
        !          1227: 
        !          1228:              if (alias_this)
        !          1229:                {
        !          1230:                  expand_assignment (current_function_decl, init, 0, 0);
        !          1231:                  return;
        !          1232:                }
        !          1233:              if (exp == DECL_RESULT (current_function_decl))
        !          1234:                {
        !          1235:                  if (DECL_INITIAL (DECL_RESULT (current_function_decl)))
        !          1236:                    fatal ("return value from function receives multiple initializations");
        !          1237:                  DECL_INITIAL (exp) = init;
        !          1238:                }
        !          1239:              expand_expr_stmt (init);
        !          1240:              return;
        !          1241:            }
        !          1242:        }
        !          1243: 
        !          1244:       /* Handle this case: when calling a constructor: xyzzy foo(bar);
        !          1245:         which really means:  xyzzy foo = bar; Ugh!
        !          1246: 
        !          1247:         We can also be called with an initializer for an object
        !          1248:         which has virtual functions, but no constructors.  In that
        !          1249:         case, we perform the assignment first, then initialize
        !          1250:         the virtual function table pointer fields.  */
        !          1251: 
        !          1252:       if (! TYPE_NEEDS_CONSTRUCTING (type))
        !          1253:        {
        !          1254:          if (init_list && TREE_CHAIN (init_list))
        !          1255:            {
        !          1256:              warning ("initializer list being treated as compound expression");
        !          1257:              init = convert (TREE_TYPE (exp), build_compound_expr (init_list));
        !          1258:              if (init == error_mark_node)
        !          1259:                return;
        !          1260:            }
        !          1261:          if (TREE_CODE (exp) == VAR_DECL
        !          1262:              && TREE_CODE (init) == CONSTRUCTOR
        !          1263:              && TREE_HAS_CONSTRUCTOR (init)
        !          1264:              && flag_pic == 0)
        !          1265:            store_init_value (exp, init);
        !          1266:          else
        !          1267:            expand_assignment (exp, init, 0, 0);
        !          1268: 
        !          1269:          if (TYPE_VIRTUAL_P (type))
        !          1270:            expand_recursive_init (binfo, true_exp, exp, init, CLASSTYPE_BASE_INIT_LIST (type), alias_this);
        !          1271:          return;
        !          1272:        }
        !          1273: 
        !          1274:       /* See whether we can go through a type conversion operator.
        !          1275:         This wins over going through a constructor because we may be
        !          1276:         able to avoid an X(X&) constructor.  */
        !          1277:       if (TREE_CODE (init) != TREE_LIST)
        !          1278:        {
        !          1279:          tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
        !          1280:            ? TREE_TYPE (init_type) : init_type;
        !          1281: 
        !          1282:          if (ttype != type && IS_AGGR_TYPE (ttype))
        !          1283:            {
        !          1284:              tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0);
        !          1285: 
        !          1286:              if (rval)
        !          1287:                {
        !          1288:                  expand_assignment (exp, rval, 0, 0);
        !          1289:                  return;
        !          1290:                }
        !          1291:            }
        !          1292:        }
        !          1293:     }
        !          1294: 
        !          1295:   if (TYPE_HAS_CONSTRUCTOR (type))
        !          1296:     {
        !          1297:       /* It fails because there may not be a constructor which takes
        !          1298:         its own type as the first (or only parameter), but which does
        !          1299:         take other types via a conversion.  So, if the thing initializing
        !          1300:         the expression is a unit element of type X, first try X(X&),
        !          1301:         followed by initialization by X.  If neither of these work
        !          1302:         out, then look hard.  */
        !          1303:       tree parms = (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
        !          1304:        ? init : build_tree_list (NULL_TREE, init);
        !          1305:       int xxref_init_possible;
        !          1306: 
        !          1307:       if (parms) init = TREE_VALUE (parms);
        !          1308: 
        !          1309:       if (TYPE_HAS_INIT_REF (type)
        !          1310:          || init == NULL_TREE
        !          1311:          || TREE_CHAIN (parms) != NULL_TREE)
        !          1312:        xxref_init_possible = 0;
        !          1313:       else
        !          1314:        {
        !          1315:          xxref_init_possible = LOOKUP_SPECULATIVELY;
        !          1316:          flags &= ~LOOKUP_COMPLAIN;
        !          1317:        }
        !          1318: 
        !          1319:       if (TYPE_USES_VIRTUAL_BASECLASSES (type))
        !          1320:        {
        !          1321:          if (true_exp == exp)
        !          1322:            parms = tree_cons (NULL_TREE, integer_one_node, parms);
        !          1323:          else
        !          1324:            parms = tree_cons (NULL_TREE, integer_zero_node, parms);
        !          1325:          flags |= LOOKUP_HAS_IN_CHARGE;
        !          1326:        }
        !          1327:       rval = build_method_call (exp, constructor_name (type),
        !          1328:                                parms, binfo, flags|xxref_init_possible);
        !          1329:       if (rval == NULL_TREE && xxref_init_possible)
        !          1330:        {
        !          1331:          tree init_type = TREE_TYPE (init);
        !          1332:          if (TREE_CODE (init_type) == REFERENCE_TYPE)
        !          1333:            init_type = TREE_TYPE (init_type);
        !          1334:          if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type)
        !          1335:              || (IS_AGGR_TYPE (init_type)
        !          1336:                  && DERIVED_FROM_P (type, init_type)))
        !          1337:            {
        !          1338:              if (type == BINFO_TYPE (binfo)
        !          1339:                  && TYPE_USES_VIRTUAL_BASECLASSES (type))
        !          1340:                {
        !          1341:                  tree addr = build_unary_op (ADDR_EXPR, exp, 0);
        !          1342:                  expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE);
        !          1343: 
        !          1344:                  expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, exp, addr, 1));
        !          1345:                }
        !          1346:              expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
        !          1347:              return;
        !          1348:            }
        !          1349:          else
        !          1350:            rval = build_method_call (exp, constructor_name (type), parms,
        !          1351:                                      binfo, flags);
        !          1352:        }
        !          1353: 
        !          1354:       /* Private, protected, or otherwise unavailable.  */
        !          1355:       if (rval == error_mark_node && (flags&LOOKUP_COMPLAIN))
        !          1356:        error_with_aggr_type (binfo, "in base initialization for class `%s'");
        !          1357:       /* A valid initialization using constructor.  */
        !          1358:       else if (rval != error_mark_node && rval != NULL_TREE)
        !          1359:        {
        !          1360:          /* p. 222: if the base class assigns to `this', then that
        !          1361:             value is used in the derived class.  */
        !          1362:          if ((flag_this_is_variable & 1) && alias_this)
        !          1363:            {
        !          1364:              TREE_TYPE (rval) = TREE_TYPE (current_class_decl);
        !          1365:              expand_assignment (current_class_decl, rval, 0, 0);
        !          1366:            }
        !          1367:          else
        !          1368:            expand_expr_stmt (rval);
        !          1369:        }
        !          1370:       else if (parms && TREE_CHAIN (parms) == NULL_TREE)
        !          1371:        {
        !          1372:          /* If we are initializing one aggregate value
        !          1373:             from another, and though there are constructors,
        !          1374:             and none accept the initializer, just do a bitwise
        !          1375:             copy.
        !          1376:             
        !          1377:             @@ This should reject initializer which a constructor
        !          1378:             @@ rejected on visibility gounds, but there is
        !          1379:             @@ no way right now to recognize that case with
        !          1380:             @@ just `error_mark_node'.  */
        !          1381:          tree itype;
        !          1382:          init = TREE_VALUE (parms);
        !          1383:          itype = TREE_TYPE (init);
        !          1384:          if (TREE_CODE (itype) == REFERENCE_TYPE)
        !          1385:            {
        !          1386:              init = convert_from_reference (init);
        !          1387:              itype = TREE_TYPE (init);
        !          1388:            }
        !          1389:          itype = TYPE_MAIN_VARIANT (itype);
        !          1390: 
        !          1391:          /* This is currently how the default X(X&) constructor
        !          1392:             is implemented.  */
        !          1393:          if (comptypes (TYPE_MAIN_VARIANT (type), itype, 0))
        !          1394:            {
        !          1395: #if 0
        !          1396:              warning ("bitwise copy in initialization of type `%s'",
        !          1397:                       TYPE_NAME_STRING (type));
        !          1398: #endif
        !          1399:              rval = build (INIT_EXPR, type, exp, init);
        !          1400:              expand_expr_stmt (rval);
        !          1401:            }
        !          1402:          else
        !          1403:            {
        !          1404:              error_with_aggr_type (binfo, "in base initialization for class `%s',");
        !          1405:              error_with_aggr_type (type, "invalid initializer to constructor for type `%s'");
        !          1406:              return;
        !          1407:            }
        !          1408:        }
        !          1409:       else
        !          1410:        {
        !          1411:          if (init == NULL_TREE)
        !          1412:            assert (parms == NULL_TREE);
        !          1413:          if (parms == NULL_TREE && TREE_VIA_VIRTUAL (binfo))
        !          1414:            error_with_aggr_type (binfo, "virtual baseclass `%s' does not have default initializer");
        !          1415:          else
        !          1416:            {
        !          1417:              error_with_aggr_type (binfo, "in base initialization for class `%s',");
        !          1418:              /* This will make an error message for us.  */
        !          1419:              build_method_call (exp, constructor_name (type), parms, binfo,
        !          1420:                                 (TYPE_USES_VIRTUAL_BASECLASSES (type)
        !          1421:                                  ? LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE
        !          1422:                                  : LOOKUP_NORMAL));
        !          1423:            }
        !          1424:          return;
        !          1425:        }
        !          1426:       /* Constructor has been called, but vtables may be for TYPE
        !          1427:         rather than for FOR_TYPE.  */
        !          1428:     }
        !          1429:   else if (TREE_CODE (type) == ARRAY_TYPE)
        !          1430:     {
        !          1431:       if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
        !          1432:        expand_vec_init (exp, exp, array_type_nelts (type), init, 0);
        !          1433:       else if (TYPE_VIRTUAL_P (TREE_TYPE (type)))
        !          1434:        sorry ("arrays of objects with virtual functions but no constructors");
        !          1435:     }
        !          1436:   else
        !          1437:     expand_recursive_init (binfo, true_exp, exp, init, CLASSTYPE_BASE_INIT_LIST (type), alias_this);
        !          1438: }
        !          1439: 
        !          1440: /* A pointer which holds the initializer.  First call to
        !          1441:    expand_aggr_init gets this value pointed to, and sets it to init_null.  */
        !          1442: static tree *init_ptr, init_null;
        !          1443: 
        !          1444: /* Subroutine of expand_recursive_init:
        !          1445: 
        !          1446:    ADDR is the address of the expression being initialized.
        !          1447:    INIT_LIST is the cons-list of initializations to be performed.
        !          1448:    ALIAS_THIS is its same, lovable self.  */
        !          1449: static void
        !          1450: expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
        !          1451:      tree binfo, true_exp, addr;
        !          1452:      tree init_list;
        !          1453:      int alias_this;
        !          1454: {
        !          1455:   while (init_list)
        !          1456:     {
        !          1457:       if (TREE_PURPOSE (init_list))
        !          1458:        {
        !          1459:          if (TREE_CODE (TREE_PURPOSE (init_list)) == FIELD_DECL)
        !          1460:            {
        !          1461:              tree member = TREE_PURPOSE (init_list);
        !          1462:              tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), 0);
        !          1463:              tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member);
        !          1464:              if (IS_AGGR_TYPE (TREE_TYPE (member)))
        !          1465:                expand_aggr_init (member_base, DECL_INITIAL (member), 0);
        !          1466:              else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE
        !          1467:                       && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member)))
        !          1468:                {
        !          1469:                  member_base = save_expr (default_conversion (member_base));
        !          1470:                  expand_vec_init (member, member_base,
        !          1471:                                   array_type_nelts (TREE_TYPE (member)),
        !          1472:                                   DECL_INITIAL (member), 0);
        !          1473:                }
        !          1474:              else expand_expr_stmt (build_modify_expr (member_base, INIT_EXPR, DECL_INITIAL (member)));
        !          1475:            }
        !          1476:          else if (TREE_CODE (TREE_PURPOSE (init_list)) == TREE_LIST)
        !          1477:            {
        !          1478:              expand_recursive_init_1 (binfo, true_exp, addr, TREE_PURPOSE (init_list), alias_this);
        !          1479:              expand_recursive_init_1 (binfo, true_exp, addr, TREE_VALUE (init_list), alias_this);
        !          1480:            }
        !          1481:          else if (TREE_CODE (TREE_PURPOSE (init_list)) == ERROR_MARK)
        !          1482:            {
        !          1483:              /* Only initialize the virtual function tables if we
        !          1484:                 are initializing the ultimate users of those vtables.  */
        !          1485:              if (TREE_VALUE (init_list))
        !          1486:                {
        !          1487:                  expand_expr_stmt (build_virtual_init (binfo, TREE_VALUE (init_list), addr));
        !          1488:                  if (TREE_VALUE (init_list) == binfo
        !          1489:                      && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
        !          1490:                    expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
        !          1491:                }
        !          1492:            }
        !          1493:          else abort ();
        !          1494:        }
        !          1495:       else if (TREE_VALUE (init_list)
        !          1496:               && TREE_CODE (TREE_VALUE (init_list)) == TREE_VEC)
        !          1497:        {
        !          1498:          tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), 0);
        !          1499:          expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr,
        !          1500:                              alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)),
        !          1501:                              LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);
        !          1502: 
        !          1503:          /* INIT_PTR is used up.  */
        !          1504:          init_ptr = &init_null;
        !          1505:        }
        !          1506:       else
        !          1507:        abort ();
        !          1508:       init_list = TREE_CHAIN (init_list);
        !          1509:     }
        !          1510: }
        !          1511: 
        !          1512: /* Initialize EXP with INIT.  Type EXP does not have a constructor,
        !          1513:    but it has a baseclass with a constructor or a virtual function
        !          1514:    table which needs initializing.
        !          1515: 
        !          1516:    INIT_LIST is a cons-list describing what parts of EXP actually
        !          1517:    need to be initialized.  INIT is given to the *unique*, first
        !          1518:    constructor within INIT_LIST.  If there are multiple first
        !          1519:    constructors, such as with multiple inheritance, INIT must
        !          1520:    be zero or an ambiguity error is reported.
        !          1521: 
        !          1522:    ALIAS_THIS is passed from `expand_aggr_init'.  See comments
        !          1523:    there.  */
        !          1524: 
        !          1525: static void
        !          1526: expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)
        !          1527:      tree binfo, true_exp, exp, init;
        !          1528:      tree init_list;
        !          1529:      int alias_this;
        !          1530: {
        !          1531:   tree *old_init_ptr = init_ptr;
        !          1532:   tree addr = build_unary_op (ADDR_EXPR, exp, 0);
        !          1533:   init_ptr = &init;
        !          1534: 
        !          1535:   if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
        !          1536:     {
        !          1537:       expand_aggr_vbase_init (binfo, exp, addr, init_list);
        !          1538:       expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
        !          1539:     }
        !          1540:   expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
        !          1541: 
        !          1542:   if (*init_ptr)
        !          1543:     {
        !          1544:       tree type = TREE_TYPE (exp);
        !          1545: 
        !          1546:       if (TREE_CODE (type) == REFERENCE_TYPE)
        !          1547:        type = TREE_TYPE (type);
        !          1548:       if (IS_AGGR_TYPE (type))
        !          1549:        error_with_aggr_type (type, "unexpected argument to constructor `%s'");
        !          1550:       else
        !          1551:        error ("unexpected argument to constructor");
        !          1552:     }
        !          1553:   init_ptr = old_init_ptr;
        !          1554: }
        !          1555: 
        !          1556: /* Report an error if NAME is not the name of a user-defined,
        !          1557:    aggregate type.  If OR_ELSE is nonzero, give an error message.  */
        !          1558: int
        !          1559: is_aggr_typedef (name, or_else)
        !          1560:      tree name;
        !          1561: {
        !          1562:   tree type;
        !          1563: 
        !          1564:   if (! IDENTIFIER_HAS_TYPE_VALUE (name))
        !          1565:     {
        !          1566:       if (or_else)
        !          1567:        error ("`%s' fails to be an aggregate typedef",
        !          1568:               IDENTIFIER_POINTER (name));
        !          1569:       return 0;
        !          1570:     }
        !          1571:   type = IDENTIFIER_TYPE_VALUE (name);
        !          1572:   if (! IS_AGGR_TYPE (type))
        !          1573:     {
        !          1574:       fatal ("type `%s' is of non-aggregate type",
        !          1575:             IDENTIFIER_POINTER (name));
        !          1576:       return 0;
        !          1577:     }
        !          1578:   return 1;
        !          1579: }
        !          1580: 
        !          1581: /* This code could just as well go in `cp-class.c', but is placed here for
        !          1582:    modularity.  */
        !          1583: 
        !          1584: /* For an expression of the form CNAME :: NAME (PARMLIST), build
        !          1585:    the appropriate function call.  */
        !          1586: tree
        !          1587: build_member_call (cname, name, parmlist)
        !          1588:      tree cname, name, parmlist;
        !          1589: {
        !          1590:   tree type, t;
        !          1591:   tree method_name = name;
        !          1592:   int dtor = 0;
        !          1593:   int dont_use_this = 0;
        !          1594:   tree basetype_path, decl;
        !          1595: 
        !          1596:   if (TREE_CODE (method_name) == BIT_NOT_EXPR)
        !          1597:     {
        !          1598:       method_name = TREE_OPERAND (method_name, 0);
        !          1599:       dtor = 1;
        !          1600:     }
        !          1601: 
        !          1602:   if (TREE_CODE (cname) == SCOPE_REF)
        !          1603:     cname = resolve_scope_to_name (NULL_TREE, cname);
        !          1604: 
        !          1605:   if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))
        !          1606:     return error_mark_node;
        !          1607: 
        !          1608:   /* An operator we did not like.  */
        !          1609:   if (name == NULL_TREE)
        !          1610:     return error_mark_node;
        !          1611: 
        !          1612:   if (dtor)
        !          1613:     {
        !          1614:       if (! TYPE_HAS_DESTRUCTOR (IDENTIFIER_TYPE_VALUE (cname)))
        !          1615:        error ("type `%s' does not have a destructor",
        !          1616:               IDENTIFIER_POINTER (cname));
        !          1617:       else
        !          1618:        error ("destructor specification error");
        !          1619:       return error_mark_node;
        !          1620:     }
        !          1621: 
        !          1622:   type = IDENTIFIER_TYPE_VALUE (cname);
        !          1623: 
        !          1624:   /* No object?  Then just fake one up, and let build_method_call
        !          1625:      figure out what to do.  */
        !          1626:   if (current_class_type == 0
        !          1627:       || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)
        !          1628:     dont_use_this = 1;
        !          1629: 
        !          1630:   if (dont_use_this)
        !          1631:     {
        !          1632:       basetype_path = NULL_TREE;
        !          1633:       decl = build1 (NOP_EXPR,
        !          1634:                     TYPE_POINTER_TO (IDENTIFIER_TYPE_VALUE (cname)),
        !          1635:                     error_mark_node);
        !          1636:     }
        !          1637:   else if (current_class_decl == 0)
        !          1638:     {
        !          1639:       dont_use_this = 1;
        !          1640:       decl = build1 (NOP_EXPR,
        !          1641:                     TYPE_POINTER_TO (IDENTIFIER_TYPE_VALUE (cname)),
        !          1642:                     error_mark_node);
        !          1643:     }
        !          1644:   else decl = current_class_decl;
        !          1645: 
        !          1646:   if (t = lookup_fnfields (TYPE_BINFO (type), method_name, 0))
        !          1647:     return build_method_call (decl, method_name, parmlist, basetype_path,
        !          1648:                              LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
        !          1649:   if (TREE_CODE (name) == IDENTIFIER_NODE
        !          1650:       && (t = lookup_field (TYPE_BINFO (type), name, 1)))
        !          1651:     {
        !          1652:       if (t == error_mark_node)
        !          1653:        return error_mark_node;
        !          1654:       if (TREE_CODE (t) == FIELD_DECL)
        !          1655:        {
        !          1656:          if (dont_use_this)
        !          1657:            {
        !          1658:              error ("invalid use of non-static field `%s'",
        !          1659:                     IDENTIFIER_POINTER (name));
        !          1660:              return error_mark_node;
        !          1661:            }
        !          1662:          decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);
        !          1663:        }
        !          1664:       else if (TREE_CODE (t) == VAR_DECL)
        !          1665:        decl = t;
        !          1666:       else
        !          1667:        {
        !          1668:          error ("invalid use of member `%s::%s'",
        !          1669:                 IDENTIFIER_POINTER (cname), name);
        !          1670:          return error_mark_node;
        !          1671:        }
        !          1672:       if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))
        !          1673:          && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl)))
        !          1674:        return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist);
        !          1675:       return build_function_call (decl, parmlist);
        !          1676:     }
        !          1677:   else
        !          1678:     {
        !          1679:       char *err_name;
        !          1680:       if (TREE_CODE (name) == IDENTIFIER_NODE)
        !          1681:        {
        !          1682:          if (IDENTIFIER_OPNAME_P (name))
        !          1683:            {
        !          1684:              char *op_name = operator_name_string (method_name);
        !          1685:              err_name = (char *)alloca (13 + strlen (op_name));
        !          1686:              sprintf (err_name, "operator %s", op_name);
        !          1687:            }
        !          1688:          else
        !          1689:            err_name = IDENTIFIER_POINTER (name);
        !          1690:        }
        !          1691:       else
        !          1692:        abort ();
        !          1693: 
        !          1694:       error ("no method `%s::%s'", IDENTIFIER_POINTER (cname), err_name);
        !          1695:       return error_mark_node;
        !          1696:     }
        !          1697: }
        !          1698: 
        !          1699: /* Build a reference to a member of an aggregate.  This is not a
        !          1700:    C++ `&', but really something which can have its address taken,
        !          1701:    and then act as a pointer to member, for example CNAME :: FIELD
        !          1702:    can have its address taken by saying & CNAME :: FIELD.
        !          1703: 
        !          1704:    @@ Prints out lousy diagnostics for operator <typename>
        !          1705:    @@ fields.
        !          1706: 
        !          1707:    @@ This function should be rewritten and placed in cp-search.c.  */
        !          1708: tree
        !          1709: build_offset_ref (cname, name)
        !          1710:      tree cname, name;
        !          1711: {
        !          1712:   tree decl, type, fnfields, fields, t = error_mark_node;
        !          1713:   tree basetypes = NULL_TREE;
        !          1714:   int dtor = 0;
        !          1715: 
        !          1716:   if (TREE_CODE (cname) == SCOPE_REF)
        !          1717:     cname = resolve_scope_to_name (NULL_TREE, cname);
        !          1718: 
        !          1719:   if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))
        !          1720:     return error_mark_node;
        !          1721: 
        !          1722:   type = IDENTIFIER_TYPE_VALUE (cname);
        !          1723: 
        !          1724:   if (TREE_CODE (name) == BIT_NOT_EXPR)
        !          1725:     {
        !          1726:       dtor = 1;
        !          1727:       name = TREE_OPERAND (name, 0);
        !          1728:     }
        !          1729: 
        !          1730:   if (TYPE_SIZE (type) == 0)
        !          1731:     {
        !          1732:       t = IDENTIFIER_CLASS_VALUE (name);
        !          1733:       if (t == 0)
        !          1734:        {
        !          1735:          error_with_aggr_type (type, "incomplete type `%s' does not have member `%s'", IDENTIFIER_POINTER (name));
        !          1736:          return error_mark_node;
        !          1737:        }
        !          1738:       if (TREE_CODE (t) == TYPE_DECL)
        !          1739:        {
        !          1740:          error_with_decl (t, "member `%s' is just a type declaration");
        !          1741:          return error_mark_node;
        !          1742:        }
        !          1743:       if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
        !          1744:        {
        !          1745:          TREE_USED (t) = 1;
        !          1746:          return t;
        !          1747:        }
        !          1748:       if (TREE_CODE (t) == FIELD_DECL)
        !          1749:        sorry ("use of member in incomplete aggregate type");
        !          1750:       else if (TREE_CODE (t) == FUNCTION_DECL)
        !          1751:        sorry ("use of member function in incomplete aggregate type");
        !          1752:       else
        !          1753:        abort ();
        !          1754:       return error_mark_node;
        !          1755:     }
        !          1756: 
        !          1757:   if (TREE_CODE (name) == TYPE_EXPR)
        !          1758:     /* Pass a TYPE_DECL to build_component_type_expr.  */
        !          1759:     return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)),
        !          1760:                                      name, NULL_TREE, 1);
        !          1761: 
        !          1762:   fnfields = lookup_fnfields (TYPE_BINFO (type), name, 0);
        !          1763:   fields = lookup_field (type, name, 0);
        !          1764: 
        !          1765:   if (fields == error_mark_node)
        !          1766:     return error_mark_node;
        !          1767: 
        !          1768:   if (fnfields)
        !          1769:     {
        !          1770:       basetypes = TREE_PURPOSE (fnfields);
        !          1771: 
        !          1772:       /* Go from the TREE_BASELINK to the member function info.  */
        !          1773:       t = TREE_VALUE (fnfields);
        !          1774: 
        !          1775:       if (fields)
        !          1776:        {
        !          1777:          if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t))
        !          1778:            {
        !          1779:              error ("ambiguous member reference: member `%s' defined as both field and function",
        !          1780:                     IDENTIFIER_POINTER (name));
        !          1781:              return error_mark_node;
        !          1782:            }
        !          1783:          if (DERIVED_FROM_P (DECL_FIELD_CONTEXT (fields), DECL_FIELD_CONTEXT (t)))
        !          1784:            ;
        !          1785:          else if (DERIVED_FROM_P (DECL_FIELD_CONTEXT (t), DECL_FIELD_CONTEXT (fields)))
        !          1786:            t = fields;
        !          1787:          else
        !          1788:            {
        !          1789:              error ("ambiguous member reference: member `%s' derives from distinct classes in multiple inheritance lattice");
        !          1790:              return error_mark_node;
        !          1791:            }
        !          1792:        }
        !          1793: 
        !          1794:       if (t == TREE_VALUE (fnfields))
        !          1795:        {
        !          1796:          extern int flag_save_memoized_contexts;
        !          1797: 
        !          1798:          /* This does not handle visibility checking yet.  */
        !          1799:          if (DECL_CHAIN (t) == NULL_TREE || dtor)
        !          1800:            {
        !          1801:              enum visibility_type visibility;
        !          1802: 
        !          1803:              /* unique functions are handled easily.  */
        !          1804:            unique:
        !          1805:              visibility = compute_visibility (basetypes, t);
        !          1806:              if (visibility == visibility_protected)
        !          1807:                {
        !          1808:                  error_with_decl (t, "member function `%s' is protected");
        !          1809:                  error ("in this context");
        !          1810:                  return error_mark_node;
        !          1811:                }
        !          1812:              if (visibility == visibility_private)
        !          1813:                {
        !          1814:                  error_with_decl (t, "member function `%s' is private");
        !          1815:                  error ("in this context");
        !          1816:                  return error_mark_node;
        !          1817:                }
        !          1818:              assemble_external (t);
        !          1819:              return build (OFFSET_REF, TREE_TYPE (t), NULL_TREE, t);
        !          1820:            }
        !          1821: 
        !          1822:          /* overloaded functions may need more work.  */
        !          1823:          if (cname == name)
        !          1824:            {
        !          1825:              if (TYPE_HAS_DESTRUCTOR (type)
        !          1826:                  && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE)
        !          1827:                {
        !          1828:                  t = DECL_CHAIN (t);
        !          1829:                  goto unique;
        !          1830:                }
        !          1831:            }
        !          1832:          /* FNFIELDS is most likely allocated on the search_obstack,
        !          1833:             which will go away after this class scope.  If we need
        !          1834:             to save this value for later (either for memoization
        !          1835:             or for use as an initializer for a static variable), then
        !          1836:             do so here.
        !          1837: 
        !          1838:             ??? The smart thing to do for the case of saving initializers
        !          1839:             is to resolve them before we're done with this scope.  */
        !          1840:          if (!TREE_PERMANENT (fnfields)
        !          1841:              && ((flag_save_memoized_contexts && global_bindings_p ())
        !          1842:                  || ! allocation_temporary_p ()))
        !          1843:            fnfields = copy_list (fnfields);
        !          1844:          t = build_tree_list (error_mark_node, fnfields);
        !          1845:          TREE_TYPE (t) = build_member_type (type, unknown_type_node);
        !          1846:          return t;
        !          1847:        }
        !          1848:     }
        !          1849: 
        !          1850:   /* Now that we know we are looking for a field, see if we
        !          1851:      have access to that field.  Lookup_field will give us the
        !          1852:      error message.  */
        !          1853: 
        !          1854:   if (current_class_type == 0
        !          1855:       || get_base_distance (type, current_class_type, 0, &basetypes) == -1)
        !          1856:     {
        !          1857:       basetypes = TYPE_BINFO (type);
        !          1858:       decl = build1 (NOP_EXPR,
        !          1859:                     IDENTIFIER_TYPE_VALUE (cname),
        !          1860:                     error_mark_node);
        !          1861:     }
        !          1862:   else if (current_class_decl == 0)
        !          1863:     decl = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (cname)),
        !          1864:                   error_mark_node);
        !          1865:   else decl = C_C_D;
        !          1866: 
        !          1867:   t = lookup_field (basetypes, name, 1);
        !          1868: 
        !          1869:   if (t == error_mark_node)
        !          1870:     return error_mark_node;
        !          1871: 
        !          1872:   if (t == NULL_TREE)
        !          1873:     {
        !          1874:       char *print_name;
        !          1875: 
        !          1876:       if (name == ansi_opname[TYPE_EXPR])
        !          1877:        {
        !          1878:          error ("type conversion operator not a member of type `%s'",
        !          1879:                 IDENTIFIER_POINTER (cname));
        !          1880:          return error_mark_node;
        !          1881:        }
        !          1882:       print_name = operator_name_string (name);
        !          1883:       /* First character of "<invalid operator>".  */
        !          1884:       if (print_name[0] == '<')
        !          1885:        error ("field `%s' is not a member of type `%s'",
        !          1886:               IDENTIFIER_POINTER (name),
        !          1887:               IDENTIFIER_POINTER (cname));
        !          1888:       else
        !          1889:        error ("operator `%s' is not a member of type `%s'",
        !          1890:               print_name, IDENTIFIER_POINTER (cname));
        !          1891:       return error_mark_node;
        !          1892:     }
        !          1893: 
        !          1894:   if (TREE_CODE (t) == TYPE_DECL)
        !          1895:     {
        !          1896:       error_with_decl (t, "member `%s' is just a type declaration");
        !          1897:       return error_mark_node;
        !          1898:     }
        !          1899:   /* static class members and class-specific enum
        !          1900:      values can be returned without further ado.  */
        !          1901:   if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
        !          1902:     {
        !          1903:       assemble_external (t);
        !          1904:       TREE_USED (t) = 1;
        !          1905:       return t;
        !          1906:     }
        !          1907: 
        !          1908:   /* static class functions too.  */
        !          1909:   if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
        !          1910:     abort ();
        !          1911: 
        !          1912:   /* In member functions, the form `cname::name' is no longer
        !          1913:      equivalent to `this->cname::name'.  */
        !          1914:   return build (OFFSET_REF, build_member_type (type, TREE_TYPE (t)), decl, t);
        !          1915: }
        !          1916: 
        !          1917: /* Given an object EXP and a member function reference MEMBER,
        !          1918:    return the address of the actual member function.  */
        !          1919: tree
        !          1920: get_member_function (exp_addr_ptr, exp, member)
        !          1921:      tree *exp_addr_ptr;
        !          1922:      tree exp, member;
        !          1923: {
        !          1924:   tree ctype = TREE_TYPE (exp);
        !          1925:   tree function = save_expr (build_unary_op (ADDR_EXPR, member, 0));
        !          1926: 
        !          1927:   if (TYPE_VIRTUAL_P (ctype)
        !          1928:       || (flag_all_virtual == 1
        !          1929:          && (TYPE_OVERLOADS_METHOD_CALL_EXPR (ctype)
        !          1930:              || TYPE_NEEDS_WRAPPER (ctype))))
        !          1931:     {
        !          1932:       tree e0, e1, e3;
        !          1933:       tree exp_addr;
        !          1934: 
        !          1935:       /* Save away the unadulterated `this' pointer.  */
        !          1936:       exp_addr = save_expr (*exp_addr_ptr);
        !          1937: 
        !          1938:       /* Cast function to signed integer.  */
        !          1939:       e0 = build1 (NOP_EXPR, integer_type_node, function);
        !          1940: 
        !          1941: #ifdef VTABLE_USES_MASK
        !          1942:       /* If we are willing to limit the number of
        !          1943:         virtual functions a class may have to some
        !          1944:         *small* number, then if, for a function address,
        !          1945:         we are passed some small number, we know that
        !          1946:         it is a virtual function index, and work from there.  */
        !          1947:       e1 = build (BIT_AND_EXPR, integer_type_node, e0, vtbl_mask);
        !          1948: #else
        !          1949:       /* There is a hack here that takes advantage of
        !          1950:         twos complement arithmetic, and the fact that
        !          1951:         there are more than one UNITS to the WORD.
        !          1952:         If the high bit is set for the `function',
        !          1953:         then we pretend it is a virtual function,
        !          1954:         and the array indexing will knock this bit
        !          1955:         out the top, leaving a valid index.  */
        !          1956:       if (UNITS_PER_WORD <= 1)
        !          1957:        abort ();
        !          1958: 
        !          1959:       e1 = build (GT_EXPR, integer_type_node, e0, integer_zero_node);
        !          1960:       e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
        !          1961:                                           build_tree_list (NULL_TREE, e1)));
        !          1962:       e1 = save_expr (e1);
        !          1963: #endif
        !          1964: 
        !          1965:       if (TREE_SIDE_EFFECTS (*exp_addr_ptr))
        !          1966:        {
        !          1967:          exp = build_indirect_ref (exp_addr, 0);
        !          1968:          *exp_addr_ptr = exp_addr;
        !          1969:        }
        !          1970: 
        !          1971:       /* This is really hairy: if the function pointer is a pointer
        !          1972:         to a non-virtual member function, then we can't go mucking
        !          1973:         with the `this' pointer (any more than we aleady have to
        !          1974:         this point).  If it is a pointer to a virtual member function,
        !          1975:         then we have to adjust the `this' pointer according to
        !          1976:         what the virtual function table tells us.  */
        !          1977: 
        !          1978:       e3 = build_vfn_ref (exp_addr_ptr, exp, e0);
        !          1979:       assert (e3 != error_mark_node);
        !          1980: 
        !          1981:       /* Change this pointer type from `void *' to the
        !          1982:         type it is really supposed to be.  */
        !          1983:       TREE_TYPE (e3) = TREE_TYPE (function);
        !          1984: 
        !          1985:       /* If non-virtual, use what we had originally.  Otherwise,
        !          1986:         use the value we get from the virtual function table.  */
        !          1987:       *exp_addr_ptr = build_conditional_expr (e1, exp_addr, *exp_addr_ptr);
        !          1988: 
        !          1989:       function = build_conditional_expr (e1, function, e3);
        !          1990:     }
        !          1991:   return build_indirect_ref (function, 0);
        !          1992: }
        !          1993: 
        !          1994: /* If a OFFSET_REF made it through to here, then it did
        !          1995:    not have its address taken.  */
        !          1996: 
        !          1997: tree
        !          1998: resolve_offset_ref (exp)
        !          1999:      tree exp;
        !          2000: {
        !          2001:   tree type = TREE_TYPE (exp);
        !          2002:   tree base = NULL_TREE;
        !          2003:   tree member;
        !          2004:   tree basetype, addr;
        !          2005: 
        !          2006:   if (TREE_CODE (exp) == TREE_LIST)
        !          2007:     return build_unary_op (ADDR_EXPR, exp, 0);
        !          2008: 
        !          2009:   if (TREE_CODE (exp) != OFFSET_REF)
        !          2010:     {
        !          2011:       assert (TREE_CODE (type) == OFFSET_TYPE);
        !          2012:       if (TYPE_OFFSET_BASETYPE (type) != current_class_type)
        !          2013:        {
        !          2014:          error ("object missing in use of pointer-to-member construct");
        !          2015:          return error_mark_node;
        !          2016:        }
        !          2017:       member = exp;
        !          2018:       type = TREE_TYPE (type);
        !          2019:       base = C_C_D;
        !          2020:     }
        !          2021:   else
        !          2022:     {
        !          2023:       member = TREE_OPERAND (exp, 1);
        !          2024:       base = TREE_OPERAND (exp, 0);
        !          2025:     }
        !          2026: 
        !          2027:   if (TREE_STATIC (member))
        !          2028:     {
        !          2029:       /* These were static members.  */
        !          2030:       if (mark_addressable (member) == 0)
        !          2031:        return error_mark_node;
        !          2032:       return member;
        !          2033:     }
        !          2034: 
        !          2035:   /* Syntax error can cause a member which should
        !          2036:      have been seen as static to be grok'd as non-static.  */
        !          2037:   if (TREE_CODE (member) == FIELD_DECL && C_C_D == NULL_TREE)
        !          2038:     {
        !          2039:       if (TREE_ADDRESSABLE (member) == 0)
        !          2040:        {
        !          2041:          error_with_decl (member, "member `%s' is non-static in static member function context");
        !          2042:          error ("at this point in file");
        !          2043:          TREE_ADDRESSABLE (member) = 1;
        !          2044:        }
        !          2045:       return error_mark_node;
        !          2046:     }
        !          2047: 
        !          2048:   /* The first case is really just a reference to a member of `this'.  */
        !          2049:   if (TREE_CODE (member) == FIELD_DECL
        !          2050:       && (base == C_C_D
        !          2051:          || (TREE_CODE (base) == NOP_EXPR
        !          2052:              && TREE_OPERAND (base, 0) == error_mark_node)))
        !          2053:     {
        !          2054:       tree basetype_path;
        !          2055:       enum visibility_type visibility;
        !          2056: 
        !          2057:       basetype = DECL_CONTEXT (member);
        !          2058:       if (get_base_distance (basetype, current_class_type, 0, &basetype_path) < 0)
        !          2059:        {
        !          2060:          error_not_base_type (basetype, current_class_type);
        !          2061:          return error_mark_node;
        !          2062:        }
        !          2063:       addr = convert_pointer_to (basetype, current_class_decl);
        !          2064:       visibility = compute_visibility (basetype_path, member);
        !          2065:       if (visibility == visibility_public)
        !          2066:        return build (COMPONENT_REF, TREE_TYPE (member),
        !          2067:                      build_indirect_ref (addr, 0), member);
        !          2068:       if (visibility == visibility_protected)
        !          2069:        {
        !          2070:          error_with_decl ("member `%s' is protected");
        !          2071:          error ("in this context");
        !          2072:          return error_mark_node;
        !          2073:        }
        !          2074:       if (visibility == visibility_private)
        !          2075:        {
        !          2076:          error_with_decl ("member `%s' is private");
        !          2077:          error ("in this context");
        !          2078:          return error_mark_node;
        !          2079:        }
        !          2080:       abort ();
        !          2081:     }
        !          2082:   /* If this is a reference to a member function, then return
        !          2083:      the address of the member function (which may involve going
        !          2084:      through the object's vtable), otherwise, return an expression
        !          2085:      for the derefernced pointer-to-member construct.  */
        !          2086:   addr = build_unary_op (ADDR_EXPR, base, 0);
        !          2087:   if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
        !          2088:     {
        !          2089:       basetype = DECL_CLASS_CONTEXT (member);
        !          2090:       addr = convert_pointer_to (basetype, addr);
        !          2091:       return build_unary_op (ADDR_EXPR, get_member_function (&addr, build_indirect_ref (addr, 0), member), 0);
        !          2092:     }
        !          2093:   else if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
        !          2094:     {
        !          2095:       basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
        !          2096:       addr = convert_pointer_to (basetype, addr);
        !          2097:       member = convert (ptr_type_node, build_unary_op (ADDR_EXPR, member, 0));
        !          2098:       return build1 (INDIRECT_REF, type,
        !          2099:                     build (PLUS_EXPR, ptr_type_node, addr, member));
        !          2100:     }
        !          2101:   abort ();
        !          2102:   /* NOTREACHED */
        !          2103:   return NULL_TREE;
        !          2104: }
        !          2105: 
        !          2106: /* Return either DECL or its known constant value (if it has one).  */
        !          2107: 
        !          2108: tree
        !          2109: decl_constant_value (decl)
        !          2110:      tree decl;
        !          2111: {
        !          2112:   if (! TREE_THIS_VOLATILE (decl)
        !          2113: #if 0
        !          2114:       /* These may be necessary for C, but they break C++.  */
        !          2115:       ! TREE_PUBLIC (decl)
        !          2116:       /* Don't change a variable array bound or initial value to a constant
        !          2117:         in a place where a variable is invalid.  */
        !          2118:       && ! pedantic
        !          2119: #endif /* 0 */
        !          2120:       && DECL_INITIAL (decl) != 0
        !          2121:       && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
        !          2122:       /* This is invalid if initial value is not constant.
        !          2123:         If it has either a function call, a memory reference,
        !          2124:         or a variable, then re-evaluating it could give different results.  */
        !          2125:       && TREE_CONSTANT (DECL_INITIAL (decl))
        !          2126:       /* Check for cases where this is sub-optimal, even though valid.  */
        !          2127:       && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
        !          2128: #if 0
        !          2129:       /* We must allow this to work outside of functions so that
        !          2130:         static constants can be used for array sizes.  */
        !          2131:       && current_function_decl != 0
        !          2132:       && DECL_MODE (decl) != BLKmode
        !          2133: #endif
        !          2134:       )
        !          2135:     return DECL_INITIAL (decl);
        !          2136:   return decl;
        !          2137: }
        !          2138: 
        !          2139: /* Friend handling routines.  */
        !          2140: /* Friend data structures:
        !          2141: 
        !          2142:    Friend lists come from TYPE_DECL nodes.  Since all aggregate
        !          2143:    types are automatically typedef'd, these node are guaranteed
        !          2144:    to exist.
        !          2145: 
        !          2146:    The TREE_PURPOSE of a friend list is the name of the friend,
        !          2147:    and its TREE_VALUE is another list.
        !          2148: 
        !          2149:    The TREE_PURPOSE of that list is a type, which allows
        !          2150:    all functions of a given type to be friends.
        !          2151:    The TREE_VALUE of that list is an individual function
        !          2152:    which is a friend.
        !          2153: 
        !          2154:    Non-member friends will match only by their DECL.  Their
        !          2155:    member type is NULL_TREE, while the type of the inner
        !          2156:    list will either be of aggregate type or error_mark_node.  */
        !          2157: 
        !          2158: /* Tell if this function specified by FUNCTION_DECL
        !          2159:    can be a friend of type TYPE.
        !          2160:    Return nonzero if friend, zero otherwise.
        !          2161: 
        !          2162:    DECL can be zero if we are calling a constructor or accessing a
        !          2163:    member in global scope.  */
        !          2164: int
        !          2165: is_friend (type, decl)
        !          2166:      tree type, decl;
        !          2167: {
        !          2168:   tree typedecl = TYPE_NAME (type);
        !          2169:   tree ctype;
        !          2170:   tree list;
        !          2171:   tree name;
        !          2172: 
        !          2173:   if (decl == NULL_TREE)
        !          2174:     return 0;
        !          2175: 
        !          2176:   ctype = DECL_CLASS_CONTEXT (decl);
        !          2177:   if (ctype)
        !          2178:     {
        !          2179:       list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (typedecl));
        !          2180:       while (list)
        !          2181:        {
        !          2182:          if (ctype == TREE_VALUE (list))
        !          2183:            return 1;
        !          2184:          list = TREE_CHAIN (list);
        !          2185:        }
        !          2186:     }
        !          2187: 
        !          2188:   list = DECL_FRIENDLIST (typedecl);
        !          2189:   name = DECL_NAME (decl);
        !          2190:   while (list)
        !          2191:     {
        !          2192:       if (name == TREE_PURPOSE (list))
        !          2193:        {
        !          2194:          tree friends = TREE_VALUE (list);
        !          2195:          name = DECL_ASSEMBLER_NAME (decl);
        !          2196:          while (friends)
        !          2197:            {
        !          2198:              if (ctype == TREE_PURPOSE (friends))
        !          2199:                return 1;
        !          2200:              if (name == DECL_ASSEMBLER_NAME (TREE_VALUE (friends)))
        !          2201:                return 1;
        !          2202:              friends = TREE_CHAIN (friends);
        !          2203:            }
        !          2204:          return 0;
        !          2205:        }
        !          2206:       list = TREE_CHAIN (list);
        !          2207:     }
        !          2208:   return 0;
        !          2209: }
        !          2210: 
        !          2211: /* Add a new friend to the friends of the aggregate type TYPE.
        !          2212:    DECL is the FUNCTION_DECL of the friend being added.  */
        !          2213: static void
        !          2214: add_friend (type, decl)
        !          2215:      tree type, decl;
        !          2216: {
        !          2217:   tree typedecl = TYPE_NAME (type);
        !          2218:   tree list = DECL_FRIENDLIST (typedecl);
        !          2219:   tree name = DECL_NAME (decl);
        !          2220:   tree ctype = TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
        !          2221:     ? DECL_CLASS_CONTEXT (decl) : error_mark_node;
        !          2222: 
        !          2223:   while (list)
        !          2224:     {
        !          2225:       if (name == TREE_PURPOSE (list))
        !          2226:        {
        !          2227:          tree friends = TREE_VALUE (list);
        !          2228:          while (friends)
        !          2229:            {
        !          2230:              if (decl == TREE_VALUE (friends))
        !          2231:                {
        !          2232:                  warning_with_decl (decl, "`%s' is already a friend of class `%s'", IDENTIFIER_POINTER (DECL_NAME (typedecl)));
        !          2233:                  return;
        !          2234:                }
        !          2235:              friends = TREE_CHAIN (friends);
        !          2236:            }
        !          2237:          TREE_VALUE (list) = tree_cons (ctype, decl, TREE_VALUE (list));
        !          2238:          return;
        !          2239:        }
        !          2240:       list = TREE_CHAIN (list);
        !          2241:     }
        !          2242:   DECL_FRIENDLIST (typedecl)
        !          2243:     = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
        !          2244:                 DECL_FRIENDLIST (typedecl));
        !          2245:   if (DECL_NAME (decl) == ansi_opname[MODIFY_EXPR])
        !          2246:     {
        !          2247:       tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
        !          2248:       TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
        !          2249:       TYPE_GETS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
        !          2250:       if (parmtypes && TREE_CHAIN (parmtypes))
        !          2251:        {
        !          2252:          tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
        !          2253:          if (TREE_CODE (parmtype) == REFERENCE_TYPE
        !          2254:              && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
        !          2255:            {
        !          2256:              TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
        !          2257:              TYPE_GETS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
        !          2258:            }
        !          2259:        }
        !          2260:     }
        !          2261: }
        !          2262: 
        !          2263: /* Declare that every member function NAME in FRIEND_TYPE
        !          2264:    (which may be NULL_TREE) is a friend of type TYPE.  */
        !          2265: static void
        !          2266: add_friends (type, name, friend_type)
        !          2267:      tree type, name, friend_type;
        !          2268: {
        !          2269:   tree typedecl = TYPE_NAME (type);
        !          2270:   tree list = DECL_FRIENDLIST (typedecl);
        !          2271: 
        !          2272:   while (list)
        !          2273:     {
        !          2274:       if (name == TREE_PURPOSE (list))
        !          2275:        {
        !          2276:          tree friends = TREE_VALUE (list);
        !          2277:          while (friends && TREE_PURPOSE (friends) != friend_type)
        !          2278:            friends = TREE_CHAIN (friends);
        !          2279:          if (friends)
        !          2280:            if (friend_type)
        !          2281:              warning ("method `%s::%s' is already a friend of class",
        !          2282:                       TYPE_NAME_STRING (friend_type),
        !          2283:                       IDENTIFIER_POINTER (name));
        !          2284:            else
        !          2285:              warning ("function `%s' is already a friend of class `%s'",
        !          2286:                       IDENTIFIER_POINTER (name),
        !          2287:                       IDENTIFIER_POINTER (DECL_NAME (typedecl)));
        !          2288:          else
        !          2289:            TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE,
        !          2290:                                           TREE_VALUE (list));
        !          2291:          return;
        !          2292:        }
        !          2293:       list = TREE_CHAIN (list);
        !          2294:     }
        !          2295:   DECL_FRIENDLIST (typedecl) =
        !          2296:     tree_cons (name,
        !          2297:               build_tree_list (friend_type, NULL_TREE),
        !          2298:               DECL_FRIENDLIST (typedecl));
        !          2299:   if (! strncmp (IDENTIFIER_POINTER (name),
        !          2300:                 IDENTIFIER_POINTER (ansi_opname[MODIFY_EXPR]),
        !          2301:                 strlen (IDENTIFIER_POINTER (ansi_opname[MODIFY_EXPR]))))
        !          2302:     {
        !          2303:       TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
        !          2304:       TYPE_GETS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
        !          2305:       sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
        !          2306:     }
        !          2307: }
        !          2308: 
        !          2309: /* Set up a cross reference so that type TYPE will
        !          2310:    make member function CTYPE::DECL a friend when CTYPE
        !          2311:    is finally defined.  */
        !          2312: void
        !          2313: xref_friend (type, decl, ctype)
        !          2314:      tree type, decl, ctype;
        !          2315: {
        !          2316:   tree typedecl = TYPE_NAME (type);
        !          2317:   tree friend_decl = TYPE_NAME (ctype);
        !          2318:   tree t = tree_cons (NULL_TREE, ctype, DECL_UNDEFINED_FRIENDS (typedecl));
        !          2319: 
        !          2320:   DECL_UNDEFINED_FRIENDS (typedecl) = t;
        !          2321:   SET_DECL_WAITING_FRIENDS (friend_decl, tree_cons (type, t, DECL_WAITING_FRIENDS (friend_decl)));
        !          2322:   TREE_TYPE (DECL_WAITING_FRIENDS (friend_decl)) = decl;
        !          2323: }
        !          2324: 
        !          2325: /* Set up a cross reference so that functions with name NAME and
        !          2326:    type CTYPE know that they are friends of TYPE.  */
        !          2327: void
        !          2328: xref_friends (type, name, ctype)
        !          2329:      tree type, name, ctype;
        !          2330: {
        !          2331:   tree typedecl = TYPE_NAME (type);
        !          2332:   tree friend_decl = TYPE_NAME (ctype);
        !          2333:   tree t = tree_cons (NULL_TREE, ctype,
        !          2334:                      DECL_UNDEFINED_FRIENDS (typedecl));
        !          2335: 
        !          2336:   DECL_UNDEFINED_FRIENDS (typedecl) = t;
        !          2337:   SET_DECL_WAITING_FRIENDS (friend_decl, tree_cons (type, t, DECL_WAITING_FRIENDS (friend_decl)));
        !          2338:   TREE_TYPE (DECL_WAITING_FRIENDS (friend_decl)) = name;
        !          2339: }
        !          2340: 
        !          2341: /* Make FRIEND_TYPE a friend class to TYPE.  If FRIEND_TYPE has already
        !          2342:    been defined, we make all of its member functions friends of
        !          2343:    TYPE.  If not, we make it a pending friend, which can later be added
        !          2344:    when its definition is seen.  If a type is defined, then its TYPE_DECL's
        !          2345:    DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
        !          2346:    classes that are not defined.  If a type has not yet been defined,
        !          2347:    then the DECL_WAITING_FRIENDS contains a list of types
        !          2348:    waiting to make it their friend.  Note that these two can both
        !          2349:    be in use at the same time!  */
        !          2350: void
        !          2351: make_friend_class (type, friend_type)
        !          2352:      tree type, friend_type;
        !          2353: {
        !          2354:   tree classes;
        !          2355: 
        !          2356:   if (type == friend_type)
        !          2357:     {
        !          2358:       warning ("class `%s' is implicitly friends with itself",
        !          2359:               TYPE_NAME_STRING (type));
        !          2360:       return;
        !          2361:     }
        !          2362: 
        !          2363:   GNU_xref_hier (TYPE_NAME_STRING (type),
        !          2364:                 TYPE_NAME_STRING (friend_type), 0, 0, 1);
        !          2365: 
        !          2366:   classes = CLASSTYPE_FRIEND_CLASSES (type);
        !          2367:   while (classes && TREE_VALUE (classes) != friend_type)
        !          2368:     classes = TREE_CHAIN (classes);
        !          2369:   if (classes)
        !          2370:     warning ("class `%s' is already friends with class `%s'",
        !          2371:             TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type));
        !          2372:   else
        !          2373:     {
        !          2374:       CLASSTYPE_FRIEND_CLASSES (type)
        !          2375:        = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
        !          2376:     }
        !          2377: }
        !          2378: 
        !          2379: /* Main friend processor.  This is large, and for modularity purposes,
        !          2380:    has been removed from grokdeclarator.  It returns `void_type_node'
        !          2381:    to indicate that something happened, though a FIELD_DECL is
        !          2382:    not returned.
        !          2383: 
        !          2384:    CTYPE is the class this friend belongs to.
        !          2385: 
        !          2386:    DECLARATOR is the name of the friend.
        !          2387: 
        !          2388:    DECL is the FUNCTION_DECL that the friend is.
        !          2389: 
        !          2390:    In case we are parsing a friend which is part of an inline
        !          2391:    definition, we will need to store PARM_DECL chain that comes
        !          2392:    with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
        !          2393: 
        !          2394:    FLAGS is just used for `grokclassfn'.
        !          2395: 
        !          2396:    QUALS say what special qualifies should apply to the object
        !          2397:    pointed to by `this'.  */
        !          2398: tree
        !          2399: do_friend (ctype, declarator, decl, parmdecls, flags, quals)
        !          2400:      tree ctype, declarator, decl, parmdecls;
        !          2401:      enum overload_flags flags;
        !          2402:      tree quals;
        !          2403: {
        !          2404:   if (ctype)
        !          2405:     {
        !          2406:       tree cname = TYPE_NAME (ctype);
        !          2407:       if (TREE_CODE (cname) == TYPE_DECL)
        !          2408:        cname = DECL_NAME (cname);
        !          2409: 
        !          2410:       /* A method friend.  */
        !          2411:       if (TREE_CODE (decl) == FUNCTION_DECL)
        !          2412:        {
        !          2413:          if (flags == NO_SPECIAL && ctype && declarator == cname)
        !          2414:            DECL_CONSTRUCTOR_P (decl) = 1;
        !          2415: 
        !          2416:          /* This will set up DECL_ARGUMENTS for us.  */
        !          2417:          grokclassfn (ctype, cname, decl, flags, quals);
        !          2418:          if (TYPE_SIZE (ctype) != 0)
        !          2419:            check_classfn (ctype, cname, decl, flags);
        !          2420: 
        !          2421:          if (TREE_TYPE (decl) != error_mark_node)
        !          2422:            {
        !          2423:              if (TYPE_SIZE (ctype))
        !          2424:                {
        !          2425:                  /* We don't call pushdecl here yet, or ever on this
        !          2426:                     actual FUNCTION_DECL.  We must preserve its TREE_CHAIN
        !          2427:                     until the end.  */
        !          2428:                  make_decl_rtl (decl, NULL_TREE, 1);
        !          2429:                  add_friend (current_class_type, decl);
        !          2430:                }
        !          2431:              else
        !          2432:                xref_friend (current_class_type, decl, ctype);
        !          2433:              DECL_FRIEND_P (decl) = 1;
        !          2434:            }
        !          2435:        }
        !          2436:       else
        !          2437:        {
        !          2438:          /* Possibly a bunch of method friends.  */
        !          2439: 
        !          2440:          /* Get the class they belong to.  */
        !          2441:          tree ctype = IDENTIFIER_TYPE_VALUE (cname);
        !          2442: 
        !          2443:          /* This class is defined, use its methods now.  */
        !          2444:          if (TYPE_SIZE (ctype))
        !          2445:            {
        !          2446:              tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
        !          2447:              if (fields)
        !          2448:                add_friends (current_class_type, declarator, ctype);
        !          2449:              else
        !          2450:                error ("method `%s' is not a member of class `%s'",
        !          2451:                       IDENTIFIER_POINTER (declarator),
        !          2452:                       IDENTIFIER_POINTER (cname));
        !          2453:            }
        !          2454:          else
        !          2455:            xref_friends (current_class_type, declarator, ctype);
        !          2456:          decl = void_type_node;
        !          2457:        }
        !          2458:     }
        !          2459:   else if (TREE_CODE (decl) == FUNCTION_DECL
        !          2460:           && ((IDENTIFIER_LENGTH (declarator) == 4
        !          2461:                && IDENTIFIER_POINTER (declarator)[0] == 'm'
        !          2462:                && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
        !          2463:               || (IDENTIFIER_LENGTH (declarator) > 10
        !          2464:                   && IDENTIFIER_POINTER (declarator)[0] == '_'
        !          2465:                   && IDENTIFIER_POINTER (declarator)[1] == '_'
        !          2466:                   && strncmp (IDENTIFIER_POINTER (declarator)+2,
        !          2467:                               "builtin_", 8) == 0)))
        !          2468:     {
        !          2469:       /* raw "main", and builtin functions never gets overloaded,
        !          2470:         but they can become friends.  */
        !          2471:       TREE_PUBLIC (decl) = 1;
        !          2472:       add_friend (current_class_type, decl);
        !          2473:       DECL_FRIEND_P (decl) = 1;
        !          2474:       if (IDENTIFIER_POINTER (declarator)[0] == '_')
        !          2475:        {
        !          2476:          if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "new"))
        !          2477:            TREE_GETS_NEW (current_class_type) = 0;
        !          2478:          else if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "delete"))
        !          2479:            TREE_GETS_DELETE (current_class_type) = 0;
        !          2480:        }
        !          2481:       decl = void_type_node;
        !          2482:     }
        !          2483:   /* A global friend.
        !          2484:      @@ or possibly a friend from a base class ?!?  */
        !          2485:   else if (TREE_CODE (decl) == FUNCTION_DECL)
        !          2486:     {
        !          2487:       /* Friends must all go through the overload machinery,
        !          2488:         even though they may not technically be overloaded.
        !          2489: 
        !          2490:         Note that because classes all wind up being top-level
        !          2491:         in their scope, their friend wind up in top-level scope as well.  */
        !          2492:       DECL_ASSEMBLER_NAME (decl)
        !          2493:        = build_decl_overload (IDENTIFIER_POINTER (declarator),
        !          2494:                               TYPE_ARG_TYPES (TREE_TYPE (decl)),
        !          2495:                               TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
        !          2496:       DECL_ARGUMENTS (decl) = parmdecls;
        !          2497: 
        !          2498:       /* We can call pushdecl here, because the TREE_CHAIN of this
        !          2499:         FUNCTION_DECL is not needed for other purposes.  */
        !          2500:       decl = pushdecl_top_level (decl);
        !          2501: 
        !          2502:       make_decl_rtl (decl, NULL_TREE, 1);
        !          2503:       add_friend (current_class_type, decl);
        !          2504: 
        !          2505:       if (! TREE_OVERLOADED (declarator)
        !          2506:          && IDENTIFIER_GLOBAL_VALUE (declarator)
        !          2507:          && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (declarator)) == FUNCTION_DECL)
        !          2508:        {
        !          2509:          error ("friend `%s' implicitly overloaded",
        !          2510:                 IDENTIFIER_POINTER (declarator));
        !          2511:          error_with_decl (IDENTIFIER_GLOBAL_VALUE (declarator),
        !          2512:                           "after declaration of non-overloaded `%s'");
        !          2513:        }
        !          2514:       DECL_FRIEND_P (decl) = 1;
        !          2515:       DECL_OVERLOADED (decl) = 1;
        !          2516:       TREE_OVERLOADED (declarator) = 1;
        !          2517:       decl = push_overloaded_decl (decl, 1);
        !          2518:     }
        !          2519:   else
        !          2520:     {
        !          2521:       /* @@ Should be able to ingest later definitions of this function
        !          2522:         before use.  */
        !          2523:       tree decl = IDENTIFIER_GLOBAL_VALUE (declarator);
        !          2524:       if (decl == NULL_TREE)
        !          2525:        {
        !          2526:          warning ("implicitly declaring `%s' as struct",
        !          2527:                   IDENTIFIER_POINTER (declarator));
        !          2528:          decl = xref_tag (record_type_node, declarator, NULL_TREE);
        !          2529:          decl = TYPE_NAME (decl);
        !          2530:        }
        !          2531: 
        !          2532:       /* Allow abbreviated declarations of overloaded functions,
        !          2533:         but not if those functions are really class names.  */
        !          2534:       if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
        !          2535:        {
        !          2536:          warning ("`friend %s' archaic, use `friend class %s' instead",
        !          2537:                   IDENTIFIER_POINTER (declarator),
        !          2538:                   IDENTIFIER_POINTER (declarator));
        !          2539:          decl = TREE_TYPE (TREE_PURPOSE (decl));
        !          2540:        }
        !          2541: 
        !          2542:       if (TREE_CODE (decl) == TREE_LIST)
        !          2543:        add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
        !          2544:       else
        !          2545:        make_friend_class (current_class_type, TREE_TYPE (decl));
        !          2546:       decl = void_type_node;
        !          2547:     }
        !          2548:   return decl;
        !          2549: }
        !          2550: 
        !          2551: /* TYPE has now been defined.  It may, however, have a number of things
        !          2552:    waiting make make it their friend.  We resolve these references
        !          2553:    here.  */
        !          2554: void
        !          2555: embrace_waiting_friends (type)
        !          2556:      tree type;
        !          2557: {
        !          2558:   tree decl = TYPE_NAME (type);
        !          2559:   tree waiters;
        !          2560: 
        !          2561:   if (TREE_CODE (decl) != TYPE_DECL)
        !          2562:     return;
        !          2563: 
        !          2564:   for (waiters = DECL_WAITING_FRIENDS (decl); waiters;
        !          2565:        waiters = TREE_CHAIN (waiters))
        !          2566:     {
        !          2567:       tree waiter = TREE_PURPOSE (waiters);
        !          2568:       tree waiter_prev = TREE_VALUE (waiters);
        !          2569:       tree decl = TREE_TYPE (waiters);
        !          2570:       tree name = decl ? (TREE_CODE (decl) == IDENTIFIER_NODE
        !          2571:                          ? decl : DECL_NAME (decl)) : NULL_TREE;
        !          2572:       if (name)
        !          2573:        {
        !          2574:          /* @@ There may be work to be done since we have not verified
        !          2575:             @@ consistency between original and friend declarations
        !          2576:             @@ of the functions waiting to become friends.  */
        !          2577:          tree field = lookup_fnfields (TYPE_BINFO (type), name, 0);
        !          2578:          if (field)
        !          2579:            if (decl == name)
        !          2580:              add_friends (waiter, name, type);
        !          2581:            else
        !          2582:              add_friend (waiter, decl);
        !          2583:          else
        !          2584:            error_with_file_and_line (DECL_SOURCE_FILE (TYPE_NAME (waiter)),
        !          2585:                                      DECL_SOURCE_LINE (TYPE_NAME (waiter)),
        !          2586:                                      "no method `%s' defined in class `%s' to be friend",
        !          2587:                                      IDENTIFIER_POINTER (DECL_NAME (TREE_TYPE (waiters))),
        !          2588:                                      TYPE_NAME_STRING (type));
        !          2589:        }
        !          2590:       else
        !          2591:        make_friend_class (type, waiter);
        !          2592: 
        !          2593:       if (TREE_CHAIN (waiter_prev))
        !          2594:        TREE_CHAIN (waiter_prev) = TREE_CHAIN (TREE_CHAIN (waiter_prev));
        !          2595:       else
        !          2596:        DECL_UNDEFINED_FRIENDS (TYPE_NAME (waiter)) = NULL_TREE;
        !          2597:     }
        !          2598: }
        !          2599: 
        !          2600: /* Common subroutines of build_new and build_vec_delete.  */
        !          2601: 
        !          2602: /* Common interface for calling "builtin" functions that are not
        !          2603:    really builtin.  */
        !          2604: 
        !          2605: tree
        !          2606: build_builtin_call (type, node, arglist)
        !          2607:      tree type;
        !          2608:      tree node;
        !          2609:      tree arglist;
        !          2610: {
        !          2611:   tree rval = build (CALL_EXPR, type, node, arglist, 0);
        !          2612:   TREE_SIDE_EFFECTS (rval) = 1;
        !          2613:   if (! TREE_USED (TREE_OPERAND (node, 0)))
        !          2614:     {
        !          2615:       assemble_external (TREE_OPERAND (node, 0));
        !          2616:       TREE_USED (TREE_OPERAND (node, 0)) = 1;
        !          2617:     }
        !          2618:   return rval;
        !          2619: }
        !          2620: 
        !          2621: /* Generate a C++ "new" expression. DECL is either a TREE_LIST
        !          2622:    (which needs to go through some sort of groktypename) or it
        !          2623:    is the name of the class we are newing. INIT is an initialization value.
        !          2624:    It is either an EXPRLIST, an EXPR_NO_COMMAS, or something in braces.
        !          2625:    If INIT is void_type_node, it means do *not* call a constructor
        !          2626:    for this instance.
        !          2627: 
        !          2628:    For types with constructors, the data returned is initialized
        !          2629:    by the approriate constructor.
        !          2630: 
        !          2631:    Whether the type has a constructor or not, if it has a pointer
        !          2632:    to a virtual function table, then that pointer is set up
        !          2633:    here.
        !          2634: 
        !          2635:    Unless I am mistaken, a call to new () will return initialized
        !          2636:    data regardless of whether the constructor itself is private or
        !          2637:    not.
        !          2638: 
        !          2639:    PLACEMENT is the `placement' list for user-defined operator new ().  */
        !          2640: 
        !          2641: tree
        !          2642: build_new (placement, decl, init, use_global_new)
        !          2643:      tree placement;
        !          2644:      tree decl, init;
        !          2645:      int use_global_new;
        !          2646: {
        !          2647:   extern tree require_complete_type ();        /* typecheck.c */
        !          2648:   tree type, true_type, size, rval;
        !          2649:   tree init1 = NULL_TREE, nelts;
        !          2650:   int has_call = 0, has_array = 0;
        !          2651:   tree alignment = NULL_TREE;
        !          2652:   tree pending_sizes = NULL_TREE;
        !          2653: 
        !          2654:   if (decl == error_mark_node)
        !          2655:     return error_mark_node;
        !          2656: 
        !          2657:   if (TREE_CODE (decl) == TREE_LIST)
        !          2658:     {
        !          2659:       tree absdcl = TREE_VALUE (decl);
        !          2660:       tree last_absdcl = NULL_TREE;
        !          2661:       int old_immediate_size_expand;
        !          2662: 
        !          2663:       if (current_function_decl
        !          2664:          && DECL_CONSTRUCTOR_P (current_function_decl))
        !          2665:        {
        !          2666:          old_immediate_size_expand = immediate_size_expand;
        !          2667:          immediate_size_expand = 0;
        !          2668:        }
        !          2669: 
        !          2670:       nelts = integer_one_node;
        !          2671: 
        !          2672:       if (absdcl && TREE_CODE (absdcl) == CALL_EXPR)
        !          2673:        {
        !          2674:          /* probably meant to be a call */
        !          2675:          has_call = 1;
        !          2676:          init1 = TREE_OPERAND (absdcl, 1);
        !          2677:          absdcl = TREE_OPERAND (absdcl, 0);
        !          2678:          TREE_VALUE (decl) = absdcl;
        !          2679:        }
        !          2680:       while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF)
        !          2681:        {
        !          2682:          last_absdcl = absdcl;
        !          2683:          absdcl = TREE_OPERAND (absdcl, 0);
        !          2684:        }
        !          2685: 
        !          2686:       if (absdcl && TREE_CODE (absdcl) == ARRAY_REF)
        !          2687:        {
        !          2688:          /* probably meant to be a vec new */
        !          2689:          tree this_nelts;
        !          2690: 
        !          2691:          has_array = 1;
        !          2692:          this_nelts = TREE_OPERAND (absdcl, 1);
        !          2693:          if (this_nelts)
        !          2694:            this_nelts = save_expr (this_nelts);
        !          2695:          absdcl = TREE_OPERAND (absdcl, 0);
        !          2696:          if (this_nelts == NULL_TREE)
        !          2697:            error ("new of array type fails to specify size");
        !          2698:          else if (this_nelts == integer_zero_node)
        !          2699:            {
        !          2700:              warning ("zero size array reserves no space");
        !          2701:              nelts = integer_zero_node;
        !          2702:            }
        !          2703:          else
        !          2704:            nelts = build_binary_op (MULT_EXPR, nelts, this_nelts);
        !          2705:        }
        !          2706: 
        !          2707:       if (last_absdcl)
        !          2708:        TREE_OPERAND (last_absdcl, 0) = absdcl;
        !          2709:       else
        !          2710:        TREE_VALUE (decl) = absdcl;
        !          2711: 
        !          2712:       type = true_type = groktypename (decl);
        !          2713:       if (! type || type == error_mark_node
        !          2714:          || true_type == error_mark_node)
        !          2715:        return error_mark_node;
        !          2716: 
        !          2717:       type = TYPE_MAIN_VARIANT (type);
        !          2718:       if (type == void_type_node)
        !          2719:        {
        !          2720:          error ("invalid type: `void []'");
        !          2721:          return error_mark_node;
        !          2722:        }
        !          2723:       if (current_function_decl
        !          2724:          && DECL_CONSTRUCTOR_P (current_function_decl))
        !          2725:        {
        !          2726:          pending_sizes = get_pending_sizes ();
        !          2727:          immediate_size_expand = old_immediate_size_expand;
        !          2728:        }
        !          2729:     }
        !          2730:   else if (TREE_CODE (decl) == IDENTIFIER_NODE)
        !          2731:     {
        !          2732:       if (IDENTIFIER_HAS_TYPE_VALUE (decl))
        !          2733:        {
        !          2734:          /* An aggregate type.  */
        !          2735:          type = IDENTIFIER_TYPE_VALUE (decl);
        !          2736:          decl = TYPE_NAME (type);
        !          2737:        }
        !          2738:       else
        !          2739:        {
        !          2740:          /* A builtin type.  */
        !          2741:          decl = lookup_name (decl, 1);
        !          2742:          assert (TREE_CODE (decl) == TYPE_DECL);
        !          2743:          type = TREE_TYPE (decl);
        !          2744:        }
        !          2745:       true_type = type;
        !          2746:     }
        !          2747:   else if (TREE_CODE (decl) == TYPE_DECL)
        !          2748:     {
        !          2749:       type = TREE_TYPE (decl);
        !          2750:       true_type = type;
        !          2751:     }
        !          2752:   else
        !          2753:     {
        !          2754:       type = decl;
        !          2755:       true_type = type;
        !          2756:       decl = TYPE_NAME (type);
        !          2757:     }
        !          2758: 
        !          2759:   if (TYPE_SIZE (type) == 0)
        !          2760:     {
        !          2761:       if (type == void_type_node)
        !          2762:        error ("invalid type for new: `void'");
        !          2763:       else
        !          2764:        incomplete_type_error (0, type);
        !          2765:       return error_mark_node;
        !          2766:     }
        !          2767: 
        !          2768:   if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
        !          2769:     {
        !          2770:       abstract_virtuals_error (NULL_TREE, type);
        !          2771:       return error_mark_node;
        !          2772:     }
        !          2773: 
        !          2774:   /* If our base type is an array, then make sure we know how many elements
        !          2775:      it has.  */
        !          2776:   while (TREE_CODE (type) == ARRAY_TYPE)
        !          2777:     {
        !          2778:       tree this_nelts = build_binary_op (PLUS_EXPR, integer_one_node,
        !          2779:                                         TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
        !          2780:       if (nelts == integer_one_node)
        !          2781:        {
        !          2782:          has_array = 1;
        !          2783:          nelts = this_nelts;
        !          2784:        }
        !          2785:       else
        !          2786:        {
        !          2787:          assert (has_array != 0);
        !          2788:          nelts = build_binary_op (MULT_EXPR, nelts, this_nelts);
        !          2789:        }
        !          2790:       type = TREE_TYPE (type);
        !          2791:     }
        !          2792:   if (has_array)
        !          2793:     size = fold (build_binary_op (MULT_EXPR, size_in_bytes (type), nelts));
        !          2794:   else
        !          2795:     size = size_in_bytes (type);
        !          2796: 
        !          2797: #if 0
        !          2798:   /* This causes troubles when the user attempts to free the storage
        !          2799:      returned by `new'.  Bottom line: it's up to malloc to do the
        !          2800:      right thing.  */
        !          2801: 
        !          2802:   /* If this type has special alignment requirements, deal with them here.  */
        !          2803:   if (TYPE_ALIGN (type) > BITS_PER_WORD)
        !          2804:     {
        !          2805:       alignment = fold (build (MINUS_EXPR, integer_type_node,
        !          2806:                               c_alignof (type), integer_one_node));
        !          2807:       size = fold (build (PLUS_EXPR, integer_type_node, size, alignment));
        !          2808:     }
        !          2809: #endif
        !          2810: 
        !          2811:   if (has_call)
        !          2812:     init = init1;
        !          2813: 
        !          2814:   /* Get to the target type of TRUE_TYPE, so we can decide whether
        !          2815:      any constructors need to be called or not.  */
        !          2816:   type = true_type;
        !          2817:   while (TREE_CODE (type) == ARRAY_TYPE)
        !          2818:     type = TREE_TYPE (type);
        !          2819: 
        !          2820: #ifdef SOS
        !          2821:   rval = NULL_TREE;
        !          2822:   if (placement == void_type_node)
        !          2823:     {
        !          2824:       /* Simple "new dynamic" construct.  */
        !          2825:       if (! IS_AGGR_TYPE (type))
        !          2826:        {
        !          2827:          error ("dynamic new can only allocate objects of aggregate type");
        !          2828:          return error_mark_node;
        !          2829:        }
        !          2830:       else if (! is_aggr_typedef (TYPE_IDENTIFIER (type), 1))
        !          2831:        return error_mark_node;
        !          2832:       else
        !          2833:        rval = build_dynamic_new (type, size, NULL_TREE, init);
        !          2834:     }
        !          2835:   else if (placement && TREE_CODE (placement) == STRING_CST)
        !          2836:     {
        !          2837:       /* A "new dynamic" construct with filename argument.  */
        !          2838:       if (! IS_AGGR_TYPE (type))
        !          2839:        {
        !          2840:          error ("dynamic new can only allocate objects of aggregate type");
        !          2841:          return error_mark_node;
        !          2842:        }
        !          2843:       else if (! is_aggr_typedef (TYPE_IDENTIFIER (type), 1))
        !          2844:        return error_mark_node;
        !          2845:       else
        !          2846:        rval = build_dynamic_new (type, size, placement, init);
        !          2847:     }
        !          2848:   if (rval)
        !          2849:     {
        !          2850: #if 0
        !          2851:       /* See comment above as to why this is disabled.  */
        !          2852:       if (alignment)
        !          2853:        {
        !          2854:          rval = build (PLUS_EXPR, TYPE_POINTER_TO (type), rval, alignment);
        !          2855:          rval = build (BIT_AND_EXPR, TYPE_POINTER_TO (type),
        !          2856:                        rval, build1 (BIT_NOT_EXPR, integer_type_node, alignment));
        !          2857:        }
        !          2858: #endif
        !          2859:       goto done;
        !          2860:     }
        !          2861: #endif
        !          2862: 
        !          2863:   if (has_array)
        !          2864:     {
        !          2865:       if (placement)
        !          2866:        {
        !          2867:          error ("placement syntax invalid for arrays");
        !          2868:          return error_mark_node;
        !          2869:        }
        !          2870: 
        !          2871:       if (TYPE_NEEDS_DESTRUCTOR (true_type))
        !          2872:        {
        !          2873:          tree extra = BI_header_size;
        !          2874:          tree cookie, exp1, exp2;
        !          2875: 
        !          2876:          size = size_binop (PLUS_EXPR, size, extra);
        !          2877:          rval = build_builtin_call (ptr_type_node, BIN,
        !          2878:                                     build_tree_list (NULL_TREE, size));
        !          2879:          rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra));
        !          2880:          /* Store header info.  */
        !          2881:          cookie = build_indirect_ref (build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
        !          2882:                                              rval, extra), 0);
        !          2883:          exp1 = build (MODIFY_EXPR, void_type_node,
        !          2884:                        build_component_ref (cookie, get_identifier ("nelts"), 0, 0),
        !          2885:                        nelts);
        !          2886:          TREE_SIDE_EFFECTS (exp1) = 1;
        !          2887:          exp2 = build (MODIFY_EXPR, void_type_node,
        !          2888:                        build_component_ref (cookie, get_identifier ("ptr_2comp"), 0, 0),
        !          2889:                        build (MINUS_EXPR, ptr_type_node, integer_zero_node, rval));
        !          2890:          TREE_SIDE_EFFECTS (exp2) = 1;
        !          2891:          rval = convert (build_pointer_type (true_type), rval);
        !          2892:          TREE_CALLS_NEW (rval) = 1;
        !          2893:          TREE_SIDE_EFFECTS (rval) = 1;
        !          2894:          rval = build_compound_expr (tree_cons (NULL_TREE, exp1,
        !          2895:                                                 tree_cons (NULL_TREE, exp2,
        !          2896:                                                            build_tree_list (NULL_TREE, rval))));
        !          2897:        }
        !          2898:       else
        !          2899:        {
        !          2900:          rval = save_expr (build_builtin_call (build_pointer_type (true_type),
        !          2901:                                                BIN,
        !          2902:                                                build_tree_list (NULL_TREE,
        !          2903:                                                                 size)));
        !          2904:        }
        !          2905:     }
        !          2906:   else
        !          2907:     {
        !          2908:       if (TYPE_LANG_SPECIFIC (true_type)
        !          2909:          && (TREE_GETS_NEW (true_type) && !use_global_new))
        !          2910:        rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL,
        !          2911:                               TYPE_POINTER_TO (true_type), size, placement);
        !          2912:       else if (placement)
        !          2913:        {
        !          2914:          rval = build_opfncall (NEW_EXPR, LOOKUP_GLOBAL|LOOKUP_COMPLAIN, ptr_type_node, size, placement);
        !          2915:          rval = convert (TYPE_POINTER_TO (true_type), rval);
        !          2916:        }
        !          2917:       else if (flag_this_is_variable
        !          2918:               && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
        !          2919:        {
        !          2920:          if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
        !          2921:            rval = NULL_TREE;
        !          2922:          else
        !          2923:            {
        !          2924:              error ("constructors take parameter lists");
        !          2925:              return error_mark_node;
        !          2926:            }
        !          2927:        }
        !          2928:       else
        !          2929:        {
        !          2930:          rval = build_builtin_call (build_pointer_type (true_type),
        !          2931:                                     BIN, build_tree_list (NULL_TREE, size));
        !          2932: #if 0
        !          2933:          /* See comment above as to why this is disabled.  */
        !          2934:          if (alignment)
        !          2935:            {
        !          2936:              rval = build (PLUS_EXPR, TYPE_POINTER_TO (true_type), rval, alignment);
        !          2937:              rval = build (BIT_AND_EXPR, TYPE_POINTER_TO (true_type),
        !          2938:                            rval, build1 (BIT_NOT_EXPR, integer_type_node, alignment));
        !          2939:            }
        !          2940: #endif
        !          2941:          TREE_CALLS_NEW (rval) = 1;
        !          2942:          TREE_SIDE_EFFECTS (rval) = 1;
        !          2943:        }
        !          2944:       /* We've figured out where the allocation is to go.
        !          2945:         If we're not eliding constructors, then if a constructor
        !          2946:         is defined, we must go through it.  */
        !          2947:       if ((rval == NULL_TREE || !flag_elide_constructors)
        !          2948:          && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
        !          2949:        {
        !          2950:          /* Constructors are never virtual.  */
        !          2951:          int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL;
        !          2952: 
        !          2953:          if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
        !          2954:            {
        !          2955:              init = tree_cons (NULL_TREE, integer_one_node, init);
        !          2956:              flags |= LOOKUP_HAS_IN_CHARGE;
        !          2957:            }
        !          2958:          rval = build_method_call (rval, constructor_name (true_type),
        !          2959:                                    init, NULL_TREE, flags);
        !          2960:          TREE_HAS_CONSTRUCTOR (rval) = 1;
        !          2961:          goto done;
        !          2962:        }
        !          2963:     }
        !          2964:   if (rval == error_mark_node)
        !          2965:     return error_mark_node;
        !          2966:   rval = save_expr (rval);
        !          2967:   TREE_HAS_CONSTRUCTOR (rval) = 1;
        !          2968: 
        !          2969:   /* Don't call any constructors or do any initialization.  */
        !          2970:   if (init == void_type_node)
        !          2971:     goto done;
        !          2972: 
        !          2973:   if (TYPE_NEEDS_CONSTRUCTING (type))
        !          2974:     {
        !          2975:       extern tree static_aggregates;
        !          2976: 
        !          2977:       if (current_function_decl == NULL_TREE)
        !          2978:        {
        !          2979:          /* In case of static initialization, SAVE_EXPR is good enough.  */
        !          2980:          init = copy_to_permanent (init);
        !          2981:          rval = copy_to_permanent (rval);
        !          2982:          static_aggregates = perm_tree_cons (init, rval, static_aggregates);
        !          2983:        }
        !          2984:       else
        !          2985:        {
        !          2986:          /* Have to wrap this in RTL_EXPR for two cases:
        !          2987:             in base or member initialization and if we
        !          2988:             are a branch of a ?: operator.  Since we
        !          2989:             can't easily know the latter, just do it always.  */
        !          2990:          tree xval = make_node (RTL_EXPR);
        !          2991: 
        !          2992:          TREE_TYPE (xval) = TREE_TYPE (rval);
        !          2993:          do_pending_stack_adjust ();
        !          2994:          start_sequence ();
        !          2995: 
        !          2996:          /* As a matter of principle, `start_sequence' should do this.  */
        !          2997:          emit_note (0, -1);
        !          2998: 
        !          2999:          if (has_array)
        !          3000:            rval = expand_vec_init (decl, rval,
        !          3001:                                    build_binary_op (MINUS_EXPR, nelts, integer_one_node),
        !          3002:                                    init, 0);
        !          3003:          else
        !          3004:            expand_aggr_init (build_indirect_ref (rval, 0), init, 0);
        !          3005: 
        !          3006:          do_pending_stack_adjust ();
        !          3007: 
        !          3008:          TREE_SIDE_EFFECTS (xval) = 1;
        !          3009:          TREE_CALLS_NEW (xval) = 1;
        !          3010:          RTL_EXPR_SEQUENCE (xval) = get_insns ();
        !          3011:          end_sequence ();
        !          3012: 
        !          3013:          if (TREE_CODE (rval) == SAVE_EXPR)
        !          3014:            {
        !          3015:              /* Errors may cause this to not get evaluated.  */
        !          3016:              if (SAVE_EXPR_RTL (rval) == 0)
        !          3017:                SAVE_EXPR_RTL (rval) = const0_rtx;
        !          3018:              RTL_EXPR_RTL (xval) = SAVE_EXPR_RTL (rval);
        !          3019:            }
        !          3020:          else
        !          3021:            {
        !          3022:              assert (TREE_CODE (rval) == VAR_DECL);
        !          3023:              RTL_EXPR_RTL (xval) = DECL_RTL (rval);
        !          3024:            }
        !          3025:          rval = xval;
        !          3026:        }
        !          3027:     }
        !          3028:   else if (has_call || init)
        !          3029:     {
        !          3030:       if (IS_AGGR_TYPE (type))
        !          3031:        {
        !          3032:          error_with_aggr_type (type, "no constructor for type `%s'");
        !          3033:          rval = error_mark_node;
        !          3034:        }
        !          3035:       else
        !          3036:        {
        !          3037:          /* New 2.0 interpretation: `new int (10)' means
        !          3038:             allocate an int, and initialize it with 10.  */
        !          3039:          init = build_c_cast (type, init);
        !          3040:          rval = build (COMPOUND_EXPR, TREE_TYPE (rval),
        !          3041:                        build_modify_expr (build_indirect_ref (rval, 0),
        !          3042:                                           NOP_EXPR, init),
        !          3043:                        rval);
        !          3044:          TREE_SIDE_EFFECTS (rval) = 1;
        !          3045:        }
        !          3046:     }
        !          3047:  done:
        !          3048:   if (pending_sizes)
        !          3049:     rval = build_compound_expr (chainon (pending_sizes,
        !          3050:                                         build_tree_list (NULL_TREE, rval)));
        !          3051: 
        !          3052:   if (flag_gc)
        !          3053:     {
        !          3054:       extern tree gc_visible;
        !          3055:       tree objbits;
        !          3056:       tree update_expr;
        !          3057: 
        !          3058:       rval = save_expr (rval);
        !          3059:       /* We don't need a `headof' operation to do this because
        !          3060:         we know where the object starts.  */
        !          3061:       objbits = build1 (INDIRECT_REF, unsigned_type_node,
        !          3062:                        build (MINUS_EXPR, ptr_type_node,
        !          3063:                               rval, c_sizeof (unsigned_type_node)));
        !          3064:       update_expr = build_modify_expr (objbits, BIT_IOR_EXPR, gc_visible);
        !          3065:       rval = build_compound_expr (tree_cons (NULL_TREE, rval,
        !          3066:                                             tree_cons (NULL_TREE, update_expr,
        !          3067:                                                        build_tree_list (NULL_TREE, rval))));
        !          3068:     }
        !          3069: 
        !          3070:   return save_expr (rval);
        !          3071: }
        !          3072: 
        !          3073: #ifdef SOS
        !          3074: /* Build a "new dynamic" call for type TYPE.  The size
        !          3075:    of the object we are newing is SIZE.  If "new dynamic" was
        !          3076:    given with an argument, that argument is in NAME.
        !          3077:    PARMS contains the parameters to the constructor.
        !          3078:    The first parameter must be an `ImportRequest *'.
        !          3079: 
        !          3080:    This is slightly hairy, because we must find the correct
        !          3081:    constructor by hand.  */
        !          3082: static tree
        !          3083: build_dynamic_new (type, size, name, parms)
        !          3084:      tree type, size;
        !          3085:      tree name, parms;
        !          3086: {
        !          3087:   tree import_parms, inner_parms;
        !          3088:   tree import_ptr = integer_zero_node;
        !          3089:   /* This variable is supposed to be the address of a "struct ref"
        !          3090:      object, but how and where should it be defined?  */
        !          3091:   tree lookup_tmp = integer_zero_node;
        !          3092:   tree import_tmp = build_unary_op (ADDR_EXPR, get_temp_name (ptr_type_node, 0), 0);
        !          3093: 
        !          3094:   if (name)
        !          3095:     {
        !          3096:       inner_parms = tree_cons (NULL_TREE, name,
        !          3097:                               build_tree_list (NULL_TREE, integer_zero_node));
        !          3098:       inner_parms = tree_cons (NULL_TREE, lookup_tmp, inner_parms);
        !          3099:       inner_parms = build_function_call (__sosLookup, inner_parms);
        !          3100:     }
        !          3101:   else
        !          3102:     inner_parms = integer_zero_node;
        !          3103: 
        !          3104:   import_parms = build_tree_list (NULL_TREE, inner_parms);
        !          3105: 
        !          3106:   if (CLASSTYPE_DYNAMIC_FILENAME (type))
        !          3107:     {
        !          3108:       inner_parms = tree_cons (NULL_TREE, CLASSTYPE_DYNAMIC_FILENAME (type),
        !          3109:                               build_tree_list (NULL_TREE, integer_zero_node));
        !          3110:       inner_parms = tree_cons (NULL_TREE, lookup_tmp, inner_parms);
        !          3111:       inner_parms = build_function_call (__sosLookup, inner_parms);
        !          3112:     }
        !          3113:   else
        !          3114:     inner_parms = integer_zero_node;
        !          3115: 
        !          3116:   import_parms = tree_cons (NULL_TREE, inner_parms, import_parms);
        !          3117:   import_parms = tree_cons (NULL_TREE, CLASSTYPE_TYPENAME_AS_STRING (type), import_parms);
        !          3118:   /* This is one parameter which could be (but should not be) evaluated twice.  */
        !          3119:   TREE_VALUE (parms) = save_expr (TREE_VALUE (parms));
        !          3120: 
        !          3121:   import_parms = tree_cons (NULL_TREE, TREE_VALUE (parms), import_parms);
        !          3122: 
        !          3123:   /* SOS?? Pass the address of a temporary which can hold the pointer
        !          3124:      to dynamic class table, but how and where is it defined? */
        !          3125:   import_parms = tree_cons (NULL_TREE, import_tmp, import_parms);
        !          3126: 
        !          3127:   import_ptr = build_function_call (__sosImport, import_parms);
        !          3128: 
        !          3129:   /* SOS?? Now, generate call to ctor, but using `import_ptr' as the function
        !          3130:      table.  Return the result of the call to the ctor.  */
        !          3131:   import_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (type), import_ptr);
        !          3132:   return build_method_call (import_ptr, TYPE_IDENTIFIER (type),
        !          3133:                            tree_cons (NULL_TREE, import_tmp, parms),
        !          3134:                            NULL_TREE, LOOKUP_DYNAMIC);
        !          3135: }
        !          3136: 
        !          3137: /* Return the name of the link table (as an IDENTIFIER_NODE)
        !          3138:    for the given TYPE.  */
        !          3139: tree
        !          3140: get_linktable_name (type)
        !          3141:      tree type;
        !          3142: {
        !          3143:   char *buf = (char *)alloca (4 + TYPE_NAME_LENGTH (type) + 1);
        !          3144:   tree name;
        !          3145: 
        !          3146:   assert (TYPE_DYNAMIC (type));
        !          3147:   sprintf (buf, "ZN_%s_", TYPE_NAME_STRING (type));
        !          3148:   return get_identifier (buf);
        !          3149: }
        !          3150: 
        !          3151: /* For a given type TYPE, grovel for a function table which
        !          3152:    can be used to support dynamic linking.  */
        !          3153: tree
        !          3154: get_sos_dtable (type, parms)
        !          3155:      tree type, parms;
        !          3156: {
        !          3157:   tree classname = CLASSTYPE_TYPENAME_AS_STRING (type);
        !          3158:   tree filename = CLASSTYPE_DYNAMIC_FILENAME (type);
        !          3159:   tree dyn_vtbl;
        !          3160:   /* This variable is supposed to be the address of a "struct ref"
        !          3161:      object, but how and where should it be defined?  */
        !          3162:   tree lookup_tmp = integer_zero_node;
        !          3163: 
        !          3164:   assert (TYPE_DYNAMIC (type));
        !          3165: 
        !          3166:   if (filename)
        !          3167:     {
        !          3168:       tree inner_parms = tree_cons (NULL_TREE, filename,
        !          3169:                                    build_tree_list (NULL_TREE, integer_zero_node));
        !          3170:       inner_parms = tree_cons (NULL_TREE, lookup_tmp, inner_parms);
        !          3171:       parms = build_tree_list (NULL_TREE, build_function_call (__sosLookup, inner_parms));
        !          3172:     }
        !          3173:   else
        !          3174:     parms = build_tree_list (NULL_TREE, integer_zero_node);
        !          3175: 
        !          3176:   parms = tree_cons (NULL_TREE, classname, parms);
        !          3177: 
        !          3178:   dyn_vtbl = build_function_call (__sosFindCode, parms);
        !          3179:   TREE_TYPE (dyn_vtbl) = build_pointer_type (ptr_type_node);
        !          3180:   return dyn_vtbl;
        !          3181: }
        !          3182: #endif
        !          3183: 
        !          3184: /* `expand_vec_init' performs initialization of a vector of aggregate
        !          3185:    types.
        !          3186: 
        !          3187:    DECL is passed only for error reporting, and provides line number
        !          3188:    and source file name information.
        !          3189:    BASE is the space where the vector will be.
        !          3190:    MAXINDEX is the maximum index of the array (one less than the
        !          3191:            number of elements).
        !          3192:    INIT is the (possibly NULL) initializer.
        !          3193: 
        !          3194:    FROM_ARRAY is 0 if we should init everything with INIT
        !          3195:    (i.e., every element initialized from INIT).
        !          3196:    FROM_ARRAY is 1 if we should index into INIT in parallel
        !          3197:    with initialization of DECL.
        !          3198:    FROM_ARRAY is 2 if we should index into INIT in parallel,
        !          3199:    but use assignment instead of initialization.  */
        !          3200: 
        !          3201: tree
        !          3202: expand_vec_init (decl, base, maxindex, init, from_array)
        !          3203:      tree decl, base, maxindex, init;
        !          3204: {
        !          3205:   tree rval;
        !          3206:   tree iterator, base2 = NULL_TREE;
        !          3207:   tree type = TREE_TYPE (TREE_TYPE (base));
        !          3208:   tree size;
        !          3209: 
        !          3210:   maxindex = convert (integer_type_node, maxindex);
        !          3211:   if (maxindex == error_mark_node)
        !          3212:     return error_mark_node;
        !          3213: 
        !          3214:   if (current_function_decl == NULL_TREE)
        !          3215:     {
        !          3216:       rval = make_tree_vec (3);
        !          3217:       TREE_VEC_ELT (rval, 0) = base;
        !          3218:       TREE_VEC_ELT (rval, 1) = maxindex;
        !          3219:       TREE_VEC_ELT (rval, 2) = init;
        !          3220:       return rval;
        !          3221:     }
        !          3222: 
        !          3223:   while (TREE_CODE (type) == ARRAY_TYPE)
        !          3224:     type = TREE_TYPE (type);
        !          3225: 
        !          3226:   size = size_in_bytes (type);
        !          3227: 
        !          3228:   /* Set to zero in case size is <= 0.  Optimizer will delete this if
        !          3229:      it is not needed.  */
        !          3230:   rval = get_temp_regvar (TYPE_POINTER_TO (type), null_pointer_node);
        !          3231:   base = default_conversion (base);
        !          3232:   base = convert (TYPE_POINTER_TO (type), base);
        !          3233:   expand_assignment (rval, base, 0, 0);
        !          3234:   base = get_temp_regvar (TYPE_POINTER_TO (type), base);
        !          3235: 
        !          3236:   if (init != NULL_TREE
        !          3237:       && TREE_CODE (init) == CONSTRUCTOR
        !          3238:       && TREE_TYPE (init) == TREE_TYPE (decl))
        !          3239:     {
        !          3240:       /* Initialization of array from {...}.  */
        !          3241:       tree elts = CONSTRUCTOR_ELTS (init);
        !          3242:       tree baseref = build1 (INDIRECT_REF, type, base);
        !          3243:       tree baseinc = build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size);
        !          3244:       int host_i = TREE_INT_CST_LOW (maxindex);
        !          3245: 
        !          3246:       if (IS_AGGR_TYPE (type))
        !          3247:        {
        !          3248:          while (elts)
        !          3249:            {
        !          3250:              host_i -= 1;
        !          3251:              expand_aggr_init (baseref, TREE_VALUE (elts), 0);
        !          3252: 
        !          3253:              expand_assignment (base, baseinc, 0, 0);
        !          3254:              elts = TREE_CHAIN (elts);
        !          3255:            }
        !          3256:          /* Initialize any elements by default if possible.  */
        !          3257:          if (host_i >= 0)
        !          3258:            {
        !          3259:              if (TYPE_NEEDS_CONSTRUCTING (type) == 0)
        !          3260:                {
        !          3261:                  if (obey_regdecls)
        !          3262:                    use_variable (DECL_RTL (base));
        !          3263:                  goto done_init;
        !          3264:                }
        !          3265: 
        !          3266:              iterator = get_temp_regvar (integer_type_node,
        !          3267:                                          build_int_2 (host_i, 0));
        !          3268:              init = NULL_TREE;
        !          3269:              goto init_by_default;
        !          3270:            }
        !          3271:        }
        !          3272:       else
        !          3273:        while (elts)
        !          3274:          {
        !          3275:            expand_assignment (baseref, TREE_VALUE (elts), 0, 0);
        !          3276: 
        !          3277:            expand_assignment (base, baseinc, 0, 0);
        !          3278:            elts = TREE_CHAIN (elts);
        !          3279:          }
        !          3280: 
        !          3281:       if (obey_regdecls)
        !          3282:        use_variable (DECL_RTL (base));
        !          3283:     }
        !          3284:   else
        !          3285:     {
        !          3286:       iterator = get_temp_regvar (integer_type_node, maxindex);
        !          3287: 
        !          3288:     init_by_default:
        !          3289: 
        !          3290:       /* If initializing one array from another,
        !          3291:         initialize element by element.  */
        !          3292:       if (from_array)
        !          3293:        {
        !          3294:          if (decl == NULL_TREE
        !          3295:              || (init && TREE_TYPE (init) != TREE_TYPE (decl)))
        !          3296:            {
        !          3297:              sorry ("initialization of array from dissimilar array type");
        !          3298:              return error_mark_node;
        !          3299:            }
        !          3300:          if (init)
        !          3301:            {
        !          3302:              base2 = default_conversion (init);
        !          3303:              base2 = get_temp_regvar (TYPE_POINTER_TO (type), base2);
        !          3304:            }
        !          3305:          else if (TYPE_LANG_SPECIFIC (type)
        !          3306:                   && TYPE_NEEDS_CONSTRUCTING (type)
        !          3307:                   && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
        !          3308:            {
        !          3309:              error ("initializer ends prematurely");
        !          3310:              return error_mark_node;
        !          3311:            }
        !          3312:        }
        !          3313: 
        !          3314:       expand_start_cond (build (GE_EXPR, integer_type_node,
        !          3315:                                iterator, integer_zero_node), 0);
        !          3316:       expand_start_loop_continue_elsewhere (1);
        !          3317: 
        !          3318:       if (from_array)
        !          3319:        {
        !          3320:          tree to = build1 (INDIRECT_REF, type, base);
        !          3321:          tree from;
        !          3322: 
        !          3323:          if (base2)
        !          3324:            from = build1 (INDIRECT_REF, type, base2);
        !          3325:          else
        !          3326:            from = NULL_TREE;
        !          3327: 
        !          3328:          if (from_array == 2)
        !          3329:            expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from));
        !          3330:          else if (TYPE_NEEDS_CONSTRUCTING (type))
        !          3331:            expand_aggr_init (to, from, 0);
        !          3332:          else if (from)
        !          3333:            expand_assignment (to, from, 0, 0);
        !          3334:          else abort ();
        !          3335:        }
        !          3336:       else if (TREE_CODE (type) == ARRAY_TYPE)
        !          3337:        {
        !          3338:          if (init != 0)
        !          3339:            sorry ("cannot initialize multi-dimensional array with initializer");
        !          3340:          expand_vec_init (decl, build1 (NOP_EXPR, TYPE_POINTER_TO (TREE_TYPE (type)), base),
        !          3341:                           array_type_nelts (type), 0, 0);
        !          3342:        }
        !          3343:       else
        !          3344:        expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0);
        !          3345: 
        !          3346:       expand_assignment (base,
        !          3347:                         build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size),
        !          3348:                         0, 0);
        !          3349:       if (base2)
        !          3350:        expand_assignment (base2,
        !          3351:                           build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0);
        !          3352:       expand_loop_continue_here ();
        !          3353:       expand_exit_loop_if_false (0, build (NE_EXPR, integer_type_node,
        !          3354:                                           build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one));
        !          3355: 
        !          3356:       if (obey_regdecls)
        !          3357:        {
        !          3358:          use_variable (DECL_RTL (base));
        !          3359:          if (base2)
        !          3360:            use_variable (DECL_RTL (base2));
        !          3361:        }
        !          3362:       expand_end_loop ();
        !          3363:       expand_end_cond ();
        !          3364:       if (obey_regdecls)
        !          3365:        use_variable (DECL_RTL (iterator));
        !          3366:     }
        !          3367:  done_init:
        !          3368: 
        !          3369:   if (obey_regdecls)
        !          3370:     use_variable (DECL_RTL (rval));
        !          3371:   return rval;
        !          3372: }
        !          3373: 
        !          3374: /* Free up storage of type TYPE, at address ADDR.
        !          3375:    TYPE is a POINTER_TYPE.
        !          3376: 
        !          3377:    This does not call any destructors.  */
        !          3378: tree
        !          3379: build_x_delete (type, addr, use_global_delete)
        !          3380:      tree type, addr;
        !          3381:      int use_global_delete;
        !          3382: {
        !          3383:   tree rval;
        !          3384: 
        !          3385:   if (!use_global_delete
        !          3386:       && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
        !          3387:       && TREE_GETS_DELETE (TREE_TYPE (type)))
        !          3388:     rval = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr);
        !          3389:   else
        !          3390:     rval = build_builtin_call (void_type_node, BID, build_tree_list (NULL_TREE, addr));
        !          3391:   return rval;
        !          3392: }
        !          3393: 
        !          3394: /* Objects returned by `build_new' may point to just what the user
        !          3395:    requested (in the case of `new X'), or they may have a cookie
        !          3396:    consisting of a special value (the two's complement of the pointer
        !          3397:    address) and the number of elements allocated (in the case of
        !          3398:    `new X[N]'.  In the latter case, we need to adjust the pointer
        !          3399:    that's passed back to the storage allocator.  */
        !          3400: 
        !          3401: static tree
        !          3402: maybe_adjust_addr_for_delete (addr)
        !          3403:      tree addr;
        !          3404: {
        !          3405:   tree cookie_addr = build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
        !          3406:                            addr, BI_header_size);
        !          3407:   tree cookie = build_indirect_ref (cookie_addr, 0);
        !          3408:   tree adjusted_addr, ptr_2comp;
        !          3409: 
        !          3410:   ptr_2comp = build_component_ref (cookie, get_identifier ("ptr_2comp"), 0, 0);
        !          3411:   adjusted_addr = save_expr (build (MINUS_EXPR, TREE_TYPE (addr), addr, BI_header_size));
        !          3412: 
        !          3413:   /* We must zero out the storage here because if the memory is freed,
        !          3414:      then later reallocated, we might get a false positive when the
        !          3415:      address is reused.  */
        !          3416:   adjusted_addr = build_compound_expr (tree_cons (NULL_TREE,
        !          3417:                                                  build_modify_expr (ptr_2comp, NOP_EXPR, null_pointer_node),
        !          3418:                                                  build_tree_list (NULL_TREE, adjusted_addr)));
        !          3419: 
        !          3420:   addr = build (COND_EXPR, TREE_TYPE (addr),
        !          3421:                build (TRUTH_ORIF_EXPR, integer_type_node,
        !          3422:                       build (EQ_EXPR, integer_type_node,
        !          3423:                              addr, integer_zero_node),
        !          3424:                       build (PLUS_EXPR, integer_type_node,
        !          3425:                              convert (ptr_type_node, addr), ptr_2comp)),
        !          3426:                addr,
        !          3427:                adjusted_addr);
        !          3428:   return addr;
        !          3429: }
        !          3430: 
        !          3431: /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
        !          3432:    ADDR is an expression which yields the store to be destroyed.
        !          3433:    AUTO_DELETE is nonzero if a call to DELETE should be made or not.
        !          3434:    If in the program, (AUTO_DELETE & 2) is non-zero, we tear down the
        !          3435:    virtual baseclasses.
        !          3436:    If in the program, (AUTO_DELETE & 1) is non-zero, then we deallocate.
        !          3437: 
        !          3438:    FLAGS is the logical disjunction of zero or more LOOKUP_
        !          3439:    flags.  See cp-tree.h for more info.
        !          3440: 
        !          3441:    MAYBE_ADJUST is nonzero iff we may need to adjust the address
        !          3442:    of the object being deleted before calling `operator delete'.
        !          3443:    This can happen when a user allocates an array with `operator new'
        !          3444:    and simply calls delete.  Ideally this is unnecessary, but there
        !          3445:    is much code that does `p = new char[n]; ... delete p;' and this code
        !          3446:    would crash otherwise.
        !          3447: 
        !          3448:    This function does not delete an object's virtual base classes.  */
        !          3449: tree
        !          3450: build_delete (type, addr, auto_delete, flags, use_global_delete, maybe_adjust)
        !          3451:      tree type, addr;
        !          3452:      tree auto_delete;
        !          3453:      int flags;
        !          3454:      int use_global_delete;
        !          3455:      int maybe_adjust;
        !          3456: {
        !          3457:   tree function, parms;
        !          3458:   tree member;
        !          3459:   tree expr;
        !          3460:   tree ref;
        !          3461:   int ptr;
        !          3462: 
        !          3463:   if (addr == error_mark_node)
        !          3464:     return error_mark_node;
        !          3465: 
        !          3466:   /* Can happen when CURRENT_EXCEPTION_OBJECT gets its type
        !          3467:      set to `error_mark_node' before it gets properly cleaned up.  */
        !          3468:   if (type == error_mark_node)
        !          3469:     return error_mark_node;
        !          3470: 
        !          3471:   type = TYPE_MAIN_VARIANT (type);
        !          3472: 
        !          3473:   if (TREE_CODE (type) == POINTER_TYPE)
        !          3474:     {
        !          3475:       type = TREE_TYPE (type);
        !          3476:       if (TYPE_SIZE (type) == 0)
        !          3477:        {
        !          3478:          incomplete_type_error (0, type);
        !          3479:          return error_mark_node;
        !          3480:        }
        !          3481:       if (TREE_CODE (type) == ARRAY_TYPE)
        !          3482:        goto handle_array;
        !          3483:       if (! IS_AGGR_TYPE (type))
        !          3484:        {
        !          3485:          if (maybe_adjust)
        !          3486:            addr = maybe_adjust_addr_for_delete (addr);
        !          3487:          return build_builtin_call (void_type_node, BID,
        !          3488:                                     build_tree_list (NULL_TREE, addr));
        !          3489:        }
        !          3490:       if (TREE_SIDE_EFFECTS (addr))
        !          3491:        addr = save_expr (addr);
        !          3492:       ref = build_indirect_ref (addr, 0);
        !          3493:       ptr = 1;
        !          3494:     }
        !          3495:   else if (TREE_CODE (type) == ARRAY_TYPE)
        !          3496:     {
        !          3497:     handle_array:
        !          3498:       if (TREE_SIDE_EFFECTS (addr))
        !          3499:        addr = save_expr (addr);
        !          3500:       return build_vec_delete (addr, array_type_nelts (type), c_sizeof (TREE_TYPE (type)),
        !          3501:                               NULL_TREE, auto_delete, integer_two_node);
        !          3502:     }
        !          3503:   else
        !          3504:     {
        !          3505:       /* Don't check PROTECT here; leave that decision to the
        !          3506:         destructor.  If the destructor is visible, call it,
        !          3507:         else report error.  */
        !          3508:       addr = build_unary_op (ADDR_EXPR, addr, 0);
        !          3509:       if (TREE_SIDE_EFFECTS (addr))
        !          3510:        addr = save_expr (addr);
        !          3511: 
        !          3512:       if (TREE_CONSTANT (addr))
        !          3513:        addr = convert_pointer_to (type, addr);
        !          3514:       else
        !          3515:        addr = convert_force (build_pointer_type (type), addr);
        !          3516: 
        !          3517:       if (TREE_CODE (addr) == NOP_EXPR
        !          3518:          && TREE_OPERAND (addr, 0) == current_class_decl)
        !          3519:        ref = C_C_D;
        !          3520:       else
        !          3521:        ref = build_indirect_ref (addr, 0);
        !          3522:       ptr = 0;
        !          3523:     }
        !          3524: 
        !          3525:   assert (IS_AGGR_TYPE (type));
        !          3526: 
        !          3527:   if (! TYPE_NEEDS_DESTRUCTOR (type))
        !          3528:     {
        !          3529:       if (auto_delete == integer_zero_node)
        !          3530:        return void_zero_node;
        !          3531:       if (maybe_adjust && addr != current_class_decl)
        !          3532:        addr = maybe_adjust_addr_for_delete (addr);
        !          3533:       if (TREE_GETS_DELETE (type) && !use_global_delete)
        !          3534:        return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr);
        !          3535:       return build_builtin_call (void_type_node, BID,
        !          3536:                                 build_tree_list (NULL_TREE, addr));
        !          3537:     }
        !          3538:   parms = build_tree_list (NULL_TREE, addr);
        !          3539: 
        !          3540:   /* Below, we will reverse the order in which these calls are made.
        !          3541:      If we have a destructor, then that destructor will take care
        !          3542:      of the base classes; otherwise, we must do that here.  */
        !          3543:   if (TYPE_HAS_DESTRUCTOR (type))
        !          3544:     {
        !          3545:       tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0));
        !          3546:       tree basetypes = TYPE_BINFO (type);
        !          3547: 
        !          3548:       if (flags & LOOKUP_PROTECT)
        !          3549:        {
        !          3550:          enum visibility_type visibility = compute_visibility (basetypes, dtor);
        !          3551: 
        !          3552:          if (visibility == visibility_private)
        !          3553:            {
        !          3554:              if (flags & LOOKUP_COMPLAIN)
        !          3555:                error_with_aggr_type (type, "destructor for type `%s' is private in this scope");
        !          3556:              return error_mark_node;
        !          3557:            }
        !          3558:          else if (visibility == visibility_protected
        !          3559:                   && (flags & LOOKUP_PROTECTED_OK) == 0)
        !          3560:            {
        !          3561:              if (flags & LOOKUP_COMPLAIN)
        !          3562:                error_with_aggr_type (type, "destructor for type `%s' is protected in this scope");
        !          3563:              return error_mark_node;
        !          3564:            }
        !          3565:        }
        !          3566: 
        !          3567:       /* Once we are in a destructor, try not going through
        !          3568:         the virtual function table to find the next destructor.  */
        !          3569:       if (DECL_VINDEX (dtor)
        !          3570:          && ! (flags & LOOKUP_NONVIRTUAL)
        !          3571:          && TREE_CODE (auto_delete) != PARM_DECL
        !          3572:          && (ptr == 1 || ! resolves_to_fixed_type_p (ref, 0)))
        !          3573:        {
        !          3574:          /* This destructor must be called via virtual function table.  */
        !          3575:          dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (DECL_CONTEXT (dtor)), 0);
        !          3576:          expr = convert_pointer_to (DECL_CLASS_CONTEXT (dtor), TREE_VALUE (parms));
        !          3577:          if (expr != TREE_VALUE (parms))
        !          3578:            {
        !          3579:              expr = fold (expr);
        !          3580:              ref = build_indirect_ref (expr, 0);
        !          3581:              TREE_VALUE (parms) = expr;
        !          3582:            }
        !          3583:          function = build_vfn_ref (&TREE_VALUE (parms), ref, DECL_VINDEX (dtor));
        !          3584:          if (function == error_mark_node)
        !          3585:            return error_mark_node;
        !          3586:          TREE_TYPE (function) = build_pointer_type (TREE_TYPE (dtor));
        !          3587:          TREE_CHAIN (parms) = build_tree_list (NULL_TREE, auto_delete);
        !          3588:          expr = build_function_call (function, parms);
        !          3589:          if (ptr && (flags & LOOKUP_DESTRUCTOR) == 0)
        !          3590:            {
        !          3591:              /* Handle the case where a virtual destructor is
        !          3592:                 being called on an item that is 0.
        !          3593: 
        !          3594:                 @@ Does this really need to be done?  */
        !          3595:              tree ifexp = build_binary_op (NE_EXPR, addr, integer_zero_node);
        !          3596: #if 0
        !          3597:              if (TREE_CODE (ref) == VAR_DECL
        !          3598:                  || TREE_CODE (ref) == COMPONENT_REF)
        !          3599:                warning ("losing in build_delete");
        !          3600: #endif
        !          3601:              expr = build (COND_EXPR, void_type_node,
        !          3602:                            ifexp, expr, void_zero_node);
        !          3603:            }
        !          3604:        }
        !          3605:       else
        !          3606:        {
        !          3607:          tree ifexp;
        !          3608: 
        !          3609:          if ((flags & LOOKUP_DESTRUCTOR)
        !          3610:              || TREE_CODE (ref) == VAR_DECL
        !          3611:              || TREE_CODE (ref) == PARM_DECL
        !          3612:              || TREE_CODE (ref) == COMPONENT_REF
        !          3613:              || TREE_CODE (ref) == ARRAY_REF)
        !          3614:            /* These can't be 0.  */
        !          3615:            ifexp = integer_one_node;
        !          3616:          else
        !          3617:            /* Handle the case where a non-virtual destructor is
        !          3618:               being called on an item that is 0.  */
        !          3619:            ifexp = build_binary_op (NE_EXPR, addr, integer_zero_node);
        !          3620: 
        !          3621:          /* Used to mean that this destructor was known to be empty,
        !          3622:             but that's now obsolete.  */
        !          3623:          assert (DECL_INITIAL (dtor) != void_type_node);
        !          3624: 
        !          3625:          TREE_CHAIN (parms) = build_tree_list (NULL_TREE, auto_delete);
        !          3626:          expr = build_function_call (dtor, parms);
        !          3627: 
        !          3628:          if (ifexp != integer_one_node)
        !          3629:            expr = build (COND_EXPR, void_type_node,
        !          3630:                          ifexp, expr, void_zero_node);
        !          3631:        }
        !          3632:       return expr;
        !          3633:     }
        !          3634:   else
        !          3635:     {
        !          3636:       /* This can get visibilties wrong.  */
        !          3637:       tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
        !          3638:       int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
        !          3639:       tree child = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
        !          3640:       tree exprstmt = NULL_TREE;
        !          3641:       tree parent_auto_delete = auto_delete;
        !          3642:       tree cond;
        !          3643: 
        !          3644:       /* If this type does not have a destructor, but does have
        !          3645:         operator delete, call the parent parent destructor (if any),
        !          3646:         but let this node do the deleting.  Otherwise, it is ok
        !          3647:         to let the parent destructor do the deleting.  */
        !          3648:       if (TREE_GETS_DELETE (type) && !use_global_delete)
        !          3649:        {
        !          3650:          parent_auto_delete = integer_zero_node;
        !          3651:          if (auto_delete == integer_zero_node)
        !          3652:            cond = NULL_TREE;
        !          3653:          else
        !          3654:            {
        !          3655:              expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr);
        !          3656:              if (expr == error_mark_node)
        !          3657:                return error_mark_node;
        !          3658:              if (auto_delete != integer_one_node)
        !          3659:                cond = build (COND_EXPR, void_type_node,
        !          3660:                              build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
        !          3661:                              expr, void_zero_node);
        !          3662:              else cond = expr;
        !          3663:            }
        !          3664:        }
        !          3665:       else if (child == NULL_TREE
        !          3666:               || (TREE_VIA_VIRTUAL (child) == 0
        !          3667:                   && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (child))))
        !          3668:        cond = build (COND_EXPR, void_type_node,
        !          3669:                      build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
        !          3670:                      build_builtin_call (void_type_node, BID, build_tree_list (NULL_TREE, addr)),
        !          3671:                      void_zero_node);
        !          3672:       else cond = NULL_TREE;
        !          3673: 
        !          3674:       if (cond)
        !          3675:        exprstmt = build_tree_list (NULL_TREE, cond);
        !          3676: 
        !          3677:       if (child
        !          3678:          && ! TREE_VIA_VIRTUAL (child)
        !          3679:          && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (child)))
        !          3680:        {
        !          3681:          tree this_auto_delete;
        !          3682: 
        !          3683:          if (BINFO_OFFSET_ZEROP (child))
        !          3684:            this_auto_delete = parent_auto_delete;
        !          3685:          else
        !          3686:            this_auto_delete = integer_zero_node;
        !          3687: 
        !          3688:          expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (child)), addr,
        !          3689:                               this_auto_delete, flags|LOOKUP_PROTECTED_OK, 0, 0);
        !          3690:          exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        !          3691:        }
        !          3692: 
        !          3693:       /* Take care of the remaining baseclasses.  */
        !          3694:       for (i = 1; i < n_baseclasses; i++)
        !          3695:        {
        !          3696:          child = TREE_VEC_ELT (binfos, i);
        !          3697:          if (! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (child))
        !          3698:              || TREE_VIA_VIRTUAL (child))
        !          3699:            continue;
        !          3700: 
        !          3701:          /* May be zero offset if other baseclasses are virtual.  */
        !          3702:          expr = fold (build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (child)),
        !          3703:                              addr, BINFO_OFFSET (child)));
        !          3704: 
        !          3705:          expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (child)), expr,
        !          3706:                               integer_zero_node,
        !          3707:                               flags|LOOKUP_PROTECTED_OK, 0, 0);
        !          3708: 
        !          3709:          exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        !          3710:        }
        !          3711: 
        !          3712:       for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
        !          3713:        {
        !          3714:          if (TREE_CODE (member) != FIELD_DECL)
        !          3715:            continue;
        !          3716:          if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member)))
        !          3717:            {
        !          3718:              tree this_member = build_component_ref (ref, DECL_NAME (member), 0, 0);
        !          3719:              tree this_type = TREE_TYPE (member);
        !          3720:              expr = build_delete (this_type, this_member, integer_two_node, flags, 0, 0);
        !          3721:              exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        !          3722:            }
        !          3723:        }
        !          3724: 
        !          3725:       if (exprstmt)
        !          3726:        return build_compound_expr (exprstmt);
        !          3727:       /* Virtual base classes make this function do nothing.  */
        !          3728:       return void_zero_node;
        !          3729:     }
        !          3730: }
        !          3731: 
        !          3732: /* For type TYPE, delete the virtual baseclass objects of DECL.  */
        !          3733: 
        !          3734: tree
        !          3735: build_vbase_delete (type, decl)
        !          3736:      tree type, decl;
        !          3737: {
        !          3738:   tree vbases = CLASSTYPE_VBASECLASSES (type);
        !          3739:   tree result = NULL_TREE;
        !          3740:   tree addr = build_unary_op (ADDR_EXPR, decl, 0);
        !          3741:   assert (addr != error_mark_node);
        !          3742:   while (vbases)
        !          3743:     {
        !          3744:       tree this_addr = convert_force (TYPE_POINTER_TO (BINFO_TYPE (vbases)), addr);
        !          3745:       result = tree_cons (NULL_TREE,
        !          3746:                          build_delete (TREE_TYPE (this_addr), this_addr,
        !          3747:                                        integer_zero_node,
        !          3748:                                        LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0),
        !          3749:                          result);
        !          3750:       vbases = TREE_CHAIN (vbases);
        !          3751:     }
        !          3752:   return build_compound_expr (nreverse (result));
        !          3753: }
        !          3754: 
        !          3755: /* Build a C++ vector delete expression.
        !          3756:    MAXINDEX is the number of elements to be deleted.
        !          3757:    ELT_SIZE is the nominal size of each element in the vector.
        !          3758:    BASE is the expression that should yield the store to be deleted.
        !          3759:    DTOR_DUMMY is a placeholder for a destructor.  The library function
        !          3760:    __builtin_vec_delete has a pointer to function in this position.
        !          3761:    This function expands (or synthesizes) these calls itself.
        !          3762:    AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
        !          3763:    AUTO_DELETE say whether each item in the container should be deallocated.
        !          3764: 
        !          3765:    This also calls delete for virtual baseclasses of elements of the vector.
        !          3766: 
        !          3767:    Update: MAXINDEX is no longer needed.  The size can be extracted from the
        !          3768:    start of the vector for pointers, and from the type for arrays.  We still
        !          3769:    use MAXINDEX for arrays because it happens to already have one of the
        !          3770:    values we'd have to extract.  (We could use MAXINDEX with pointers to
        !          3771:    confirm the size, and trap if the numbers differ; not clear that it'd
        !          3772:    be worth bothering.)  */
        !          3773: tree
        !          3774: build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete)
        !          3775:      tree base, maxindex, elt_size;
        !          3776:      tree dtor_dummy;
        !          3777:      tree auto_delete_vec, auto_delete;
        !          3778: {
        !          3779:   tree ptype = TREE_TYPE (base);
        !          3780:   tree type;
        !          3781:   tree rval;
        !          3782:   /* Temporary variables used by the loop.  */
        !          3783:   tree tbase, size_exp;
        !          3784: 
        !          3785:   /* This is the body of the loop that implements the deletion of a
        !          3786:      single element, and moves temp variables to next elements.  */
        !          3787:   tree body;
        !          3788: 
        !          3789:   /* This is the LOOP_EXPR that governs the deletetion of the elements.  */
        !          3790:   tree loop;
        !          3791: 
        !          3792:   /* This is the thing that governs what to do after the loop has run.  */
        !          3793:   tree deallocate_expr = 0;
        !          3794: 
        !          3795:   /* This is the BIND_EXPR which holds the outermost iterator of the
        !          3796:      loop.  It is convenient to set this variable up and test it before
        !          3797:      executing any other code in the loop.
        !          3798:      This is also the containing expression returned by this function.  */
        !          3799:   tree controller = NULL_TREE;
        !          3800: 
        !          3801:   /* This is the BLOCK to record the symbol binding for debugging.  */
        !          3802:   tree block;
        !          3803: 
        !          3804:   base = stabilize_reference (base);
        !          3805: 
        !          3806:   if (TREE_CODE (ptype) == POINTER_TYPE)
        !          3807:     {
        !          3808:       /* Step back one from start of vector, and read dimension.  */
        !          3809:       tree cookie_addr = build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
        !          3810:                                base, BI_header_size);
        !          3811:       tree cookie = build_indirect_ref (cookie_addr, 0);
        !          3812:       maxindex = build_component_ref (cookie, get_identifier ("nelts"), 0, 0);
        !          3813:       do
        !          3814:        ptype = TREE_TYPE (ptype);
        !          3815:       while (TREE_CODE (ptype) == ARRAY_TYPE);
        !          3816:     }
        !          3817:   else if (TREE_CODE (ptype) == ARRAY_TYPE)
        !          3818:     {
        !          3819:       /* If we're passed an array, the maxindex we're passed is for the
        !          3820:         first dimension we'll be looking at.  So start our loop on the
        !          3821:         second dimension (if any).
        !          3822: 
        !          3823:         We could as easily extract it by calling array_type_nelts here,
        !          3824:         and eliminating maxindex as an argument to this function.  */
        !          3825:       assert (array_type_nelts (ptype) == maxindex);
        !          3826:       maxindex = fold (build (PLUS_EXPR, integer_type_node,
        !          3827:                              maxindex, integer_one_node));
        !          3828:       ptype = TREE_TYPE (ptype);
        !          3829:       while (TREE_CODE (ptype) == ARRAY_TYPE)
        !          3830:        {
        !          3831:          /* array_type_nelts actually returns
        !          3832:             the max index, so add 1.  */
        !          3833:          tree n = fold (build (PLUS_EXPR, integer_type_node,
        !          3834:                                array_type_nelts (ptype), integer_one_node));
        !          3835:          maxindex = fold (build (MULT_EXPR, integer_type_node, maxindex, n));
        !          3836:          ptype = TREE_TYPE (ptype);
        !          3837:        }
        !          3838:       base = build_unary_op (ADDR_EXPR, base, 1);
        !          3839:     }
        !          3840:   else
        !          3841:     {
        !          3842:       error ("type to vector delete is neither pointer or array type");
        !          3843:       return error_mark_node;
        !          3844:     }
        !          3845:   type = ptype;
        !          3846:   ptype = TYPE_POINTER_TO (type);
        !          3847: 
        !          3848:   if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
        !          3849:     {
        !          3850:       loop = integer_zero_node;
        !          3851:       goto no_destructor;
        !          3852:     }
        !          3853: 
        !          3854:   size_exp = size_in_bytes (type);
        !          3855:   tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
        !          3856:   TREE_REGDECL (tbase) = 1;
        !          3857:   DECL_INITIAL (tbase) = fold (build (PLUS_EXPR, ptype, base,
        !          3858:                                      size_binop (MULT_EXPR, size_exp,
        !          3859:                                                  maxindex)));
        !          3860: 
        !          3861:   controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
        !          3862:   TREE_SIDE_EFFECTS (controller) = 1;
        !          3863:   block = build_block (tbase, 0, 0, 0, 0);
        !          3864:   add_block_current_level (block);
        !          3865: 
        !          3866:   if (auto_delete != integer_zero_node
        !          3867:       && auto_delete != integer_two_node)
        !          3868:     {
        !          3869:       tree base_tbd = convert (ptype,
        !          3870:                               build_binary_op (MINUS_EXPR,
        !          3871:                                                convert (ptr_type_node, base),
        !          3872:                                                BI_header_size));
        !          3873:       body = build_tree_list (NULL_TREE,
        !          3874:                              build_x_delete (ptr_type_node, base_tbd, 0));
        !          3875:       body = build (COND_EXPR, void_type_node,
        !          3876:                    build (BIT_AND_EXPR, integer_type_node,
        !          3877:                           auto_delete, integer_one_node),
        !          3878:                    body, integer_zero_node);
        !          3879:     }
        !          3880:   else
        !          3881:     body = NULL_TREE;
        !          3882: 
        !          3883:   body = tree_cons (NULL_TREE,
        !          3884:                    build_delete (ptype, tbase, auto_delete,
        !          3885:                                  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0, 0),
        !          3886:                    body);
        !          3887: 
        !          3888:   body = tree_cons (NULL_TREE,
        !          3889:                    build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
        !          3890:                    body);
        !          3891: 
        !          3892:   body = tree_cons (NULL_TREE,
        !          3893:                    build (EXIT_EXPR, void_type_node,
        !          3894:                           build (EQ_EXPR, integer_type_node, base, tbase)),
        !          3895:                    body);
        !          3896: 
        !          3897:   loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
        !          3898: 
        !          3899:  no_destructor:
        !          3900:   /* If the delete flag is one, or anything else with the low bit set,
        !          3901:      delete the storage.  */
        !          3902:   if (auto_delete_vec == integer_zero_node
        !          3903:       || auto_delete_vec == integer_two_node)
        !          3904:     deallocate_expr = integer_zero_node;
        !          3905:   else
        !          3906:     {
        !          3907:       tree base_tbd;
        !          3908:       if (loop == integer_zero_node)
        !          3909:        /* no header */
        !          3910:        base_tbd = base;
        !          3911:       else
        !          3912:        base_tbd = convert (ptype,
        !          3913:                            build_binary_op (MINUS_EXPR,
        !          3914:                                             convert (ptr_type_node, base),
        !          3915:                                             BI_header_size));
        !          3916:       deallocate_expr = build_x_delete (ptr_type_node, base_tbd, 1);
        !          3917:       if (auto_delete_vec != integer_one_node)
        !          3918:        deallocate_expr = build (COND_EXPR, void_type_node,
        !          3919:                                 build (BIT_AND_EXPR, integer_type_node,
        !          3920:                                        auto_delete_vec, integer_one_node),
        !          3921:                                 deallocate_expr, integer_zero_node);
        !          3922:     }
        !          3923: 
        !          3924:   if (loop && deallocate_expr != integer_zero_node)
        !          3925:     {
        !          3926:       body = tree_cons (NULL_TREE, loop,
        !          3927:                        tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
        !          3928:       body = build_compound_expr (body);
        !          3929:     }
        !          3930:   else
        !          3931:     body = loop;
        !          3932: 
        !          3933:   if (controller)
        !          3934:     {
        !          3935:       TREE_OPERAND (controller, 1) = body;
        !          3936:       return controller;
        !          3937:     }
        !          3938:   else
        !          3939:     return convert (void_type_node, body);
        !          3940: }

unix.superglobalmegacorp.com

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