Annotation of GNUtools/cc/cp-cvt.c, revision 1.1

1.1     ! root        1: /* Language-level data type conversion for GNU C++.
        !             2:    Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
        !             3:    Hacked by Michael Tiemann ([email protected])
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 2, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: 
        !            22: /* This file contains the functions for converting C expressions
        !            23:    to different data types.  The only entry point is `convert'.
        !            24:    Every language front end must have a `convert' function
        !            25:    but what kind of conversions it does will depend on the language.  */
        !            26: 
        !            27: #include "config.h"
        !            28: #include "tree.h"
        !            29: #include "flags.h"
        !            30: #include "cp-tree.h"
        !            31: #include "cp-class.h"
        !            32: #include "convert.h"
        !            33: 
        !            34: #undef NULL
        !            35: #define NULL (char *)0
        !            36: 
        !            37: /* Change of width--truncation and extension of integers or reals--
        !            38:    is represented with NOP_EXPR.  Proper functioning of many things
        !            39:    assumes that no other conversions can be NOP_EXPRs.
        !            40: 
        !            41:    Conversion between integer and pointer is represented with CONVERT_EXPR.
        !            42:    Converting integer to real uses FLOAT_EXPR
        !            43:    and real to integer uses FIX_TRUNC_EXPR.
        !            44: 
        !            45:    Here is a list of all the functions that assume that widening and
        !            46:    narrowing is always done with a NOP_EXPR:
        !            47:      In convert.c, convert_to_integer.
        !            48:      In c-typeck.c, build_binary_op_nodefault (boolean ops),
        !            49:         and truthvalue_conversion.
        !            50:      In expr.c: expand_expr, for operands of a MULT_EXPR.
        !            51:      In fold-const.c: fold.
        !            52:      In tree.c: get_narrower and get_unwidened.
        !            53: 
        !            54:    C++: in multiple-inheritance, converting between pointers may involve
        !            55:    adjusting them by a delta stored within the class definition.  */
        !            56: 
        !            57: /* Subroutines of `convert'.  */
        !            58: 
        !            59: /* Build a thunk.  What it is, is an entry point that when called will
        !            60:    adjust the this pointer (the first argument) by offset, and then
        !            61:    goto the real address of the function given by REAL_ADDR that we
        !            62:    would like called.  What we return is the address of the thunk.  */
        !            63: static tree
        !            64: build_thunk (offset, real_addr)
        !            65:      tree offset, real_addr;
        !            66: {
        !            67:   if (TREE_CODE (real_addr) != ADDR_EXPR
        !            68:       || TREE_CODE (TREE_OPERAND (real_addr, 0)) != FUNCTION_DECL)
        !            69:     {
        !            70:       sorry ("MI pointer to member conversion too complex");
        !            71:       return error_mark_node;
        !            72:     }
        !            73:   sorry ("MI pointer to member conversion too complex");
        !            74:   return error_mark_node;
        !            75: }
        !            76: 
        !            77: /* Convert a `pointer to member' (POINTER_TYPE to METHOD_TYPE) into
        !            78:    another `pointer to method'.  This may involved the creation of
        !            79:    a thunk to handle the this offset calculation.  */
        !            80: static tree
        !            81: convert_fn_ptr (type, expr)
        !            82:      tree type, expr;
        !            83: {
        !            84:   tree binfo = get_binfo (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (expr))),
        !            85:                          TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
        !            86:                          1);
        !            87:   if (binfo == error_mark_node)
        !            88:     {
        !            89:       error ("  in pointer to member conversion");
        !            90:       return error_mark_node;
        !            91:     }
        !            92:   if (binfo == NULL_TREE)
        !            93:     {
        !            94:       /* ARM 4.8 restriction. */
        !            95:       error ("invalid pointer to member conversion");
        !            96:       return error_mark_node;
        !            97:     }
        !            98:   if (BINFO_OFFSET_ZEROP (binfo))
        !            99:     return build1 (NOP_EXPR, type, expr);
        !           100:   return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr));
        !           101: }
        !           102: 
        !           103: /* if converting pointer to pointer
        !           104:      if dealing with classes, check for derived->base or vice versa
        !           105:      else if dealing with method pointers, delegate
        !           106:      else convert blindly
        !           107:    else if converting class, pass off to build_type_conversion
        !           108:    else try C-style pointer conversion  */
        !           109: static tree
        !           110: cp_convert_to_pointer (type, expr)
        !           111:      tree type, expr;
        !           112: {
        !           113:   register tree intype = TREE_TYPE (expr);
        !           114:   register enum tree_code form = TREE_CODE (intype);
        !           115:   
        !           116:   if (form == POINTER_TYPE)
        !           117:     {
        !           118:       intype = TYPE_MAIN_VARIANT (intype);
        !           119: 
        !           120:       if (TYPE_MAIN_VARIANT (type) != intype
        !           121:          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
        !           122:          && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
        !           123:        {
        !           124:          enum tree_code code = PLUS_EXPR;
        !           125:          tree binfo = get_binfo (TREE_TYPE (type), TREE_TYPE (intype), 1);
        !           126:          if (binfo == error_mark_node)
        !           127:            return error_mark_node;
        !           128:          if (binfo == NULL_TREE)
        !           129:            {
        !           130:              binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 1);
        !           131:              if (binfo == error_mark_node)
        !           132:                return error_mark_node;
        !           133:              code = MINUS_EXPR;
        !           134:            }
        !           135:          if (binfo && TREE_CODE (binfo) == TREE_VEC)
        !           136:            {
        !           137:              if (TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (type))
        !           138:                  || TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (intype))
        !           139:                  || ! BINFO_OFFSET_ZEROP (binfo))
        !           140:                {
        !           141:                  /* Need to get the path we took.  */
        !           142:                  tree path;
        !           143: 
        !           144:                  if (code == PLUS_EXPR)
        !           145:                    get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), 0, &path);
        !           146:                  else
        !           147:                    get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), 0, &path);
        !           148:                  return build_vbase_path (code, type, expr, path, 0);
        !           149:                }
        !           150:            }
        !           151:        }
        !           152:       if (TYPE_MAIN_VARIANT (type) != intype
        !           153:          && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
        !           154:          && TREE_CODE (type) == POINTER_TYPE
        !           155:          && TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE)
        !           156:        return convert_fn_ptr (type, expr);
        !           157: 
        !           158:       return build1 (NOP_EXPR, type, expr);
        !           159:     }
        !           160: 
        !           161:   my_friendly_assert (form != OFFSET_TYPE, 186);
        !           162: 
        !           163:   if (IS_AGGR_TYPE (intype))
        !           164:     {
        !           165:       /* If we cannot convert to the specific pointer type,
        !           166:         try to convert to the type `void *'.  */
        !           167:       tree rval;
        !           168:       rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
        !           169:       if (rval)
        !           170:        {
        !           171:          if (rval == error_mark_node)
        !           172:            error ("ambiguous pointer conversion");
        !           173:          return rval;
        !           174:        }
        !           175:     }
        !           176: 
        !           177:   return convert_to_pointer (type, expr);
        !           178: }
        !           179: 
        !           180: /* Like convert, except permit conversions to take place which
        !           181:    are not normally allowed due to visibility restrictions
        !           182:    (such as conversion from sub-type to private super-type).  */
        !           183: static tree
        !           184: convert_to_pointer_force (type, expr)
        !           185:      tree type, expr;
        !           186: {
        !           187:   register tree intype = TREE_TYPE (expr);
        !           188:   register enum tree_code form = TREE_CODE (intype);
        !           189:   
        !           190:   if (integer_zerop (expr))
        !           191:     {
        !           192:       if (type == TREE_TYPE (null_pointer_node))
        !           193:        return null_pointer_node;
        !           194:       expr = build_int_2 (0, 0);
        !           195:       TREE_TYPE (expr) = type;
        !           196:       return expr;
        !           197:     }
        !           198: 
        !           199:   if (form == POINTER_TYPE)
        !           200:     {
        !           201:       intype = TYPE_MAIN_VARIANT (intype);
        !           202: 
        !           203:       if (TYPE_MAIN_VARIANT (type) != intype
        !           204:          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
        !           205:          && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
        !           206:        {
        !           207:          enum tree_code code = PLUS_EXPR;
        !           208:          tree path;
        !           209:          int distance = get_base_distance (TREE_TYPE (type),
        !           210:                                            TREE_TYPE (intype), 0, &path);
        !           211:          if (distance == -2)
        !           212:            {
        !           213:            ambig:
        !           214:              cp_error ("type `%T' is ambiguous baseclass of `%s'", TREE_TYPE (type),
        !           215:                                    TYPE_NAME_STRING (TREE_TYPE (intype)));
        !           216:              return error_mark_node;
        !           217:            }
        !           218:          if (distance == -1)
        !           219:            {
        !           220:              distance = get_base_distance (TREE_TYPE (intype),
        !           221:                                            TREE_TYPE (type), 0, &path);
        !           222:              if (distance == -2)
        !           223:                goto ambig;
        !           224:              if (distance < 0)
        !           225:                /* Doesn't need any special help from us.  */
        !           226:                return build1 (NOP_EXPR, type, expr);
        !           227: 
        !           228:              code = MINUS_EXPR;
        !           229:            }
        !           230:          return build_vbase_path (code, type, expr, path, 0);
        !           231:        }
        !           232:       return build1 (NOP_EXPR, type, expr);
        !           233:     }
        !           234: 
        !           235:   return cp_convert_to_pointer (type, expr);
        !           236: }
        !           237: 
        !           238: /* We are passing something to a function which requires a reference.
        !           239:    The type we are interested in is in TYPE. The initial
        !           240:    value we have to begin with is in ARG.
        !           241: 
        !           242:    FLAGS controls how we manage visibility checking.
        !           243:    CHECKCONST controls if we report error messages on const subversion.  */
        !           244: static tree
        !           245: build_up_reference (type, arg, flags, checkconst)
        !           246:      tree type, arg;
        !           247:      int flags, checkconst;
        !           248: {
        !           249:   tree rval, targ;
        !           250:   int literal_flag = 0;
        !           251:   tree argtype = TREE_TYPE (arg), basetype = argtype;
        !           252:   tree target_type = TREE_TYPE (type);
        !           253:   tree binfo = NULL_TREE;
        !           254: 
        !           255:   my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
        !           256:   if (flags != 0
        !           257:       && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
        !           258:       && IS_AGGR_TYPE (argtype)
        !           259:       && IS_AGGR_TYPE (target_type))
        !           260:     {
        !           261:       binfo = get_binfo (target_type, argtype,
        !           262:                              (flags & LOOKUP_PROTECTED_OK) ? 3 : 2);
        !           263:       if ((flags & LOOKUP_PROTECT) && binfo == error_mark_node)
        !           264:        return error_mark_node;
        !           265:       if (binfo == NULL_TREE)
        !           266:        return error_not_base_type (target_type, argtype);
        !           267:       basetype = BINFO_TYPE (binfo);
        !           268:     }
        !           269: 
        !           270:   /* Pass along const and volatile down into the type. */
        !           271:   if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
        !           272:     target_type = build_type_variant (target_type, TYPE_READONLY (type),
        !           273:                                      TYPE_VOLATILE (type));
        !           274:   targ = arg;
        !           275:   if (TREE_CODE (targ) == SAVE_EXPR)
        !           276:     targ = TREE_OPERAND (targ, 0);
        !           277: 
        !           278:   switch (TREE_CODE (targ))
        !           279:     {
        !           280:     case INDIRECT_REF:
        !           281:       /* This is a call to a constructor which did not know what it was
        !           282:         initializing until now: it needs to initialize a temporary.  */
        !           283:       if (TREE_HAS_CONSTRUCTOR (targ))
        !           284:        {
        !           285:          tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1);
        !           286:          TREE_HAS_CONSTRUCTOR (targ) = 0;
        !           287:          return build_up_reference (type, temp, flags, 1);
        !           288:        }
        !           289:       /* Let &* cancel out to simplify resulting code.
        !           290:          Also, throw away intervening NOP_EXPRs.  */
        !           291:       arg = TREE_OPERAND (targ, 0);
        !           292:       if (TREE_CODE (arg) == NOP_EXPR || TREE_CODE (arg) == NON_LVALUE_EXPR
        !           293:          || (TREE_CODE (arg) == CONVERT_EXPR && TREE_REFERENCE_EXPR (arg)))
        !           294:        arg = TREE_OPERAND (arg, 0);
        !           295: 
        !           296:       /* in doing a &*, we have to get rid of the const'ness on the pointer
        !           297:         value.  Haven't thought about volatile here.  Pointers come to mind
        !           298:         here.  */
        !           299:       if (TREE_READONLY (arg))
        !           300:        {
        !           301:          arg = copy_node (arg);
        !           302:          TREE_READONLY (arg) = 0;
        !           303:        }
        !           304: 
        !           305:       rval = build1 (CONVERT_EXPR, type, arg);
        !           306:       TREE_REFERENCE_EXPR (rval) = 1;
        !           307: 
        !           308:       /* propagate the const flag on something like:
        !           309: 
        !           310:         class Base {
        !           311:         public:
        !           312:           int foo;
        !           313:         };
        !           314: 
        !           315:       class Derived : public Base {
        !           316:       public:
        !           317:        int bar;
        !           318:       };
        !           319: 
        !           320:       void func(Base&);
        !           321: 
        !           322:       void func2(const Derived& d) {
        !           323:        func(d);
        !           324:       }
        !           325: 
        !           326:         on the d parameter.  The below could have been avoided, if the flags
        !           327:         were down in the tree, not sure why they are not.  (mrs) */
        !           328:       /* The below code may have to be propagated to other parts of this
        !           329:         switch.  */
        !           330:       if (TREE_READONLY (targ) && !TREE_READONLY (arg)
        !           331:          && (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL)
        !           332:          && TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
        !           333:          && (TYPE_READONLY (target_type) && checkconst))
        !           334:        {
        !           335:          arg = copy_node (arg);
        !           336:          TREE_READONLY (arg) = TREE_READONLY (targ);
        !           337:        }
        !           338:       literal_flag = TREE_CONSTANT (arg);
        !           339: 
        !           340:       goto done_but_maybe_warn;
        !           341: 
        !           342:       /* Get this out of a register if we happened to be in one by accident.
        !           343:         Also, build up references to non-lvalues it we must.  */
        !           344:       /* For &x[y], return (&) x+y */
        !           345:     case ARRAY_REF:
        !           346:       if (mark_addressable (TREE_OPERAND (targ, 0)) == 0)
        !           347:        return error_mark_node;
        !           348:       rval = build_binary_op (PLUS_EXPR, TREE_OPERAND (targ, 0),
        !           349:                              TREE_OPERAND (targ, 1), 1);
        !           350:       TREE_TYPE (rval) = type;
        !           351:       if (TREE_CONSTANT (TREE_OPERAND (targ, 1))
        !           352:          && staticp (TREE_OPERAND (targ, 0)))
        !           353:        TREE_CONSTANT (rval) = 1;
        !           354:       goto done;
        !           355: 
        !           356:     case SCOPE_REF:
        !           357:       /* Could be a reference to a static member.  */
        !           358:       {
        !           359:        tree field = TREE_OPERAND (targ, 1);
        !           360:        if (TREE_STATIC (field))
        !           361:          {
        !           362:            rval = build1 (ADDR_EXPR, type, field);
        !           363:            literal_flag = 1;
        !           364:            goto done;
        !           365:          }
        !           366:       }
        !           367: 
        !           368:       /* We should have farmed out member pointers above.  */
        !           369:       my_friendly_abort (188);
        !           370: 
        !           371:     case COMPONENT_REF:
        !           372:       rval = build_component_addr (targ, build_pointer_type (argtype),
        !           373:                                   "attempt to make a reference to bit-field structure member `%s'");
        !           374:       TREE_TYPE (rval) = type;
        !           375:       literal_flag = staticp (TREE_OPERAND (targ, 0));
        !           376: 
        !           377:       goto done_but_maybe_warn;
        !           378: 
        !           379:       /* Anything not already handled and not a true memory reference
        !           380:         needs to have a reference built up.  Do so silently for
        !           381:         things like integers and return values from function,
        !           382:         but complain if we need a reference to something declared
        !           383:         as `register'.  */
        !           384: 
        !           385:     case RESULT_DECL:
        !           386:       if (staticp (targ))
        !           387:        literal_flag = 1;
        !           388:       TREE_ADDRESSABLE (targ) = 1;
        !           389:       put_var_into_stack (targ);
        !           390:       break;
        !           391: 
        !           392:     case PARM_DECL:
        !           393:       if (targ == current_class_decl)
        !           394:        {
        !           395:          error ("address of `this' not available");
        !           396: #if 0
        !           397:          /* This code makes the following core dump the compiler on a sun4,
        !           398:             if the code below is used.
        !           399: 
        !           400:             class e_decl;
        !           401:             class a_decl;
        !           402:             typedef a_decl* a_ref;
        !           403: 
        !           404:             class a_s {
        !           405:             public:
        !           406:               a_s();
        !           407:               void* append(a_ref& item);
        !           408:             };
        !           409:             class a_decl {
        !           410:             public:
        !           411:               a_decl (e_decl *parent);
        !           412:               a_s  generic_s;
        !           413:               a_s  decls;
        !           414:               e_decl* parent;
        !           415:             };
        !           416: 
        !           417:             class e_decl {
        !           418:             public:
        !           419:               e_decl();
        !           420:               a_s implementations;
        !           421:             };
        !           422: 
        !           423:             void foobar(void *);
        !           424: 
        !           425:             a_decl::a_decl(e_decl *parent) {
        !           426:               parent->implementations.append(this);
        !           427:             }
        !           428:           */
        !           429: 
        !           430:          TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */
        !           431:          put_var_into_stack (targ);
        !           432:          break;
        !           433: #else
        !           434:          return error_mark_node;
        !           435: #endif
        !           436:        }
        !           437:       /* Fall through.  */
        !           438:     case VAR_DECL:
        !           439:     case CONST_DECL:
        !           440:       if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ))
        !           441:        warning ("address needed to build reference for `%s', which is declared `register'",
        !           442:                 IDENTIFIER_POINTER (DECL_NAME (targ)));
        !           443:       else if (staticp (targ))
        !           444:        literal_flag = 1;
        !           445: 
        !           446:       TREE_ADDRESSABLE (targ) = 1;
        !           447:       put_var_into_stack (targ);
        !           448:       break;
        !           449: 
        !           450:     case COMPOUND_EXPR:
        !           451:       {
        !           452:        tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1),
        !           453:                                                  LOOKUP_PROTECT, checkconst);
        !           454:        rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference);
        !           455:        TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1));
        !           456:        return rval;
        !           457:       }
        !           458: 
        !           459:     case MODIFY_EXPR:
        !           460:     case INIT_EXPR:
        !           461:       {
        !           462:        tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0),
        !           463:                                                  LOOKUP_PROTECT, checkconst);
        !           464:        rval = build (COMPOUND_EXPR, type, arg, real_reference);
        !           465:        TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0));
        !           466:        return rval;
        !           467:       }
        !           468: 
        !           469:     case COND_EXPR:
        !           470:       return build (COND_EXPR, type,
        !           471:                    TREE_OPERAND (targ, 0),
        !           472:                    build_up_reference (type, TREE_OPERAND (targ, 1),
        !           473:                                        LOOKUP_PROTECT, checkconst),
        !           474:                    build_up_reference (type, TREE_OPERAND (targ, 2),
        !           475:                                        LOOKUP_PROTECT, checkconst));
        !           476: 
        !           477:     case WITH_CLEANUP_EXPR:
        !           478:       return build (WITH_CLEANUP_EXPR, type,
        !           479:                    build_up_reference (type, TREE_OPERAND (targ, 0),
        !           480:                                        LOOKUP_PROTECT, checkconst),
        !           481:                    0, TREE_OPERAND (targ, 2));
        !           482: 
        !           483:     case BIND_EXPR:
        !           484:       arg = TREE_OPERAND (targ, 1);
        !           485:       if (arg == NULL_TREE)
        !           486:        {
        !           487:          compiler_error ("({ ... }) expression not expanded when needed for reference");
        !           488:          return error_mark_node;
        !           489:        }
        !           490:       rval = build1 (ADDR_EXPR, type, arg);
        !           491:       TREE_REFERENCE_EXPR (rval) = 1;
        !           492:       return rval;
        !           493: 
        !           494:     default:
        !           495:       break;
        !           496:     }
        !           497: 
        !           498:   if (TREE_ADDRESSABLE (targ) == 0)
        !           499:     {
        !           500:       tree temp;
        !           501: 
        !           502:       if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
        !           503:        {
        !           504:          temp = build_cplus_new (argtype, targ, 1);
        !           505:          rval = build1 (ADDR_EXPR, type, temp);
        !           506:          goto done;
        !           507:        }
        !           508:       else
        !           509:        {
        !           510:          temp = get_temp_name (argtype, 0);
        !           511:          if (global_bindings_p ())
        !           512:            {
        !           513:              /* Give this new temp some rtl and initialize it.  */
        !           514:              DECL_INITIAL (temp) = targ;
        !           515:              TREE_STATIC (temp) = 1;
        !           516:              finish_decl (temp, targ, NULL_TREE, 0);
        !           517:              /* Do this after declaring it static.  */
        !           518:              rval = build_unary_op (ADDR_EXPR, temp, 0);
        !           519:              literal_flag = TREE_CONSTANT (rval);
        !           520:              goto done;
        !           521:            }
        !           522:          else
        !           523:            {
        !           524:              rval = build_unary_op (ADDR_EXPR, temp, 0);
        !           525:              /* Put a value into the rtl.  */
        !           526:              if (IS_AGGR_TYPE (argtype))
        !           527:                {
        !           528:                  /* This may produce surprising results,
        !           529:                     since we commit to initializing the temp
        !           530:                     when the temp may not actually get used.  */
        !           531:                  expand_aggr_init (temp, targ, 0);
        !           532:                  TREE_TYPE (rval) = type;
        !           533:                  literal_flag = TREE_CONSTANT (rval);
        !           534:                  goto done;
        !           535:                }
        !           536:              else
        !           537:                {
        !           538:                  if (binfo && !BINFO_OFFSET_ZEROP (binfo))
        !           539:                    rval = convert_pointer_to (target_type, rval);
        !           540:                  else
        !           541:                    TREE_TYPE (rval) = type;
        !           542: 
        !           543:                  temp = build (MODIFY_EXPR, argtype, temp, arg);
        !           544:                  TREE_SIDE_EFFECTS (temp) = 1;
        !           545:                  return build (COMPOUND_EXPR, type, temp, rval);
        !           546:                }
        !           547:            }
        !           548:        }
        !           549:     }
        !           550:   else
        !           551:     {
        !           552:       if (TREE_CODE (arg) == SAVE_EXPR)
        !           553:        my_friendly_abort (5);
        !           554:       rval = build1 (ADDR_EXPR, type, arg);
        !           555:     }
        !           556: 
        !           557:  done_but_maybe_warn:
        !           558:   if (checkconst && TREE_READONLY (arg) && ! TYPE_READONLY (target_type))
        !           559:     readonly_error (arg, "conversion to reference", 1);
        !           560: 
        !           561:  done:
        !           562:   if (TYPE_USES_COMPLEX_INHERITANCE (argtype))
        !           563:     {
        !           564:       TREE_TYPE (rval) = TYPE_POINTER_TO (argtype);
        !           565:       rval = convert_pointer_to (target_type, rval);
        !           566:       TREE_TYPE (rval) = type;
        !           567:     }
        !           568:   TREE_CONSTANT (rval) = literal_flag;
        !           569:   return rval;
        !           570: }
        !           571: 
        !           572: /* For C++: Only need to do one-level references, but cannot
        !           573:    get tripped up on signed/unsigned differences.
        !           574: 
        !           575:    If DECL is NULL_TREE it means convert as though casting (by force).
        !           576:    If it is ERROR_MARK_NODE, it means the conversion is implicit,
        !           577:    and that temporaries may be created.
        !           578:    Make sure the use of user-defined conversion operators is un-ambiguous.
        !           579:    Otherwise, DECL is a _DECL node which can be used in error reporting.
        !           580: 
        !           581:    FNDECL, PARMNUM, and ERRTYPE are only used when checking for use of
        !           582:    volatile or const references where they aren't desired.  */
        !           583: 
        !           584: tree
        !           585: convert_to_reference (decl, reftype, expr, fndecl, parmnum,
        !           586:                      errtype, strict, flags)
        !           587: 
        !           588:      tree decl;
        !           589:      tree reftype, expr;
        !           590:      tree fndecl;
        !           591:      int parmnum;
        !           592:      char *errtype;
        !           593:      int strict, flags;
        !           594: {
        !           595:   register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
        !           596:   register tree intype = TREE_TYPE (expr);
        !           597:   register enum tree_code form = TREE_CODE (intype);
        !           598:   tree rval = NULL_TREE;
        !           599: 
        !           600:   if (TREE_CODE(type) == ARRAY_TYPE)
        !           601:     type = build_pointer_type (TREE_TYPE(type));
        !           602:   if (form == REFERENCE_TYPE)
        !           603:     intype = TREE_TYPE (intype);
        !           604:   intype = TYPE_MAIN_VARIANT (intype);
        !           605: 
        !           606:   /* @@ Probably need to have a check for X(X&) here.  */
        !           607: 
        !           608:   if (IS_AGGR_TYPE (intype))
        !           609:     {
        !           610:       rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
        !           611:       if (rval)
        !           612:        {
        !           613:          if (rval == error_mark_node)
        !           614:            error ("ambiguous pointer conversion");
        !           615:          return rval;
        !           616:        }
        !           617:       else if (type != intype
        !           618:               && (rval = build_type_conversion (CONVERT_EXPR, type, expr, 1)))
        !           619:        {
        !           620:          if (rval == error_mark_node)
        !           621:            return rval;
        !           622:          if (TYPE_NEEDS_DESTRUCTOR (type))
        !           623:            {
        !           624:              rval = convert_to_reference (NULL_TREE, reftype, rval, NULL_TREE,
        !           625: -1, (char *)NULL, strict, flags);
        !           626:            }
        !           627:          else
        !           628:            {
        !           629:              decl = get_temp_name (type, 0);
        !           630:              rval = build (INIT_EXPR, type, decl, rval);
        !           631:              rval = build (COMPOUND_EXPR, reftype, rval,
        !           632:                            convert_to_reference (NULL_TREE, reftype, decl,
        !           633:                                                  NULL_TREE, -1, (char*)NULL,
        !           634:                                                  strict, flags));
        !           635:            }
        !           636:        }
        !           637: 
        !           638:       if (form == REFERENCE_TYPE
        !           639:          && type != intype
        !           640:          && TYPE_USES_COMPLEX_INHERITANCE (intype))
        !           641:        {
        !           642:          /* If it may move around, build a fresh reference.  */
        !           643:          expr = convert_from_reference (expr);
        !           644:          form = TREE_CODE (TREE_TYPE (expr));
        !           645:        }
        !           646:     }
        !           647: 
        !           648:   /* @@ Perhaps this should try to go through a constructor first
        !           649:      @@ for proper initialization, but I am not sure when that
        !           650:      @@ is needed or desirable.  */
        !           651: 
        !           652:   if (((IS_AGGR_TYPE (type) || IS_AGGR_TYPE (intype))
        !           653:        && comptypes (type, intype, strict))
        !           654:       || (!IS_AGGR_TYPE (type)
        !           655: #if 1
        !           656:          && ((TREE_CODE (type) == TREE_CODE (intype)
        !           657:               && int_size_in_bytes (type) == int_size_in_bytes (intype))
        !           658:              || TREE_READONLY (TREE_TYPE (reftype)))))
        !           659: #else
        !           660:          && (comptypes (type, intype, 1)
        !           661:              || TREE_READONLY (TREE_TYPE (reftype)))))
        !           662: #endif
        !           663: 
        !           664:     {
        !           665:       /* Section 13.  */
        !           666:       /* Since convert_for_initialization didn't call convert_for_assignment,
        !           667:         we have to do this checking here.  FIXME: We should have a common
        !           668:         routine between here and convert_for_assignment.  */
        !           669:       if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
        !           670:        {
        !           671:          register tree ttl = TREE_TYPE (reftype);
        !           672:          register tree ttr = TREE_TYPE (TREE_TYPE (expr));
        !           673: 
        !           674:          if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
        !           675:            warn_for_assignment ("%s of non-`const &' reference from `const &'",
        !           676:                                 "reference to const given for argument %d of `%s'",
        !           677:                                 errtype, fndecl, parmnum, pedantic);
        !           678:          if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
        !           679:            warn_for_assignment ("%s of non-`volatile &' reference from `volatile &'",
        !           680:                                 "reference to volatile given for argument %d of `%s'", 
        !           681:                                 errtype, fndecl, parmnum, pedantic);
        !           682:        }
        !           683: 
        !           684:       /* If EXPR is of aggregate type, and is really a CALL_EXPR,
        !           685:         then we don't need to convert it to reference type if
        !           686:         it is only being used to initialize DECL which is also
        !           687:         of the same aggregate type.  */
        !           688:       if (form == REFERENCE_TYPE
        !           689:          || (decl != NULL_TREE && decl != error_mark_node
        !           690:              && IS_AGGR_TYPE (type)
        !           691:              && TREE_CODE (expr) == CALL_EXPR
        !           692:              && TYPE_MAIN_VARIANT (type) == intype))
        !           693:        {
        !           694:          if (decl && decl != error_mark_node)
        !           695:            {
        !           696:              tree e1 = build (INIT_EXPR, void_type_node, decl, expr);
        !           697:              tree e2;
        !           698: 
        !           699:              TREE_SIDE_EFFECTS (e1) = 1;
        !           700:              if (form == REFERENCE_TYPE)
        !           701:                e2 = build1 (NOP_EXPR, reftype, decl);
        !           702:              else
        !           703:                {
        !           704:                  e2 = build_unary_op (ADDR_EXPR, decl, 0);
        !           705:                  TREE_TYPE (e2) = reftype;
        !           706:                  TREE_REFERENCE_EXPR (e2) = 1;
        !           707:                }
        !           708:              return build_compound_expr (tree_cons (NULL_TREE, e1,
        !           709:                                                     build_tree_list (NULL_TREE, e2)));
        !           710:            }
        !           711:          expr = copy_node (expr);
        !           712:          TREE_TYPE (expr) = reftype;
        !           713:          return expr;
        !           714:        }
        !           715:       if (decl == error_mark_node)
        !           716:        flags |= LOOKUP_PROTECTED_OK;
        !           717:       return build_up_reference (reftype, expr, flags, decl!=NULL_TREE);
        !           718:     }
        !           719: 
        !           720:   /* Definitely need to go through a constructor here.  */
        !           721:   if (TYPE_HAS_CONSTRUCTOR (type))
        !           722:     {
        !           723:       tree init = build_method_call (NULL_TREE, constructor_name_full (type),
        !           724:                                     build_tree_list (NULL_TREE, expr),
        !           725:                                     TYPE_BINFO (type), LOOKUP_NO_CONVERSION);
        !           726: 
        !           727:       if (init != error_mark_node)
        !           728:        {
        !           729:          if (rval)
        !           730:            {
        !           731:              error ("both constructor and type conversion operator apply");
        !           732:              return error_mark_node;
        !           733:            }
        !           734:        }
        !           735:       else
        !           736:        {
        !           737:          /* If a type conversion operator works, then pass that along
        !           738:             to the ctor.  */
        !           739:          if (rval != NULL_TREE)
        !           740:            expr = rval;
        !           741:        }
        !           742: 
        !           743:       init = build_method_call (NULL_TREE, constructor_name_full (type),
        !           744:                                build_tree_list (NULL_TREE, expr),
        !           745:                                TYPE_BINFO (type), LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
        !           746: 
        !           747:       if (init == error_mark_node)
        !           748:        return error_mark_node;
        !           749:       rval = build_cplus_new (type, init, 1);
        !           750:       if (decl == error_mark_node)
        !           751:        flags |= LOOKUP_PROTECTED_OK;
        !           752:       return build_up_reference (reftype, rval, flags, decl!=NULL_TREE);
        !           753:     }
        !           754: 
        !           755:   if (rval)
        !           756:     {
        !           757:       /* If we found a way to convert earlier, then use it. */
        !           758:       return rval;
        !           759:     }
        !           760: 
        !           761:   my_friendly_assert (form != OFFSET_TYPE, 189);
        !           762: 
        !           763:   cp_error ("cannot convert type `%T' to type `%T'", intype, reftype);
        !           764: 
        !           765:   return error_mark_node;
        !           766: }
        !           767: 
        !           768: /* We are using a reference VAL for its value. Bash that reference all the
        !           769:    way down to its lowest form. */
        !           770: tree
        !           771: convert_from_reference (val)
        !           772:      tree val;
        !           773: {
        !           774:   tree type = TREE_TYPE (val);
        !           775: 
        !           776:   if (TREE_CODE (type) == OFFSET_TYPE)
        !           777:     type = TREE_TYPE (type);
        !           778:  if (TREE_CODE (type) == REFERENCE_TYPE)
        !           779:     {
        !           780:       tree target_type = TREE_TYPE (type);
        !           781:       tree nval;
        !           782: 
        !           783:       /* This can happen if we cast to a reference type.  */
        !           784:       if (TREE_CODE (val) == ADDR_EXPR)
        !           785:        {
        !           786:          nval = build1 (NOP_EXPR, build_pointer_type (target_type), val);
        !           787:          nval = build_indirect_ref (nval, NULL_PTR);
        !           788:          /* The below was missing, are other important flags missing too? */
        !           789:          TREE_SIDE_EFFECTS (nval) = TREE_SIDE_EFFECTS (val);
        !           790:          return nval;
        !           791:        }
        !           792: 
        !           793:       nval = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (target_type), val);
        !           794: 
        !           795:       TREE_THIS_VOLATILE (nval) = TYPE_VOLATILE (target_type);
        !           796:       TREE_SIDE_EFFECTS (nval) = TYPE_VOLATILE (target_type);
        !           797:       TREE_READONLY (nval) = TYPE_READONLY (target_type);
        !           798:       /* The below was missing, are other important flags missing too? */
        !           799:       TREE_SIDE_EFFECTS (nval) |= TREE_SIDE_EFFECTS (val);
        !           800:       return nval;
        !           801:     }
        !           802:   return val;
        !           803: }
        !           804: 
        !           805: /* See if there is a constructor of type TYPE which will convert
        !           806:    EXPR.  The reference manual seems to suggest (8.5.6) that we need
        !           807:    not worry about finding constructors for base classes, then converting
        !           808:    to the derived class.
        !           809: 
        !           810:    MSGP is a pointer to a message that would be an appropriate error
        !           811:    string.  If MSGP is NULL, then we are not interested in reporting
        !           812:    errors.  */
        !           813: tree
        !           814: convert_to_aggr (type, expr, msgp, protect)
        !           815:      tree type, expr;
        !           816:      char **msgp;
        !           817:      int protect;
        !           818: {
        !           819:   tree basetype = type;
        !           820:   tree name = TYPE_IDENTIFIER (basetype);
        !           821:   tree function, fndecl, fntype, parmtypes, parmlist, result;
        !           822:   tree method_name;
        !           823:   enum visibility_type visibility;
        !           824:   int can_be_private, can_be_protected;
        !           825: 
        !           826:   if (! TYPE_HAS_CONSTRUCTOR (basetype))
        !           827:     {
        !           828:       if (msgp)
        !           829:        *msgp = "type `%s' does not have a constructor";
        !           830:       return error_mark_node;
        !           831:     }
        !           832: 
        !           833:   visibility = visibility_public;
        !           834:   can_be_private = 0;
        !           835:   can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name;
        !           836: 
        !           837:   parmlist = build_tree_list (NULL_TREE, expr);
        !           838:   parmtypes = tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node);
        !           839: 
        !           840:   if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
        !           841:     {
        !           842:       parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
        !           843:       parmlist = tree_cons (NULL_TREE, integer_one_node, parmlist);
        !           844:     }
        !           845: 
        !           846:   /* The type of the first argument will be filled in inside the loop.  */
        !           847:   parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
        !           848:   parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
        !           849: 
        !           850:   method_name = build_decl_overload (name, parmtypes, 1);
        !           851: 
        !           852:   /* constructors are up front.  */
        !           853:   fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
        !           854:   if (TYPE_HAS_DESTRUCTOR (basetype))
        !           855:     fndecl = DECL_CHAIN (fndecl);
        !           856: 
        !           857:   while (fndecl)
        !           858:     {
        !           859:       if (DECL_ASSEMBLER_NAME (fndecl) == method_name)
        !           860:        {
        !           861:          function = fndecl;
        !           862:          if (protect)
        !           863:            {
        !           864:              if (TREE_PRIVATE (fndecl))
        !           865:                {
        !           866:                  can_be_private =
        !           867:                    (basetype == current_class_type
        !           868:                     || is_friend (basetype, current_function_decl)
        !           869:                     || purpose_member (basetype, DECL_VISIBILITY (fndecl)));
        !           870:                  if (! can_be_private)
        !           871:                    goto found;
        !           872:                }
        !           873:              else if (TREE_PROTECTED (fndecl))
        !           874:                {
        !           875:                  if (! can_be_protected)
        !           876:                    goto found;
        !           877:                }
        !           878:            }
        !           879:          goto found_and_ok;
        !           880:        }
        !           881:       fndecl = DECL_CHAIN (fndecl);
        !           882:     }
        !           883: 
        !           884:   /* No exact conversion was found.  See if an approximate
        !           885:      one will do.  */
        !           886:   fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
        !           887:   if (TYPE_HAS_DESTRUCTOR (basetype))
        !           888:     fndecl = DECL_CHAIN (fndecl);
        !           889: 
        !           890:   {
        !           891:     int saw_private = 0;
        !           892:     int saw_protected = 0;
        !           893:     struct candidate *candidates =
        !           894:       (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate));
        !           895:     struct candidate *cp = candidates;
        !           896: 
        !           897:     while (fndecl)
        !           898:       {
        !           899:        function = fndecl;
        !           900:        if (flag_ansi_overloading)
        !           901:          {
        !           902:            cp->v.ansi_harshness = (struct harshness_code *)alloca (3 * sizeof (struct harshness_code));
        !           903:            cp->h_len = 2;
        !           904:          }
        !           905:        else
        !           906:          cp->v.old_harshness = (unsigned short *)alloca (3 * sizeof (short));
        !           907: 
        !           908:        compute_conversion_costs (fndecl, parmlist, cp, 2);
        !           909:        if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE) == 0)
        !           910:            || (!flag_ansi_overloading && cp->evil == 0))
        !           911:          {
        !           912:            cp->u.field = fndecl;
        !           913:            if (protect)
        !           914:              {
        !           915:                if (TREE_PRIVATE (fndecl))
        !           916:                  visibility = visibility_private;
        !           917:                else if (TREE_PROTECTED (fndecl))
        !           918:                  visibility = visibility_protected;
        !           919:                else
        !           920:                  visibility = visibility_public;
        !           921:              }
        !           922:            else
        !           923:              visibility = visibility_public;
        !           924: 
        !           925:            if (visibility == visibility_private
        !           926:                ? (basetype == current_class_type
        !           927:                   || is_friend (basetype, cp->function)
        !           928:                   || purpose_member (basetype, DECL_VISIBILITY (fndecl)))
        !           929:                : visibility == visibility_protected
        !           930:                ? (can_be_protected
        !           931:                   || purpose_member (basetype, DECL_VISIBILITY (fndecl)))
        !           932:                : 1)
        !           933:              {
        !           934:                if ((flag_ansi_overloading && cp->h.code <= TRIVIAL_CODE)
        !           935:                    || (!flag_ansi_overloading
        !           936:                        && cp->user == 0 && cp->b_or_d == 0
        !           937:                        && cp->easy <= 1))
        !           938:                  goto found_and_ok;
        !           939:                cp++;
        !           940:              }
        !           941:            else
        !           942:              {
        !           943:                if (visibility == visibility_private)
        !           944:                  saw_private = 1;
        !           945:                else
        !           946:                  saw_protected = 1;
        !           947:              }
        !           948:          }
        !           949:        fndecl = DECL_CHAIN (fndecl);
        !           950:       }
        !           951:     if (cp - candidates)
        !           952:       {
        !           953:        /* Rank from worst to best.  Then cp will point to best one.
        !           954:           Private fields have their bits flipped.  For unsigned
        !           955:           numbers, this should make them look very large.
        !           956:           If the best alternate has a (signed) negative value,
        !           957:           then all we ever saw were private members.  */
        !           958:        if (cp - candidates > 1)
        !           959:          qsort (candidates,    /* char *base */
        !           960:                 cp - candidates, /* int nel */
        !           961:                 sizeof (struct candidate), /* int width */
        !           962:                 rank_for_overload); /* int (*compar)() */
        !           963: 
        !           964:        --cp;
        !           965:        if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE))
        !           966:            || (!flag_ansi_overloading && cp->evil > 1))
        !           967:          {
        !           968:            if (msgp)
        !           969:              *msgp = "ambiguous type conversion possible for `%s'";
        !           970:            return error_mark_node;
        !           971:          }
        !           972: 
        !           973:        function = cp->function;
        !           974:        fndecl = cp->u.field;
        !           975:        goto found_and_ok;
        !           976:       }
        !           977:     else if (msgp)
        !           978:       {
        !           979:        if (saw_private)
        !           980:          if (saw_protected)
        !           981:            *msgp = "only private and protected conversions apply";
        !           982:          else
        !           983:            *msgp = "only private conversions apply";
        !           984:        else if (saw_protected)
        !           985:          *msgp = "only protected conversions apply";
        !           986:       }
        !           987:     return error_mark_node;
        !           988:   }
        !           989:   /* NOTREACHED */
        !           990: 
        !           991:  not_found:
        !           992:   if (msgp) *msgp = "no appropriate conversion to type `%s'";
        !           993:   return error_mark_node;
        !           994:  found:
        !           995:   if (visibility == visibility_private)
        !           996:     if (! can_be_private)
        !           997:       {
        !           998:        if (msgp)
        !           999:          *msgp = TREE_PRIVATE (fndecl)
        !          1000:            ? "conversion to type `%s' is private"
        !          1001:            : "conversion to type `%s' is from private base class";
        !          1002:        return error_mark_node;
        !          1003:       }
        !          1004:   if (visibility == visibility_protected)
        !          1005:     if (! can_be_protected)
        !          1006:       {
        !          1007:        if (msgp)
        !          1008:          *msgp = TREE_PRIVATE (fndecl)
        !          1009:            ? "conversion to type `%s' is protected"
        !          1010:            : "conversion to type `%s' is from protected base class";
        !          1011:        return error_mark_node;
        !          1012:       }
        !          1013:   function = fndecl;
        !          1014:  found_and_ok:
        !          1015: 
        !          1016:   /* It will convert, but we don't do anything about it yet.  */
        !          1017:   if (msgp == 0)
        !          1018:     return NULL_TREE;
        !          1019: 
        !          1020:   fntype = TREE_TYPE (function);
        !          1021:   if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL)
        !          1022:     function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
        !          1023:   else
        !          1024:     function = default_conversion (function);
        !          1025: 
        !          1026:   result = build_nt (CALL_EXPR, function,
        !          1027:                     convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
        !          1028:                                        parmlist, NULL_TREE, LOOKUP_NORMAL),
        !          1029:                     NULL_TREE);
        !          1030:   TREE_TYPE (result) = TREE_TYPE (fntype);
        !          1031:   TREE_SIDE_EFFECTS (result) = 1;
        !          1032:   TREE_RAISES (result) = !! TYPE_RAISES_EXCEPTIONS (fntype);
        !          1033:   return result;
        !          1034: }
        !          1035: 
        !          1036: /* Call this when we know (for any reason) that expr is not, in fact,
        !          1037:    zero.  This routine is like convert_pointer_to, but it pays
        !          1038:    attention to which specific instance of what type we want to
        !          1039:    convert to.  This routine should eventually become
        !          1040:    convert_to_pointer after all references to convert_to_pointer
        !          1041:    are removed.  */
        !          1042: tree
        !          1043: convert_pointer_to_real (binfo, expr)
        !          1044:      tree binfo, expr;
        !          1045: {
        !          1046:   register tree intype = TREE_TYPE (expr);
        !          1047:   tree ptr_type;
        !          1048:   tree type, rval;
        !          1049: 
        !          1050:   if (TREE_CODE (binfo) == TREE_VEC)
        !          1051:     type = BINFO_TYPE (binfo);
        !          1052:   else if (IS_AGGR_TYPE (binfo))
        !          1053:     {
        !          1054:       type = binfo;
        !          1055:     }
        !          1056:   else
        !          1057:     {
        !          1058:       type = binfo;
        !          1059:       binfo = NULL_TREE;
        !          1060:     }
        !          1061: 
        !          1062:   ptr_type = build_pointer_type (type);
        !          1063:   if (ptr_type == TYPE_MAIN_VARIANT (intype))
        !          1064:     return expr;
        !          1065: 
        !          1066:   if (intype == error_mark_node)
        !          1067:     return error_mark_node;
        !          1068: 
        !          1069:   my_friendly_assert (!integer_zerop (expr), 191);
        !          1070: 
        !          1071:   if (TREE_CODE (type) == RECORD_TYPE
        !          1072:       && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE
        !          1073:       && type != TYPE_MAIN_VARIANT (TREE_TYPE (intype)))
        !          1074:     {
        !          1075:       tree path;
        !          1076:       int distance
        !          1077:        = get_base_distance (binfo, TYPE_MAIN_VARIANT (TREE_TYPE (intype)),
        !          1078:                             0, &path);
        !          1079: 
        !          1080:       /* This function shouldn't be called with unqualified arguments
        !          1081:         but if it is, give them an error message that they can read.
        !          1082:         */
        !          1083:       if (distance < 0)
        !          1084:        {
        !          1085:          error ("cannot convert a pointer of type `%s'",
        !          1086:                 TYPE_NAME_STRING (TREE_TYPE (intype)));
        !          1087:          cp_error ("to a pointer of type `%T'", type);
        !          1088: 
        !          1089:          if (distance == -2)
        !          1090:            cp_error ("because `%T' is an ambiguous base class", type);
        !          1091:          return error_mark_node;
        !          1092:        }
        !          1093: 
        !          1094:       return build_vbase_path (PLUS_EXPR, ptr_type, expr, path, 1);
        !          1095:     }
        !          1096:   rval = build1 (NOP_EXPR, ptr_type,
        !          1097:                 TREE_CODE (expr) == NOP_EXPR ? TREE_OPERAND (expr, 0) : expr);
        !          1098:   TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
        !          1099:   return rval;
        !          1100: }
        !          1101: 
        !          1102: /* Call this when we know (for any reason) that expr is
        !          1103:    not, in fact, zero.  This routine gets a type out of the first
        !          1104:    argument and uses it to search for the type to convert to.  If there
        !          1105:    is more than one instance of that type in the expr, the conversion is
        !          1106:    ambiguous.  This routine should eventually go away, and all
        !          1107:    callers should use convert_to_pointer_real.  */
        !          1108: tree
        !          1109: convert_pointer_to (binfo, expr)
        !          1110:      tree binfo, expr;
        !          1111: {
        !          1112:   tree type;
        !          1113: 
        !          1114:   if (TREE_CODE (binfo) == TREE_VEC)
        !          1115:     type = BINFO_TYPE (binfo);
        !          1116:   else if (IS_AGGR_TYPE (binfo))
        !          1117:       type = binfo;
        !          1118:   else
        !          1119:       type = binfo;
        !          1120:   return convert_pointer_to_real (type, expr);
        !          1121: }
        !          1122: 
        !          1123: /* Same as above, but don't abort if we get an "ambiguous" baseclass.
        !          1124:    There's only one virtual baseclass we are looking for, and once
        !          1125:    we find one such virtual baseclass, we have found them all.  */
        !          1126: 
        !          1127: tree
        !          1128: convert_pointer_to_vbase (binfo, expr)
        !          1129:      tree binfo;
        !          1130:      tree expr;
        !          1131: {
        !          1132:   tree intype = TREE_TYPE (TREE_TYPE (expr));
        !          1133:   tree binfos = TYPE_BINFO_BASETYPES (intype);
        !          1134:   int i;
        !          1135: 
        !          1136:   for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
        !          1137:     {
        !          1138:       tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
        !          1139:       if (BINFO_TYPE (binfo) == basetype)
        !          1140:        return convert_pointer_to (binfo, expr);
        !          1141:       if (binfo_member (BINFO_TYPE (binfo), CLASSTYPE_VBASECLASSES (basetype)))
        !          1142:        return convert_pointer_to_vbase (binfo, convert_pointer_to (basetype, expr));
        !          1143:     }
        !          1144:   my_friendly_abort (6);
        !          1145:   /* NOTREACHED */
        !          1146:   return NULL_TREE;
        !          1147: }
        !          1148: 
        !          1149: /* Create an expression whose value is that of EXPR,
        !          1150:    converted to type TYPE.  The TREE_TYPE of the value
        !          1151:    is always TYPE.  This function implements all reasonable
        !          1152:    conversions; callers should filter out those that are
        !          1153:    not permitted by the language being compiled.  */
        !          1154: 
        !          1155: tree
        !          1156: convert (type, expr)
        !          1157:      tree type, expr;
        !          1158: {
        !          1159:   register tree e = expr;
        !          1160:   register enum tree_code code = TREE_CODE (type);
        !          1161: 
        !          1162:   if (type == TREE_TYPE (expr)
        !          1163:       || TREE_CODE (expr) == ERROR_MARK)
        !          1164:     return expr;
        !          1165:   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
        !          1166:     return fold (build1 (NOP_EXPR, type, expr));
        !          1167:   if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
        !          1168:     return error_mark_node;
        !          1169:   if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
        !          1170:     {
        !          1171:       error ("void value not ignored as it ought to be");
        !          1172:       return error_mark_node;
        !          1173:     }
        !          1174:   if (code == VOID_TYPE)
        !          1175:     {
        !          1176:       /* We're converting to a void type; see if they have an
        !          1177:         `operator void'.  */
        !          1178:       tree rval = build_type_conversion (NOP_EXPR, type, e, 0);
        !          1179:       /* If we can convert to void type via a type conversion, do so.  */
        !          1180:       if (rval)
        !          1181:        return rval;
        !          1182:       return build1 (CONVERT_EXPR, type, e);
        !          1183:     }
        !          1184: #if 0
        !          1185:   /* This is incorrect.  A truncation can't be stripped this way.
        !          1186:      Extensions will be stripped by the use of get_unwidened.  */
        !          1187:   if (TREE_CODE (expr) == NOP_EXPR)
        !          1188:     return convert (type, TREE_OPERAND (expr, 0));
        !          1189: #endif
        !          1190: 
        !          1191:   /* Just convert to the type of the member.  */
        !          1192:   if (code == OFFSET_TYPE)
        !          1193:     {
        !          1194:       type = TREE_TYPE (type);
        !          1195:       code = TREE_CODE (type);
        !          1196:     }
        !          1197: 
        !          1198:   /* C++ */
        !          1199:   if (code == REFERENCE_TYPE)
        !          1200:     return fold (convert_to_reference (error_mark_node,
        !          1201:                                       type, e,
        !          1202:                                       NULL_TREE, -1, (char *)NULL,
        !          1203:                                       -1, LOOKUP_NORMAL));
        !          1204:   else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
        !          1205:     e = convert_from_reference (e);
        !          1206: 
        !          1207:   if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
        !          1208:     {
        !          1209:       tree intype = TREE_TYPE (expr);
        !          1210:       enum tree_code form = TREE_CODE (intype);
        !          1211:       if (flag_int_enum_equivalence == 0
        !          1212:          && TREE_CODE (type) == ENUMERAL_TYPE
        !          1213:          && form == INTEGER_TYPE)
        !          1214:        {
        !          1215:          cp_pedwarn ("anachronistic conversion from `int' to `%#T'", type);
        !          1216: 
        !          1217:          if (flag_pedantic_errors)
        !          1218:            return error_mark_node;
        !          1219:        }
        !          1220:       if (form == OFFSET_TYPE)
        !          1221:        cp_error_at ("pointer-to-member expression object not composed with type `%D' object",
        !          1222:                     TYPE_NAME (TYPE_OFFSET_BASETYPE (intype)));
        !          1223:       else if (IS_AGGR_TYPE (intype))
        !          1224:        {
        !          1225:          tree rval;
        !          1226:          rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
        !          1227:          if (rval) return rval;
        !          1228:          cp_error ("`%#T' used where an `int' was expected", intype);
        !          1229:          return error_mark_node;
        !          1230:        }
        !          1231:       return fold (convert_to_integer (type, e));
        !          1232:     }
        !          1233:   if (code == POINTER_TYPE)
        !          1234:     return fold (cp_convert_to_pointer (type, e));
        !          1235:   if (code == REAL_TYPE)
        !          1236:     {
        !          1237:       if (IS_AGGR_TYPE (TREE_TYPE (e)))
        !          1238:        {
        !          1239:          tree rval;
        !          1240:          rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
        !          1241:          if (rval)
        !          1242:            return rval;
        !          1243:          else
        !          1244:            cp_error ("`%#T' used where a floating point value was expected",
        !          1245:                      TREE_TYPE (e));
        !          1246:        }
        !          1247:       return fold (convert_to_real (type, e));
        !          1248:     }
        !          1249: 
        !          1250:   /* New C++ semantics:  since assignment is now based on
        !          1251:      memberwise copying,  if the rhs type is derived from the
        !          1252:      lhs type, then we may still do a conversion.  */
        !          1253:   if (IS_AGGR_TYPE_CODE (code))
        !          1254:     {
        !          1255:       tree dtype = TREE_TYPE (e);
        !          1256: 
        !          1257:       if (TREE_CODE (dtype) == REFERENCE_TYPE)
        !          1258:        {
        !          1259:          e = convert_from_reference (e);
        !          1260:          dtype = TREE_TYPE (e);
        !          1261:        }
        !          1262:       dtype = TYPE_MAIN_VARIANT (dtype);
        !          1263: 
        !          1264:       /* Conversion between aggregate types.  New C++ semantics allow
        !          1265:         objects of derived type to be cast to objects of base type.
        !          1266:         Old semantics only allowed this between pointers.
        !          1267: 
        !          1268:         There may be some ambiguity between using a constructor
        !          1269:         vs. using a type conversion operator when both apply.  */
        !          1270: 
        !          1271:       if (IS_AGGR_TYPE (dtype))
        !          1272:        {
        !          1273:          tree binfo;
        !          1274: 
        !          1275:          tree conversion = TYPE_HAS_CONVERSION (dtype)
        !          1276:            ? build_type_conversion (CONVERT_EXPR, type, e, 1) : NULL_TREE;
        !          1277: 
        !          1278:          if (TYPE_HAS_CONSTRUCTOR (type))
        !          1279:            {
        !          1280:              tree rval = build_method_call (NULL_TREE, constructor_name_full (type),
        !          1281:                                             build_tree_list (NULL_TREE, e),
        !          1282:                                             TYPE_BINFO (type),
        !          1283:                                             conversion ? LOOKUP_NO_CONVERSION : 0);
        !          1284: 
        !          1285:              if (rval != error_mark_node)
        !          1286:                {
        !          1287:                  if (conversion)
        !          1288:                    {
        !          1289:                      error ("both constructor and type conversion operator apply");
        !          1290:                      return error_mark_node;
        !          1291:                    }
        !          1292:                  /* call to constructor successful.  */
        !          1293:                  rval = build_cplus_new (type, rval, 0);
        !          1294:                  return rval;
        !          1295:                }
        !          1296:            }
        !          1297:          /* Type conversion successful/applies.  */
        !          1298:          if (conversion)
        !          1299:            {
        !          1300:              if (conversion == error_mark_node)
        !          1301:                error ("ambiguous pointer conversion");
        !          1302:              return conversion;
        !          1303:            }
        !          1304: 
        !          1305:          /* now try normal C++ assignment semantics.  */
        !          1306:          binfo = TYPE_BINFO (dtype);
        !          1307:          if (BINFO_TYPE (binfo) == type
        !          1308:              || (binfo = get_binfo (type, dtype, 1)))
        !          1309:            {
        !          1310:              if (binfo == error_mark_node)
        !          1311:                return error_mark_node;
        !          1312:            }
        !          1313:          if (binfo != NULL_TREE)
        !          1314:            {
        !          1315:              if (lvalue_p (e))
        !          1316:                {
        !          1317:                  e = build_unary_op (ADDR_EXPR, e, 0);
        !          1318: 
        !          1319:                  if (! BINFO_OFFSET_ZEROP (binfo))
        !          1320:                    e = build (PLUS_EXPR, TYPE_POINTER_TO (type),
        !          1321:                               e, BINFO_OFFSET (binfo));
        !          1322:                  return build1 (INDIRECT_REF, type, e);
        !          1323:                }
        !          1324: 
        !          1325:              sorry ("addressable aggregates");
        !          1326:              return error_mark_node;
        !          1327:            }
        !          1328:          error ("conversion between incompatible aggregate types requested");
        !          1329:          return error_mark_node;
        !          1330:        }
        !          1331:       /* conversion from non-aggregate to aggregate type requires constructor.  */
        !          1332:       else if (TYPE_HAS_CONSTRUCTOR (type))
        !          1333:        {
        !          1334:          tree rval;
        !          1335:          tree init = build_method_call (NULL_TREE, constructor_name_full (type),
        !          1336:                                         build_tree_list (NULL_TREE, e),
        !          1337:                                         TYPE_BINFO (type), LOOKUP_NORMAL);
        !          1338:          if (init == error_mark_node)
        !          1339:            {
        !          1340:              cp_error ("in conversion to type `%T'", type);
        !          1341:              return error_mark_node;
        !          1342:            }
        !          1343:          rval = build_cplus_new (type, init, 0);
        !          1344:          return rval;
        !          1345:        }
        !          1346:     }
        !          1347: 
        !          1348:   /* If TYPE or TREE_TYPE (EXPR) is not on the permanent_obstack,
        !          1349:      then the it won't be hashed and hence compare as not equal,
        !          1350:      even when it is.  */
        !          1351:   if (code == ARRAY_TYPE
        !          1352:       && TREE_TYPE (TREE_TYPE (expr)) == TREE_TYPE (type)
        !          1353:       && index_type_equal (TYPE_DOMAIN (TREE_TYPE (expr)), TYPE_DOMAIN (type)))
        !          1354:     return expr;
        !          1355: 
        !          1356:   error ("conversion to non-scalar type requested");
        !          1357:   return error_mark_node;
        !          1358: }
        !          1359: 
        !          1360: /* Like convert, except permit conversions to take place which
        !          1361:    are not normally allowed due to visibility restrictions
        !          1362:    (such as conversion from sub-type to private super-type).  */
        !          1363: tree
        !          1364: convert_force (type, expr)
        !          1365:      tree type;
        !          1366:      tree expr;
        !          1367: {
        !          1368:   register tree e = expr;
        !          1369:   register enum tree_code code = TREE_CODE (type);
        !          1370: 
        !          1371:   if (code == REFERENCE_TYPE)
        !          1372:     return fold (convert_to_reference (0, type, e,
        !          1373:                                       NULL_TREE, -1, (char *)NULL,
        !          1374:                                       -1, 0));
        !          1375:   else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
        !          1376:     e = convert_from_reference (e);
        !          1377: 
        !          1378:   if (code == POINTER_TYPE)
        !          1379:     return fold (convert_to_pointer_force (type, e));
        !          1380: 
        !          1381:   {
        !          1382:     int old_equiv = flag_int_enum_equivalence;
        !          1383:     flag_int_enum_equivalence = 1;
        !          1384:     e = convert (type, e);
        !          1385:     flag_int_enum_equivalence = old_equiv;
        !          1386:   }
        !          1387:   return e;
        !          1388: }
        !          1389: 
        !          1390: /* Subroutine of build_type_conversion.  */
        !          1391: static tree
        !          1392: build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
        !          1393:      tree xtype, basetype;
        !          1394:      tree expr;
        !          1395:      tree typename;
        !          1396:      int for_sure;
        !          1397: {
        !          1398:   tree first_arg = expr;
        !          1399:   tree rval;
        !          1400:   int flags;
        !          1401: 
        !          1402:   if (for_sure == 0)
        !          1403:     {
        !          1404:       if (! lvalue_p (expr))
        !          1405:        first_arg = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node);
        !          1406:       flags = LOOKUP_PROTECT;
        !          1407:     }
        !          1408:   else
        !          1409:     flags = LOOKUP_NORMAL;
        !          1410: 
        !          1411:   rval = build_method_call (first_arg, constructor_name_full (typename),
        !          1412:                            NULL_TREE, NULL_TREE, flags);
        !          1413:   if (rval == error_mark_node)
        !          1414:     {
        !          1415:       if (for_sure == 0)
        !          1416:        return NULL_TREE;
        !          1417:       return error_mark_node;
        !          1418:     }
        !          1419:   if (first_arg != expr)
        !          1420:     {
        !          1421:       expr = build_up_reference (build_reference_type (TREE_TYPE (expr)), expr,
        !          1422:                                 LOOKUP_COMPLAIN, 1);
        !          1423:       TREE_VALUE (TREE_OPERAND (rval, 1)) = build_unary_op (ADDR_EXPR, expr, 0);
        !          1424:     }
        !          1425:   if (TREE_CODE (TREE_TYPE (rval)) == REFERENCE_TYPE
        !          1426:       && TREE_CODE (xtype) != REFERENCE_TYPE)
        !          1427:     rval = default_conversion (rval);
        !          1428: 
        !          1429:   if (pedantic
        !          1430:       && TREE_TYPE (xtype)
        !          1431:       && (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval)))
        !          1432:          > TREE_READONLY (TREE_TYPE (xtype))))
        !          1433:     pedwarn ("user-defined conversion casting away `const'");
        !          1434:   return convert (xtype, rval);
        !          1435: }
        !          1436: 
        !          1437: /* Convert an aggregate EXPR to type XTYPE.  If a conversion
        !          1438:    exists, return the attempted conversion.  This may
        !          1439:    return ERROR_MARK_NODE if the conversion is not
        !          1440:    allowed (references private members, etc).
        !          1441:    If no conversion exists, NULL_TREE is returned.
        !          1442: 
        !          1443:    If (FOR_SURE & 1) is non-zero, then we allow this type conversion
        !          1444:    to take place immediately.  Otherwise, we build a SAVE_EXPR
        !          1445:    which can be evaluated if the results are ever needed.
        !          1446: 
        !          1447:    If FOR_SURE >= 2, then we only look for exact conversions.
        !          1448: 
        !          1449:    TYPE may be a reference type, in which case we first look
        !          1450:    for something that will convert to a reference type.  If
        !          1451:    that fails, we will try to look for something of the
        !          1452:    reference's target type, and then return a reference to that.  */
        !          1453: tree
        !          1454: build_type_conversion (code, xtype, expr, for_sure)
        !          1455:      enum tree_code code;
        !          1456:      tree xtype, expr;
        !          1457:      int for_sure;
        !          1458: {
        !          1459:   /* C++: check to see if we can convert this aggregate type
        !          1460:      into the required scalar type.  */
        !          1461:   tree type, type_default;
        !          1462:   tree typename = build_typename_overload (xtype), *typenames;
        !          1463:   int n_variants = 0;
        !          1464:   tree basetype, save_basetype;
        !          1465:   tree rval;
        !          1466:   int exact_conversion = for_sure >= 2;
        !          1467:   for_sure &= 1;
        !          1468: 
        !          1469:   if (expr == error_mark_node)
        !          1470:     return error_mark_node;
        !          1471: 
        !          1472:   basetype = TREE_TYPE (expr);
        !          1473:   if (TREE_CODE (basetype) == REFERENCE_TYPE)
        !          1474:     basetype = TREE_TYPE (basetype);
        !          1475: 
        !          1476:   basetype = TYPE_MAIN_VARIANT (basetype);
        !          1477:   if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))
        !          1478:     return NULL_TREE;
        !          1479: 
        !          1480:   if (TREE_CODE (xtype) == POINTER_TYPE
        !          1481:       || TREE_CODE (xtype) == REFERENCE_TYPE)
        !          1482:     {
        !          1483:       /* Prepare to match a variant of this type.  */
        !          1484:       type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
        !          1485:       for (n_variants = 0; type; type = TYPE_NEXT_VARIANT (type))
        !          1486:        n_variants++;
        !          1487:       typenames = (tree *)alloca (n_variants * sizeof (tree));
        !          1488:       for (n_variants = 0, type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
        !          1489:           type; n_variants++, type = TYPE_NEXT_VARIANT (type))
        !          1490:        {
        !          1491:          if (type == TREE_TYPE (xtype))
        !          1492:            typenames[n_variants] = typename;
        !          1493:          else if (TREE_CODE (xtype) == POINTER_TYPE)
        !          1494:            typenames[n_variants] = build_typename_overload (build_pointer_type (type));
        !          1495:          else
        !          1496:            typenames[n_variants] = build_typename_overload (build_reference_type (type));
        !          1497:        }
        !          1498:     }
        !          1499: 
        !          1500:   save_basetype = basetype;
        !          1501:   type = xtype;
        !          1502: 
        !          1503:   while (TYPE_HAS_CONVERSION (basetype))
        !          1504:     {
        !          1505:       int i;
        !          1506:       if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
        !          1507:        return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1508:       for (i = 0; i < n_variants; i++)
        !          1509:        if (typenames[i] != typename
        !          1510:            && lookup_fnfields (TYPE_BINFO (basetype), typenames[i], 0))
        !          1511:          return build_type_conversion_1 (xtype, basetype, expr, typenames[i], for_sure);
        !          1512: 
        !          1513:       if (TYPE_BINFO_BASETYPES (basetype))
        !          1514:        basetype = TYPE_BINFO_BASETYPE (basetype, 0);
        !          1515:       else
        !          1516:        break;
        !          1517:     }
        !          1518: 
        !          1519:   if (TREE_CODE (type) == REFERENCE_TYPE)
        !          1520:     {
        !          1521:       tree first_arg = expr;
        !          1522:       type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
        !          1523:       basetype = save_basetype;
        !          1524: 
        !          1525:       /* May need to build a temporary for this.  */
        !          1526:       while (TYPE_HAS_CONVERSION (basetype))
        !          1527:        {
        !          1528:          if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
        !          1529:            {
        !          1530:              int flags;
        !          1531: 
        !          1532:              if (for_sure == 0)
        !          1533:                {
        !          1534:                  if (! lvalue_p (expr))
        !          1535:                    first_arg = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node);
        !          1536:                  flags = LOOKUP_PROTECT;
        !          1537:                }
        !          1538:              else
        !          1539:                flags = LOOKUP_NORMAL;
        !          1540:              rval = build_method_call (first_arg, constructor_name_full (typename),
        !          1541:                                        NULL_TREE, NULL_TREE, flags);
        !          1542:              if (rval == error_mark_node)
        !          1543:                {
        !          1544:                  if (for_sure == 0)
        !          1545:                    return NULL_TREE;
        !          1546:                  return error_mark_node;
        !          1547:                }
        !          1548:              TREE_VALUE (TREE_OPERAND (rval, 1)) = expr;
        !          1549: 
        !          1550:              if (IS_AGGR_TYPE (type))
        !          1551:                {
        !          1552:                  tree init = build_method_call (NULL_TREE,
        !          1553:                                                 constructor_name_full (type),
        !          1554:                                                 build_tree_list (NULL_TREE, rval), NULL_TREE, LOOKUP_NORMAL);
        !          1555:                  tree temp = build_cplus_new (type, init, 1);
        !          1556:                  return build_up_reference (TYPE_REFERENCE_TO (type), temp,
        !          1557:                                             LOOKUP_COMPLAIN, 1);
        !          1558:                }
        !          1559:              return convert (xtype, rval);
        !          1560:            }
        !          1561:          if (TYPE_BINFO_BASETYPES (basetype))
        !          1562:            basetype = TYPE_BINFO_BASETYPE (basetype, 0);
        !          1563:          else
        !          1564:            break;
        !          1565:        }
        !          1566:       /* No free conversions for reference types, right?.  */
        !          1567:       return NULL_TREE;
        !          1568:     }
        !          1569: 
        !          1570:   if (exact_conversion)
        !          1571:     return NULL_TREE;
        !          1572: 
        !          1573:   /* No perfect match found, try default.  */
        !          1574:   if (code == CONVERT_EXPR && TREE_CODE (type) == POINTER_TYPE)
        !          1575:     type_default = ptr_type_node;
        !          1576:   else if (type == void_type_node)
        !          1577:     return NULL_TREE;
        !          1578:   else
        !          1579:     {
        !          1580:       tree tmp = default_conversion (build1 (NOP_EXPR, type, integer_zero_node));
        !          1581:       if (tmp == error_mark_node)
        !          1582:        return NULL_TREE;
        !          1583:       type_default = TREE_TYPE (tmp);
        !          1584:     }
        !          1585: 
        !          1586:   basetype = save_basetype;
        !          1587: 
        !          1588:   if (type_default != type)
        !          1589:     {
        !          1590:       type = type_default;
        !          1591:       typename = build_typename_overload (type);
        !          1592: 
        !          1593:       while (TYPE_HAS_CONVERSION (basetype))
        !          1594:        {
        !          1595:          if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
        !          1596:            return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1597:          if (TYPE_BINFO_BASETYPES (basetype))
        !          1598:            basetype = TYPE_BINFO_BASETYPE (basetype, 0);
        !          1599:          else
        !          1600:            break;
        !          1601:        }
        !          1602:     }
        !          1603: 
        !          1604:  try_pointer:
        !          1605: 
        !          1606:   if (type == ptr_type_node)
        !          1607:     {
        !          1608:       /* Try converting to some other pointer type
        !          1609:         with which void* is compatible, or in situations
        !          1610:         in which void* is appropriate (such as &&,||, and !).  */
        !          1611: 
        !          1612:       while (TYPE_HAS_CONVERSION (basetype))
        !          1613:        {
        !          1614:          if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
        !          1615:            {
        !          1616:              if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
        !          1617:                return error_mark_node;
        !          1618:              typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
        !          1619:              return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1620:            }
        !          1621:          if (TYPE_BINFO_BASETYPES (basetype))
        !          1622:            basetype = TYPE_BINFO_BASETYPE (basetype, 0);
        !          1623:          else
        !          1624:            break;
        !          1625:        }
        !          1626:     }
        !          1627:   if (TREE_CODE (type) == POINTER_TYPE
        !          1628:       && TYPE_READONLY (TREE_TYPE (type))
        !          1629:       && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
        !          1630:     {
        !          1631:       /* Try converting to some other pointer type
        !          1632:         with which const void* is compatible.  */
        !          1633: 
        !          1634:       while (TYPE_HAS_CONVERSION (basetype))
        !          1635:        {
        !          1636:          if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0)
        !          1637:            {
        !          1638:              if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node)
        !          1639:                return error_mark_node;
        !          1640:              typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv));
        !          1641:              return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1642:            }
        !          1643:          if (TYPE_BINFO_BASETYPES (basetype))
        !          1644:            basetype = TYPE_BINFO_BASETYPE (basetype, 0);
        !          1645:          else
        !          1646:            break;
        !          1647:        }
        !          1648:     }
        !          1649:   /* Use the longer or shorter conversion that is appropriate.  Have
        !          1650:      to check against 0 because the conversion may come from a baseclass.  */
        !          1651:   if (TREE_CODE (type) == INTEGER_TYPE
        !          1652:       && TYPE_HAS_INT_CONVERSION (basetype)
        !          1653:       && CLASSTYPE_CONVERSION (basetype, int_conv) != 0
        !          1654:       && CLASSTYPE_CONVERSION (basetype, int_conv) != error_mark_node)
        !          1655:     {
        !          1656:       typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, int_conv));
        !          1657:       return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1658:     }
        !          1659: 
        !          1660:   if (TREE_CODE (type) == REAL_TYPE
        !          1661:       && TYPE_HAS_REAL_CONVERSION (basetype)
        !          1662:       && CLASSTYPE_CONVERSION (basetype, real_conv) != 0
        !          1663:       && CLASSTYPE_CONVERSION (basetype, real_conv) != error_mark_node)
        !          1664:     {
        !          1665:       /* Only accept using an operator double() if there isn't a conflicting
        !          1666:         operator int().  */
        !          1667:       if (flag_ansi_overloading && TYPE_HAS_INT_CONVERSION (basetype))
        !          1668:        {
        !          1669:          error ("two possible conversions for type `%s'",
        !          1670:                 TYPE_NAME_STRING (type));
        !          1671:          return error_mark_node;
        !          1672:        }
        !          1673: 
        !          1674:       typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, real_conv));
        !          1675:       return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1676:     }
        !          1677: 
        !          1678:   /* THIS IS A KLUDGE.  */
        !          1679:   if (TREE_CODE (type) != POINTER_TYPE
        !          1680:       && (code == TRUTH_ANDIF_EXPR
        !          1681:          || code == TRUTH_ORIF_EXPR
        !          1682:          || code == TRUTH_NOT_EXPR))
        !          1683:     {
        !          1684:       /* Here's when we can convert to a pointer.  */
        !          1685:       type = ptr_type_node;
        !          1686:       goto try_pointer;
        !          1687:     }
        !          1688: 
        !          1689:   /* THESE ARE TOTAL KLUDGES.  */
        !          1690:   /* Default promotion yields no new alternatives, try
        !          1691:      conversions which are anti-default, such as
        !          1692: 
        !          1693:      double -> float or int -> unsigned or unsigned -> long
        !          1694: 
        !          1695:      */
        !          1696:   if (type_default == type
        !          1697:       && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE))
        !          1698:     {
        !          1699:       int not_again = 0;
        !          1700: 
        !          1701:       if (type == double_type_node)
        !          1702:        typename = build_typename_overload (float_type_node);
        !          1703:       else if (type == integer_type_node)
        !          1704:        typename = build_typename_overload (unsigned_type_node);
        !          1705:       else if (type == unsigned_type_node)
        !          1706:        typename = build_typename_overload (long_integer_type_node);
        !          1707: 
        !          1708:     again:
        !          1709:       basetype = save_basetype;
        !          1710:       while (TYPE_HAS_CONVERSION (basetype))
        !          1711:        {
        !          1712:          if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
        !          1713:            return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1714:          if (TYPE_BINFO_BASETYPES (basetype))
        !          1715:            basetype = TYPE_BINFO_BASETYPE (basetype, 0);
        !          1716:          else
        !          1717:            break;
        !          1718:        }
        !          1719:       if (! not_again)
        !          1720:        {
        !          1721:          if (type == integer_type_node)
        !          1722:            {
        !          1723:              typename = build_typename_overload (long_integer_type_node);
        !          1724:              not_again = 1;
        !          1725:              goto again;
        !          1726:            }
        !          1727:          else
        !          1728:            {
        !          1729:              typename = build_typename_overload (integer_type_node);
        !          1730:              not_again = 1;
        !          1731:              goto again;
        !          1732:            }
        !          1733:        }
        !          1734:     }
        !          1735: 
        !          1736:   /* Now, try C promotions...
        !          1737: 
        !          1738:      float -> int
        !          1739:      int -> float, void *
        !          1740:      void * -> int
        !          1741: 
        !          1742:      Truthvalue conversions let us try to convert
        !          1743:      to pointer if we were going for int, and to int
        !          1744:      if we were looking for pointer.  */
        !          1745: 
        !          1746:     basetype = save_basetype;
        !          1747:     if (TREE_CODE (type) == REAL_TYPE
        !          1748:        || (TREE_CODE (type) == POINTER_TYPE
        !          1749:            && (code == TRUTH_ANDIF_EXPR
        !          1750:                || code == TRUTH_ORIF_EXPR
        !          1751:                || code == TRUTH_NOT_EXPR)))
        !          1752:       type = integer_type_node;
        !          1753:     else if (TREE_CODE (type) == INTEGER_TYPE)
        !          1754:       if (TYPE_HAS_REAL_CONVERSION (basetype))
        !          1755:        type = double_type_node;
        !          1756:       else
        !          1757:        return NULL_TREE;
        !          1758:     else
        !          1759:       return NULL_TREE;
        !          1760: 
        !          1761:     typename = build_typename_overload (type);
        !          1762:     while (TYPE_HAS_CONVERSION (basetype))
        !          1763:       {
        !          1764:        if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
        !          1765:          {
        !          1766:            rval = build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
        !          1767:            return rval;
        !          1768:          }
        !          1769:        if (TYPE_BINFO_BASETYPES (basetype))
        !          1770:          basetype = TYPE_BINFO_BASETYPE (basetype, 0);
        !          1771:        else
        !          1772:          break;
        !          1773:       }
        !          1774: 
        !          1775:   return NULL_TREE;
        !          1776: }
        !          1777: 
        !          1778: /* Must convert two aggregate types to non-aggregate type.
        !          1779:    Attempts to find a non-ambiguous, "best" type conversion.
        !          1780: 
        !          1781:    Return 1 on success, 0 on failure.
        !          1782: 
        !          1783:    @@ What are the real semantics of this supposed to be??? */
        !          1784: int
        !          1785: build_default_binary_type_conversion (code, arg1, arg2)
        !          1786:      enum tree_code code;
        !          1787:      tree *arg1, *arg2;
        !          1788: {
        !          1789:   tree type1 = TREE_TYPE (*arg1);
        !          1790:   tree type2 = TREE_TYPE (*arg2);
        !          1791:   char *name1, *name2;
        !          1792: 
        !          1793:   if (TREE_CODE (type1) == REFERENCE_TYPE
        !          1794:       || TREE_CODE (type1) == POINTER_TYPE)
        !          1795:     type1 = TREE_TYPE (type1);
        !          1796:   if (TREE_CODE (type2) == REFERENCE_TYPE
        !          1797:       || TREE_CODE (type2) == POINTER_TYPE)
        !          1798:     type2 = TREE_TYPE (type2);
        !          1799: 
        !          1800:   if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL)
        !          1801:     {
        !          1802:       tree decl = typedecl_for_tag (type1);
        !          1803:       if (decl)
        !          1804:        error ("type conversion nonexistent for type `%s'",
        !          1805:               IDENTIFIER_POINTER (DECL_NAME (decl)));
        !          1806:       else
        !          1807:        error ("type conversion nonexistent for non-C++ type");
        !          1808:       return 0;
        !          1809:     }
        !          1810:   if (TREE_CODE (TYPE_NAME (type2)) != TYPE_DECL)
        !          1811:     {
        !          1812:       tree decl = typedecl_for_tag (type2);
        !          1813:       if (decl)
        !          1814:        error ("type conversion nonexistent for type `%s'",
        !          1815:               IDENTIFIER_POINTER (decl));
        !          1816:       else
        !          1817:        error ("type conversion nonexistent for non-C++ type");
        !          1818:       return 0;
        !          1819:     }
        !          1820: 
        !          1821:   name1 = TYPE_NAME_STRING (type1);
        !          1822:   name2 = TYPE_NAME_STRING (type2);
        !          1823: 
        !          1824:   if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1))
        !          1825:     {
        !          1826:       if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
        !          1827:        error ("type conversion required for binary operation on types `%s' and `%s'",
        !          1828:               name1, name2);
        !          1829:       else
        !          1830:        error ("type conversion required for type `%s'", name1);
        !          1831:       return 0;
        !          1832:     }
        !          1833:   else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
        !          1834:     {
        !          1835:       error ("type conversion required for type `%s'", name2);
        !          1836:       return 0;
        !          1837:     }
        !          1838: 
        !          1839:   if (TYPE_HAS_INT_CONVERSION (type1) && TYPE_HAS_REAL_CONVERSION (type1))
        !          1840:     warning ("ambiguous type conversion for type `%s', defaulting to int", name1);
        !          1841:   if (TYPE_HAS_INT_CONVERSION (type1))
        !          1842:     {
        !          1843:       *arg1 = build_type_conversion (code, integer_type_node, *arg1, 1);
        !          1844:       *arg2 = build_type_conversion (code, integer_type_node, *arg2, 1);
        !          1845:     }
        !          1846:   else if (TYPE_HAS_REAL_CONVERSION (type1))
        !          1847:     {
        !          1848:       *arg1 = build_type_conversion (code, double_type_node, *arg1, 1);
        !          1849:       *arg2 = build_type_conversion (code, double_type_node, *arg2, 1);
        !          1850:     }
        !          1851:   else
        !          1852:     {
        !          1853:       *arg1 = build_type_conversion (code, ptr_type_node, *arg1, 1);
        !          1854:       if (*arg1 == error_mark_node)
        !          1855:        error ("ambiguous pointer conversion");
        !          1856:       *arg2 = build_type_conversion (code, ptr_type_node, *arg2, 1);
        !          1857:       if (*arg1 != error_mark_node && *arg2 == error_mark_node)
        !          1858:        error ("ambiguous pointer conversion");
        !          1859:     }
        !          1860:   if (*arg1 == 0)
        !          1861:     {
        !          1862:       if (*arg2 == 0 && type1 != type2)
        !          1863:        error ("default type conversion for types `%s' and `%s' failed",
        !          1864:               name1, name2);
        !          1865:       else
        !          1866:        error ("default type conversion for type `%s' failed", name1);
        !          1867:       return 0;
        !          1868:     }
        !          1869:   else if (*arg2 == 0)
        !          1870:     {
        !          1871:       error ("default type conversion for type `%s' failed", name2);
        !          1872:       return 0;
        !          1873:     }
        !          1874:   return 1;
        !          1875: }
        !          1876: 
        !          1877: /* Must convert two aggregate types to non-aggregate type.
        !          1878:    Attempts to find a non-ambiguous, "best" type conversion.
        !          1879: 
        !          1880:    Return 1 on success, 0 on failure.
        !          1881: 
        !          1882:    The type of the argument is expected to be of aggregate type here.
        !          1883: 
        !          1884:    @@ What are the real semantics of this supposed to be??? */
        !          1885: int
        !          1886: build_default_unary_type_conversion (code, arg)
        !          1887:      enum tree_code code;
        !          1888:      tree *arg;
        !          1889: {
        !          1890:   tree type = TREE_TYPE (*arg);
        !          1891:   tree id = TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
        !          1892:     ? TYPE_IDENTIFIER (type) : TYPE_NAME (type);
        !          1893:   char *name = IDENTIFIER_POINTER (id);
        !          1894: 
        !          1895:   if (! TYPE_HAS_CONVERSION (type))
        !          1896:     {
        !          1897:       error ("type conversion required for type `%s'", name);
        !          1898:       return 0;
        !          1899:     }
        !          1900: 
        !          1901:   if (TYPE_HAS_INT_CONVERSION (type) && TYPE_HAS_REAL_CONVERSION (type))
        !          1902:     warning ("ambiguous type conversion for type `%s', defaulting to int",
        !          1903:             name);
        !          1904:   if (TYPE_HAS_INT_CONVERSION (type))
        !          1905:     *arg = build_type_conversion (code, integer_type_node, *arg, 1);
        !          1906:   else if (TYPE_HAS_REAL_CONVERSION (type))
        !          1907:     *arg = build_type_conversion (code, double_type_node, *arg, 1);
        !          1908:   else
        !          1909:     {
        !          1910:       *arg = build_type_conversion (code, ptr_type_node, *arg, 1);
        !          1911:       if (*arg == error_mark_node)
        !          1912:        error ("ambiguous pointer conversion");
        !          1913:     }
        !          1914:   if (*arg == NULL_TREE)
        !          1915:     {
        !          1916:       error ("default type conversion for type `%s' failed", name);
        !          1917:       return 0;
        !          1918:     }
        !          1919:   return 1;
        !          1920: }

unix.superglobalmegacorp.com

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