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

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

unix.superglobalmegacorp.com

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