Home | History | Annotate | Line # | Download | only in dmd
      1  1.1  mrg /**
      2  1.1  mrg  * Semantic analysis for cast-expressions.
      3  1.1  mrg  *
      4  1.1  mrg  * Copyright:   Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
      5  1.1  mrg  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
      6  1.1  mrg  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
      7  1.1  mrg  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d)
      8  1.1  mrg  * Documentation:  https://dlang.org/phobos/dmd_dcast.html
      9  1.1  mrg  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dcast.d
     10  1.1  mrg  */
     11  1.1  mrg 
     12  1.1  mrg module dmd.dcast;
     13  1.1  mrg 
     14  1.1  mrg import core.stdc.stdio;
     15  1.1  mrg import core.stdc.string;
     16  1.1  mrg import dmd.aggregate;
     17  1.1  mrg import dmd.aliasthis;
     18  1.1  mrg import dmd.arrayop;
     19  1.1  mrg import dmd.arraytypes;
     20  1.1  mrg import dmd.astenums;
     21  1.1  mrg import dmd.dclass;
     22  1.1  mrg import dmd.declaration;
     23  1.1  mrg import dmd.dscope;
     24  1.1  mrg import dmd.dstruct;
     25  1.1  mrg import dmd.dsymbol;
     26  1.1  mrg import dmd.errors;
     27  1.1  mrg import dmd.escape;
     28  1.1  mrg import dmd.expression;
     29  1.1  mrg import dmd.expressionsem;
     30  1.1  mrg import dmd.func;
     31  1.1  mrg import dmd.globals;
     32  1.1  mrg import dmd.hdrgen;
     33  1.1  mrg import dmd.impcnvtab;
     34  1.1  mrg import dmd.id;
     35  1.1  mrg import dmd.importc;
     36  1.1  mrg import dmd.init;
     37  1.1  mrg import dmd.intrange;
     38  1.1  mrg import dmd.mtype;
     39  1.1  mrg import dmd.opover;
     40  1.1  mrg import dmd.root.ctfloat;
     41  1.1  mrg import dmd.common.outbuffer;
     42  1.1  mrg import dmd.root.rmem;
     43  1.1  mrg import dmd.root.utf;
     44  1.1  mrg import dmd.tokens;
     45  1.1  mrg import dmd.typesem;
     46  1.1  mrg import dmd.visitor;
     47  1.1  mrg 
     48  1.1  mrg enum LOG = false;
     49  1.1  mrg 
     50  1.1  mrg /**
     51  1.1  mrg  * Attempt to implicitly cast the expression into type `t`.
     52  1.1  mrg  *
     53  1.1  mrg  * This routine will change `e`. To check the matching level,
     54  1.1  mrg  * use `implicitConvTo`.
     55  1.1  mrg  *
     56  1.1  mrg  * Params:
     57  1.1  mrg  *   e = Expression that is to be casted
     58  1.1  mrg  *   sc = Current scope
     59  1.1  mrg  *   t = Expected resulting type
     60  1.1  mrg  *
     61  1.1  mrg  * Returns:
     62  1.1  mrg  *   The resulting casted expression (mutating `e`), or `ErrorExp`
     63  1.1  mrg  *    if such an implicit conversion is not possible.
     64  1.1  mrg  */
     65  1.1  mrg Expression implicitCastTo(Expression e, Scope* sc, Type t)
     66  1.1  mrg {
     67  1.1  mrg     Expression visit(Expression e)
     68  1.1  mrg     {
     69  1.1  mrg         //printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
     70  1.1  mrg 
     71  1.1  mrg         if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t))
     72  1.1  mrg         {
     73  1.1  mrg             if (match == MATCH.constant && (e.type.constConv(t) || !e.isLvalue() && e.type.equivalent(t)))
     74  1.1  mrg             {
     75  1.1  mrg                 /* Do not emit CastExp for const conversions and
     76  1.1  mrg                  * unique conversions on rvalue.
     77  1.1  mrg                  */
     78  1.1  mrg                 auto result = e.copy();
     79  1.1  mrg                 result.type = t;
     80  1.1  mrg                 return result;
     81  1.1  mrg             }
     82  1.1  mrg 
     83  1.1  mrg             auto ad = isAggregate(e.type);
     84  1.1  mrg             if (ad && ad.aliasthis)
     85  1.1  mrg             {
     86  1.1  mrg                 auto ts = ad.type.isTypeStruct();
     87  1.1  mrg                 const adMatch = ts
     88  1.1  mrg                     ? ts.implicitConvToWithoutAliasThis(t)
     89  1.1  mrg                     : ad.type.isTypeClass().implicitConvToWithoutAliasThis(t);
     90  1.1  mrg 
     91  1.1  mrg                 if (!adMatch)
     92  1.1  mrg                 {
     93  1.1  mrg                     Type tob = t.toBasetype();
     94  1.1  mrg                     Type t1b = e.type.toBasetype();
     95  1.1  mrg                     if (ad != isAggregate(tob))
     96  1.1  mrg                     {
     97  1.1  mrg                         if (t1b.ty == Tclass && tob.ty == Tclass)
     98  1.1  mrg                         {
     99  1.1  mrg                             ClassDeclaration t1cd = t1b.isClassHandle();
    100  1.1  mrg                             ClassDeclaration tocd = tob.isClassHandle();
    101  1.1  mrg                             int offset;
    102  1.1  mrg                             if (tocd.isBaseOf(t1cd, &offset))
    103  1.1  mrg                             {
    104  1.1  mrg                                 auto result = new CastExp(e.loc, e, t);
    105  1.1  mrg                                 result.type = t;
    106  1.1  mrg                                 return result;
    107  1.1  mrg                             }
    108  1.1  mrg                         }
    109  1.1  mrg 
    110  1.1  mrg                         /* Forward the cast to our alias this member, rewrite to:
    111  1.1  mrg                          *   cast(to)e1.aliasthis
    112  1.1  mrg                          */
    113  1.1  mrg                         auto result = resolveAliasThis(sc, e);
    114  1.1  mrg                         return result.castTo(sc, t);
    115  1.1  mrg                    }
    116  1.1  mrg                 }
    117  1.1  mrg             }
    118  1.1  mrg 
    119  1.1  mrg             return e.castTo(sc, t);
    120  1.1  mrg         }
    121  1.1  mrg 
    122  1.1  mrg         auto result = e.optimize(WANTvalue);
    123  1.1  mrg         if (result != e)
    124  1.1  mrg         {
    125  1.1  mrg             return implicitCastTo(result, sc, t);
    126  1.1  mrg         }
    127  1.1  mrg 
    128  1.1  mrg         if (t.ty != Terror && e.type.ty != Terror)
    129  1.1  mrg         {
    130  1.1  mrg             if (!t.deco)
    131  1.1  mrg             {
    132  1.1  mrg                 e.error("forward reference to type `%s`", t.toChars());
    133  1.1  mrg             }
    134  1.1  mrg             else
    135  1.1  mrg             {
    136  1.1  mrg                 //printf("type %p ty %d deco %p\n", type, type.ty, type.deco);
    137  1.1  mrg                 //type = type.typeSemantic(loc, sc);
    138  1.1  mrg                 //printf("type %s t %s\n", type.deco, t.deco);
    139  1.1  mrg                 auto ts = toAutoQualChars(e.type, t);
    140  1.1  mrg                 e.error("cannot implicitly convert expression `%s` of type `%s` to `%s`",
    141  1.1  mrg                     e.toChars(), ts[0], ts[1]);
    142  1.1  mrg             }
    143  1.1  mrg         }
    144  1.1  mrg         return ErrorExp.get();
    145  1.1  mrg     }
    146  1.1  mrg 
    147  1.1  mrg     Expression visitString(StringExp e)
    148  1.1  mrg     {
    149  1.1  mrg         //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
    150  1.1  mrg         auto result = visit(e);
    151  1.1  mrg         if (auto se = result.isStringExp())
    152  1.1  mrg         {
    153  1.1  mrg             // Retain polysemous nature if it started out that way
    154  1.1  mrg             se.committed = e.committed;
    155  1.1  mrg         }
    156  1.1  mrg         return result;
    157  1.1  mrg     }
    158  1.1  mrg 
    159  1.1  mrg     Expression visitError(ErrorExp e)
    160  1.1  mrg     {
    161  1.1  mrg         return e;
    162  1.1  mrg     }
    163  1.1  mrg 
    164  1.1  mrg     Expression visitFunc(FuncExp e)
    165  1.1  mrg     {
    166  1.1  mrg         //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
    167  1.1  mrg         FuncExp fe;
    168  1.1  mrg         if (e.matchType(t, sc, &fe) > MATCH.nomatch)
    169  1.1  mrg         {
    170  1.1  mrg             return fe;
    171  1.1  mrg         }
    172  1.1  mrg         return visit(e);
    173  1.1  mrg     }
    174  1.1  mrg 
    175  1.1  mrg     Expression visitArrayLiteral(ArrayLiteralExp e)
    176  1.1  mrg     {
    177  1.1  mrg         auto result = visit(e);
    178  1.1  mrg 
    179  1.1  mrg         Type tb = result.type.toBasetype();
    180  1.1  mrg         if (auto ta = tb.isTypeDArray())
    181  1.1  mrg             if (global.params.useTypeInfo && Type.dtypeinfo)
    182  1.1  mrg                 semanticTypeInfo(sc, ta.next);
    183  1.1  mrg         return result;
    184  1.1  mrg     }
    185  1.1  mrg 
    186  1.1  mrg     Expression visitSlice(SliceExp e)
    187  1.1  mrg     {
    188  1.1  mrg         auto result = visit(e);
    189  1.1  mrg 
    190  1.1  mrg         if (auto se = result.isSliceExp())
    191  1.1  mrg             if (auto ale = se.e1.isArrayLiteralExp())
    192  1.1  mrg             {
    193  1.1  mrg                 Type tb = t.toBasetype();
    194  1.1  mrg                 Type tx = (tb.ty == Tsarray)
    195  1.1  mrg                     ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.dim : 0)
    196  1.1  mrg                     : tb.nextOf().arrayOf();
    197  1.1  mrg                 se.e1 = ale.implicitCastTo(sc, tx);
    198  1.1  mrg             }
    199  1.1  mrg 
    200  1.1  mrg         return result;
    201  1.1  mrg     }
    202  1.1  mrg 
    203  1.1  mrg     switch (e.op)
    204  1.1  mrg     {
    205  1.1  mrg         default              : return visit            (e);
    206  1.1  mrg         case EXP.string_     : return visitString      (e.isStringExp());
    207  1.1  mrg         case EXP.error       : return visitError       (e.isErrorExp());
    208  1.1  mrg         case EXP.function_   : return visitFunc        (e.isFuncExp());
    209  1.1  mrg         case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
    210  1.1  mrg         case EXP.slice       : return visitSlice       (e.isSliceExp());
    211  1.1  mrg     }
    212  1.1  mrg }
    213  1.1  mrg 
    214  1.1  mrg /**
    215  1.1  mrg  * Checks whether or not an expression can be implicitly converted
    216  1.1  mrg  * to type `t`.
    217  1.1  mrg  *
    218  1.1  mrg  * Unlike `implicitCastTo`, this routine does not perform the actual cast,
    219  1.1  mrg  * but only checks up to what `MATCH` level the conversion would be possible.
    220  1.1  mrg  *
    221  1.1  mrg  * Params:
    222  1.1  mrg  *   e = Expression that is to be casted
    223  1.1  mrg  *   t = Expected resulting type
    224  1.1  mrg  *
    225  1.1  mrg  * Returns:
    226  1.1  mrg  *   The `MATCH` level between `e.type` and `t`.
    227  1.1  mrg  */
    228  1.1  mrg MATCH implicitConvTo(Expression e, Type t)
    229  1.1  mrg {
    230  1.1  mrg     MATCH visit(Expression e)
    231  1.1  mrg     {
    232  1.1  mrg         version (none)
    233  1.1  mrg         {
    234  1.1  mrg             printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    235  1.1  mrg         }
    236  1.1  mrg         //static int nest; if (++nest == 10) assert(0);
    237  1.1  mrg         if (t == Type.terror)
    238  1.1  mrg             return MATCH.nomatch;
    239  1.1  mrg         if (!e.type)
    240  1.1  mrg         {
    241  1.1  mrg             e.error("`%s` is not an expression", e.toChars());
    242  1.1  mrg             e.type = Type.terror;
    243  1.1  mrg         }
    244  1.1  mrg 
    245  1.1  mrg         Expression ex = e.optimize(WANTvalue);
    246  1.1  mrg         if (ex.type.equals(t))
    247  1.1  mrg         {
    248  1.1  mrg             return MATCH.exact;
    249  1.1  mrg         }
    250  1.1  mrg         if (ex != e)
    251  1.1  mrg         {
    252  1.1  mrg             //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars());
    253  1.1  mrg             return ex.implicitConvTo(t);
    254  1.1  mrg         }
    255  1.1  mrg 
    256  1.1  mrg         MATCH match = e.type.implicitConvTo(t);
    257  1.1  mrg         if (match != MATCH.nomatch)
    258  1.1  mrg         {
    259  1.1  mrg             return match;
    260  1.1  mrg         }
    261  1.1  mrg 
    262  1.1  mrg         /* See if we can do integral narrowing conversions
    263  1.1  mrg          */
    264  1.1  mrg         if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic())
    265  1.1  mrg         {
    266  1.1  mrg             IntRange src = getIntRange(e);
    267  1.1  mrg             IntRange target = IntRange.fromType(t);
    268  1.1  mrg             if (target.contains(src))
    269  1.1  mrg             {
    270  1.1  mrg                 return MATCH.convert;
    271  1.1  mrg             }
    272  1.1  mrg         }
    273  1.1  mrg         return MATCH.nomatch;
    274  1.1  mrg     }
    275  1.1  mrg 
    276  1.1  mrg     /******
    277  1.1  mrg      * Given expression e of type t, see if we can implicitly convert e
    278  1.1  mrg      * to type tprime, where tprime is type t with mod bits added.
    279  1.1  mrg      * Returns:
    280  1.1  mrg      *      match level
    281  1.1  mrg      */
    282  1.1  mrg     static MATCH implicitMod(Expression e, Type t, MOD mod)
    283  1.1  mrg     {
    284  1.1  mrg         Type tprime;
    285  1.1  mrg         if (t.ty == Tpointer)
    286  1.1  mrg             tprime = t.nextOf().castMod(mod).pointerTo();
    287  1.1  mrg         else if (t.ty == Tarray)
    288  1.1  mrg             tprime = t.nextOf().castMod(mod).arrayOf();
    289  1.1  mrg         else if (t.ty == Tsarray)
    290  1.1  mrg             tprime = t.nextOf().castMod(mod).sarrayOf(t.size() / t.nextOf().size());
    291  1.1  mrg         else
    292  1.1  mrg             tprime = t.castMod(mod);
    293  1.1  mrg 
    294  1.1  mrg         return e.implicitConvTo(tprime);
    295  1.1  mrg     }
    296  1.1  mrg 
    297  1.1  mrg     static MATCH implicitConvToAddMin(BinExp e, Type t)
    298  1.1  mrg     {
    299  1.1  mrg         /* Is this (ptr +- offset)? If so, then ask ptr
    300  1.1  mrg          * if the conversion can be done.
    301  1.1  mrg          * This is to support doing things like implicitly converting a mutable unique
    302  1.1  mrg          * pointer to an immutable pointer.
    303  1.1  mrg          */
    304  1.1  mrg 
    305  1.1  mrg         Type tb = t.toBasetype();
    306  1.1  mrg         Type typeb = e.type.toBasetype();
    307  1.1  mrg 
    308  1.1  mrg         if (typeb.ty != Tpointer || tb.ty != Tpointer)
    309  1.1  mrg             return MATCH.nomatch;
    310  1.1  mrg 
    311  1.1  mrg         Type t1b = e.e1.type.toBasetype();
    312  1.1  mrg         Type t2b = e.e2.type.toBasetype();
    313  1.1  mrg         if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb))
    314  1.1  mrg         {
    315  1.1  mrg             // ptr + offset
    316  1.1  mrg             // ptr - offset
    317  1.1  mrg             MATCH m = e.e1.implicitConvTo(t);
    318  1.1  mrg             return (m > MATCH.constant) ? MATCH.constant : m;
    319  1.1  mrg         }
    320  1.1  mrg         if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb))
    321  1.1  mrg         {
    322  1.1  mrg             // offset + ptr
    323  1.1  mrg             MATCH m = e.e2.implicitConvTo(t);
    324  1.1  mrg             return (m > MATCH.constant) ? MATCH.constant : m;
    325  1.1  mrg         }
    326  1.1  mrg 
    327  1.1  mrg         return MATCH.nomatch;
    328  1.1  mrg     }
    329  1.1  mrg 
    330  1.1  mrg     MATCH visitAdd(AddExp e)
    331  1.1  mrg     {
    332  1.1  mrg         version (none)
    333  1.1  mrg         {
    334  1.1  mrg             printf("AddExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    335  1.1  mrg         }
    336  1.1  mrg         auto result = visit(e);
    337  1.1  mrg         if (result == MATCH.nomatch)
    338  1.1  mrg             result = implicitConvToAddMin(e, t);
    339  1.1  mrg         return result;
    340  1.1  mrg     }
    341  1.1  mrg 
    342  1.1  mrg     MATCH visitMin(MinExp e)
    343  1.1  mrg     {
    344  1.1  mrg         version (none)
    345  1.1  mrg         {
    346  1.1  mrg             printf("MinExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    347  1.1  mrg         }
    348  1.1  mrg         auto result = visit(e);
    349  1.1  mrg         if (result == MATCH.nomatch)
    350  1.1  mrg             result = implicitConvToAddMin(e, t);
    351  1.1  mrg         return result;
    352  1.1  mrg     }
    353  1.1  mrg 
    354  1.1  mrg     MATCH visitInteger(IntegerExp e)
    355  1.1  mrg     {
    356  1.1  mrg         version (none)
    357  1.1  mrg         {
    358  1.1  mrg             printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    359  1.1  mrg         }
    360  1.1  mrg         MATCH m = e.type.implicitConvTo(t);
    361  1.1  mrg         if (m >= MATCH.constant)
    362  1.1  mrg         {
    363  1.1  mrg             return m;
    364  1.1  mrg         }
    365  1.1  mrg 
    366  1.1  mrg         TY ty = e.type.toBasetype().ty;
    367  1.1  mrg         TY toty = t.toBasetype().ty;
    368  1.1  mrg         TY oldty = ty;
    369  1.1  mrg 
    370  1.1  mrg         if (m == MATCH.nomatch && t.ty == Tenum)
    371  1.1  mrg             return MATCH.nomatch;
    372  1.1  mrg 
    373  1.1  mrg         if (auto tv = t.isTypeVector())
    374  1.1  mrg         {
    375  1.1  mrg             TypeBasic tb = tv.elementType();
    376  1.1  mrg             if (tb.ty == Tvoid)
    377  1.1  mrg                 return MATCH.nomatch;
    378  1.1  mrg             toty = tb.ty;
    379  1.1  mrg         }
    380  1.1  mrg 
    381  1.1  mrg         switch (ty)
    382  1.1  mrg         {
    383  1.1  mrg         case Tbool:
    384  1.1  mrg         case Tint8:
    385  1.1  mrg         case Tchar:
    386  1.1  mrg         case Tuns8:
    387  1.1  mrg         case Tint16:
    388  1.1  mrg         case Tuns16:
    389  1.1  mrg         case Twchar:
    390  1.1  mrg             ty = Tint32;
    391  1.1  mrg             break;
    392  1.1  mrg 
    393  1.1  mrg         case Tdchar:
    394  1.1  mrg             ty = Tuns32;
    395  1.1  mrg             break;
    396  1.1  mrg 
    397  1.1  mrg         default:
    398  1.1  mrg             break;
    399  1.1  mrg         }
    400  1.1  mrg 
    401  1.1  mrg         // Only allow conversion if no change in value
    402  1.1  mrg         immutable dinteger_t value = e.toInteger();
    403  1.1  mrg 
    404  1.1  mrg         bool isLosslesslyConvertibleToFP(T)()
    405  1.1  mrg         {
    406  1.1  mrg             if (e.type.isunsigned())
    407  1.1  mrg             {
    408  1.1  mrg                 const f = cast(T) value;
    409  1.1  mrg                 return cast(dinteger_t) f == value;
    410  1.1  mrg             }
    411  1.1  mrg 
    412  1.1  mrg             const f = cast(T) cast(sinteger_t) value;
    413  1.1  mrg             return cast(sinteger_t) f == cast(sinteger_t) value;
    414  1.1  mrg         }
    415  1.1  mrg 
    416  1.1  mrg         switch (toty)
    417  1.1  mrg         {
    418  1.1  mrg         case Tbool:
    419  1.1  mrg             if ((value & 1) != value)
    420  1.1  mrg                 return MATCH.nomatch;
    421  1.1  mrg             break;
    422  1.1  mrg 
    423  1.1  mrg         case Tint8:
    424  1.1  mrg             if (ty == Tuns64 && value & ~0x7FU)
    425  1.1  mrg                 return MATCH.nomatch;
    426  1.1  mrg             else if (cast(byte)value != value)
    427  1.1  mrg                 return MATCH.nomatch;
    428  1.1  mrg             break;
    429  1.1  mrg 
    430  1.1  mrg         case Tchar:
    431  1.1  mrg             if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
    432  1.1  mrg                 return MATCH.nomatch;
    433  1.1  mrg             goto case Tuns8;
    434  1.1  mrg         case Tuns8:
    435  1.1  mrg             //printf("value = %llu %llu\n", cast(dinteger_t)cast(ubyte)value, value);
    436  1.1  mrg             if (cast(ubyte)value != value)
    437  1.1  mrg                 return MATCH.nomatch;
    438  1.1  mrg             break;
    439  1.1  mrg 
    440  1.1  mrg         case Tint16:
    441  1.1  mrg             if (ty == Tuns64 && value & ~0x7FFFU)
    442  1.1  mrg                 return MATCH.nomatch;
    443  1.1  mrg             else if (cast(short)value != value)
    444  1.1  mrg                 return MATCH.nomatch;
    445  1.1  mrg             break;
    446  1.1  mrg 
    447  1.1  mrg         case Twchar:
    448  1.1  mrg             if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
    449  1.1  mrg                 return MATCH.nomatch;
    450  1.1  mrg             goto case Tuns16;
    451  1.1  mrg         case Tuns16:
    452  1.1  mrg             if (cast(ushort)value != value)
    453  1.1  mrg                 return MATCH.nomatch;
    454  1.1  mrg             break;
    455  1.1  mrg 
    456  1.1  mrg         case Tint32:
    457  1.1  mrg             if (ty == Tuns32)
    458  1.1  mrg             {
    459  1.1  mrg             }
    460  1.1  mrg             else if (ty == Tuns64 && value & ~0x7FFFFFFFU)
    461  1.1  mrg                 return MATCH.nomatch;
    462  1.1  mrg             else if (cast(int)value != value)
    463  1.1  mrg                 return MATCH.nomatch;
    464  1.1  mrg             break;
    465  1.1  mrg 
    466  1.1  mrg         case Tuns32:
    467  1.1  mrg             if (ty == Tint32)
    468  1.1  mrg             {
    469  1.1  mrg             }
    470  1.1  mrg             else if (cast(uint)value != value)
    471  1.1  mrg                 return MATCH.nomatch;
    472  1.1  mrg             break;
    473  1.1  mrg 
    474  1.1  mrg         case Tdchar:
    475  1.1  mrg             if (value > 0x10FFFFU)
    476  1.1  mrg                 return MATCH.nomatch;
    477  1.1  mrg             break;
    478  1.1  mrg 
    479  1.1  mrg         case Tfloat32:
    480  1.1  mrg             if (!isLosslesslyConvertibleToFP!float)
    481  1.1  mrg                 return MATCH.nomatch;
    482  1.1  mrg             break;
    483  1.1  mrg 
    484  1.1  mrg         case Tfloat64:
    485  1.1  mrg             if (!isLosslesslyConvertibleToFP!double)
    486  1.1  mrg                 return MATCH.nomatch;
    487  1.1  mrg             break;
    488  1.1  mrg 
    489  1.1  mrg         case Tfloat80:
    490  1.1  mrg             if (!isLosslesslyConvertibleToFP!real_t)
    491  1.1  mrg                 return MATCH.nomatch;
    492  1.1  mrg             break;
    493  1.1  mrg 
    494  1.1  mrg         case Tpointer:
    495  1.1  mrg             //printf("type = %s\n", type.toBasetype().toChars());
    496  1.1  mrg             //printf("t = %s\n", t.toBasetype().toChars());
    497  1.1  mrg             if (ty == Tpointer && e.type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty)
    498  1.1  mrg             {
    499  1.1  mrg                 /* Allow things like:
    500  1.1  mrg                  *      const char* P = cast(char *)3;
    501  1.1  mrg                  *      char* q = P;
    502  1.1  mrg                  */
    503  1.1  mrg                 break;
    504  1.1  mrg             }
    505  1.1  mrg             goto default;
    506  1.1  mrg 
    507  1.1  mrg         default:
    508  1.1  mrg             return visit(e);
    509  1.1  mrg         }
    510  1.1  mrg 
    511  1.1  mrg         //printf("MATCH.convert\n");
    512  1.1  mrg         return MATCH.convert;
    513  1.1  mrg     }
    514  1.1  mrg 
    515  1.1  mrg     MATCH visitError(ErrorExp e)
    516  1.1  mrg     {
    517  1.1  mrg         return MATCH.nomatch;
    518  1.1  mrg     }
    519  1.1  mrg 
    520  1.1  mrg     MATCH visitNull(NullExp e)
    521  1.1  mrg     {
    522  1.1  mrg         version (none)
    523  1.1  mrg         {
    524  1.1  mrg             printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    525  1.1  mrg         }
    526  1.1  mrg         if (e.type.equals(t))
    527  1.1  mrg         {
    528  1.1  mrg             return MATCH.exact;
    529  1.1  mrg         }
    530  1.1  mrg 
    531  1.1  mrg         /* Allow implicit conversions from immutable to mutable|const,
    532  1.1  mrg          * and mutable to immutable. It works because, after all, a null
    533  1.1  mrg          * doesn't actually point to anything.
    534  1.1  mrg          */
    535  1.1  mrg         if (t.equivalent(e.type))
    536  1.1  mrg         {
    537  1.1  mrg             return MATCH.constant;
    538  1.1  mrg         }
    539  1.1  mrg 
    540  1.1  mrg         return visit(e);
    541  1.1  mrg     }
    542  1.1  mrg 
    543  1.1  mrg     MATCH visitStructLiteral(StructLiteralExp e)
    544  1.1  mrg     {
    545  1.1  mrg         version (none)
    546  1.1  mrg         {
    547  1.1  mrg             printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    548  1.1  mrg         }
    549  1.1  mrg         auto result = visit(e);
    550  1.1  mrg         if (result != MATCH.nomatch)
    551  1.1  mrg             return result;
    552  1.1  mrg         if (e.type.ty == t.ty && e.type.isTypeStruct() && e.type.isTypeStruct().sym == t.isTypeStruct().sym)
    553  1.1  mrg         {
    554  1.1  mrg             result = MATCH.constant;
    555  1.1  mrg             foreach (i, el; (*e.elements)[])
    556  1.1  mrg             {
    557  1.1  mrg                 if (!el)
    558  1.1  mrg                     continue;
    559  1.1  mrg                 Type te = e.sd.fields[i].type.addMod(t.mod);
    560  1.1  mrg                 MATCH m2 = el.implicitConvTo(te);
    561  1.1  mrg                 //printf("\t%s => %s, match = %d\n", el.toChars(), te.toChars(), m2);
    562  1.1  mrg                 if (m2 < result)
    563  1.1  mrg                     result = m2;
    564  1.1  mrg             }
    565  1.1  mrg         }
    566  1.1  mrg         return result;
    567  1.1  mrg     }
    568  1.1  mrg 
    569  1.1  mrg     MATCH visitString(StringExp e)
    570  1.1  mrg     {
    571  1.1  mrg         version (none)
    572  1.1  mrg         {
    573  1.1  mrg             printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", e.toChars(), e.committed, e.type.toChars(), t.toChars());
    574  1.1  mrg         }
    575  1.1  mrg         if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
    576  1.1  mrg             return MATCH.nomatch;
    577  1.1  mrg 
    578  1.1  mrg         if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
    579  1.1  mrg             return visit(e);
    580  1.1  mrg 
    581  1.1  mrg         TY tyn = e.type.nextOf().ty;
    582  1.1  mrg 
    583  1.1  mrg         if (!tyn.isSomeChar)
    584  1.1  mrg             return visit(e);
    585  1.1  mrg 
    586  1.1  mrg         switch (t.ty)
    587  1.1  mrg         {
    588  1.1  mrg         case Tsarray:
    589  1.1  mrg             if (e.type.ty == Tsarray)
    590  1.1  mrg             {
    591  1.1  mrg                 TY tynto = t.nextOf().ty;
    592  1.1  mrg                 if (tynto == tyn)
    593  1.1  mrg                 {
    594  1.1  mrg                     if (e.type.isTypeSArray().dim.toInteger() == t.isTypeSArray().dim.toInteger())
    595  1.1  mrg                     {
    596  1.1  mrg                         return MATCH.exact;
    597  1.1  mrg                     }
    598  1.1  mrg                     return MATCH.nomatch;
    599  1.1  mrg                 }
    600  1.1  mrg                 if (tynto.isSomeChar)
    601  1.1  mrg                 {
    602  1.1  mrg                     if (e.committed && tynto != tyn)
    603  1.1  mrg                         return MATCH.nomatch;
    604  1.1  mrg                     size_t fromlen = e.numberOfCodeUnits(tynto);
    605  1.1  mrg                     size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
    606  1.1  mrg                     if (tolen < fromlen)
    607  1.1  mrg                         return MATCH.nomatch;
    608  1.1  mrg                     if (tolen != fromlen)
    609  1.1  mrg                     {
    610  1.1  mrg                         // implicit length extending
    611  1.1  mrg                         return MATCH.convert;
    612  1.1  mrg                     }
    613  1.1  mrg                 }
    614  1.1  mrg                 if (!e.committed && tynto.isSomeChar)
    615  1.1  mrg                 {
    616  1.1  mrg                     return MATCH.exact;
    617  1.1  mrg                 }
    618  1.1  mrg             }
    619  1.1  mrg             else if (e.type.ty == Tarray)
    620  1.1  mrg             {
    621  1.1  mrg                 TY tynto = t.nextOf().ty;
    622  1.1  mrg                 if (tynto.isSomeChar)
    623  1.1  mrg                 {
    624  1.1  mrg                     if (e.committed && tynto != tyn)
    625  1.1  mrg                         return MATCH.nomatch;
    626  1.1  mrg                     size_t fromlen = e.numberOfCodeUnits(tynto);
    627  1.1  mrg                     size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
    628  1.1  mrg                     if (tolen < fromlen)
    629  1.1  mrg                         return MATCH.nomatch;
    630  1.1  mrg                     if (tolen != fromlen)
    631  1.1  mrg                     {
    632  1.1  mrg                         // implicit length extending
    633  1.1  mrg                         return MATCH.convert;
    634  1.1  mrg                     }
    635  1.1  mrg                 }
    636  1.1  mrg                 if (tynto == tyn)
    637  1.1  mrg                 {
    638  1.1  mrg                     return MATCH.exact;
    639  1.1  mrg                 }
    640  1.1  mrg                 if (!e.committed && tynto.isSomeChar)
    641  1.1  mrg                 {
    642  1.1  mrg                     return MATCH.exact;
    643  1.1  mrg                 }
    644  1.1  mrg             }
    645  1.1  mrg             goto case; /+ fall through +/
    646  1.1  mrg         case Tarray:
    647  1.1  mrg         case Tpointer:
    648  1.1  mrg             Type tn = t.nextOf();
    649  1.1  mrg             MATCH m = MATCH.exact;
    650  1.1  mrg             if (e.type.nextOf().mod != tn.mod)
    651  1.1  mrg             {
    652  1.1  mrg                 // https://issues.dlang.org/show_bug.cgi?id=16183
    653  1.1  mrg                 if (!tn.isConst() && !tn.isImmutable())
    654  1.1  mrg                     return MATCH.nomatch;
    655  1.1  mrg                 m = MATCH.constant;
    656  1.1  mrg             }
    657  1.1  mrg             if (!e.committed)
    658  1.1  mrg             {
    659  1.1  mrg                 switch (tn.ty)
    660  1.1  mrg                 {
    661  1.1  mrg                 case Tchar:
    662  1.1  mrg                     if (e.postfix == 'w' || e.postfix == 'd')
    663  1.1  mrg                         m = MATCH.convert;
    664  1.1  mrg                     return m;
    665  1.1  mrg                 case Twchar:
    666  1.1  mrg                     if (e.postfix != 'w')
    667  1.1  mrg                         m = MATCH.convert;
    668  1.1  mrg                     return m;
    669  1.1  mrg                 case Tdchar:
    670  1.1  mrg                     if (e.postfix != 'd')
    671  1.1  mrg                         m = MATCH.convert;
    672  1.1  mrg                     return m;
    673  1.1  mrg                 case Tenum:
    674  1.1  mrg                     if (tn.isTypeEnum().sym.isSpecial())
    675  1.1  mrg                     {
    676  1.1  mrg                         /* Allow string literal -> const(wchar_t)[]
    677  1.1  mrg                          */
    678  1.1  mrg                         if (TypeBasic tob = tn.toBasetype().isTypeBasic())
    679  1.1  mrg                         return tn.implicitConvTo(tob);
    680  1.1  mrg                     }
    681  1.1  mrg                     break;
    682  1.1  mrg                 default:
    683  1.1  mrg                     break;
    684  1.1  mrg                 }
    685  1.1  mrg             }
    686  1.1  mrg             break;
    687  1.1  mrg 
    688  1.1  mrg         default:
    689  1.1  mrg             break;
    690  1.1  mrg         }
    691  1.1  mrg 
    692  1.1  mrg         return visit(e);
    693  1.1  mrg     }
    694  1.1  mrg 
    695  1.1  mrg     MATCH visitArrayLiteral(ArrayLiteralExp e)
    696  1.1  mrg     {
    697  1.1  mrg         version (none)
    698  1.1  mrg         {
    699  1.1  mrg             printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    700  1.1  mrg         }
    701  1.1  mrg         Type tb = t.toBasetype();
    702  1.1  mrg         Type typeb = e.type.toBasetype();
    703  1.1  mrg 
    704  1.1  mrg         auto result = MATCH.nomatch;
    705  1.1  mrg         if ((tb.ty == Tarray || tb.ty == Tsarray) &&
    706  1.1  mrg             (typeb.ty == Tarray || typeb.ty == Tsarray))
    707  1.1  mrg         {
    708  1.1  mrg             result = MATCH.exact;
    709  1.1  mrg             Type typen = typeb.nextOf().toBasetype();
    710  1.1  mrg 
    711  1.1  mrg             if (auto tsa = tb.isTypeSArray())
    712  1.1  mrg             {
    713  1.1  mrg                 if (e.elements.dim != tsa.dim.toInteger())
    714  1.1  mrg                     result = MATCH.nomatch;
    715  1.1  mrg             }
    716  1.1  mrg 
    717  1.1  mrg             Type telement = tb.nextOf();
    718  1.1  mrg             if (!e.elements.dim)
    719  1.1  mrg             {
    720  1.1  mrg                 if (typen.ty != Tvoid)
    721  1.1  mrg                     result = typen.implicitConvTo(telement);
    722  1.1  mrg             }
    723  1.1  mrg             else
    724  1.1  mrg             {
    725  1.1  mrg                 if (e.basis)
    726  1.1  mrg                 {
    727  1.1  mrg                     MATCH m = e.basis.implicitConvTo(telement);
    728  1.1  mrg                     if (m < result)
    729  1.1  mrg                         result = m;
    730  1.1  mrg                 }
    731  1.1  mrg                 for (size_t i = 0; i < e.elements.dim; i++)
    732  1.1  mrg                 {
    733  1.1  mrg                     Expression el = (*e.elements)[i];
    734  1.1  mrg                     if (result == MATCH.nomatch)
    735  1.1  mrg                         break;
    736  1.1  mrg                     if (!el)
    737  1.1  mrg                         continue;
    738  1.1  mrg                     MATCH m = el.implicitConvTo(telement);
    739  1.1  mrg                     if (m < result)
    740  1.1  mrg                         result = m; // remember worst match
    741  1.1  mrg                 }
    742  1.1  mrg             }
    743  1.1  mrg 
    744  1.1  mrg             if (!result)
    745  1.1  mrg                 result = e.type.implicitConvTo(t);
    746  1.1  mrg 
    747  1.1  mrg             return result;
    748  1.1  mrg         }
    749  1.1  mrg         else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
    750  1.1  mrg         {
    751  1.1  mrg             result = MATCH.exact;
    752  1.1  mrg             // Convert array literal to vector type
    753  1.1  mrg             TypeVector tv = tb.isTypeVector();
    754  1.1  mrg             TypeSArray tbase = tv.basetype.isTypeSArray();
    755  1.1  mrg             assert(tbase);
    756  1.1  mrg             const edim = e.elements.dim;
    757  1.1  mrg             const tbasedim = tbase.dim.toInteger();
    758  1.1  mrg             if (edim > tbasedim)
    759  1.1  mrg             {
    760  1.1  mrg                 return MATCH.nomatch;
    761  1.1  mrg             }
    762  1.1  mrg 
    763  1.1  mrg             Type telement = tv.elementType();
    764  1.1  mrg             if (edim < tbasedim)
    765  1.1  mrg             {
    766  1.1  mrg                 Expression el = typeb.nextOf.defaultInitLiteral(e.loc);
    767  1.1  mrg                 MATCH m = el.implicitConvTo(telement);
    768  1.1  mrg                 if (m < result)
    769  1.1  mrg                     result = m; // remember worst match
    770  1.1  mrg             }
    771  1.1  mrg             foreach (el; (*e.elements)[])
    772  1.1  mrg             {
    773  1.1  mrg                 MATCH m = el.implicitConvTo(telement);
    774  1.1  mrg                 if (m < result)
    775  1.1  mrg                     result = m; // remember worst match
    776  1.1  mrg                 if (result == MATCH.nomatch)
    777  1.1  mrg                     break; // no need to check for worse
    778  1.1  mrg             }
    779  1.1  mrg             return result;
    780  1.1  mrg         }
    781  1.1  mrg 
    782  1.1  mrg         return visit(e);
    783  1.1  mrg     }
    784  1.1  mrg 
    785  1.1  mrg     MATCH visitAssocArrayLiteral(AssocArrayLiteralExp e)
    786  1.1  mrg     {
    787  1.1  mrg         auto taa = t.toBasetype().isTypeAArray();
    788  1.1  mrg         Type typeb = e.type.toBasetype();
    789  1.1  mrg 
    790  1.1  mrg         if (!(taa && typeb.ty == Taarray))
    791  1.1  mrg             return visit(e);
    792  1.1  mrg 
    793  1.1  mrg         auto result = MATCH.exact;
    794  1.1  mrg         foreach (i, el; (*e.keys)[])
    795  1.1  mrg         {
    796  1.1  mrg             MATCH m = el.implicitConvTo(taa.index);
    797  1.1  mrg             if (m < result)
    798  1.1  mrg                 result = m; // remember worst match
    799  1.1  mrg             if (result == MATCH.nomatch)
    800  1.1  mrg                 break; // no need to check for worse
    801  1.1  mrg             el = (*e.values)[i];
    802  1.1  mrg             m = el.implicitConvTo(taa.nextOf());
    803  1.1  mrg             if (m < result)
    804  1.1  mrg                 result = m; // remember worst match
    805  1.1  mrg             if (result == MATCH.nomatch)
    806  1.1  mrg                 break; // no need to check for worse
    807  1.1  mrg         }
    808  1.1  mrg         return result;
    809  1.1  mrg     }
    810  1.1  mrg 
    811  1.1  mrg     MATCH visitCall(CallExp e)
    812  1.1  mrg     {
    813  1.1  mrg         enum LOG = false;
    814  1.1  mrg         static if (LOG)
    815  1.1  mrg         {
    816  1.1  mrg             printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    817  1.1  mrg         }
    818  1.1  mrg 
    819  1.1  mrg         auto result = visit(e);
    820  1.1  mrg         if (result != MATCH.nomatch)
    821  1.1  mrg             return result;
    822  1.1  mrg 
    823  1.1  mrg         /* Allow the result of strongly pure functions to
    824  1.1  mrg          * convert to immutable
    825  1.1  mrg          */
    826  1.1  mrg         if (e.f &&
    827  1.1  mrg             // lots of legacy code breaks with the following purity check
    828  1.1  mrg             (global.params.useDIP1000 != FeatureState.enabled || e.f.isPure() >= PURE.const_) &&
    829  1.1  mrg              e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive.
    830  1.1  mrg            )
    831  1.1  mrg         {
    832  1.1  mrg             result = e.type.immutableOf().implicitConvTo(t);
    833  1.1  mrg             if (result > MATCH.constant) // Match level is MATCH.constant at best.
    834  1.1  mrg                 result = MATCH.constant;
    835  1.1  mrg             return result;
    836  1.1  mrg         }
    837  1.1  mrg 
    838  1.1  mrg         /* Conversion is 'const' conversion if:
    839  1.1  mrg          * 1. function is pure (weakly pure is ok)
    840  1.1  mrg          * 2. implicit conversion only fails because of mod bits
    841  1.1  mrg          * 3. each function parameter can be implicitly converted to the mod bits
    842  1.1  mrg          */
    843  1.1  mrg         auto tf = (e.f ? e.f.type : e.e1.type).toBasetype().isTypeFunction();
    844  1.1  mrg         if (!tf)
    845  1.1  mrg             return result;
    846  1.1  mrg 
    847  1.1  mrg         if (tf.purity == PURE.impure)
    848  1.1  mrg             return result;
    849  1.1  mrg         if (e.f && e.f.isNested())
    850  1.1  mrg             return result;
    851  1.1  mrg 
    852  1.1  mrg         /* See if fail only because of mod bits.
    853  1.1  mrg          *
    854  1.1  mrg          * https://issues.dlang.org/show_bug.cgi?id=14155
    855  1.1  mrg          * All pure functions can access global immutable data.
    856  1.1  mrg          * So the returned pointer may refer an immutable global data,
    857  1.1  mrg          * and then the returned pointer that points non-mutable object
    858  1.1  mrg          * cannot be unique pointer.
    859  1.1  mrg          *
    860  1.1  mrg          * Example:
    861  1.1  mrg          *  immutable g;
    862  1.1  mrg          *  static this() { g = 1; }
    863  1.1  mrg          *  const(int*) foo() pure { return &g; }
    864  1.1  mrg          *  void test() {
    865  1.1  mrg          *    immutable(int*) ip = foo(); // OK
    866  1.1  mrg          *    int* mp = foo();            // should be disallowed
    867  1.1  mrg          *  }
    868  1.1  mrg          */
    869  1.1  mrg         if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
    870  1.1  mrg         {
    871  1.1  mrg             return result;
    872  1.1  mrg         }
    873  1.1  mrg         // Allow a conversion to immutable type, or
    874  1.1  mrg         // conversions of mutable types between thread-local and shared.
    875  1.1  mrg 
    876  1.1  mrg         /* Get mod bits of what we're converting to
    877  1.1  mrg          */
    878  1.1  mrg         Type tb = t.toBasetype();
    879  1.1  mrg         MOD mod = tb.mod;
    880  1.1  mrg         if (tf.isref)
    881  1.1  mrg         {
    882  1.1  mrg         }
    883  1.1  mrg         else
    884  1.1  mrg         {
    885  1.1  mrg             if (Type ti = getIndirection(t))
    886  1.1  mrg                 mod = ti.mod;
    887  1.1  mrg         }
    888  1.1  mrg         static if (LOG)
    889  1.1  mrg         {
    890  1.1  mrg             printf("mod = x%x\n", mod);
    891  1.1  mrg         }
    892  1.1  mrg         if (mod & MODFlags.wild)
    893  1.1  mrg             return result; // not sure what to do with this
    894  1.1  mrg 
    895  1.1  mrg         /* Apply mod bits to each function parameter,
    896  1.1  mrg          * and see if we can convert the function argument to the modded type
    897  1.1  mrg          */
    898  1.1  mrg 
    899  1.1  mrg         size_t nparams = tf.parameterList.length;
    900  1.1  mrg         size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
    901  1.1  mrg         if (auto dve = e.e1.isDotVarExp())
    902  1.1  mrg         {
    903  1.1  mrg             /* Treat 'this' as just another function argument
    904  1.1  mrg              */
    905  1.1  mrg             Type targ = dve.e1.type;
    906  1.1  mrg             if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
    907  1.1  mrg                 return result;
    908  1.1  mrg         }
    909  1.1  mrg         foreach (const i; j .. e.arguments.dim)
    910  1.1  mrg         {
    911  1.1  mrg             Expression earg = (*e.arguments)[i];
    912  1.1  mrg             Type targ = earg.type.toBasetype();
    913  1.1  mrg             static if (LOG)
    914  1.1  mrg             {
    915  1.1  mrg                 printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
    916  1.1  mrg             }
    917  1.1  mrg             if (i - j < nparams)
    918  1.1  mrg             {
    919  1.1  mrg                 Parameter fparam = tf.parameterList[i - j];
    920  1.1  mrg                 if (fparam.storageClass & STC.lazy_)
    921  1.1  mrg                     return result; // not sure what to do with this
    922  1.1  mrg                 Type tparam = fparam.type;
    923  1.1  mrg                 if (!tparam)
    924  1.1  mrg                     continue;
    925  1.1  mrg                 if (fparam.isReference())
    926  1.1  mrg                 {
    927  1.1  mrg                     if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
    928  1.1  mrg                         return result;
    929  1.1  mrg                     continue;
    930  1.1  mrg                 }
    931  1.1  mrg             }
    932  1.1  mrg             static if (LOG)
    933  1.1  mrg             {
    934  1.1  mrg                 printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
    935  1.1  mrg             }
    936  1.1  mrg             if (implicitMod(earg, targ, mod) == MATCH.nomatch)
    937  1.1  mrg                 return result;
    938  1.1  mrg         }
    939  1.1  mrg 
    940  1.1  mrg         /* Success
    941  1.1  mrg          */
    942  1.1  mrg         return MATCH.constant;
    943  1.1  mrg     }
    944  1.1  mrg 
    945  1.1  mrg     MATCH visitAddr(AddrExp e)
    946  1.1  mrg     {
    947  1.1  mrg         version (none)
    948  1.1  mrg         {
    949  1.1  mrg             printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
    950  1.1  mrg         }
    951  1.1  mrg         auto result = e.type.implicitConvTo(t);
    952  1.1  mrg         //printf("\tresult = %d\n", result);
    953  1.1  mrg 
    954  1.1  mrg         if (result != MATCH.nomatch)
    955  1.1  mrg             return result;
    956  1.1  mrg 
    957  1.1  mrg         Type tb = t.toBasetype();
    958  1.1  mrg         Type typeb = e.type.toBasetype();
    959  1.1  mrg 
    960  1.1  mrg         // Look for pointers to functions where the functions are overloaded.
    961  1.1  mrg         if (e.e1.op == EXP.overloadSet &&
    962  1.1  mrg             (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
    963  1.1  mrg         {
    964  1.1  mrg             OverExp eo = e.e1.isOverExp();
    965  1.1  mrg             FuncDeclaration f = null;
    966  1.1  mrg             foreach (s; eo.vars.a[])
    967  1.1  mrg             {
    968  1.1  mrg                 FuncDeclaration f2 = s.isFuncDeclaration();
    969  1.1  mrg                 assert(f2);
    970  1.1  mrg                 if (f2.overloadExactMatch(tb.nextOf()))
    971  1.1  mrg                 {
    972  1.1  mrg                     if (f)
    973  1.1  mrg                     {
    974  1.1  mrg                         /* Error if match in more than one overload set,
    975  1.1  mrg                          * even if one is a 'better' match than the other.
    976  1.1  mrg                          */
    977  1.1  mrg                         ScopeDsymbol.multiplyDefined(e.loc, f, f2);
    978  1.1  mrg                     }
    979  1.1  mrg                     else
    980  1.1  mrg                         f = f2;
    981  1.1  mrg                     result = MATCH.exact;
    982  1.1  mrg                 }
    983  1.1  mrg             }
    984  1.1  mrg         }
    985  1.1  mrg 
    986  1.1  mrg         if (e.e1.op == EXP.variable &&
    987  1.1  mrg             typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
    988  1.1  mrg             tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
    989  1.1  mrg         {
    990  1.1  mrg             /* I don't think this can ever happen -
    991  1.1  mrg              * it should have been
    992  1.1  mrg              * converted to a SymOffExp.
    993  1.1  mrg              */
    994  1.1  mrg             assert(0);
    995  1.1  mrg         }
    996  1.1  mrg 
    997  1.1  mrg         //printf("\tresult = %d\n", result);
    998  1.1  mrg         return result;
    999  1.1  mrg     }
   1000  1.1  mrg 
   1001  1.1  mrg     MATCH visitSymOff(SymOffExp e)
   1002  1.1  mrg     {
   1003  1.1  mrg         version (none)
   1004  1.1  mrg         {
   1005  1.1  mrg             printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   1006  1.1  mrg         }
   1007  1.1  mrg         auto result = e.type.implicitConvTo(t);
   1008  1.1  mrg         //printf("\tresult = %d\n", result);
   1009  1.1  mrg         if (result != MATCH.nomatch)
   1010  1.1  mrg             return result;
   1011  1.1  mrg 
   1012  1.1  mrg         Type tb = t.toBasetype();
   1013  1.1  mrg         Type typeb = e.type.toBasetype();
   1014  1.1  mrg 
   1015  1.1  mrg         // Look for pointers to functions where the functions are overloaded.
   1016  1.1  mrg         if (typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
   1017  1.1  mrg             (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
   1018  1.1  mrg         {
   1019  1.1  mrg             if (FuncDeclaration f = e.var.isFuncDeclaration())
   1020  1.1  mrg             {
   1021  1.1  mrg                 f = f.overloadExactMatch(tb.nextOf());
   1022  1.1  mrg                 if (f)
   1023  1.1  mrg                 {
   1024  1.1  mrg                     if ((tb.ty == Tdelegate && (f.needThis() || f.isNested())) ||
   1025  1.1  mrg                         (tb.ty == Tpointer && !(f.needThis() || f.isNested())))
   1026  1.1  mrg                     {
   1027  1.1  mrg                         result = MATCH.exact;
   1028  1.1  mrg                     }
   1029  1.1  mrg                 }
   1030  1.1  mrg             }
   1031  1.1  mrg         }
   1032  1.1  mrg         //printf("\tresult = %d\n", result);
   1033  1.1  mrg         return result;
   1034  1.1  mrg     }
   1035  1.1  mrg 
   1036  1.1  mrg     MATCH visitDelegate(DelegateExp e)
   1037  1.1  mrg     {
   1038  1.1  mrg         version (none)
   1039  1.1  mrg         {
   1040  1.1  mrg             printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   1041  1.1  mrg         }
   1042  1.1  mrg         auto result = e.type.implicitConvTo(t);
   1043  1.1  mrg         if (result != MATCH.nomatch)
   1044  1.1  mrg             return result;
   1045  1.1  mrg 
   1046  1.1  mrg         Type tb = t.toBasetype();
   1047  1.1  mrg         Type typeb = e.type.toBasetype();
   1048  1.1  mrg 
   1049  1.1  mrg         // Look for pointers to functions where the functions are overloaded.
   1050  1.1  mrg         if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
   1051  1.1  mrg         {
   1052  1.1  mrg             if (e.func && e.func.overloadExactMatch(tb.nextOf()))
   1053  1.1  mrg                 result = MATCH.exact;
   1054  1.1  mrg         }
   1055  1.1  mrg         return result;
   1056  1.1  mrg     }
   1057  1.1  mrg 
   1058  1.1  mrg     MATCH visitFunc(FuncExp e)
   1059  1.1  mrg     {
   1060  1.1  mrg         //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
   1061  1.1  mrg         MATCH m = e.matchType(t, null, null, 1);
   1062  1.1  mrg         if (m > MATCH.nomatch)
   1063  1.1  mrg         {
   1064  1.1  mrg             return m;
   1065  1.1  mrg         }
   1066  1.1  mrg         return visit(e);
   1067  1.1  mrg     }
   1068  1.1  mrg 
   1069  1.1  mrg     MATCH visitAnd(AndExp e)
   1070  1.1  mrg     {
   1071  1.1  mrg         auto result = visit(e);
   1072  1.1  mrg         if (result != MATCH.nomatch)
   1073  1.1  mrg             return result;
   1074  1.1  mrg 
   1075  1.1  mrg         MATCH m1 = e.e1.implicitConvTo(t);
   1076  1.1  mrg         MATCH m2 = e.e2.implicitConvTo(t);
   1077  1.1  mrg 
   1078  1.1  mrg         // Pick the worst match
   1079  1.1  mrg         return (m1 < m2) ? m1 : m2;
   1080  1.1  mrg     }
   1081  1.1  mrg 
   1082  1.1  mrg     MATCH visitOr(OrExp e)
   1083  1.1  mrg     {
   1084  1.1  mrg         auto result = visit(e);
   1085  1.1  mrg         if (result != MATCH.nomatch)
   1086  1.1  mrg             return result;
   1087  1.1  mrg 
   1088  1.1  mrg         MATCH m1 = e.e1.implicitConvTo(t);
   1089  1.1  mrg         MATCH m2 = e.e2.implicitConvTo(t);
   1090  1.1  mrg 
   1091  1.1  mrg         // Pick the worst match
   1092  1.1  mrg         return (m1 < m2) ? m1 : m2;
   1093  1.1  mrg     }
   1094  1.1  mrg 
   1095  1.1  mrg     MATCH visitXor(XorExp e)
   1096  1.1  mrg     {
   1097  1.1  mrg         auto result = visit(e);
   1098  1.1  mrg         if (result != MATCH.nomatch)
   1099  1.1  mrg             return result;
   1100  1.1  mrg 
   1101  1.1  mrg         MATCH m1 = e.e1.implicitConvTo(t);
   1102  1.1  mrg         MATCH m2 = e.e2.implicitConvTo(t);
   1103  1.1  mrg 
   1104  1.1  mrg         // Pick the worst match
   1105  1.1  mrg         return (m1 < m2) ? m1 : m2;
   1106  1.1  mrg     }
   1107  1.1  mrg 
   1108  1.1  mrg     MATCH visitCond(CondExp e)
   1109  1.1  mrg     {
   1110  1.1  mrg         e.econd = e.econd.optimize(WANTvalue);
   1111  1.1  mrg         const opt = e.econd.toBool();
   1112  1.1  mrg         if (opt.isPresent())
   1113  1.1  mrg         {
   1114  1.1  mrg             auto result = visit(e);
   1115  1.1  mrg             if (result != MATCH.nomatch)
   1116  1.1  mrg                 return result;
   1117  1.1  mrg         }
   1118  1.1  mrg 
   1119  1.1  mrg         MATCH m1 = e.e1.implicitConvTo(t);
   1120  1.1  mrg         MATCH m2 = e.e2.implicitConvTo(t);
   1121  1.1  mrg         //printf("CondExp: m1 %d m2 %d\n", m1, m2);
   1122  1.1  mrg 
   1123  1.1  mrg         // Pick the worst match
   1124  1.1  mrg         return (m1 < m2) ? m1 : m2;
   1125  1.1  mrg     }
   1126  1.1  mrg 
   1127  1.1  mrg     MATCH visitComma(CommaExp e)
   1128  1.1  mrg     {
   1129  1.1  mrg         return e.e2.implicitConvTo(t);
   1130  1.1  mrg     }
   1131  1.1  mrg 
   1132  1.1  mrg     MATCH visitCast(CastExp e)
   1133  1.1  mrg     {
   1134  1.1  mrg         version (none)
   1135  1.1  mrg         {
   1136  1.1  mrg             printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   1137  1.1  mrg         }
   1138  1.1  mrg         auto result = e.type.implicitConvTo(t);
   1139  1.1  mrg         if (result != MATCH.nomatch)
   1140  1.1  mrg             return result;
   1141  1.1  mrg 
   1142  1.1  mrg         if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
   1143  1.1  mrg             result = MATCH.convert;
   1144  1.1  mrg         else
   1145  1.1  mrg             result = visit(e);
   1146  1.1  mrg         return result;
   1147  1.1  mrg     }
   1148  1.1  mrg 
   1149  1.1  mrg     MATCH visitNew(NewExp e)
   1150  1.1  mrg     {
   1151  1.1  mrg         version (none)
   1152  1.1  mrg         {
   1153  1.1  mrg             printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   1154  1.1  mrg         }
   1155  1.1  mrg         auto result = visit(e);
   1156  1.1  mrg         if (result != MATCH.nomatch)
   1157  1.1  mrg             return result;
   1158  1.1  mrg 
   1159  1.1  mrg         /* Calling new() is like calling a pure function. We can implicitly convert the
   1160  1.1  mrg          * return from new() to t using the same algorithm as in CallExp, with the function
   1161  1.1  mrg          * 'arguments' being:
   1162  1.1  mrg          *    thisexp
   1163  1.1  mrg          *    arguments
   1164  1.1  mrg          *    .init
   1165  1.1  mrg          * 'member' need to be pure.
   1166  1.1  mrg          */
   1167  1.1  mrg 
   1168  1.1  mrg         /* See if fail only because of mod bits
   1169  1.1  mrg          */
   1170  1.1  mrg         if (e.type.immutableOf().implicitConvTo(t.immutableOf()) == MATCH.nomatch)
   1171  1.1  mrg             return MATCH.nomatch;
   1172  1.1  mrg 
   1173  1.1  mrg         /* Get mod bits of what we're converting to
   1174  1.1  mrg          */
   1175  1.1  mrg         Type tb = t.toBasetype();
   1176  1.1  mrg         MOD mod = tb.mod;
   1177  1.1  mrg         if (Type ti = getIndirection(t))
   1178  1.1  mrg             mod = ti.mod;
   1179  1.1  mrg         static if (LOG)
   1180  1.1  mrg         {
   1181  1.1  mrg             printf("mod = x%x\n", mod);
   1182  1.1  mrg         }
   1183  1.1  mrg         if (mod & MODFlags.wild)
   1184  1.1  mrg             return MATCH.nomatch; // not sure what to do with this
   1185  1.1  mrg 
   1186  1.1  mrg         /* Apply mod bits to each argument,
   1187  1.1  mrg          * and see if we can convert the argument to the modded type
   1188  1.1  mrg          */
   1189  1.1  mrg 
   1190  1.1  mrg         if (e.thisexp)
   1191  1.1  mrg         {
   1192  1.1  mrg             /* Treat 'this' as just another function argument
   1193  1.1  mrg              */
   1194  1.1  mrg             Type targ = e.thisexp.type;
   1195  1.1  mrg             if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
   1196  1.1  mrg                 return MATCH.nomatch;
   1197  1.1  mrg         }
   1198  1.1  mrg 
   1199  1.1  mrg         /* Check call to 'member'
   1200  1.1  mrg          */
   1201  1.1  mrg         if (e.member)
   1202  1.1  mrg         {
   1203  1.1  mrg             FuncDeclaration fd = e.member;
   1204  1.1  mrg             if (fd.errors || fd.type.ty != Tfunction)
   1205  1.1  mrg                 return MATCH.nomatch; // error
   1206  1.1  mrg             TypeFunction tf = fd.type.isTypeFunction();
   1207  1.1  mrg             if (tf.purity == PURE.impure)
   1208  1.1  mrg                 return MATCH.nomatch; // impure
   1209  1.1  mrg 
   1210  1.1  mrg             if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
   1211  1.1  mrg             {
   1212  1.1  mrg                 return MATCH.nomatch;
   1213  1.1  mrg             }
   1214  1.1  mrg             // Allow a conversion to immutable type, or
   1215  1.1  mrg             // conversions of mutable types between thread-local and shared.
   1216  1.1  mrg 
   1217  1.1  mrg             Expressions* args = e.arguments;
   1218  1.1  mrg 
   1219  1.1  mrg             size_t nparams = tf.parameterList.length;
   1220  1.1  mrg             // if TypeInfoArray was prepended
   1221  1.1  mrg             size_t j = tf.isDstyleVariadic();
   1222  1.1  mrg             for (size_t i = j; i < e.arguments.dim; ++i)
   1223  1.1  mrg             {
   1224  1.1  mrg                 Expression earg = (*args)[i];
   1225  1.1  mrg                 Type targ = earg.type.toBasetype();
   1226  1.1  mrg                 static if (LOG)
   1227  1.1  mrg                 {
   1228  1.1  mrg                     printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
   1229  1.1  mrg                 }
   1230  1.1  mrg                 if (i - j < nparams)
   1231  1.1  mrg                 {
   1232  1.1  mrg                     Parameter fparam = tf.parameterList[i - j];
   1233  1.1  mrg                     if (fparam.storageClass & STC.lazy_)
   1234  1.1  mrg                         return MATCH.nomatch; // not sure what to do with this
   1235  1.1  mrg                     Type tparam = fparam.type;
   1236  1.1  mrg                     if (!tparam)
   1237  1.1  mrg                         continue;
   1238  1.1  mrg                     if (fparam.isReference())
   1239  1.1  mrg                     {
   1240  1.1  mrg                         if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
   1241  1.1  mrg                             return MATCH.nomatch;
   1242  1.1  mrg                         continue;
   1243  1.1  mrg                     }
   1244  1.1  mrg                 }
   1245  1.1  mrg                 static if (LOG)
   1246  1.1  mrg                 {
   1247  1.1  mrg                     printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
   1248  1.1  mrg                 }
   1249  1.1  mrg                 if (implicitMod(earg, targ, mod) == MATCH.nomatch)
   1250  1.1  mrg                     return MATCH.nomatch;
   1251  1.1  mrg             }
   1252  1.1  mrg         }
   1253  1.1  mrg 
   1254  1.1  mrg         /* If no 'member', then construction is by simple assignment,
   1255  1.1  mrg          * and just straight check 'arguments'
   1256  1.1  mrg          */
   1257  1.1  mrg         if (!e.member && e.arguments)
   1258  1.1  mrg         {
   1259  1.1  mrg             for (size_t i = 0; i < e.arguments.dim; ++i)
   1260  1.1  mrg             {
   1261  1.1  mrg                 Expression earg = (*e.arguments)[i];
   1262  1.1  mrg                 if (!earg) // https://issues.dlang.org/show_bug.cgi?id=14853
   1263  1.1  mrg                            // if it's on overlapped field
   1264  1.1  mrg                     continue;
   1265  1.1  mrg                 Type targ = earg.type.toBasetype();
   1266  1.1  mrg                 static if (LOG)
   1267  1.1  mrg                 {
   1268  1.1  mrg                     printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
   1269  1.1  mrg                     printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
   1270  1.1  mrg                 }
   1271  1.1  mrg                 if (implicitMod(earg, targ, mod) == MATCH.nomatch)
   1272  1.1  mrg                     return MATCH.nomatch;
   1273  1.1  mrg             }
   1274  1.1  mrg         }
   1275  1.1  mrg 
   1276  1.1  mrg         /* Consider the .init expression as an argument
   1277  1.1  mrg          */
   1278  1.1  mrg         Type ntb = e.newtype.toBasetype();
   1279  1.1  mrg         if (ntb.ty == Tarray)
   1280  1.1  mrg             ntb = ntb.nextOf().toBasetype();
   1281  1.1  mrg         if (auto ts = ntb.isTypeStruct())
   1282  1.1  mrg         {
   1283  1.1  mrg             // Don't allow nested structs - uplevel reference may not be convertible
   1284  1.1  mrg             StructDeclaration sd = ts.sym;
   1285  1.1  mrg             sd.size(e.loc); // resolve any forward references
   1286  1.1  mrg             if (sd.isNested())
   1287  1.1  mrg                 return MATCH.nomatch;
   1288  1.1  mrg         }
   1289  1.1  mrg         if (ntb.isZeroInit(e.loc))
   1290  1.1  mrg         {
   1291  1.1  mrg             /* Zeros are implicitly convertible, except for special cases.
   1292  1.1  mrg              */
   1293  1.1  mrg             if (auto tc = ntb.isTypeClass())
   1294  1.1  mrg             {
   1295  1.1  mrg                 /* With new() must look at the class instance initializer.
   1296  1.1  mrg                  */
   1297  1.1  mrg                 ClassDeclaration cd = tc.sym;
   1298  1.1  mrg 
   1299  1.1  mrg                 cd.size(e.loc); // resolve any forward references
   1300  1.1  mrg 
   1301  1.1  mrg                 if (cd.isNested())
   1302  1.1  mrg                     return MATCH.nomatch; // uplevel reference may not be convertible
   1303  1.1  mrg 
   1304  1.1  mrg                 assert(!cd.isInterfaceDeclaration());
   1305  1.1  mrg 
   1306  1.1  mrg                 struct ClassCheck
   1307  1.1  mrg                 {
   1308  1.1  mrg                     extern (C++) static bool convertible(Expression e, ClassDeclaration cd, MOD mod)
   1309  1.1  mrg                     {
   1310  1.1  mrg                         for (size_t i = 0; i < cd.fields.dim; i++)
   1311  1.1  mrg                         {
   1312  1.1  mrg                             VarDeclaration v = cd.fields[i];
   1313  1.1  mrg                             Initializer _init = v._init;
   1314  1.1  mrg                             if (_init)
   1315  1.1  mrg                             {
   1316  1.1  mrg                                 if (_init.isVoidInitializer())
   1317  1.1  mrg                                 {
   1318  1.1  mrg                                 }
   1319  1.1  mrg                                 else if (ExpInitializer ei = _init.isExpInitializer())
   1320  1.1  mrg                                 {
   1321  1.1  mrg                                     // https://issues.dlang.org/show_bug.cgi?id=21319
   1322  1.1  mrg                                     // This is to prevent re-analyzing the same expression
   1323  1.1  mrg                                     // over and over again.
   1324  1.1  mrg                                     if (ei.exp == e)
   1325  1.1  mrg                                         return false;
   1326  1.1  mrg                                     Type tb = v.type.toBasetype();
   1327  1.1  mrg                                     if (implicitMod(ei.exp, tb, mod) == MATCH.nomatch)
   1328  1.1  mrg                                         return false;
   1329  1.1  mrg                                 }
   1330  1.1  mrg                                 else
   1331  1.1  mrg                                 {
   1332  1.1  mrg                                     /* Enhancement: handle StructInitializer and ArrayInitializer
   1333  1.1  mrg                                      */
   1334  1.1  mrg                                     return false;
   1335  1.1  mrg                                 }
   1336  1.1  mrg                             }
   1337  1.1  mrg                             else if (!v.type.isZeroInit(e.loc))
   1338  1.1  mrg                                 return false;
   1339  1.1  mrg                         }
   1340  1.1  mrg                         return cd.baseClass ? convertible(e, cd.baseClass, mod) : true;
   1341  1.1  mrg                     }
   1342  1.1  mrg                 }
   1343  1.1  mrg 
   1344  1.1  mrg                 if (!ClassCheck.convertible(e, cd, mod))
   1345  1.1  mrg                     return MATCH.nomatch;
   1346  1.1  mrg             }
   1347  1.1  mrg         }
   1348  1.1  mrg         else
   1349  1.1  mrg         {
   1350  1.1  mrg             Expression earg = e.newtype.defaultInitLiteral(e.loc);
   1351  1.1  mrg             Type targ = e.newtype.toBasetype();
   1352  1.1  mrg 
   1353  1.1  mrg             if (implicitMod(earg, targ, mod) == MATCH.nomatch)
   1354  1.1  mrg                 return MATCH.nomatch;
   1355  1.1  mrg         }
   1356  1.1  mrg 
   1357  1.1  mrg         /* Success
   1358  1.1  mrg          */
   1359  1.1  mrg         return MATCH.constant;
   1360  1.1  mrg     }
   1361  1.1  mrg 
   1362  1.1  mrg     MATCH visitSlice(SliceExp e)
   1363  1.1  mrg     {
   1364  1.1  mrg         //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e.toChars(), e.type.toChars());
   1365  1.1  mrg         auto result = visit(e);
   1366  1.1  mrg         if (result != MATCH.nomatch)
   1367  1.1  mrg             return result;
   1368  1.1  mrg 
   1369  1.1  mrg         Type tb = t.toBasetype();
   1370  1.1  mrg         Type typeb = e.type.toBasetype();
   1371  1.1  mrg 
   1372  1.1  mrg         if (tb.ty == Tsarray && typeb.ty == Tarray)
   1373  1.1  mrg         {
   1374  1.1  mrg             typeb = toStaticArrayType(e);
   1375  1.1  mrg             if (typeb)
   1376  1.1  mrg             {
   1377  1.1  mrg                 // Try: T[] -> T[dim]
   1378  1.1  mrg                 // (Slice with compile-time known boundaries to static array)
   1379  1.1  mrg                 result = typeb.implicitConvTo(t);
   1380  1.1  mrg                 if (result > MATCH.convert)
   1381  1.1  mrg                     result = MATCH.convert; // match with implicit conversion at most
   1382  1.1  mrg             }
   1383  1.1  mrg             return result;
   1384  1.1  mrg         }
   1385  1.1  mrg 
   1386  1.1  mrg         /* If the only reason it won't convert is because of the mod bits,
   1387  1.1  mrg          * then test for conversion by seeing if e1 can be converted with those
   1388  1.1  mrg          * same mod bits.
   1389  1.1  mrg          */
   1390  1.1  mrg         Type t1b = e.e1.type.toBasetype();
   1391  1.1  mrg         if (tb.ty == Tarray && typeb.equivalent(tb))
   1392  1.1  mrg         {
   1393  1.1  mrg             Type tbn = tb.nextOf();
   1394  1.1  mrg             Type tx = null;
   1395  1.1  mrg 
   1396  1.1  mrg             /* If e.e1 is dynamic array or pointer, the uniqueness of e.e1
   1397  1.1  mrg              * is equivalent with the uniqueness of the referred data. And in here
   1398  1.1  mrg              * we can have arbitrary typed reference for that.
   1399  1.1  mrg              */
   1400  1.1  mrg             if (t1b.ty == Tarray)
   1401  1.1  mrg                 tx = tbn.arrayOf();
   1402  1.1  mrg             if (t1b.ty == Tpointer)
   1403  1.1  mrg                 tx = tbn.pointerTo();
   1404  1.1  mrg 
   1405  1.1  mrg             /* If e.e1 is static array, at least it should be an rvalue.
   1406  1.1  mrg              * If not, e.e1 is a reference, and its uniqueness does not link
   1407  1.1  mrg              * to the uniqueness of the referred data.
   1408  1.1  mrg              */
   1409  1.1  mrg             if (t1b.ty == Tsarray && !e.e1.isLvalue())
   1410  1.1  mrg                 tx = tbn.sarrayOf(t1b.size() / tbn.size());
   1411  1.1  mrg 
   1412  1.1  mrg             if (tx)
   1413  1.1  mrg             {
   1414  1.1  mrg                 result = e.e1.implicitConvTo(tx);
   1415  1.1  mrg                 if (result > MATCH.constant) // Match level is MATCH.constant at best.
   1416  1.1  mrg                     result = MATCH.constant;
   1417  1.1  mrg             }
   1418  1.1  mrg         }
   1419  1.1  mrg 
   1420  1.1  mrg         // Enhancement 10724
   1421  1.1  mrg         if (tb.ty == Tpointer && e.e1.op == EXP.string_)
   1422  1.1  mrg             result = e.e1.implicitConvTo(t);
   1423  1.1  mrg         return result;
   1424  1.1  mrg     }
   1425  1.1  mrg 
   1426  1.1  mrg     MATCH visitTuple(TupleExp e)
   1427  1.1  mrg     {
   1428  1.1  mrg         auto result = e.type.implicitConvTo(t);
   1429  1.1  mrg         if (result != MATCH.nomatch)
   1430  1.1  mrg             return result;
   1431  1.1  mrg 
   1432  1.1  mrg         /* If target type is a tuple of same length, test conversion of
   1433  1.1  mrg          * each expression to the corresponding type in the tuple.
   1434  1.1  mrg          */
   1435  1.1  mrg         TypeTuple totuple = t.isTypeTuple();
   1436  1.1  mrg         if (totuple && e.exps.length == totuple.arguments.length)
   1437  1.1  mrg         {
   1438  1.1  mrg             result = MATCH.exact;
   1439  1.1  mrg             foreach (i, ex; *e.exps)
   1440  1.1  mrg             {
   1441  1.1  mrg                 auto to = (*totuple.arguments)[i].type;
   1442  1.1  mrg                 MATCH mi = ex.implicitConvTo(to);
   1443  1.1  mrg                 if (mi < result)
   1444  1.1  mrg                     result = mi;
   1445  1.1  mrg             }
   1446  1.1  mrg         }
   1447  1.1  mrg         return result;
   1448  1.1  mrg     }
   1449  1.1  mrg 
   1450  1.1  mrg     switch (e.op)
   1451  1.1  mrg     {
   1452  1.1  mrg         default                   : return visit(e);
   1453  1.1  mrg         case EXP.add              : return visitAdd(e.isAddExp());
   1454  1.1  mrg         case EXP.min              : return visitMin(e.isMinExp());
   1455  1.1  mrg         case EXP.int64            : return visitInteger(e.isIntegerExp());
   1456  1.1  mrg         case EXP.error            : return visitError(e.isErrorExp());
   1457  1.1  mrg         case EXP.null_            : return visitNull(e.isNullExp());
   1458  1.1  mrg         case EXP.structLiteral    : return visitStructLiteral(e.isStructLiteralExp());
   1459  1.1  mrg         case EXP.string_          : return visitString(e.isStringExp());
   1460  1.1  mrg         case EXP.arrayLiteral     : return visitArrayLiteral(e.isArrayLiteralExp());
   1461  1.1  mrg         case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
   1462  1.1  mrg         case EXP.call             : return visitCall(e.isCallExp());
   1463  1.1  mrg         case EXP.address          : return visitAddr(e.isAddrExp());
   1464  1.1  mrg         case EXP.symbolOffset     : return visitSymOff(e.isSymOffExp());
   1465  1.1  mrg         case EXP.delegate_        : return visitDelegate(e.isDelegateExp());
   1466  1.1  mrg         case EXP.function_        : return visitFunc(e.isFuncExp());
   1467  1.1  mrg         case EXP.and              : return visitAnd(e.isAndExp());
   1468  1.1  mrg         case EXP.or               : return visitOr(e.isOrExp());
   1469  1.1  mrg         case EXP.xor              : return visitXor(e.isXorExp());
   1470  1.1  mrg         case EXP.question         : return visitCond(e.isCondExp());
   1471  1.1  mrg         case EXP.comma            : return visitComma(e.isCommaExp());
   1472  1.1  mrg         case EXP.cast_            : return visitCast(e.isCastExp());
   1473  1.1  mrg         case EXP.new_             : return visitNew(e.isNewExp());
   1474  1.1  mrg         case EXP.slice            : return visitSlice(e.isSliceExp());
   1475  1.1  mrg         case EXP.tuple            : return visitTuple(e.isTupleExp());
   1476  1.1  mrg     }
   1477  1.1  mrg }
   1478  1.1  mrg 
   1479  1.1  mrg /**
   1480  1.1  mrg  * Same as implicitConvTo(); except follow C11 rules, which are quite a bit
   1481  1.1  mrg  * more permissive than D.
   1482  1.1  mrg  * C11 6.3 and 6.5.16.1
   1483  1.1  mrg  * Params:
   1484  1.1  mrg  *   e = Expression that is to be casted
   1485  1.1  mrg  *   t = Expected resulting type
   1486  1.1  mrg  * Returns:
   1487  1.1  mrg  *   The `MATCH` level between `e.type` and `t`.
   1488  1.1  mrg  */
   1489  1.1  mrg MATCH cimplicitConvTo(Expression e, Type t)
   1490  1.1  mrg {
   1491  1.1  mrg     Type tb = t.toBasetype();
   1492  1.1  mrg     Type typeb = e.type.toBasetype();
   1493  1.1  mrg 
   1494  1.1  mrg     if (tb.equals(typeb))
   1495  1.1  mrg         return MATCH.exact;
   1496  1.1  mrg     if ((typeb.isintegral() || typeb.isfloating()) &&
   1497  1.1  mrg         (tb.isintegral() || tb.isfloating()))
   1498  1.1  mrg         return MATCH.convert;
   1499  1.1  mrg     if (tb.ty == Tpointer && typeb.isintegral()) // C11 6.3.2.3-5
   1500  1.1  mrg         return MATCH.convert;
   1501  1.1  mrg     if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
   1502  1.1  mrg         return MATCH.convert;
   1503  1.1  mrg     if (tb.ty == Tpointer && typeb.ty == Tpointer) // C11 6.3.2.3-7
   1504  1.1  mrg         return MATCH.convert;
   1505  1.1  mrg 
   1506  1.1  mrg     return implicitConvTo(e, t);
   1507  1.1  mrg }
   1508  1.1  mrg 
   1509  1.1  mrg /*****************************************
   1510  1.1  mrg  */
   1511  1.1  mrg Type toStaticArrayType(SliceExp e)
   1512  1.1  mrg {
   1513  1.1  mrg     if (e.lwr && e.upr)
   1514  1.1  mrg     {
   1515  1.1  mrg         // For the following code to work, e should be optimized beforehand.
   1516  1.1  mrg         // (eg. $ in lwr and upr should be already resolved, if possible)
   1517  1.1  mrg         Expression lwr = e.lwr.optimize(WANTvalue);
   1518  1.1  mrg         Expression upr = e.upr.optimize(WANTvalue);
   1519  1.1  mrg         if (lwr.isConst() && upr.isConst())
   1520  1.1  mrg         {
   1521  1.1  mrg             size_t len = cast(size_t)(upr.toUInteger() - lwr.toUInteger());
   1522  1.1  mrg             return e.type.toBasetype().nextOf().sarrayOf(len);
   1523  1.1  mrg         }
   1524  1.1  mrg     }
   1525  1.1  mrg     else
   1526  1.1  mrg     {
   1527  1.1  mrg         Type t1b = e.e1.type.toBasetype();
   1528  1.1  mrg         if (t1b.ty == Tsarray)
   1529  1.1  mrg             return t1b;
   1530  1.1  mrg     }
   1531  1.1  mrg     return null;
   1532  1.1  mrg }
   1533  1.1  mrg 
   1534  1.1  mrg /**************************************
   1535  1.1  mrg  * Do an explicit cast.
   1536  1.1  mrg  * Assume that the expression `e` does not have any indirections.
   1537  1.1  mrg  * (Parameter 'att' is used to stop 'alias this' recursion)
   1538  1.1  mrg  */
   1539  1.1  mrg Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
   1540  1.1  mrg {
   1541  1.1  mrg     Expression visit(Expression e)
   1542  1.1  mrg     {
   1543  1.1  mrg         //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
   1544  1.1  mrg         version (none)
   1545  1.1  mrg         {
   1546  1.1  mrg             printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   1547  1.1  mrg         }
   1548  1.1  mrg         if (e.type.equals(t))
   1549  1.1  mrg         {
   1550  1.1  mrg             return e;
   1551  1.1  mrg         }
   1552  1.1  mrg         if (auto ve = e.isVarExp())
   1553  1.1  mrg         {
   1554  1.1  mrg             VarDeclaration v = ve.var.isVarDeclaration();
   1555  1.1  mrg             if (v && v.storage_class & STC.manifest)
   1556  1.1  mrg             {
   1557  1.1  mrg                 auto result = e.ctfeInterpret();
   1558  1.1  mrg                 /* https://issues.dlang.org/show_bug.cgi?id=18236
   1559  1.1  mrg                  *
   1560  1.1  mrg                  * The expression returned by ctfeInterpret points
   1561  1.1  mrg                  * to the line where the manifest constant was declared
   1562  1.1  mrg                  * so we need to update the location before trying to cast
   1563  1.1  mrg                  */
   1564  1.1  mrg                 result.loc = e.loc;
   1565  1.1  mrg                 return result.castTo(sc, t);
   1566  1.1  mrg             }
   1567  1.1  mrg         }
   1568  1.1  mrg 
   1569  1.1  mrg         Type tob = t.toBasetype();
   1570  1.1  mrg         Type t1b = e.type.toBasetype();
   1571  1.1  mrg         if (tob.equals(t1b))
   1572  1.1  mrg         {
   1573  1.1  mrg             auto result = e.copy(); // because of COW for assignment to e.type
   1574  1.1  mrg             result.type = t;
   1575  1.1  mrg             return result;
   1576  1.1  mrg         }
   1577  1.1  mrg 
   1578  1.1  mrg         /* Make semantic error against invalid cast between concrete types.
   1579  1.1  mrg          * Assume that 'e' is never be any placeholder expressions.
   1580  1.1  mrg          * The result of these checks should be consistent with CastExp::toElem().
   1581  1.1  mrg          */
   1582  1.1  mrg 
   1583  1.1  mrg         // Fat Value types
   1584  1.1  mrg         const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray || tob.ty == Tvector);
   1585  1.1  mrg         const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray || t1b.ty == Tvector);
   1586  1.1  mrg 
   1587  1.1  mrg         // Fat Reference types
   1588  1.1  mrg         const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate);
   1589  1.1  mrg         const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate);
   1590  1.1  mrg 
   1591  1.1  mrg         // Reference types
   1592  1.1  mrg         const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass);
   1593  1.1  mrg         const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
   1594  1.1  mrg 
   1595  1.1  mrg         // Arithmetic types (== valueable basic types)
   1596  1.1  mrg         const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
   1597  1.1  mrg         const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
   1598  1.1  mrg 
   1599  1.1  mrg         // Try casting the alias this member.
   1600  1.1  mrg         // Return the expression if it succeeds, null otherwise.
   1601  1.1  mrg         Expression tryAliasThisCast()
   1602  1.1  mrg         {
   1603  1.1  mrg             if (isRecursiveAliasThis(att, t1b))
   1604  1.1  mrg                 return null;
   1605  1.1  mrg 
   1606  1.1  mrg             /* Forward the cast to our alias this member, rewrite to:
   1607  1.1  mrg              *   cast(to)e1.aliasthis
   1608  1.1  mrg              */
   1609  1.1  mrg             auto exp = resolveAliasThis(sc, e);
   1610  1.1  mrg             const errors = global.startGagging();
   1611  1.1  mrg             exp = castTo(exp, sc, t, att);
   1612  1.1  mrg             return global.endGagging(errors) ? null : exp;
   1613  1.1  mrg         }
   1614  1.1  mrg 
   1615  1.1  mrg         bool hasAliasThis;
   1616  1.1  mrg         if (AggregateDeclaration t1ad = isAggregate(t1b))
   1617  1.1  mrg         {
   1618  1.1  mrg             AggregateDeclaration toad = isAggregate(tob);
   1619  1.1  mrg             if (t1ad != toad && t1ad.aliasthis)
   1620  1.1  mrg             {
   1621  1.1  mrg                 if (t1b.ty == Tclass && tob.ty == Tclass)
   1622  1.1  mrg                 {
   1623  1.1  mrg                     ClassDeclaration t1cd = t1b.isClassHandle();
   1624  1.1  mrg                     ClassDeclaration tocd = tob.isClassHandle();
   1625  1.1  mrg                     int offset;
   1626  1.1  mrg                     if (tocd.isBaseOf(t1cd, &offset))
   1627  1.1  mrg                         goto Lok;
   1628  1.1  mrg                 }
   1629  1.1  mrg                 hasAliasThis = true;
   1630  1.1  mrg             }
   1631  1.1  mrg         }
   1632  1.1  mrg         else if (tob.ty == Tvector && t1b.ty != Tvector)
   1633  1.1  mrg         {
   1634  1.1  mrg             //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
   1635  1.1  mrg             TypeVector tv = tob.isTypeVector();
   1636  1.1  mrg             Expression result = new CastExp(e.loc, e, tv.elementType());
   1637  1.1  mrg             result = new VectorExp(e.loc, result, tob);
   1638  1.1  mrg             result = result.expressionSemantic(sc);
   1639  1.1  mrg             return result;
   1640  1.1  mrg         }
   1641  1.1  mrg         else if (tob.ty != Tvector && t1b.ty == Tvector)
   1642  1.1  mrg         {
   1643  1.1  mrg             // T[n] <-- __vector(U[m])
   1644  1.1  mrg             if (tob.ty == Tsarray)
   1645  1.1  mrg             {
   1646  1.1  mrg                 if (t1b.size(e.loc) == tob.size(e.loc))
   1647  1.1  mrg                     goto Lok;
   1648  1.1  mrg             }
   1649  1.1  mrg             goto Lfail;
   1650  1.1  mrg         }
   1651  1.1  mrg         else if (t1b.implicitConvTo(tob) == MATCH.constant && t.equals(e.type.constOf()))
   1652  1.1  mrg         {
   1653  1.1  mrg             auto result = e.copy();
   1654  1.1  mrg             result.type = t;
   1655  1.1  mrg             return result;
   1656  1.1  mrg         }
   1657  1.1  mrg 
   1658  1.1  mrg         // arithmetic values vs. other arithmetic values
   1659  1.1  mrg         // arithmetic values vs. T*
   1660  1.1  mrg         if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer))
   1661  1.1  mrg         {
   1662  1.1  mrg             goto Lok;
   1663  1.1  mrg         }
   1664  1.1  mrg 
   1665  1.1  mrg         // arithmetic values vs. references or fat values
   1666  1.1  mrg         if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV))
   1667  1.1  mrg         {
   1668  1.1  mrg             goto Lfail;
   1669  1.1  mrg         }
   1670  1.1  mrg 
   1671  1.1  mrg         // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
   1672  1.1  mrg         if (tob_isFV && t1b_isFV)
   1673  1.1  mrg         {
   1674  1.1  mrg             if (hasAliasThis)
   1675  1.1  mrg             {
   1676  1.1  mrg                 auto result = tryAliasThisCast();
   1677  1.1  mrg                 if (result)
   1678  1.1  mrg                     return result;
   1679  1.1  mrg             }
   1680  1.1  mrg 
   1681  1.1  mrg             if (t1b.size(e.loc) == tob.size(e.loc))
   1682  1.1  mrg                 goto Lok;
   1683  1.1  mrg 
   1684  1.1  mrg             auto ts = toAutoQualChars(e.type, t);
   1685  1.1  mrg             e.error("cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
   1686  1.1  mrg                 e.toChars(), ts[0], ts[1]);
   1687  1.1  mrg             return ErrorExp.get();
   1688  1.1  mrg         }
   1689  1.1  mrg 
   1690  1.1  mrg         // Fat values vs. null or references
   1691  1.1  mrg         if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR))
   1692  1.1  mrg         {
   1693  1.1  mrg             if (tob.ty == Tpointer && t1b.ty == Tsarray)
   1694  1.1  mrg             {
   1695  1.1  mrg                 // T[n] sa;
   1696  1.1  mrg                 // cast(U*)sa; // ==> cast(U*)sa.ptr;
   1697  1.1  mrg                 return new AddrExp(e.loc, e, t);
   1698  1.1  mrg             }
   1699  1.1  mrg             if (tob.ty == Tarray && t1b.ty == Tsarray)
   1700  1.1  mrg             {
   1701  1.1  mrg                 // T[n] sa;
   1702  1.1  mrg                 // cast(U[])sa; // ==> cast(U[])sa[];
   1703  1.1  mrg                 if (global.params.useDIP1000 == FeatureState.enabled)
   1704  1.1  mrg                 {
   1705  1.1  mrg                     if (auto v = expToVariable(e))
   1706  1.1  mrg                     {
   1707  1.1  mrg                         if (e.type.hasPointers() && !checkAddressVar(sc, e, v))
   1708  1.1  mrg                             goto Lfail;
   1709  1.1  mrg                     }
   1710  1.1  mrg                 }
   1711  1.1  mrg                 const fsize = t1b.nextOf().size();
   1712  1.1  mrg                 const tsize = tob.nextOf().size();
   1713  1.1  mrg                 if (fsize == SIZE_INVALID || tsize == SIZE_INVALID)
   1714  1.1  mrg                 {
   1715  1.1  mrg                     return ErrorExp.get();
   1716  1.1  mrg                 }
   1717  1.1  mrg                 if (fsize != tsize)
   1718  1.1  mrg                 {
   1719  1.1  mrg                     const dim = t1b.isTypeSArray().dim.toInteger();
   1720  1.1  mrg                     if (tsize == 0 || (dim * fsize) % tsize != 0)
   1721  1.1  mrg                     {
   1722  1.1  mrg                         e.error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
   1723  1.1  mrg                                 e.toChars(), e.type.toChars(), t.toChars());
   1724  1.1  mrg                         return ErrorExp.get();
   1725  1.1  mrg                     }
   1726  1.1  mrg                 }
   1727  1.1  mrg                 goto Lok;
   1728  1.1  mrg             }
   1729  1.1  mrg             goto Lfail;
   1730  1.1  mrg         }
   1731  1.1  mrg 
   1732  1.1  mrg         /* For references, any reinterpret casts are allowed to same 'ty' type.
   1733  1.1  mrg          *      T* to U*
   1734  1.1  mrg          *      R1 function(P1) to R2 function(P2)
   1735  1.1  mrg          *      R1 delegate(P1) to R2 delegate(P2)
   1736  1.1  mrg          *      T[] to U[]
   1737  1.1  mrg          *      V1[K1] to V2[K2]
   1738  1.1  mrg          *      class/interface A to B  (will be a dynamic cast if possible)
   1739  1.1  mrg          */
   1740  1.1  mrg         if (tob.ty == t1b.ty && tob_isR && t1b_isR)
   1741  1.1  mrg             goto Lok;
   1742  1.1  mrg 
   1743  1.1  mrg         // typeof(null) <-- non-null references or values
   1744  1.1  mrg         if (tob.ty == Tnull && t1b.ty != Tnull)
   1745  1.1  mrg             goto Lfail; // https://issues.dlang.org/show_bug.cgi?id=14629
   1746  1.1  mrg         // typeof(null) --> non-null references or arithmetic values
   1747  1.1  mrg         if (t1b.ty == Tnull && tob.ty != Tnull)
   1748  1.1  mrg             goto Lok;
   1749  1.1  mrg 
   1750  1.1  mrg         // Check size mismatch of references.
   1751  1.1  mrg         // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
   1752  1.1  mrg         if (tob_isFR && t1b_isR || t1b_isFR && tob_isR)
   1753  1.1  mrg         {
   1754  1.1  mrg             if (tob.ty == Tpointer && t1b.ty == Tarray)
   1755  1.1  mrg             {
   1756  1.1  mrg                 // T[] da;
   1757  1.1  mrg                 // cast(U*)da; // ==> cast(U*)da.ptr;
   1758  1.1  mrg                 goto Lok;
   1759  1.1  mrg             }
   1760  1.1  mrg             if (tob.ty == Tpointer && t1b.ty == Tdelegate)
   1761  1.1  mrg             {
   1762  1.1  mrg                 // void delegate() dg;
   1763  1.1  mrg                 // cast(U*)dg; // ==> cast(U*)dg.ptr;
   1764  1.1  mrg                 // Note that it happens even when U is a Tfunction!
   1765  1.1  mrg                 e.deprecation("casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
   1766  1.1  mrg                 goto Lok;
   1767  1.1  mrg             }
   1768  1.1  mrg             goto Lfail;
   1769  1.1  mrg         }
   1770  1.1  mrg 
   1771  1.1  mrg         if (t1b.ty == Tvoid && tob.ty != Tvoid)
   1772  1.1  mrg         {
   1773  1.1  mrg         Lfail:
   1774  1.1  mrg             /* if the cast cannot be performed, maybe there is an alias
   1775  1.1  mrg              * this that can be used for casting.
   1776  1.1  mrg              */
   1777  1.1  mrg             if (hasAliasThis)
   1778  1.1  mrg             {
   1779  1.1  mrg                 auto result = tryAliasThisCast();
   1780  1.1  mrg                 if (result)
   1781  1.1  mrg                     return result;
   1782  1.1  mrg             }
   1783  1.1  mrg             e.error("cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
   1784  1.1  mrg             return ErrorExp.get();
   1785  1.1  mrg         }
   1786  1.1  mrg 
   1787  1.1  mrg     Lok:
   1788  1.1  mrg         auto result = new CastExp(e.loc, e, t);
   1789  1.1  mrg         result.type = t; // Don't call semantic()
   1790  1.1  mrg         //printf("Returning: %s\n", result.toChars());
   1791  1.1  mrg         return result;
   1792  1.1  mrg     }
   1793  1.1  mrg 
   1794  1.1  mrg     Expression visitError(ErrorExp e)
   1795  1.1  mrg     {
   1796  1.1  mrg         return e;
   1797  1.1  mrg     }
   1798  1.1  mrg 
   1799  1.1  mrg     Expression visitReal(RealExp e)
   1800  1.1  mrg     {
   1801  1.1  mrg         if (!e.type.equals(t))
   1802  1.1  mrg         {
   1803  1.1  mrg             if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
   1804  1.1  mrg             {
   1805  1.1  mrg                 auto result = e.copy();
   1806  1.1  mrg                 result.type = t;
   1807  1.1  mrg                 return result;
   1808  1.1  mrg             }
   1809  1.1  mrg             else
   1810  1.1  mrg                 return visit(e);
   1811  1.1  mrg         }
   1812  1.1  mrg         return e;
   1813  1.1  mrg     }
   1814  1.1  mrg 
   1815  1.1  mrg     Expression visitComplex(ComplexExp e)
   1816  1.1  mrg     {
   1817  1.1  mrg         if (!e.type.equals(t))
   1818  1.1  mrg         {
   1819  1.1  mrg             if (e.type.iscomplex() && t.iscomplex())
   1820  1.1  mrg             {
   1821  1.1  mrg                 auto result = e.copy();
   1822  1.1  mrg                 result.type = t;
   1823  1.1  mrg                 return result;
   1824  1.1  mrg             }
   1825  1.1  mrg             else
   1826  1.1  mrg                 return visit(e);
   1827  1.1  mrg         }
   1828  1.1  mrg         return e;
   1829  1.1  mrg     }
   1830  1.1  mrg 
   1831  1.1  mrg     Expression visitStructLiteral(StructLiteralExp e)
   1832  1.1  mrg     {
   1833  1.1  mrg         auto result = visit(e);
   1834  1.1  mrg         if (auto sle = result.isStructLiteralExp())
   1835  1.1  mrg             sle.stype = t; // commit type
   1836  1.1  mrg         return result;
   1837  1.1  mrg     }
   1838  1.1  mrg 
   1839  1.1  mrg     Expression visitString(StringExp e)
   1840  1.1  mrg     {
   1841  1.1  mrg         /* This follows copy-on-write; any changes to 'this'
   1842  1.1  mrg          * will result in a copy.
   1843  1.1  mrg          * The this.string member is considered immutable.
   1844  1.1  mrg          */
   1845  1.1  mrg         int copied = 0;
   1846  1.1  mrg 
   1847  1.1  mrg         //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
   1848  1.1  mrg 
   1849  1.1  mrg         if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
   1850  1.1  mrg             (!sc || !(sc.flags & SCOPE.Cfile)))
   1851  1.1  mrg         {
   1852  1.1  mrg             e.error("cannot convert string literal to `void*`");
   1853  1.1  mrg             return ErrorExp.get();
   1854  1.1  mrg         }
   1855  1.1  mrg 
   1856  1.1  mrg         StringExp se = e;
   1857  1.1  mrg 
   1858  1.1  mrg         Expression lcast()
   1859  1.1  mrg         {
   1860  1.1  mrg             auto result = new CastExp(e.loc, se, t);
   1861  1.1  mrg             result.type = t; // so semantic() won't be run on e
   1862  1.1  mrg             return result;
   1863  1.1  mrg         }
   1864  1.1  mrg 
   1865  1.1  mrg         if (!e.committed)
   1866  1.1  mrg         {
   1867  1.1  mrg             se = e.copy().isStringExp();
   1868  1.1  mrg             se.committed = 1;
   1869  1.1  mrg             copied = 1;
   1870  1.1  mrg         }
   1871  1.1  mrg 
   1872  1.1  mrg         if (e.type.equals(t))
   1873  1.1  mrg         {
   1874  1.1  mrg             return se;
   1875  1.1  mrg         }
   1876  1.1  mrg 
   1877  1.1  mrg         Type tb = t.toBasetype();
   1878  1.1  mrg         Type typeb = e.type.toBasetype();
   1879  1.1  mrg 
   1880  1.1  mrg         //printf("\ttype = %s\n", e.type.toChars());
   1881  1.1  mrg         if (tb.ty == Tdelegate && typeb.ty != Tdelegate)
   1882  1.1  mrg         {
   1883  1.1  mrg             return visit(e);
   1884  1.1  mrg         }
   1885  1.1  mrg 
   1886  1.1  mrg         if (typeb.equals(tb))
   1887  1.1  mrg         {
   1888  1.1  mrg             if (!copied)
   1889  1.1  mrg             {
   1890  1.1  mrg                 se = e.copy().isStringExp();
   1891  1.1  mrg                 copied = 1;
   1892  1.1  mrg             }
   1893  1.1  mrg             se.type = t;
   1894  1.1  mrg             return se;
   1895  1.1  mrg         }
   1896  1.1  mrg 
   1897  1.1  mrg         /* Handle reinterpret casts:
   1898  1.1  mrg          *  cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
   1899  1.1  mrg          *  cast(wchar[2])"abcd"c --> [\u6261, \u6463]
   1900  1.1  mrg          *  cast(wchar[1])"abcd"c --> [\u6261]
   1901  1.1  mrg          *  cast(char[4])"a" --> ['a', 0, 0, 0]
   1902  1.1  mrg          */
   1903  1.1  mrg         if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
   1904  1.1  mrg         {
   1905  1.1  mrg             se = e.copy().isStringExp();
   1906  1.1  mrg             uinteger_t szx = tb.nextOf().size();
   1907  1.1  mrg             assert(szx <= 255);
   1908  1.1  mrg             se.sz = cast(ubyte)szx;
   1909  1.1  mrg             se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
   1910  1.1  mrg             se.committed = 1;
   1911  1.1  mrg             se.type = t;
   1912  1.1  mrg 
   1913  1.1  mrg             /* If larger than source, pad with zeros.
   1914  1.1  mrg              */
   1915  1.1  mrg             const fullSize = (se.len + 1) * se.sz; // incl. terminating 0
   1916  1.1  mrg             if (fullSize > (e.len + 1) * e.sz)
   1917  1.1  mrg             {
   1918  1.1  mrg                 void* s = mem.xmalloc(fullSize);
   1919  1.1  mrg                 const srcSize = e.len * e.sz;
   1920  1.1  mrg                 const data = se.peekData();
   1921  1.1  mrg                 memcpy(s, data.ptr, srcSize);
   1922  1.1  mrg                 memset(s + srcSize, 0, fullSize - srcSize);
   1923  1.1  mrg                 se.setData(s, se.len, se.sz);
   1924  1.1  mrg             }
   1925  1.1  mrg             return se;
   1926  1.1  mrg         }
   1927  1.1  mrg 
   1928  1.1  mrg         if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer)
   1929  1.1  mrg         {
   1930  1.1  mrg             if (!copied)
   1931  1.1  mrg             {
   1932  1.1  mrg                 se = e.copy().isStringExp();
   1933  1.1  mrg                 copied = 1;
   1934  1.1  mrg             }
   1935  1.1  mrg             return lcast();
   1936  1.1  mrg         }
   1937  1.1  mrg         if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
   1938  1.1  mrg         {
   1939  1.1  mrg             if (!copied)
   1940  1.1  mrg             {
   1941  1.1  mrg                 se = e.copy().isStringExp();
   1942  1.1  mrg                 copied = 1;
   1943  1.1  mrg             }
   1944  1.1  mrg             return lcast();
   1945  1.1  mrg         }
   1946  1.1  mrg 
   1947  1.1  mrg         const nextSz = typeb.nextOf().size();
   1948  1.1  mrg         if (nextSz == SIZE_INVALID)
   1949  1.1  mrg         {
   1950  1.1  mrg             return ErrorExp.get();
   1951  1.1  mrg         }
   1952  1.1  mrg         if (nextSz == tb.nextOf().size())
   1953  1.1  mrg         {
   1954  1.1  mrg             if (!copied)
   1955  1.1  mrg             {
   1956  1.1  mrg                 se = e.copy().isStringExp();
   1957  1.1  mrg                 copied = 1;
   1958  1.1  mrg             }
   1959  1.1  mrg             if (tb.ty == Tsarray)
   1960  1.1  mrg                 goto L2; // handle possible change in static array dimension
   1961  1.1  mrg             se.type = t;
   1962  1.1  mrg             return se;
   1963  1.1  mrg         }
   1964  1.1  mrg 
   1965  1.1  mrg         if (e.committed)
   1966  1.1  mrg             goto Lcast;
   1967  1.1  mrg 
   1968  1.1  mrg         auto X(T, U)(T tf, U tt)
   1969  1.1  mrg         {
   1970  1.1  mrg             return (cast(int)tf * 256 + cast(int)tt);
   1971  1.1  mrg         }
   1972  1.1  mrg 
   1973  1.1  mrg         {
   1974  1.1  mrg             OutBuffer buffer;
   1975  1.1  mrg             size_t newlen = 0;
   1976  1.1  mrg             int tfty = typeb.nextOf().toBasetype().ty;
   1977  1.1  mrg             int ttty = tb.nextOf().toBasetype().ty;
   1978  1.1  mrg             switch (X(tfty, ttty))
   1979  1.1  mrg             {
   1980  1.1  mrg             case X(Tchar, Tchar):
   1981  1.1  mrg             case X(Twchar, Twchar):
   1982  1.1  mrg             case X(Tdchar, Tdchar):
   1983  1.1  mrg                 break;
   1984  1.1  mrg 
   1985  1.1  mrg             case X(Tchar, Twchar):
   1986  1.1  mrg                 for (size_t u = 0; u < e.len;)
   1987  1.1  mrg                 {
   1988  1.1  mrg                     dchar c;
   1989  1.1  mrg                     if (const s = utf_decodeChar(se.peekString(), u, c))
   1990  1.1  mrg                         e.error("%.*s", cast(int)s.length, s.ptr);
   1991  1.1  mrg                     else
   1992  1.1  mrg                         buffer.writeUTF16(c);
   1993  1.1  mrg                 }
   1994  1.1  mrg                 newlen = buffer.length / 2;
   1995  1.1  mrg                 buffer.writeUTF16(0);
   1996  1.1  mrg                 goto L1;
   1997  1.1  mrg 
   1998  1.1  mrg             case X(Tchar, Tdchar):
   1999  1.1  mrg                 for (size_t u = 0; u < e.len;)
   2000  1.1  mrg                 {
   2001  1.1  mrg                     dchar c;
   2002  1.1  mrg                     if (const s = utf_decodeChar(se.peekString(), u, c))
   2003  1.1  mrg                         e.error("%.*s", cast(int)s.length, s.ptr);
   2004  1.1  mrg                     buffer.write4(c);
   2005  1.1  mrg                     newlen++;
   2006  1.1  mrg                 }
   2007  1.1  mrg                 buffer.write4(0);
   2008  1.1  mrg                 goto L1;
   2009  1.1  mrg 
   2010  1.1  mrg             case X(Twchar, Tchar):
   2011  1.1  mrg                 for (size_t u = 0; u < e.len;)
   2012  1.1  mrg                 {
   2013  1.1  mrg                     dchar c;
   2014  1.1  mrg                     if (const s = utf_decodeWchar(se.peekWstring(), u, c))
   2015  1.1  mrg                         e.error("%.*s", cast(int)s.length, s.ptr);
   2016  1.1  mrg                     else
   2017  1.1  mrg                         buffer.writeUTF8(c);
   2018  1.1  mrg                 }
   2019  1.1  mrg                 newlen = buffer.length;
   2020  1.1  mrg                 buffer.writeUTF8(0);
   2021  1.1  mrg                 goto L1;
   2022  1.1  mrg 
   2023  1.1  mrg             case X(Twchar, Tdchar):
   2024  1.1  mrg                 for (size_t u = 0; u < e.len;)
   2025  1.1  mrg                 {
   2026  1.1  mrg                     dchar c;
   2027  1.1  mrg                     if (const s = utf_decodeWchar(se.peekWstring(), u, c))
   2028  1.1  mrg                         e.error("%.*s", cast(int)s.length, s.ptr);
   2029  1.1  mrg                     buffer.write4(c);
   2030  1.1  mrg                     newlen++;
   2031  1.1  mrg                 }
   2032  1.1  mrg                 buffer.write4(0);
   2033  1.1  mrg                 goto L1;
   2034  1.1  mrg 
   2035  1.1  mrg             case X(Tdchar, Tchar):
   2036  1.1  mrg                 for (size_t u = 0; u < e.len; u++)
   2037  1.1  mrg                 {
   2038  1.1  mrg                     uint c = se.peekDstring()[u];
   2039  1.1  mrg                     if (!utf_isValidDchar(c))
   2040  1.1  mrg                         e.error("invalid UCS-32 char \\U%08x", c);
   2041  1.1  mrg                     else
   2042  1.1  mrg                         buffer.writeUTF8(c);
   2043  1.1  mrg                     newlen++;
   2044  1.1  mrg                 }
   2045  1.1  mrg                 newlen = buffer.length;
   2046  1.1  mrg                 buffer.writeUTF8(0);
   2047  1.1  mrg                 goto L1;
   2048  1.1  mrg 
   2049  1.1  mrg             case X(Tdchar, Twchar):
   2050  1.1  mrg                 for (size_t u = 0; u < e.len; u++)
   2051  1.1  mrg                 {
   2052  1.1  mrg                     uint c = se.peekDstring()[u];
   2053  1.1  mrg                     if (!utf_isValidDchar(c))
   2054  1.1  mrg                         e.error("invalid UCS-32 char \\U%08x", c);
   2055  1.1  mrg                     else
   2056  1.1  mrg                         buffer.writeUTF16(c);
   2057  1.1  mrg                     newlen++;
   2058  1.1  mrg                 }
   2059  1.1  mrg                 newlen = buffer.length / 2;
   2060  1.1  mrg                 buffer.writeUTF16(0);
   2061  1.1  mrg                 goto L1;
   2062  1.1  mrg 
   2063  1.1  mrg             L1:
   2064  1.1  mrg                 if (!copied)
   2065  1.1  mrg                 {
   2066  1.1  mrg                     se = e.copy().isStringExp();
   2067  1.1  mrg                     copied = 1;
   2068  1.1  mrg                 }
   2069  1.1  mrg 
   2070  1.1  mrg                 {
   2071  1.1  mrg                     uinteger_t szx = tb.nextOf().size();
   2072  1.1  mrg                     assert(szx <= 255);
   2073  1.1  mrg                     se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
   2074  1.1  mrg                 }
   2075  1.1  mrg                 break;
   2076  1.1  mrg 
   2077  1.1  mrg             default:
   2078  1.1  mrg                 assert(typeb.nextOf().size() != tb.nextOf().size());
   2079  1.1  mrg                 goto Lcast;
   2080  1.1  mrg             }
   2081  1.1  mrg         }
   2082  1.1  mrg     L2:
   2083  1.1  mrg         assert(copied);
   2084  1.1  mrg 
   2085  1.1  mrg         // See if need to truncate or extend the literal
   2086  1.1  mrg         if (auto tsa = tb.isTypeSArray())
   2087  1.1  mrg         {
   2088  1.1  mrg             size_t dim2 = cast(size_t)tsa.dim.toInteger();
   2089  1.1  mrg             //printf("dim from = %d, to = %d\n", cast(int)se.len, cast(int)dim2);
   2090  1.1  mrg 
   2091  1.1  mrg             // Changing dimensions
   2092  1.1  mrg             if (dim2 != se.len)
   2093  1.1  mrg             {
   2094  1.1  mrg                 // Copy when changing the string literal
   2095  1.1  mrg                 const newsz = se.sz;
   2096  1.1  mrg                 const d = (dim2 < se.len) ? dim2 : se.len;
   2097  1.1  mrg                 void* s = mem.xmalloc((dim2 + 1) * newsz);
   2098  1.1  mrg                 memcpy(s, se.peekData().ptr, d * newsz);
   2099  1.1  mrg                 // Extend with 0, add terminating 0
   2100  1.1  mrg                 memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz);
   2101  1.1  mrg                 se.setData(s, dim2, newsz);
   2102  1.1  mrg             }
   2103  1.1  mrg         }
   2104  1.1  mrg         se.type = t;
   2105  1.1  mrg         return se;
   2106  1.1  mrg 
   2107  1.1  mrg     Lcast:
   2108  1.1  mrg         auto result = new CastExp(e.loc, se, t);
   2109  1.1  mrg         result.type = t; // so semantic() won't be run on e
   2110  1.1  mrg         return result;
   2111  1.1  mrg     }
   2112  1.1  mrg 
   2113  1.1  mrg     Expression visitAddr(AddrExp e)
   2114  1.1  mrg     {
   2115  1.1  mrg         version (none)
   2116  1.1  mrg         {
   2117  1.1  mrg             printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   2118  1.1  mrg         }
   2119  1.1  mrg         Type tb = t.toBasetype();
   2120  1.1  mrg         Type typeb = e.type.toBasetype();
   2121  1.1  mrg 
   2122  1.1  mrg         if (tb.equals(typeb))
   2123  1.1  mrg         {
   2124  1.1  mrg             auto result = e.copy();
   2125  1.1  mrg             result.type = t;
   2126  1.1  mrg             return result;
   2127  1.1  mrg         }
   2128  1.1  mrg 
   2129  1.1  mrg         // Look for pointers to functions where the functions are overloaded.
   2130  1.1  mrg         if (e.e1.isOverExp() &&
   2131  1.1  mrg             (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
   2132  1.1  mrg         {
   2133  1.1  mrg             OverExp eo = e.e1.isOverExp();
   2134  1.1  mrg             FuncDeclaration f = null;
   2135  1.1  mrg             for (size_t i = 0; i < eo.vars.a.dim; i++)
   2136  1.1  mrg             {
   2137  1.1  mrg                 auto s = eo.vars.a[i];
   2138  1.1  mrg                 auto f2 = s.isFuncDeclaration();
   2139  1.1  mrg                 assert(f2);
   2140  1.1  mrg                 if (f2.overloadExactMatch(tb.nextOf()))
   2141  1.1  mrg                 {
   2142  1.1  mrg                     if (f)
   2143  1.1  mrg                     {
   2144  1.1  mrg                         /* Error if match in more than one overload set,
   2145  1.1  mrg                          * even if one is a 'better' match than the other.
   2146  1.1  mrg                          */
   2147  1.1  mrg                         ScopeDsymbol.multiplyDefined(e.loc, f, f2);
   2148  1.1  mrg                     }
   2149  1.1  mrg                     else
   2150  1.1  mrg                         f = f2;
   2151  1.1  mrg                 }
   2152  1.1  mrg             }
   2153  1.1  mrg             if (f)
   2154  1.1  mrg             {
   2155  1.1  mrg                 f.tookAddressOf++;
   2156  1.1  mrg                 auto se = new SymOffExp(e.loc, f, 0, false);
   2157  1.1  mrg                 auto se2 = se.expressionSemantic(sc);
   2158  1.1  mrg                 // Let SymOffExp::castTo() do the heavy lifting
   2159  1.1  mrg                 return visit(se2);
   2160  1.1  mrg             }
   2161  1.1  mrg         }
   2162  1.1  mrg 
   2163  1.1  mrg         if (e.e1.isVarExp() &&
   2164  1.1  mrg             typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
   2165  1.1  mrg             tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
   2166  1.1  mrg         {
   2167  1.1  mrg             auto ve = e.e1.isVarExp();
   2168  1.1  mrg             auto f = ve.var.isFuncDeclaration();
   2169  1.1  mrg             if (f)
   2170  1.1  mrg             {
   2171  1.1  mrg                 assert(f.isImportedSymbol());
   2172  1.1  mrg                 f = f.overloadExactMatch(tb.nextOf());
   2173  1.1  mrg                 if (f)
   2174  1.1  mrg                 {
   2175  1.1  mrg                     Expression result = new VarExp(e.loc, f, false);
   2176  1.1  mrg                     result.type = f.type;
   2177  1.1  mrg                     result = new AddrExp(e.loc, result, t);
   2178  1.1  mrg                     return result;
   2179  1.1  mrg                 }
   2180  1.1  mrg             }
   2181  1.1  mrg         }
   2182  1.1  mrg 
   2183  1.1  mrg         if (auto f = isFuncAddress(e))
   2184  1.1  mrg         {
   2185  1.1  mrg             if (f.checkForwardRef(e.loc))
   2186  1.1  mrg             {
   2187  1.1  mrg                 return ErrorExp.get();
   2188  1.1  mrg             }
   2189  1.1  mrg         }
   2190  1.1  mrg 
   2191  1.1  mrg         return visit(e);
   2192  1.1  mrg     }
   2193  1.1  mrg 
   2194  1.1  mrg     Expression visitTuple(TupleExp e)
   2195  1.1  mrg     {
   2196  1.1  mrg         if (e.type.equals(t))
   2197  1.1  mrg         {
   2198  1.1  mrg             return e;
   2199  1.1  mrg         }
   2200  1.1  mrg 
   2201  1.1  mrg         /* If target type is a tuple of same length, cast each expression to
   2202  1.1  mrg          * the corresponding type in the tuple.
   2203  1.1  mrg          */
   2204  1.1  mrg         TypeTuple totuple;
   2205  1.1  mrg         if (auto tt = t.isTypeTuple())
   2206  1.1  mrg             totuple = e.exps.length == tt.arguments.length ? tt : null;
   2207  1.1  mrg 
   2208  1.1  mrg         TupleExp te = e.copy().isTupleExp();
   2209  1.1  mrg         te.e0 = e.e0 ? e.e0.copy() : null;
   2210  1.1  mrg         te.exps = e.exps.copy();
   2211  1.1  mrg         for (size_t i = 0; i < te.exps.dim; i++)
   2212  1.1  mrg         {
   2213  1.1  mrg             Expression ex = (*te.exps)[i];
   2214  1.1  mrg             ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
   2215  1.1  mrg             (*te.exps)[i] = ex;
   2216  1.1  mrg         }
   2217  1.1  mrg         if (totuple)
   2218  1.1  mrg             te.type = totuple;
   2219  1.1  mrg         return te;
   2220  1.1  mrg 
   2221  1.1  mrg         /* Questionable behavior: In here, result.type is not set to t
   2222  1.1  mrg          *  if target type is not a tuple of same length.
   2223  1.1  mrg          * Therefoe:
   2224  1.1  mrg          *  TypeTuple!(int, int) values;
   2225  1.1  mrg          *  auto values2 = cast(long)values;
   2226  1.1  mrg          *  // typeof(values2) == TypeTuple!(int, int) !!
   2227  1.1  mrg          *
   2228  1.1  mrg          * Only when the casted tuple is immediately expanded, it would work.
   2229  1.1  mrg          *  auto arr = [cast(long)values];
   2230  1.1  mrg          *  // typeof(arr) == long[]
   2231  1.1  mrg          */
   2232  1.1  mrg     }
   2233  1.1  mrg 
   2234  1.1  mrg     Expression visitArrayLiteral(ArrayLiteralExp e)
   2235  1.1  mrg     {
   2236  1.1  mrg         version (none)
   2237  1.1  mrg         {
   2238  1.1  mrg             printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
   2239  1.1  mrg         }
   2240  1.1  mrg 
   2241  1.1  mrg         ArrayLiteralExp ae = e;
   2242  1.1  mrg 
   2243  1.1  mrg         Type tb = t.toBasetype();
   2244  1.1  mrg         if (tb.ty == Tarray && global.params.useDIP1000 == FeatureState.enabled)
   2245  1.1  mrg         {
   2246  1.1  mrg             if (checkArrayLiteralEscape(sc, ae, false))
   2247  1.1  mrg             {
   2248  1.1  mrg                 return ErrorExp.get();
   2249  1.1  mrg             }
   2250  1.1  mrg         }
   2251  1.1  mrg 
   2252  1.1  mrg         if (e.type == t)
   2253  1.1  mrg         {
   2254  1.1  mrg             return e;
   2255  1.1  mrg         }
   2256  1.1  mrg         Type typeb = e.type.toBasetype();
   2257  1.1  mrg 
   2258  1.1  mrg         if ((tb.ty == Tarray || tb.ty == Tsarray) &&
   2259  1.1  mrg             (typeb.ty == Tarray || typeb.ty == Tsarray))
   2260  1.1  mrg         {
   2261  1.1  mrg             if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
   2262  1.1  mrg             {
   2263  1.1  mrg                 // Don't do anything to cast non-void[] to void[]
   2264  1.1  mrg             }
   2265  1.1  mrg             else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid)
   2266  1.1  mrg             {
   2267  1.1  mrg                 // Don't do anything for casting void[n] to others
   2268  1.1  mrg             }
   2269  1.1  mrg             else
   2270  1.1  mrg             {
   2271  1.1  mrg                 if (auto tsa = tb.isTypeSArray())
   2272  1.1  mrg                 {
   2273  1.1  mrg                     if (e.elements.dim != tsa.dim.toInteger())
   2274  1.1  mrg                         goto L1;
   2275  1.1  mrg                 }
   2276  1.1  mrg 
   2277  1.1  mrg                 ae = e.copy().isArrayLiteralExp();
   2278  1.1  mrg                 if (e.basis)
   2279  1.1  mrg                     ae.basis = e.basis.castTo(sc, tb.nextOf());
   2280  1.1  mrg                 ae.elements = e.elements.copy();
   2281  1.1  mrg                 for (size_t i = 0; i < e.elements.dim; i++)
   2282  1.1  mrg                 {
   2283  1.1  mrg                     Expression ex = (*e.elements)[i];
   2284  1.1  mrg                     if (!ex)
   2285  1.1  mrg                         continue;
   2286  1.1  mrg                     ex = ex.castTo(sc, tb.nextOf());
   2287  1.1  mrg                     (*ae.elements)[i] = ex;
   2288  1.1  mrg                 }
   2289  1.1  mrg                 ae.type = t;
   2290  1.1  mrg                 return ae;
   2291  1.1  mrg             }
   2292  1.1  mrg         }
   2293  1.1  mrg         else if (tb.ty == Tpointer && typeb.ty == Tsarray)
   2294  1.1  mrg         {
   2295  1.1  mrg             Type tp = typeb.nextOf().pointerTo();
   2296  1.1  mrg             if (!tp.equals(ae.type))
   2297  1.1  mrg             {
   2298  1.1  mrg                 ae = e.copy().isArrayLiteralExp();
   2299  1.1  mrg                 ae.type = tp;
   2300  1.1  mrg             }
   2301  1.1  mrg         }
   2302  1.1  mrg         else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
   2303  1.1  mrg         {
   2304  1.1  mrg             // Convert array literal to vector type
   2305  1.1  mrg             TypeVector tv = tb.isTypeVector();
   2306  1.1  mrg             TypeSArray tbase = tv.basetype.isTypeSArray();
   2307  1.1  mrg             assert(tbase.ty == Tsarray);
   2308  1.1  mrg             const edim = e.elements.dim;
   2309  1.1  mrg             const tbasedim = tbase.dim.toInteger();
   2310  1.1  mrg             if (edim > tbasedim)
   2311  1.1  mrg                 goto L1;
   2312  1.1  mrg 
   2313  1.1  mrg             ae = e.copy().isArrayLiteralExp();
   2314  1.1  mrg             ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
   2315  1.1  mrg             ae.elements = e.elements.copy();
   2316  1.1  mrg             Type telement = tv.elementType();
   2317  1.1  mrg             foreach (i; 0 .. edim)
   2318  1.1  mrg             {
   2319  1.1  mrg                 Expression ex = (*e.elements)[i];
   2320  1.1  mrg                 ex = ex.castTo(sc, telement);
   2321  1.1  mrg                 (*ae.elements)[i] = ex;
   2322  1.1  mrg             }
   2323  1.1  mrg             // Fill in the rest with the default initializer
   2324  1.1  mrg             ae.elements.setDim(cast(size_t)tbasedim);
   2325  1.1  mrg             foreach (i; edim .. cast(size_t)tbasedim)
   2326  1.1  mrg             {
   2327  1.1  mrg                 Expression ex = typeb.nextOf.defaultInitLiteral(e.loc);
   2328  1.1  mrg                 ex = ex.castTo(sc, telement);
   2329  1.1  mrg                 (*ae.elements)[i] = ex;
   2330  1.1  mrg             }
   2331  1.1  mrg             Expression ev = new VectorExp(e.loc, ae, tb);
   2332  1.1  mrg             ev = ev.expressionSemantic(sc);
   2333  1.1  mrg             return ev;
   2334  1.1  mrg         }
   2335  1.1  mrg     L1:
   2336  1.1  mrg         return visit(ae);
   2337  1.1  mrg     }
   2338  1.1  mrg 
   2339  1.1  mrg     Expression visitAssocArrayLiteral(AssocArrayLiteralExp e)
   2340  1.1  mrg     {
   2341  1.1  mrg         //printf("AssocArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
   2342  1.1  mrg         if (e.type == t)
   2343  1.1  mrg         {
   2344  1.1  mrg             return e;
   2345  1.1  mrg         }
   2346  1.1  mrg 
   2347  1.1  mrg         Type tb = t.toBasetype();
   2348  1.1  mrg         Type typeb = e.type.toBasetype();
   2349  1.1  mrg 
   2350  1.1  mrg         if (tb.ty == Taarray && typeb.ty == Taarray &&
   2351  1.1  mrg             tb.nextOf().toBasetype().ty != Tvoid)
   2352  1.1  mrg         {
   2353  1.1  mrg             AssocArrayLiteralExp ae = e.copy().isAssocArrayLiteralExp();
   2354  1.1  mrg             ae.keys = e.keys.copy();
   2355  1.1  mrg             ae.values = e.values.copy();
   2356  1.1  mrg             assert(e.keys.dim == e.values.dim);
   2357  1.1  mrg             for (size_t i = 0; i < e.keys.dim; i++)
   2358  1.1  mrg             {
   2359  1.1  mrg                 Expression ex = (*e.values)[i];
   2360  1.1  mrg                 ex = ex.castTo(sc, tb.nextOf());
   2361  1.1  mrg                 (*ae.values)[i] = ex;
   2362  1.1  mrg 
   2363  1.1  mrg                 ex = (*e.keys)[i];
   2364  1.1  mrg                 ex = ex.castTo(sc, tb.isTypeAArray().index);
   2365  1.1  mrg                 (*ae.keys)[i] = ex;
   2366  1.1  mrg             }
   2367  1.1  mrg             ae.type = t;
   2368  1.1  mrg             return ae;
   2369  1.1  mrg         }
   2370  1.1  mrg         return visit(e);
   2371  1.1  mrg     }
   2372  1.1  mrg 
   2373  1.1  mrg     Expression visitSymOff(SymOffExp e)
   2374  1.1  mrg     {
   2375  1.1  mrg         version (none)
   2376  1.1  mrg         {
   2377  1.1  mrg             printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   2378  1.1  mrg         }
   2379  1.1  mrg         if (e.type == t && !e.hasOverloads)
   2380  1.1  mrg         {
   2381  1.1  mrg             return e;
   2382  1.1  mrg         }
   2383  1.1  mrg 
   2384  1.1  mrg         Type tb = t.toBasetype();
   2385  1.1  mrg         Type typeb = e.type.toBasetype();
   2386  1.1  mrg 
   2387  1.1  mrg         if (tb.equals(typeb))
   2388  1.1  mrg         {
   2389  1.1  mrg             auto result = e.copy();
   2390  1.1  mrg             result.type = t;
   2391  1.1  mrg             result.isSymOffExp().hasOverloads = false;
   2392  1.1  mrg             return result;
   2393  1.1  mrg         }
   2394  1.1  mrg 
   2395  1.1  mrg         // Look for pointers to functions where the functions are overloaded.
   2396  1.1  mrg         if (e.hasOverloads &&
   2397  1.1  mrg             typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
   2398  1.1  mrg             (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
   2399  1.1  mrg         {
   2400  1.1  mrg             FuncDeclaration f = e.var.isFuncDeclaration();
   2401  1.1  mrg             f = f ? f.overloadExactMatch(tb.nextOf()) : null;
   2402  1.1  mrg             if (f)
   2403  1.1  mrg             {
   2404  1.1  mrg                 Expression result;
   2405  1.1  mrg                 if (tb.ty == Tdelegate)
   2406  1.1  mrg                 {
   2407  1.1  mrg                     if (f.needThis() && hasThis(sc))
   2408  1.1  mrg                     {
   2409  1.1  mrg                         result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false);
   2410  1.1  mrg                         result = result.expressionSemantic(sc);
   2411  1.1  mrg                     }
   2412  1.1  mrg                     else if (f.needThis())
   2413  1.1  mrg                     {
   2414  1.1  mrg                         e.error("no `this` to create delegate for `%s`", f.toChars());
   2415  1.1  mrg                         return ErrorExp.get();
   2416  1.1  mrg                     }
   2417  1.1  mrg                     else if (f.isNested())
   2418  1.1  mrg                     {
   2419  1.1  mrg                         result = new DelegateExp(e.loc, IntegerExp.literal!0, f, false);
   2420  1.1  mrg                         result = result.expressionSemantic(sc);
   2421  1.1  mrg                     }
   2422  1.1  mrg                     else
   2423  1.1  mrg                     {
   2424  1.1  mrg                         e.error("cannot cast from function pointer to delegate");
   2425  1.1  mrg                         return ErrorExp.get();
   2426  1.1  mrg                     }
   2427  1.1  mrg                 }
   2428  1.1  mrg                 else
   2429  1.1  mrg                 {
   2430  1.1  mrg                     result = new SymOffExp(e.loc, f, 0, false);
   2431  1.1  mrg                     result.type = t;
   2432  1.1  mrg                 }
   2433  1.1  mrg                 f.tookAddressOf++;
   2434  1.1  mrg                 return result;
   2435  1.1  mrg             }
   2436  1.1  mrg         }
   2437  1.1  mrg 
   2438  1.1  mrg         if (auto f = isFuncAddress(e))
   2439  1.1  mrg         {
   2440  1.1  mrg             if (f.checkForwardRef(e.loc))
   2441  1.1  mrg             {
   2442  1.1  mrg                 return ErrorExp.get();
   2443  1.1  mrg             }
   2444  1.1  mrg         }
   2445  1.1  mrg 
   2446  1.1  mrg         return visit(e);
   2447  1.1  mrg     }
   2448  1.1  mrg 
   2449  1.1  mrg     Expression visitDelegate(DelegateExp e)
   2450  1.1  mrg     {
   2451  1.1  mrg         version (none)
   2452  1.1  mrg         {
   2453  1.1  mrg             printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
   2454  1.1  mrg         }
   2455  1.1  mrg         static immutable msg = "cannot form delegate due to covariant return type";
   2456  1.1  mrg 
   2457  1.1  mrg         Type tb = t.toBasetype();
   2458  1.1  mrg         Type typeb = e.type.toBasetype();
   2459  1.1  mrg 
   2460  1.1  mrg         if (tb.equals(typeb) && !e.hasOverloads)
   2461  1.1  mrg         {
   2462  1.1  mrg             int offset;
   2463  1.1  mrg             e.func.tookAddressOf++;
   2464  1.1  mrg             if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
   2465  1.1  mrg                 e.error("%s", msg.ptr);
   2466  1.1  mrg             auto result = e.copy();
   2467  1.1  mrg             result.type = t;
   2468  1.1  mrg             return result;
   2469  1.1  mrg         }
   2470  1.1  mrg 
   2471  1.1  mrg         // Look for delegates to functions where the functions are overloaded.
   2472  1.1  mrg         if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
   2473  1.1  mrg         {
   2474  1.1  mrg             if (e.func)
   2475  1.1  mrg             {
   2476  1.1  mrg                 auto f = e.func.overloadExactMatch(tb.nextOf());
   2477  1.1  mrg                 if (f)
   2478  1.1  mrg                 {
   2479  1.1  mrg                     int offset;
   2480  1.1  mrg                     if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
   2481  1.1  mrg                         e.error("%s", msg.ptr);
   2482  1.1  mrg                     if (f != e.func)    // if address not already marked as taken
   2483  1.1  mrg                         f.tookAddressOf++;
   2484  1.1  mrg                     auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
   2485  1.1  mrg                     result.type = t;
   2486  1.1  mrg                     return result;
   2487  1.1  mrg                 }
   2488  1.1  mrg                 if (e.func.tintro)
   2489  1.1  mrg                     e.error("%s", msg.ptr);
   2490  1.1  mrg             }
   2491  1.1  mrg         }
   2492  1.1  mrg 
   2493  1.1  mrg         if (auto f = isFuncAddress(e))
   2494  1.1  mrg         {
   2495  1.1  mrg             if (f.checkForwardRef(e.loc))
   2496  1.1  mrg             {
   2497  1.1  mrg                 return ErrorExp.get();
   2498  1.1  mrg             }
   2499  1.1  mrg         }
   2500  1.1  mrg 
   2501  1.1  mrg         return visit(e);
   2502  1.1  mrg     }
   2503  1.1  mrg 
   2504  1.1  mrg     Expression visitFunc(FuncExp e)
   2505  1.1  mrg     {
   2506  1.1  mrg         //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
   2507  1.1  mrg         FuncExp fe;
   2508  1.1  mrg         if (e.matchType(t, sc, &fe, 1) > MATCH.nomatch)
   2509  1.1  mrg         {
   2510  1.1  mrg             return fe;
   2511  1.1  mrg         }
   2512  1.1  mrg         return visit(e);
   2513  1.1  mrg     }
   2514  1.1  mrg 
   2515  1.1  mrg     Expression visitCond(CondExp e)
   2516  1.1  mrg     {
   2517  1.1  mrg         if (!e.type.equals(t))
   2518  1.1  mrg         {
   2519  1.1  mrg             auto result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t));
   2520  1.1  mrg             result.type = t;
   2521  1.1  mrg             return result;
   2522  1.1  mrg         }
   2523  1.1  mrg         return e;
   2524  1.1  mrg     }
   2525  1.1  mrg 
   2526  1.1  mrg     Expression visitComma(CommaExp e)
   2527  1.1  mrg     {
   2528  1.1  mrg         Expression e2c = e.e2.castTo(sc, t);
   2529  1.1  mrg 
   2530  1.1  mrg         if (e2c != e.e2)
   2531  1.1  mrg         {
   2532  1.1  mrg             auto result = new CommaExp(e.loc, e.e1, e2c);
   2533  1.1  mrg             result.type = e2c.type;
   2534  1.1  mrg             return result;
   2535  1.1  mrg         }
   2536  1.1  mrg         else
   2537  1.1  mrg         {
   2538  1.1  mrg             e.type = e.e2.type;
   2539  1.1  mrg             return e;
   2540  1.1  mrg         }
   2541  1.1  mrg     }
   2542  1.1  mrg 
   2543  1.1  mrg     Expression visitSlice(SliceExp e)
   2544  1.1  mrg     {
   2545  1.1  mrg         //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e.toChars(), e.type.toChars(), t.toChars());
   2546  1.1  mrg 
   2547  1.1  mrg         Type tb = t.toBasetype();
   2548  1.1  mrg         Type typeb = e.type.toBasetype();
   2549  1.1  mrg 
   2550  1.1  mrg         if (e.type.equals(t) || typeb.ty != Tarray ||
   2551  1.1  mrg             (tb.ty != Tarray && tb.ty != Tsarray))
   2552  1.1  mrg         {
   2553  1.1  mrg             return visit(e);
   2554  1.1  mrg         }
   2555  1.1  mrg 
   2556  1.1  mrg         if (tb.ty == Tarray)
   2557  1.1  mrg         {
   2558  1.1  mrg             if (typeb.nextOf().equivalent(tb.nextOf()))
   2559  1.1  mrg             {
   2560  1.1  mrg                 // T[] to const(T)[]
   2561  1.1  mrg                 auto result = e.copy();
   2562  1.1  mrg                 result.type = t;
   2563  1.1  mrg                 return result;
   2564  1.1  mrg             }
   2565  1.1  mrg             else
   2566  1.1  mrg             {
   2567  1.1  mrg                 return visit(e);
   2568  1.1  mrg             }
   2569  1.1  mrg         }
   2570  1.1  mrg 
   2571  1.1  mrg         // Handle the cast from Tarray to Tsarray with CT-known slicing
   2572  1.1  mrg 
   2573  1.1  mrg         TypeSArray tsa = toStaticArrayType(e).isTypeSArray();
   2574  1.1  mrg         if (tsa && tsa.size(e.loc) == tb.size(e.loc))
   2575  1.1  mrg         {
   2576  1.1  mrg             /* Match if the sarray sizes are equal:
   2577  1.1  mrg              *  T[a .. b] to const(T)[b-a]
   2578  1.1  mrg              *  T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
   2579  1.1  mrg              *
   2580  1.1  mrg              * If a SliceExp has Tsarray, it will become lvalue.
   2581  1.1  mrg              * That's handled in SliceExp::isLvalue and toLvalue
   2582  1.1  mrg              */
   2583  1.1  mrg             auto result = e.copy();
   2584  1.1  mrg             result.type = t;
   2585  1.1  mrg             return result;
   2586  1.1  mrg         }
   2587  1.1  mrg         if (tsa && tsa.dim.equals(tb.isTypeSArray().dim))
   2588  1.1  mrg         {
   2589  1.1  mrg             /* Match if the dimensions are equal
   2590  1.1  mrg              * with the implicit conversion of e.e1:
   2591  1.1  mrg              *  cast(float[2]) [2.0, 1.0, 0.0][0..2];
   2592  1.1  mrg              */
   2593  1.1  mrg             Type t1b = e.e1.type.toBasetype();
   2594  1.1  mrg             if (t1b.ty == Tsarray)
   2595  1.1  mrg                 t1b = tb.nextOf().sarrayOf(t1b.isTypeSArray().dim.toInteger());
   2596  1.1  mrg             else if (t1b.ty == Tarray)
   2597  1.1  mrg                 t1b = tb.nextOf().arrayOf();
   2598  1.1  mrg             else if (t1b.ty == Tpointer)
   2599  1.1  mrg                 t1b = tb.nextOf().pointerTo();
   2600  1.1  mrg             else
   2601  1.1  mrg                 assert(0);
   2602  1.1  mrg             if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
   2603  1.1  mrg             {
   2604  1.1  mrg                 Expression e1x = e.e1.implicitCastTo(sc, t1b);
   2605  1.1  mrg                 assert(e1x.op != EXP.error);
   2606  1.1  mrg                 e = e.copy().isSliceExp();
   2607  1.1  mrg                 e.e1 = e1x;
   2608  1.1  mrg                 e.type = t;
   2609  1.1  mrg                 return e;
   2610  1.1  mrg             }
   2611  1.1  mrg         }
   2612  1.1  mrg         auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
   2613  1.1  mrg         e.error("cannot cast expression `%s` of type `%s` to `%s`",
   2614  1.1  mrg             e.toChars(), ts[0], ts[1]);
   2615  1.1  mrg         return ErrorExp.get();
   2616  1.1  mrg     }
   2617  1.1  mrg 
   2618  1.1  mrg     // Casting to noreturn isn't an actual cast
   2619  1.1  mrg     // Rewrite cast(<qual> noreturn) <exp>
   2620  1.1  mrg     // as      <exp>, assert(false)
   2621  1.1  mrg     if (t.isTypeNoreturn())
   2622  1.1  mrg     {
   2623  1.1  mrg         // Don't generate an unreachable assert(false) if e will abort
   2624  1.1  mrg         if (e.type.isTypeNoreturn())
   2625  1.1  mrg         {
   2626  1.1  mrg             // Paint e to accomodate for different type qualifiers
   2627  1.1  mrg             e.type = t;
   2628  1.1  mrg             return e;
   2629  1.1  mrg         }
   2630  1.1  mrg 
   2631  1.1  mrg         auto ini = t.defaultInitLiteral(e.loc);
   2632  1.1  mrg         return Expression.combine(e, ini);
   2633  1.1  mrg     }
   2634  1.1  mrg 
   2635  1.1  mrg     switch (e.op)
   2636  1.1  mrg     {
   2637  1.1  mrg         default                   : return visit(e);
   2638  1.1  mrg         case EXP.error            : return visitError(e.isErrorExp());
   2639  1.1  mrg         case EXP.float64          : return visitReal(e.isRealExp());
   2640  1.1  mrg         case EXP.complex80        : return visitComplex(e.isComplexExp());
   2641  1.1  mrg         case EXP.structLiteral    : return visitStructLiteral(e.isStructLiteralExp());
   2642  1.1  mrg         case EXP.string_          : return visitString(e.isStringExp());
   2643  1.1  mrg         case EXP.address          : return visitAddr(e.isAddrExp());
   2644  1.1  mrg         case EXP.tuple            : return visitTuple(e.isTupleExp());
   2645  1.1  mrg         case EXP.arrayLiteral     : return visitArrayLiteral(e.isArrayLiteralExp());
   2646  1.1  mrg         case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
   2647  1.1  mrg         case EXP.symbolOffset     : return visitSymOff(e.isSymOffExp());
   2648  1.1  mrg         case EXP.delegate_        : return visitDelegate(e.isDelegateExp());
   2649  1.1  mrg         case EXP.function_        : return visitFunc(e.isFuncExp());
   2650  1.1  mrg         case EXP.question         : return visitCond(e.isCondExp());
   2651  1.1  mrg         case EXP.comma            : return visitComma(e.isCommaExp());
   2652  1.1  mrg         case EXP.slice            : return visitSlice(e.isSliceExp());
   2653  1.1  mrg     }
   2654  1.1  mrg }
   2655  1.1  mrg 
   2656  1.1  mrg /****************************************
   2657  1.1  mrg  * Set type inference target
   2658  1.1  mrg  *      t       Target type
   2659  1.1  mrg  *      flag    1: don't put an error when inference fails
   2660  1.1  mrg  */
   2661  1.1  mrg Expression inferType(Expression e, Type t, int flag = 0)
   2662  1.1  mrg {
   2663  1.1  mrg     Expression visitAle(ArrayLiteralExp ale)
   2664  1.1  mrg     {
   2665  1.1  mrg         Type tb = t.toBasetype();
   2666  1.1  mrg         if (tb.ty == Tarray || tb.ty == Tsarray)
   2667  1.1  mrg         {
   2668  1.1  mrg             Type tn = tb.nextOf();
   2669  1.1  mrg             if (ale.basis)
   2670  1.1  mrg                 ale.basis = inferType(ale.basis, tn, flag);
   2671  1.1  mrg             for (size_t i = 0; i < ale.elements.dim; i++)
   2672  1.1  mrg             {
   2673  1.1  mrg                 if (Expression e = (*ale.elements)[i])
   2674  1.1  mrg                 {
   2675  1.1  mrg                     e = inferType(e, tn, flag);
   2676  1.1  mrg                     (*ale.elements)[i] = e;
   2677  1.1  mrg                 }
   2678  1.1  mrg             }
   2679  1.1  mrg         }
   2680  1.1  mrg         return ale;
   2681  1.1  mrg     }
   2682  1.1  mrg 
   2683  1.1  mrg     Expression visitAar(AssocArrayLiteralExp aale)
   2684  1.1  mrg     {
   2685  1.1  mrg         Type tb = t.toBasetype();
   2686  1.1  mrg         if (auto taa = tb.isTypeAArray())
   2687  1.1  mrg         {
   2688  1.1  mrg             Type ti = taa.index;
   2689  1.1  mrg             Type tv = taa.nextOf();
   2690  1.1  mrg             for (size_t i = 0; i < aale.keys.dim; i++)
   2691  1.1  mrg             {
   2692  1.1  mrg                 if (Expression e = (*aale.keys)[i])
   2693  1.1  mrg                 {
   2694  1.1  mrg                     e = inferType(e, ti, flag);
   2695  1.1  mrg                     (*aale.keys)[i] = e;
   2696  1.1  mrg                 }
   2697  1.1  mrg             }
   2698  1.1  mrg             for (size_t i = 0; i < aale.values.dim; i++)
   2699  1.1  mrg             {
   2700  1.1  mrg                 if (Expression e = (*aale.values)[i])
   2701  1.1  mrg                 {
   2702  1.1  mrg                     e = inferType(e, tv, flag);
   2703  1.1  mrg                     (*aale.values)[i] = e;
   2704  1.1  mrg                 }
   2705  1.1  mrg             }
   2706  1.1  mrg         }
   2707  1.1  mrg         return aale;
   2708  1.1  mrg     }
   2709  1.1  mrg 
   2710  1.1  mrg     Expression visitFun(FuncExp fe)
   2711  1.1  mrg     {
   2712  1.1  mrg         //printf("FuncExp::inferType('%s'), to=%s\n", fe.type ? fe.type.toChars() : "null", t.toChars());
   2713  1.1  mrg         if (t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction)
   2714  1.1  mrg         {
   2715  1.1  mrg             fe.fd.treq = t;
   2716  1.1  mrg         }
   2717  1.1  mrg         return fe;
   2718  1.1  mrg     }
   2719  1.1  mrg 
   2720  1.1  mrg     Expression visitTer(CondExp ce)
   2721  1.1  mrg     {
   2722  1.1  mrg         Type tb = t.toBasetype();
   2723  1.1  mrg         ce.e1 = inferType(ce.e1, tb, flag);
   2724  1.1  mrg         ce.e2 = inferType(ce.e2, tb, flag);
   2725  1.1  mrg         return ce;
   2726  1.1  mrg     }
   2727  1.1  mrg 
   2728  1.1  mrg     if (t) switch (e.op)
   2729  1.1  mrg     {
   2730  1.1  mrg         case EXP.arrayLiteral:      return visitAle(e.isArrayLiteralExp());
   2731  1.1  mrg         case EXP.assocArrayLiteral: return visitAar(e.isAssocArrayLiteralExp());
   2732  1.1  mrg         case EXP.function_:         return visitFun(e.isFuncExp());
   2733  1.1  mrg         case EXP.question:          return visitTer(e.isCondExp());
   2734  1.1  mrg         default:
   2735  1.1  mrg     }
   2736  1.1  mrg     return e;
   2737  1.1  mrg }
   2738  1.1  mrg 
   2739  1.1  mrg /****************************************
   2740  1.1  mrg  * Scale addition/subtraction to/from pointer.
   2741  1.1  mrg  */
   2742  1.1  mrg Expression scaleFactor(BinExp be, Scope* sc)
   2743  1.1  mrg {
   2744  1.1  mrg     Type t1b = be.e1.type.toBasetype();
   2745  1.1  mrg     Type t2b = be.e2.type.toBasetype();
   2746  1.1  mrg     Expression eoff;
   2747  1.1  mrg 
   2748  1.1  mrg     if (t1b.ty == Tpointer && t2b.isintegral())
   2749  1.1  mrg     {
   2750  1.1  mrg         // Need to adjust operator by the stride
   2751  1.1  mrg         // Replace (ptr + int) with (ptr + (int * stride))
   2752  1.1  mrg         Type t = Type.tptrdiff_t;
   2753  1.1  mrg 
   2754  1.1  mrg         uinteger_t stride = t1b.nextOf().size(be.loc);
   2755  1.1  mrg         if (!t.equals(t2b))
   2756  1.1  mrg             be.e2 = be.e2.castTo(sc, t);
   2757  1.1  mrg         eoff = be.e2;
   2758  1.1  mrg         be.e2 = new MulExp(be.loc, be.e2, new IntegerExp(Loc.initial, stride, t));
   2759  1.1  mrg         be.e2.type = t;
   2760  1.1  mrg         be.type = be.e1.type;
   2761  1.1  mrg     }
   2762  1.1  mrg     else if (t2b.ty == Tpointer && t1b.isintegral())
   2763  1.1  mrg     {
   2764  1.1  mrg         // Need to adjust operator by the stride
   2765  1.1  mrg         // Replace (int + ptr) with (ptr + (int * stride))
   2766  1.1  mrg         Type t = Type.tptrdiff_t;
   2767  1.1  mrg         Expression e;
   2768  1.1  mrg 
   2769  1.1  mrg         uinteger_t stride = t2b.nextOf().size(be.loc);
   2770  1.1  mrg         if (!t.equals(t1b))
   2771  1.1  mrg             e = be.e1.castTo(sc, t);
   2772  1.1  mrg         else
   2773  1.1  mrg             e = be.e1;
   2774  1.1  mrg         eoff = e;
   2775  1.1  mrg         e = new MulExp(be.loc, e, new IntegerExp(Loc.initial, stride, t));
   2776  1.1  mrg         e.type = t;
   2777  1.1  mrg         be.type = be.e2.type;
   2778  1.1  mrg         be.e1 = be.e2;
   2779  1.1  mrg         be.e2 = e;
   2780  1.1  mrg     }
   2781  1.1  mrg     else
   2782  1.1  mrg         assert(0);
   2783  1.1  mrg 
   2784  1.1  mrg     if (sc.func && !sc.intypeof)
   2785  1.1  mrg     {
   2786  1.1  mrg         eoff = eoff.optimize(WANTvalue);
   2787  1.1  mrg         if (eoff.op == EXP.int64 && eoff.toInteger() == 0)
   2788  1.1  mrg         {
   2789  1.1  mrg         }
   2790  1.1  mrg         else if (sc.func.setUnsafe())
   2791  1.1  mrg         {
   2792  1.1  mrg             be.error("pointer arithmetic not allowed in @safe functions");
   2793  1.1  mrg             return ErrorExp.get();
   2794  1.1  mrg         }
   2795  1.1  mrg     }
   2796  1.1  mrg 
   2797  1.1  mrg     return be;
   2798  1.1  mrg }
   2799  1.1  mrg 
   2800  1.1  mrg /**************************************
   2801  1.1  mrg  * Return true if e is an empty array literal with dimensionality
   2802  1.1  mrg  * equal to or less than type of other array.
   2803  1.1  mrg  * [], [[]], [[[]]], etc.
   2804  1.1  mrg  * I.e., make sure that [1,2] is compatible with [],
   2805  1.1  mrg  * [[1,2]] is compatible with [[]], etc.
   2806  1.1  mrg  */
   2807  1.1  mrg private bool isVoidArrayLiteral(Expression e, Type other)
   2808  1.1  mrg {
   2809  1.1  mrg     while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && (e.isArrayLiteralExp().elements.dim == 1))
   2810  1.1  mrg     {
   2811  1.1  mrg         auto ale = e.isArrayLiteralExp();
   2812  1.1  mrg         e = ale[0];
   2813  1.1  mrg         if (other.ty == Tsarray || other.ty == Tarray)
   2814  1.1  mrg             other = other.nextOf();
   2815  1.1  mrg         else
   2816  1.1  mrg             return false;
   2817  1.1  mrg     }
   2818  1.1  mrg     if (other.ty != Tsarray && other.ty != Tarray)
   2819  1.1  mrg         return false;
   2820  1.1  mrg     Type t = e.type;
   2821  1.1  mrg     return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && e.isArrayLiteralExp().elements.dim == 0);
   2822  1.1  mrg }
   2823  1.1  mrg 
   2824  1.1  mrg /**
   2825  1.1  mrg  * Merge types of `e1` and `e2` into a common subset
   2826  1.1  mrg  *
   2827  1.1  mrg  * Parameters `e1` and `e2` will be rewritten in place as needed.
   2828  1.1  mrg  *
   2829  1.1  mrg  * Params:
   2830  1.1  mrg  *     sc  = Current scope
   2831  1.1  mrg  *     op  = Operator such as `e1 op e2`. In practice, either EXP.question
   2832  1.1  mrg  *           or one of the binary operator.
   2833  1.1  mrg  *     pe1 = The LHS of the operation, will be rewritten
   2834  1.1  mrg  *     pe2 = The RHS of the operation, will be rewritten
   2835  1.1  mrg  *
   2836  1.1  mrg  * Returns:
   2837  1.1  mrg  *      The resulting type in case of success, `null` in case of error
   2838  1.1  mrg  */
   2839  1.1  mrg Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2)
   2840  1.1  mrg {
   2841  1.1  mrg     //printf("typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
   2842  1.1  mrg 
   2843  1.1  mrg     Expression e1 = pe1;
   2844  1.1  mrg     Expression e2 = pe2;
   2845  1.1  mrg 
   2846  1.1  mrg     // ImportC: do array/function conversions
   2847  1.1  mrg     if (sc)
   2848  1.1  mrg     {
   2849  1.1  mrg         e1 = e1.arrayFuncConv(sc);
   2850  1.1  mrg         e2 = e2.arrayFuncConv(sc);
   2851  1.1  mrg     }
   2852  1.1  mrg 
   2853  1.1  mrg     Type Lret(Type result)
   2854  1.1  mrg     {
   2855  1.1  mrg         pe1 = e1;
   2856  1.1  mrg         pe2 = e2;
   2857  1.1  mrg 
   2858  1.1  mrg         version (none)
   2859  1.1  mrg         {
   2860  1.1  mrg             printf("-typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
   2861  1.1  mrg             if (e1.type)
   2862  1.1  mrg                 printf("\tt1 = %s\n", e1.type.toChars());
   2863  1.1  mrg             if (e2.type)
   2864  1.1  mrg                 printf("\tt2 = %s\n", e2.type.toChars());
   2865  1.1  mrg             printf("\ttype = %s\n", result.toChars());
   2866  1.1  mrg         }
   2867  1.1  mrg         return result;
   2868  1.1  mrg     }
   2869  1.1  mrg 
   2870  1.1  mrg     /// Converts one of the expression to the other
   2871  1.1  mrg     Type convert(ref Expression from, Type to)
   2872  1.1  mrg     {
   2873  1.1  mrg         from = from.castTo(sc, to);
   2874  1.1  mrg         return Lret(to);
   2875  1.1  mrg     }
   2876  1.1  mrg 
   2877  1.1  mrg     /// Converts both expression to a third type
   2878  1.1  mrg     Type coerce(Type towards)
   2879  1.1  mrg     {
   2880  1.1  mrg         e1 = e1.castTo(sc, towards);
   2881  1.1  mrg         e2 = e2.castTo(sc, towards);
   2882  1.1  mrg         return Lret(towards);
   2883  1.1  mrg     }
   2884  1.1  mrg 
   2885  1.1  mrg     Type t1b = e1.type.toBasetype();
   2886  1.1  mrg     Type t2b = e2.type.toBasetype();
   2887  1.1  mrg 
   2888  1.1  mrg     if (sc && sc.flags & SCOPE.Cfile)
   2889  1.1  mrg     {
   2890  1.1  mrg         // Integral types can be implicitly converted to pointers
   2891  1.1  mrg         if ((t1b.ty == Tpointer) != (t2b.ty == Tpointer))
   2892  1.1  mrg         {
   2893  1.1  mrg             if (t1b.isintegral())
   2894  1.1  mrg             {
   2895  1.1  mrg                 return convert(e1, t2b);
   2896  1.1  mrg             }
   2897  1.1  mrg             else if (t2b.isintegral())
   2898  1.1  mrg             {
   2899  1.1  mrg                 return convert(e2, t1b);
   2900  1.1  mrg             }
   2901  1.1  mrg         }
   2902  1.1  mrg     }
   2903  1.1  mrg 
   2904  1.1  mrg     if (op != EXP.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
   2905  1.1  mrg     {
   2906  1.1  mrg         if (op == EXP.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
   2907  1.1  mrg         {
   2908  1.1  mrg             e1 = e1.castTo(sc, Type.tdchar);
   2909  1.1  mrg             e2 = e2.castTo(sc, Type.tdchar);
   2910  1.1  mrg         }
   2911  1.1  mrg         else
   2912  1.1  mrg         {
   2913  1.1  mrg             e1 = integralPromotions(e1, sc);
   2914  1.1  mrg             e2 = integralPromotions(e2, sc);
   2915  1.1  mrg         }
   2916  1.1  mrg     }
   2917  1.1  mrg 
   2918  1.1  mrg     MATCH m;
   2919  1.1  mrg     Type t1 = e1.type;
   2920  1.1  mrg     Type t2 = e2.type;
   2921  1.1  mrg     assert(t1);
   2922  1.1  mrg     Type t = t1;
   2923  1.1  mrg 
   2924  1.1  mrg     /* The start type of alias this type recursion.
   2925  1.1  mrg      * In following case, we should save A, and stop recursion
   2926  1.1  mrg      * if it appears again.
   2927  1.1  mrg      *      X -> Y -> [A] -> B -> A -> B -> ...
   2928  1.1  mrg      */
   2929  1.1  mrg     Type att1 = null;
   2930  1.1  mrg     Type att2 = null;
   2931  1.1  mrg 
   2932  1.1  mrg     if (t1.mod != t2.mod &&
   2933  1.1  mrg         t1.ty == Tenum && t2.ty == Tenum &&
   2934  1.1  mrg         t1.isTypeEnum().sym == t2.isTypeEnum().sym)
   2935  1.1  mrg     {
   2936  1.1  mrg         ubyte mod = MODmerge(t1.mod, t2.mod);
   2937  1.1  mrg         t1 = t1.castMod(mod);
   2938  1.1  mrg         t2 = t2.castMod(mod);
   2939  1.1  mrg     }
   2940  1.1  mrg 
   2941  1.1  mrg Lagain:
   2942  1.1  mrg     t1b = t1.toBasetype();
   2943  1.1  mrg     t2b = t2.toBasetype();
   2944  1.1  mrg 
   2945  1.1  mrg     const ty = implicitConvCommonTy(t1b.ty, t2b.ty);
   2946  1.1  mrg     if (ty != Terror)
   2947  1.1  mrg     {
   2948  1.1  mrg         const ty1 = implicitConvTy1(t1b.ty, t2b.ty);
   2949  1.1  mrg         const ty2 = implicitConvTy1(t2b.ty, t1b.ty);
   2950  1.1  mrg 
   2951  1.1  mrg         if (t1b.ty == ty1) // if no promotions
   2952  1.1  mrg         {
   2953  1.1  mrg             if (t1.equals(t2))
   2954  1.1  mrg                 return Lret(t1);
   2955  1.1  mrg 
   2956  1.1  mrg             if (t1b.equals(t2b))
   2957  1.1  mrg                 return Lret(t1b);
   2958  1.1  mrg         }
   2959  1.1  mrg 
   2960  1.1  mrg         t1 = Type.basic[ty1];
   2961  1.1  mrg         t2 = Type.basic[ty2];
   2962  1.1  mrg 
   2963  1.1  mrg         if (!(t1 && t2))
   2964  1.1  mrg             return null;
   2965  1.1  mrg         e1 = e1.castTo(sc, t1);
   2966  1.1  mrg         e2 = e2.castTo(sc, t2);
   2967  1.1  mrg         return Lret(Type.basic[ty]);
   2968  1.1  mrg     }
   2969  1.1  mrg 
   2970  1.1  mrg     t1 = t1b;
   2971  1.1  mrg     t2 = t2b;
   2972  1.1  mrg 
   2973  1.1  mrg     if (t1.ty == Ttuple || t2.ty == Ttuple)
   2974  1.1  mrg         return null;
   2975  1.1  mrg 
   2976  1.1  mrg     if (t1.equals(t2))
   2977  1.1  mrg     {
   2978  1.1  mrg         // merging can not result in new enum type
   2979  1.1  mrg         if (t.ty == Tenum)
   2980  1.1  mrg             return Lret(t1b);
   2981  1.1  mrg         return Lret(t);
   2982  1.1  mrg     }
   2983  1.1  mrg 
   2984  1.1  mrg     if ((t1.ty == Tpointer && t2.ty == Tpointer) || (t1.ty == Tdelegate && t2.ty == Tdelegate))
   2985  1.1  mrg     {
   2986  1.1  mrg         // Bring pointers to compatible type
   2987  1.1  mrg         Type t1n = t1.nextOf();
   2988  1.1  mrg         Type t2n = t2.nextOf();
   2989  1.1  mrg 
   2990  1.1  mrg         if (t1n.equals(t2n))
   2991  1.1  mrg             return Lret(t);
   2992  1.1  mrg 
   2993  1.1  mrg         if (t1n.ty == Tvoid) // pointers to void are always compatible
   2994  1.1  mrg             return Lret(t2);
   2995  1.1  mrg 
   2996  1.1  mrg         if (t2n.ty == Tvoid)
   2997  1.1  mrg             return Lret(t);
   2998  1.1  mrg 
   2999  1.1  mrg         if (t1.implicitConvTo(t2))
   3000  1.1  mrg             return convert(e1, t2);
   3001  1.1  mrg 
   3002  1.1  mrg         if (t2.implicitConvTo(t1))
   3003  1.1  mrg             return convert(e2, t1);
   3004  1.1  mrg 
   3005  1.1  mrg         if (t1n.ty == Tfunction && t2n.ty == Tfunction)
   3006  1.1  mrg         {
   3007  1.1  mrg             TypeFunction tf1 = t1n.isTypeFunction();
   3008  1.1  mrg             TypeFunction tf2 = t2n.isTypeFunction();
   3009  1.1  mrg             tf1.purityLevel();
   3010  1.1  mrg             tf2.purityLevel();
   3011  1.1  mrg 
   3012  1.1  mrg             TypeFunction d = tf1.syntaxCopy();
   3013  1.1  mrg 
   3014  1.1  mrg             if (tf1.purity != tf2.purity)
   3015  1.1  mrg                 d.purity = PURE.impure;
   3016  1.1  mrg             assert(d.purity != PURE.fwdref);
   3017  1.1  mrg 
   3018  1.1  mrg             d.isnothrow = (tf1.isnothrow && tf2.isnothrow);
   3019  1.1  mrg             d.isnogc = (tf1.isnogc && tf2.isnogc);
   3020  1.1  mrg 
   3021  1.1  mrg             if (tf1.trust == tf2.trust)
   3022  1.1  mrg                 d.trust = tf1.trust;
   3023  1.1  mrg             else if (tf1.trust <= TRUST.system || tf2.trust <= TRUST.system)
   3024  1.1  mrg                 d.trust = TRUST.system;
   3025  1.1  mrg             else
   3026  1.1  mrg                 d.trust = TRUST.trusted;
   3027  1.1  mrg 
   3028  1.1  mrg             Type tx = (t1.ty == Tdelegate) ? new TypeDelegate(d) : d.pointerTo();
   3029  1.1  mrg             tx = tx.typeSemantic(e1.loc, sc);
   3030  1.1  mrg 
   3031  1.1  mrg             if (t1.implicitConvTo(tx) && t2.implicitConvTo(tx))
   3032  1.1  mrg                 return coerce(tx);
   3033  1.1  mrg             return null;
   3034  1.1  mrg         }
   3035  1.1  mrg 
   3036  1.1  mrg         if (t1n.mod != t2n.mod)
   3037  1.1  mrg         {
   3038  1.1  mrg             if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
   3039  1.1  mrg                 return null;
   3040  1.1  mrg             ubyte mod = MODmerge(t1n.mod, t2n.mod);
   3041  1.1  mrg             t1 = t1n.castMod(mod).pointerTo();
   3042  1.1  mrg             t2 = t2n.castMod(mod).pointerTo();
   3043  1.1  mrg             t = t1;
   3044  1.1  mrg             goto Lagain;
   3045  1.1  mrg         }
   3046  1.1  mrg 
   3047  1.1  mrg         if (t1n.ty == Tclass && t2n.ty == Tclass)
   3048  1.1  mrg         {
   3049  1.1  mrg             ClassDeclaration cd1 = t1n.isClassHandle();
   3050  1.1  mrg             ClassDeclaration cd2 = t2n.isClassHandle();
   3051  1.1  mrg             int offset;
   3052  1.1  mrg             if (cd1.isBaseOf(cd2, &offset))
   3053  1.1  mrg             {
   3054  1.1  mrg                 if (offset)
   3055  1.1  mrg                     e2 = e2.castTo(sc, t);
   3056  1.1  mrg                 return Lret(t);
   3057  1.1  mrg             }
   3058  1.1  mrg 
   3059  1.1  mrg             if (cd2.isBaseOf(cd1, &offset))
   3060  1.1  mrg             {
   3061  1.1  mrg                 if (offset)
   3062  1.1  mrg                     e1 = e1.castTo(sc, t2);
   3063  1.1  mrg                 return Lret(t2);
   3064  1.1  mrg             }
   3065  1.1  mrg 
   3066  1.1  mrg             return null;
   3067  1.1  mrg         }
   3068  1.1  mrg 
   3069  1.1  mrg         t1 = t1n.constOf().pointerTo();
   3070  1.1  mrg         t2 = t2n.constOf().pointerTo();
   3071  1.1  mrg         if (t1.implicitConvTo(t2))
   3072  1.1  mrg             return convert(e1, t2);
   3073  1.1  mrg         if (t2.implicitConvTo(t1))
   3074  1.1  mrg             return convert(e2, t1);
   3075  1.1  mrg         return null;
   3076  1.1  mrg     }
   3077  1.1  mrg 
   3078  1.1  mrg     if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
   3079  1.1  mrg     {
   3080  1.1  mrg         /*  (T[n] op void*)   => T[]
   3081  1.1  mrg          *  (T[]  op void*)   => T[]
   3082  1.1  mrg          *  (T[n] op void[0]) => T[]
   3083  1.1  mrg          *  (T[]  op void[0]) => T[]
   3084  1.1  mrg          *  (T[n] op void[])  => T[]
   3085  1.1  mrg          *  (T[]  op void[])  => T[]
   3086  1.1  mrg          */
   3087  1.1  mrg         return coerce(t1.nextOf().arrayOf());
   3088  1.1  mrg     }
   3089  1.1  mrg 
   3090  1.1  mrg     if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
   3091  1.1  mrg     {
   3092  1.1  mrg         /*  (void*   op T[n]) => T[]
   3093  1.1  mrg          *  (void*   op T[])  => T[]
   3094  1.1  mrg          *  (void[0] op T[n]) => T[]
   3095  1.1  mrg          *  (void[0] op T[])  => T[]
   3096  1.1  mrg          *  (void[]  op T[n]) => T[]
   3097  1.1  mrg          *  (void[]  op T[])  => T[]
   3098  1.1  mrg          */
   3099  1.1  mrg         return coerce(t2.nextOf().arrayOf());
   3100  1.1  mrg     }
   3101  1.1  mrg 
   3102  1.1  mrg     if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
   3103  1.1  mrg     {
   3104  1.1  mrg         // https://issues.dlang.org/show_bug.cgi?id=7285
   3105  1.1  mrg         // Tsarray op [x, y, ...] should to be Tsarray
   3106  1.1  mrg         // https://issues.dlang.org/show_bug.cgi?id=14737
   3107  1.1  mrg         // Tsarray ~ [x, y, ...] should to be Tarray
   3108  1.1  mrg         if (t1.ty == Tsarray && e2.op == EXP.arrayLiteral && op != EXP.concatenate)
   3109  1.1  mrg             return convert(e2, t1);
   3110  1.1  mrg         if (m == MATCH.constant && (op == EXP.addAssign || op == EXP.minAssign || op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign || op == EXP.powAssign || op == EXP.andAssign || op == EXP.orAssign || op == EXP.xorAssign))
   3111  1.1  mrg         {
   3112  1.1  mrg             // Don't make the lvalue const
   3113  1.1  mrg             return Lret(t2);
   3114  1.1  mrg         }
   3115  1.1  mrg         return convert(e1, t2);
   3116  1.1  mrg     }
   3117  1.1  mrg 
   3118  1.1  mrg     if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
   3119  1.1  mrg     {
   3120  1.1  mrg         // https://issues.dlang.org/show_bug.cgi?id=7285
   3121  1.1  mrg         // https://issues.dlang.org/show_bug.cgi?id=14737
   3122  1.1  mrg         if (t2.ty == Tsarray && e1.op == EXP.arrayLiteral && op != EXP.concatenate)
   3123  1.1  mrg             return convert(e1, t2);
   3124  1.1  mrg         return convert(e2, t1);
   3125  1.1  mrg     }
   3126  1.1  mrg 
   3127  1.1  mrg     if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod)
   3128  1.1  mrg     {
   3129  1.1  mrg         /* If one is mutable and the other immutable, then retry
   3130  1.1  mrg          * with both of them as const
   3131  1.1  mrg          */
   3132  1.1  mrg         Type t1n = t1.nextOf();
   3133  1.1  mrg         Type t2n = t2.nextOf();
   3134  1.1  mrg         ubyte mod;
   3135  1.1  mrg         if (e1.op == EXP.null_ && e2.op != EXP.null_)
   3136  1.1  mrg             mod = t2n.mod;
   3137  1.1  mrg         else if (e1.op != EXP.null_ && e2.op == EXP.null_)
   3138  1.1  mrg             mod = t1n.mod;
   3139  1.1  mrg         else if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
   3140  1.1  mrg             return null;
   3141  1.1  mrg         else
   3142  1.1  mrg             mod = MODmerge(t1n.mod, t2n.mod);
   3143  1.1  mrg 
   3144  1.1  mrg         if (t1.ty == Tpointer)
   3145  1.1  mrg             t1 = t1n.castMod(mod).pointerTo();
   3146  1.1  mrg         else
   3147  1.1  mrg             t1 = t1n.castMod(mod).arrayOf();
   3148  1.1  mrg 
   3149  1.1  mrg         if (t2.ty == Tpointer)
   3150  1.1  mrg             t2 = t2n.castMod(mod).pointerTo();
   3151  1.1  mrg         else
   3152  1.1  mrg             t2 = t2n.castMod(mod).arrayOf();
   3153  1.1  mrg         t = t1;
   3154  1.1  mrg         goto Lagain;
   3155  1.1  mrg     }
   3156  1.1  mrg 
   3157  1.1  mrg     if (t1.ty == Tclass && t2.ty == Tclass)
   3158  1.1  mrg     {
   3159  1.1  mrg         if (t1.mod != t2.mod)
   3160  1.1  mrg         {
   3161  1.1  mrg             ubyte mod;
   3162  1.1  mrg             if (e1.op == EXP.null_ && e2.op != EXP.null_)
   3163  1.1  mrg                 mod = t2.mod;
   3164  1.1  mrg             else if (e1.op != EXP.null_ && e2.op == EXP.null_)
   3165  1.1  mrg                 mod = t1.mod;
   3166  1.1  mrg             else if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
   3167  1.1  mrg                 return null;
   3168  1.1  mrg             else
   3169  1.1  mrg                 mod = MODmerge(t1.mod, t2.mod);
   3170  1.1  mrg             t1 = t1.castMod(mod);
   3171  1.1  mrg             t2 = t2.castMod(mod);
   3172  1.1  mrg             t = t1;
   3173  1.1  mrg             goto Lagain;
   3174  1.1  mrg         }
   3175  1.1  mrg         goto Lcc;
   3176  1.1  mrg     }
   3177  1.1  mrg 
   3178  1.1  mrg     if (t1.ty == Tclass || t2.ty == Tclass)
   3179  1.1  mrg     {
   3180  1.1  mrg     Lcc:
   3181  1.1  mrg         while (1)
   3182  1.1  mrg         {
   3183  1.1  mrg             MATCH i1woat = MATCH.exact;
   3184  1.1  mrg             MATCH i2woat = MATCH.exact;
   3185  1.1  mrg 
   3186  1.1  mrg             if (auto t2c = t2.isTypeClass())
   3187  1.1  mrg                 i1woat = t2c.implicitConvToWithoutAliasThis(t1);
   3188  1.1  mrg             if (auto t1c = t1.isTypeClass())
   3189  1.1  mrg                 i2woat = t1c.implicitConvToWithoutAliasThis(t2);
   3190  1.1  mrg 
   3191  1.1  mrg             MATCH i1 = e2.implicitConvTo(t1);
   3192  1.1  mrg             MATCH i2 = e1.implicitConvTo(t2);
   3193  1.1  mrg 
   3194  1.1  mrg             if (i1 && i2)
   3195  1.1  mrg             {
   3196  1.1  mrg                 // We have the case of class vs. void*, so pick class
   3197  1.1  mrg                 if (t1.ty == Tpointer)
   3198  1.1  mrg                     i1 = MATCH.nomatch;
   3199  1.1  mrg                 else if (t2.ty == Tpointer)
   3200  1.1  mrg                     i2 = MATCH.nomatch;
   3201  1.1  mrg             }
   3202  1.1  mrg 
   3203  1.1  mrg             // Match but without 'alias this' on classes
   3204  1.1  mrg             if (i2 && i2woat)
   3205  1.1  mrg                 return coerce(t2);
   3206  1.1  mrg             if (i1 && i1woat)
   3207  1.1  mrg                 return coerce(t1);
   3208  1.1  mrg 
   3209  1.1  mrg             // Here use implicitCastTo() instead of castTo() to try 'alias this' on classes
   3210  1.1  mrg             Type coerceImplicit(Type towards)
   3211  1.1  mrg             {
   3212  1.1  mrg                 e1 = e1.implicitCastTo(sc, towards);
   3213  1.1  mrg                 e2 = e2.implicitCastTo(sc, towards);
   3214  1.1  mrg                 return Lret(towards);
   3215  1.1  mrg             }
   3216  1.1  mrg 
   3217  1.1  mrg             // Implicit conversion with 'alias this'
   3218  1.1  mrg             if (i2)
   3219  1.1  mrg                 return coerceImplicit(t2);
   3220  1.1  mrg             if (i1)
   3221  1.1  mrg                 return coerceImplicit(t1);
   3222  1.1  mrg 
   3223  1.1  mrg             if (t1.ty == Tclass && t2.ty == Tclass)
   3224  1.1  mrg             {
   3225  1.1  mrg                 TypeClass tc1 = t1.isTypeClass();
   3226  1.1  mrg                 TypeClass tc2 = t2.isTypeClass();
   3227  1.1  mrg 
   3228  1.1  mrg                 /* Pick 'tightest' type
   3229  1.1  mrg                  */
   3230  1.1  mrg                 ClassDeclaration cd1 = tc1.sym.baseClass;
   3231  1.1  mrg                 ClassDeclaration cd2 = tc2.sym.baseClass;
   3232  1.1  mrg                 if (cd1 && cd2)
   3233  1.1  mrg                 {
   3234  1.1  mrg                     t1 = cd1.type.castMod(t1.mod);
   3235  1.1  mrg                     t2 = cd2.type.castMod(t2.mod);
   3236  1.1  mrg                 }
   3237  1.1  mrg                 else if (cd1)
   3238  1.1  mrg                     t1 = cd1.type;
   3239  1.1  mrg                 else if (cd2)
   3240  1.1  mrg                     t2 = cd2.type;
   3241  1.1  mrg                 else
   3242  1.1  mrg                     return null;
   3243  1.1  mrg             }
   3244  1.1  mrg             else if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
   3245  1.1  mrg             {
   3246  1.1  mrg                 if (isRecursiveAliasThis(att1, e1.type))
   3247  1.1  mrg                     return null;
   3248  1.1  mrg                 //printf("att tmerge(c || c) e1 = %s\n", e1.type.toChars());
   3249  1.1  mrg                 e1 = resolveAliasThis(sc, e1);
   3250  1.1  mrg                 t1 = e1.type;
   3251  1.1  mrg                 continue;
   3252  1.1  mrg             }
   3253  1.1  mrg             else if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
   3254  1.1  mrg             {
   3255  1.1  mrg                 if (isRecursiveAliasThis(att2, e2.type))
   3256  1.1  mrg                     return null;
   3257  1.1  mrg                 //printf("att tmerge(c || c) e2 = %s\n", e2.type.toChars());
   3258  1.1  mrg                 e2 = resolveAliasThis(sc, e2);
   3259  1.1  mrg                 t2 = e2.type;
   3260  1.1  mrg                 continue;
   3261  1.1  mrg             }
   3262  1.1  mrg             else
   3263  1.1  mrg                 return null;
   3264  1.1  mrg         }
   3265  1.1  mrg     }
   3266  1.1  mrg 
   3267  1.1  mrg     if (t1.ty == Tstruct && t2.ty == Tstruct)
   3268  1.1  mrg     {
   3269  1.1  mrg         if (t1.mod != t2.mod)
   3270  1.1  mrg         {
   3271  1.1  mrg             if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
   3272  1.1  mrg                 return null;
   3273  1.1  mrg             ubyte mod = MODmerge(t1.mod, t2.mod);
   3274  1.1  mrg             t1 = t1.castMod(mod);
   3275  1.1  mrg             t2 = t2.castMod(mod);
   3276  1.1  mrg             t = t1;
   3277  1.1  mrg             goto Lagain;
   3278  1.1  mrg         }
   3279  1.1  mrg 
   3280  1.1  mrg         TypeStruct ts1 = t1.isTypeStruct();
   3281  1.1  mrg         TypeStruct ts2 = t2.isTypeStruct();
   3282  1.1  mrg         if (ts1.sym != ts2.sym)
   3283  1.1  mrg         {
   3284  1.1  mrg             if (!ts1.sym.aliasthis && !ts2.sym.aliasthis)
   3285  1.1  mrg                 return null;
   3286  1.1  mrg 
   3287  1.1  mrg             MATCH i1 = MATCH.nomatch;
   3288  1.1  mrg             MATCH i2 = MATCH.nomatch;
   3289  1.1  mrg 
   3290  1.1  mrg             Expression e1b = null;
   3291  1.1  mrg             Expression e2b = null;
   3292  1.1  mrg             if (ts2.sym.aliasthis)
   3293  1.1  mrg             {
   3294  1.1  mrg                 if (isRecursiveAliasThis(att2, e2.type))
   3295  1.1  mrg                     return null;
   3296  1.1  mrg                 //printf("att tmerge(s && s) e2 = %s\n", e2.type.toChars());
   3297  1.1  mrg                 e2b = resolveAliasThis(sc, e2);
   3298  1.1  mrg                 i1 = e2b.implicitConvTo(t1);
   3299  1.1  mrg             }
   3300  1.1  mrg             if (ts1.sym.aliasthis)
   3301  1.1  mrg             {
   3302  1.1  mrg                 if (isRecursiveAliasThis(att1, e1.type))
   3303  1.1  mrg                     return null;
   3304  1.1  mrg                 //printf("att tmerge(s && s) e1 = %s\n", e1.type.toChars());
   3305  1.1  mrg                 e1b = resolveAliasThis(sc, e1);
   3306  1.1  mrg                 i2 = e1b.implicitConvTo(t2);
   3307  1.1  mrg             }
   3308  1.1  mrg             if (i1 && i2)
   3309  1.1  mrg                 return null;
   3310  1.1  mrg 
   3311  1.1  mrg             if (i1)
   3312  1.1  mrg                 return convert(e2, t1);
   3313  1.1  mrg             if (i2)
   3314  1.1  mrg                 return convert(e1, t2);
   3315  1.1  mrg 
   3316  1.1  mrg             if (e1b)
   3317  1.1  mrg             {
   3318  1.1  mrg                 e1 = e1b;
   3319  1.1  mrg                 t1 = e1b.type.toBasetype();
   3320  1.1  mrg             }
   3321  1.1  mrg             if (e2b)
   3322  1.1  mrg             {
   3323  1.1  mrg                 e2 = e2b;
   3324  1.1  mrg                 t2 = e2b.type.toBasetype();
   3325  1.1  mrg             }
   3326  1.1  mrg             t = t1;
   3327  1.1  mrg             goto Lagain;
   3328  1.1  mrg         }
   3329  1.1  mrg     }
   3330  1.1  mrg 
   3331  1.1  mrg     if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
   3332  1.1  mrg     {
   3333  1.1  mrg         if (isRecursiveAliasThis(att1, e1.type))
   3334  1.1  mrg             return null;
   3335  1.1  mrg         //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
   3336  1.1  mrg         e1 = resolveAliasThis(sc, e1);
   3337  1.1  mrg         t1 = e1.type;
   3338  1.1  mrg         t = t1;
   3339  1.1  mrg         goto Lagain;
   3340  1.1  mrg     }
   3341  1.1  mrg 
   3342  1.1  mrg     if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
   3343  1.1  mrg     {
   3344  1.1  mrg         if (isRecursiveAliasThis(att2, e2.type))
   3345  1.1  mrg             return null;
   3346  1.1  mrg         //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
   3347  1.1  mrg         e2 = resolveAliasThis(sc, e2);
   3348  1.1  mrg         t2 = e2.type;
   3349  1.1  mrg         t = t2;
   3350  1.1  mrg         goto Lagain;
   3351  1.1  mrg     }
   3352  1.1  mrg 
   3353  1.1  mrg     if ((e1.op == EXP.string_ || e1.op == EXP.null_) && e1.implicitConvTo(t2))
   3354  1.1  mrg         return convert(e1, t2);
   3355  1.1  mrg     if ((e2.op == EXP.string_ || e2.op == EXP.null_) && e2.implicitConvTo(t1))
   3356  1.1  mrg         return convert(e2, t1);
   3357  1.1  mrg     if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf()))
   3358  1.1  mrg         return coerce(t1.nextOf().arrayOf());
   3359  1.1  mrg     if (t1.ty == Tsarray && t2.ty == Tsarray && e1.implicitConvTo(t2.nextOf().arrayOf()))
   3360  1.1  mrg         return coerce(t2.nextOf().arrayOf());
   3361  1.1  mrg 
   3362  1.1  mrg     if (t1.ty == Tvector && t2.ty == Tvector)
   3363  1.1  mrg     {
   3364  1.1  mrg         // https://issues.dlang.org/show_bug.cgi?id=13841
   3365  1.1  mrg         // all vector types should have no common types between
   3366  1.1  mrg         // different vectors, even though their sizes are same.
   3367  1.1  mrg         auto tv1 = t1.isTypeVector();
   3368  1.1  mrg         auto tv2 = t2.isTypeVector();
   3369  1.1  mrg         if (!tv1.basetype.equals(tv2.basetype))
   3370  1.1  mrg             return null;
   3371  1.1  mrg 
   3372  1.1  mrg         goto LmodCompare;
   3373  1.1  mrg     }
   3374  1.1  mrg 
   3375  1.1  mrg     if (t1.ty == Tvector && t2.ty != Tvector && e2.implicitConvTo(t1))
   3376  1.1  mrg     {
   3377  1.1  mrg         e2 = e2.castTo(sc, t1);
   3378  1.1  mrg         t2 = t1;
   3379  1.1  mrg         t = t1;
   3380  1.1  mrg         goto Lagain;
   3381  1.1  mrg     }
   3382  1.1  mrg 
   3383  1.1  mrg     if (t2.ty == Tvector && t1.ty != Tvector && e1.implicitConvTo(t2))
   3384  1.1  mrg     {
   3385  1.1  mrg         e1 = e1.castTo(sc, t2);
   3386  1.1  mrg         t1 = t2;
   3387  1.1  mrg         t = t1;
   3388  1.1  mrg         goto Lagain;
   3389  1.1  mrg     }
   3390  1.1  mrg 
   3391  1.1  mrg     if (t1.isintegral() && t2.isintegral())
   3392  1.1  mrg     {
   3393  1.1  mrg         if (t1.ty != t2.ty)
   3394  1.1  mrg         {
   3395  1.1  mrg             if (t1.ty == Tvector || t2.ty == Tvector)
   3396  1.1  mrg                 return null;
   3397  1.1  mrg             e1 = integralPromotions(e1, sc);
   3398  1.1  mrg             e2 = integralPromotions(e2, sc);
   3399  1.1  mrg             t1 = e1.type;
   3400  1.1  mrg             t2 = e2.type;
   3401  1.1  mrg             goto Lagain;
   3402  1.1  mrg         }
   3403  1.1  mrg         assert(t1.ty == t2.ty);
   3404  1.1  mrg LmodCompare:
   3405  1.1  mrg         if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
   3406  1.1  mrg             return null;
   3407  1.1  mrg         ubyte mod = MODmerge(t1.mod, t2.mod);
   3408  1.1  mrg 
   3409  1.1  mrg         t1 = t1.castMod(mod);
   3410  1.1  mrg         t2 = t2.castMod(mod);
   3411  1.1  mrg         t = t1;
   3412  1.1  mrg         e1 = e1.castTo(sc, t);
   3413  1.1  mrg         e2 = e2.castTo(sc, t);
   3414  1.1  mrg         goto Lagain;
   3415  1.1  mrg     }
   3416  1.1  mrg 
   3417  1.1  mrg     if (t1.ty == Tnull && t2.ty == Tnull)
   3418  1.1  mrg     {
   3419  1.1  mrg         ubyte mod = MODmerge(t1.mod, t2.mod);
   3420  1.1  mrg         return coerce(t1.castMod(mod));
   3421  1.1  mrg     }
   3422  1.1  mrg 
   3423  1.1  mrg     if (t2.ty == Tnull && (t1.ty == Tpointer || t1.ty == Taarray || t1.ty == Tarray))
   3424  1.1  mrg         return convert(e2, t1);
   3425  1.1  mrg     if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray))
   3426  1.1  mrg         return convert(e1, t2);
   3427  1.1  mrg 
   3428  1.1  mrg     /// Covers array operations for user-defined types
   3429  1.1  mrg     Type checkArrayOpType(Expression e1, Expression e2, EXP op, Scope *sc)
   3430  1.1  mrg     {
   3431  1.1  mrg         // scalar op scalar - we shouldn't be here
   3432  1.1  mrg         if (e1.type.ty != Tarray && e1.type.ty != Tsarray && e2.type.ty != Tarray && e2.type.ty != Tsarray)
   3433  1.1  mrg             return null;
   3434  1.1  mrg 
   3435  1.1  mrg         // only supporting slices and array literals
   3436  1.1  mrg         if (!e1.isSliceExp() && !e1.isArrayLiteralExp() && !e2.isSliceExp() && !e2.isArrayLiteralExp())
   3437  1.1  mrg             return null;
   3438  1.1  mrg 
   3439  1.1  mrg         // start with e1 op e2 and if either one of e1 or e2 is a slice or array literal,
   3440  1.1  mrg         // replace it with the first element of the array
   3441  1.1  mrg         Expression lhs = e1;
   3442  1.1  mrg         Expression rhs = e2;
   3443  1.1  mrg 
   3444  1.1  mrg         // T[x .. y] op ?
   3445  1.1  mrg         if (auto se1 = e1.isSliceExp())
   3446  1.1  mrg             lhs = new IndexExp(Loc.initial, se1.e1, IntegerExp.literal!0);
   3447  1.1  mrg 
   3448  1.1  mrg         // [t1, t2, .. t3] op ?
   3449  1.1  mrg         if (auto ale1 = e1.isArrayLiteralExp())
   3450  1.1  mrg             lhs = ale1.opIndex(0);
   3451  1.1  mrg 
   3452  1.1  mrg         // ? op U[z .. t]
   3453  1.1  mrg         if (auto se2 = e2.isSliceExp())
   3454  1.1  mrg             rhs = new IndexExp(Loc.initial, se2.e1, IntegerExp.literal!0);
   3455  1.1  mrg 
   3456  1.1  mrg         // ? op [u1, u2, .. u3]
   3457  1.1  mrg         if (auto ale2 = e2.isArrayLiteralExp())
   3458  1.1  mrg             rhs = ale2.opIndex(0);
   3459  1.1  mrg 
   3460  1.1  mrg         // create a new binary expression with the new lhs and rhs (at this stage, at least
   3461  1.1  mrg         // one of lhs/rhs has been replaced with the 0'th element of the array it was before)
   3462  1.1  mrg         Expression exp;
   3463  1.1  mrg         switch (op)
   3464  1.1  mrg         {
   3465  1.1  mrg             case EXP.add:
   3466  1.1  mrg                 exp = new AddExp(Loc.initial, lhs, rhs); break;
   3467  1.1  mrg             case EXP.min:
   3468  1.1  mrg                 exp = new MinExp(Loc.initial, lhs, rhs); break;
   3469  1.1  mrg             case EXP.mul:
   3470  1.1  mrg                 exp = new MulExp(Loc.initial, lhs, rhs); break;
   3471  1.1  mrg             case EXP.div:
   3472  1.1  mrg                 exp = new DivExp(Loc.initial, lhs, rhs); break;
   3473  1.1  mrg             case EXP.pow:
   3474  1.1  mrg                 exp = new PowExp(Loc.initial, lhs, rhs); break;
   3475  1.1  mrg             default:
   3476  1.1  mrg                 exp = null;
   3477  1.1  mrg         }
   3478  1.1  mrg 
   3479  1.1  mrg         if (exp)
   3480  1.1  mrg         {
   3481  1.1  mrg             // if T op U is valid and has type V
   3482  1.1  mrg             // then T[] op U and T op U[] should be valid and have type V[]
   3483  1.1  mrg             Expression e = exp.trySemantic(sc);
   3484  1.1  mrg             if (e && e.type)
   3485  1.1  mrg                 return e.type.arrayOf;
   3486  1.1  mrg         }
   3487  1.1  mrg 
   3488  1.1  mrg         return null;
   3489  1.1  mrg     }
   3490  1.1  mrg 
   3491  1.1  mrg     if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
   3492  1.1  mrg     {
   3493  1.1  mrg         if (e2.implicitConvTo(t1.nextOf()))
   3494  1.1  mrg         {
   3495  1.1  mrg             // T[] op T
   3496  1.1  mrg             // T[] op cast(T)U
   3497  1.1  mrg             e2 = e2.castTo(sc, t1.nextOf());
   3498  1.1  mrg             return Lret(t1.nextOf().arrayOf());
   3499  1.1  mrg         }
   3500  1.1  mrg         if (t1.nextOf().implicitConvTo(e2.type))
   3501  1.1  mrg         {
   3502  1.1  mrg             // (cast(T)U)[] op T    (https://issues.dlang.org/show_bug.cgi?id=12780)
   3503  1.1  mrg             // e1 is left as U[], it will be handled in arrayOp() later.
   3504  1.1  mrg             return Lret(e2.type.arrayOf());
   3505  1.1  mrg         }
   3506  1.1  mrg         if (t2.ty == Tarray && isArrayOpOperand(e2))
   3507  1.1  mrg         {
   3508  1.1  mrg             if (t1.nextOf().implicitConvTo(t2.nextOf()))
   3509  1.1  mrg             {
   3510  1.1  mrg                 // (cast(T)U)[] op T[]  (https://issues.dlang.org/show_bug.cgi?id=12780)
   3511  1.1  mrg                 t = t2.nextOf().arrayOf();
   3512  1.1  mrg                 // if cast won't be handled in arrayOp() later
   3513  1.1  mrg                 if (!isArrayOpImplicitCast(t1.isTypeDArray(), t2.isTypeDArray()))
   3514  1.1  mrg                     e1 = e1.castTo(sc, t);
   3515  1.1  mrg                 return Lret(t);
   3516  1.1  mrg             }
   3517  1.1  mrg             if (t2.nextOf().implicitConvTo(t1.nextOf()))
   3518  1.1  mrg             {
   3519  1.1  mrg                 // T[] op (cast(T)U)[]  (https://issues.dlang.org/show_bug.cgi?id=12780)
   3520  1.1  mrg                 // e2 is left as U[], it will be handled in arrayOp() later.
   3521  1.1  mrg                 t = t1.nextOf().arrayOf();
   3522  1.1  mrg                 // if cast won't be handled in arrayOp() later
   3523  1.1  mrg                 if (!isArrayOpImplicitCast(t2.isTypeDArray(), t1.isTypeDArray()))
   3524  1.1  mrg                     e2 = e2.castTo(sc, t);
   3525  1.1  mrg                 return Lret(t);
   3526  1.1  mrg             }
   3527  1.1  mrg         }
   3528  1.1  mrg 
   3529  1.1  mrg         t = checkArrayOpType(e1, e2, op, sc);
   3530  1.1  mrg         if (t !is null)
   3531  1.1  mrg             return Lret(t);
   3532  1.1  mrg 
   3533  1.1  mrg         return null;
   3534  1.1  mrg     }
   3535  1.1  mrg     else if (t2.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2))
   3536  1.1  mrg     {
   3537  1.1  mrg         if (e1.implicitConvTo(t2.nextOf()))
   3538  1.1  mrg         {
   3539  1.1  mrg             // T op T[]
   3540  1.1  mrg             // cast(T)U op T[]
   3541  1.1  mrg             e1 = e1.castTo(sc, t2.nextOf());
   3542  1.1  mrg             t = t2.nextOf().arrayOf();
   3543  1.1  mrg         }
   3544  1.1  mrg         else if (t2.nextOf().implicitConvTo(e1.type))
   3545  1.1  mrg         {
   3546  1.1  mrg             // T op (cast(T)U)[]    (https://issues.dlang.org/show_bug.cgi?id=12780)
   3547  1.1  mrg             // e2 is left as U[], it will be handled in arrayOp() later.
   3548  1.1  mrg             t = e1.type.arrayOf();
   3549  1.1  mrg         }
   3550  1.1  mrg         else
   3551  1.1  mrg         {
   3552  1.1  mrg             t = checkArrayOpType(e1, e2, op, sc);
   3553  1.1  mrg             if (t is null)
   3554  1.1  mrg                 return null;
   3555  1.1  mrg         }
   3556  1.1  mrg 
   3557  1.1  mrg         //printf("test %s\n", EXPtoString(op).ptr);
   3558  1.1  mrg         e1 = e1.optimize(WANTvalue);
   3559  1.1  mrg         if (isCommutative(op) && e1.isConst())
   3560  1.1  mrg         {
   3561  1.1  mrg             /* Swap operands to minimize number of functions generated
   3562  1.1  mrg              */
   3563  1.1  mrg             //printf("swap %s\n", EXPtoString(op).ptr);
   3564  1.1  mrg             Expression tmp = e1;
   3565  1.1  mrg             e1 = e2;
   3566  1.1  mrg             e2 = tmp;
   3567  1.1  mrg         }
   3568  1.1  mrg         return Lret(t);
   3569  1.1  mrg     }
   3570  1.1  mrg 
   3571  1.1  mrg     return null;
   3572  1.1  mrg }
   3573  1.1  mrg 
   3574  1.1  mrg /************************************
   3575  1.1  mrg  * Bring leaves to common type.
   3576  1.1  mrg  * Returns:
   3577  1.1  mrg  *    null on success, ErrorExp if error occurs
   3578  1.1  mrg  */
   3579  1.1  mrg Expression typeCombine(BinExp be, Scope* sc)
   3580  1.1  mrg {
   3581  1.1  mrg     Expression errorReturn()
   3582  1.1  mrg     {
   3583  1.1  mrg         Expression ex = be.incompatibleTypes();
   3584  1.1  mrg         if (ex.op == EXP.error)
   3585  1.1  mrg             return ex;
   3586  1.1  mrg         return ErrorExp.get();
   3587  1.1  mrg     }
   3588  1.1  mrg 
   3589  1.1  mrg     Type t1 = be.e1.type.toBasetype();
   3590  1.1  mrg     Type t2 = be.e2.type.toBasetype();
   3591  1.1  mrg 
   3592  1.1  mrg     if (be.op == EXP.min || be.op == EXP.add)
   3593  1.1  mrg     {
   3594  1.1  mrg         // struct+struct, and class+class are errors
   3595  1.1  mrg         if (t1.ty == Tstruct && t2.ty == Tstruct)
   3596  1.1  mrg             return errorReturn();
   3597  1.1  mrg         else if (t1.ty == Tclass && t2.ty == Tclass)
   3598  1.1  mrg             return errorReturn();
   3599  1.1  mrg         else if (t1.ty == Taarray && t2.ty == Taarray)
   3600  1.1  mrg             return errorReturn();
   3601  1.1  mrg     }
   3602  1.1  mrg 
   3603  1.1  mrg     if (auto result = typeMerge(sc, be.op, be.e1, be.e2))
   3604  1.1  mrg     {
   3605  1.1  mrg         if (be.type is null)
   3606  1.1  mrg             be.type = result;
   3607  1.1  mrg     }
   3608  1.1  mrg     else
   3609  1.1  mrg         return errorReturn();
   3610  1.1  mrg 
   3611  1.1  mrg     // If the types have no value, return an error
   3612  1.1  mrg     if (be.e1.op == EXP.error)
   3613  1.1  mrg         return be.e1;
   3614  1.1  mrg     if (be.e2.op == EXP.error)
   3615  1.1  mrg         return be.e2;
   3616  1.1  mrg     return null;
   3617  1.1  mrg }
   3618  1.1  mrg 
   3619  1.1  mrg /***********************************
   3620  1.1  mrg  * Do integral promotions (convertchk).
   3621  1.1  mrg  * Don't convert <array of> to <pointer to>
   3622  1.1  mrg  */
   3623  1.1  mrg Expression integralPromotions(Expression e, Scope* sc)
   3624  1.1  mrg {
   3625  1.1  mrg     //printf("integralPromotions %s %s\n", e.toChars(), e.type.toChars());
   3626  1.1  mrg     switch (e.type.toBasetype().ty)
   3627  1.1  mrg     {
   3628  1.1  mrg     case Tvoid:
   3629  1.1  mrg         e.error("void has no value");
   3630  1.1  mrg         return ErrorExp.get();
   3631  1.1  mrg 
   3632  1.1  mrg     case Tint8:
   3633  1.1  mrg     case Tuns8:
   3634  1.1  mrg     case Tint16:
   3635  1.1  mrg     case Tuns16:
   3636  1.1  mrg     case Tbool:
   3637  1.1  mrg     case Tchar:
   3638  1.1  mrg     case Twchar:
   3639  1.1  mrg         e = e.castTo(sc, Type.tint32);
   3640  1.1  mrg         break;
   3641  1.1  mrg 
   3642  1.1  mrg     case Tdchar:
   3643  1.1  mrg         e = e.castTo(sc, Type.tuns32);
   3644  1.1  mrg         break;
   3645  1.1  mrg 
   3646  1.1  mrg     default:
   3647  1.1  mrg         break;
   3648  1.1  mrg     }
   3649  1.1  mrg     return e;
   3650  1.1  mrg }
   3651  1.1  mrg 
   3652  1.1  mrg /******************************************************
   3653  1.1  mrg  * This provides a transition from the non-promoting behavior
   3654  1.1  mrg  * of unary + - ~ to the C-like integral promotion behavior.
   3655  1.1  mrg  * Params:
   3656  1.1  mrg  *    sc = context
   3657  1.1  mrg  *    ue = NegExp, UAddExp, or ComExp which is revised per rules
   3658  1.1  mrg  * References:
   3659  1.1  mrg  *      https://issues.dlang.org/show_bug.cgi?id=16997
   3660  1.1  mrg  */
   3661  1.1  mrg 
   3662  1.1  mrg void fix16997(Scope* sc, UnaExp ue)
   3663  1.1  mrg {
   3664  1.1  mrg     if (global.params.fix16997 || sc.flags & SCOPE.Cfile)
   3665  1.1  mrg         ue.e1 = integralPromotions(ue.e1, sc);          // desired C-like behavor
   3666  1.1  mrg     else
   3667  1.1  mrg     {
   3668  1.1  mrg         switch (ue.e1.type.toBasetype.ty)
   3669  1.1  mrg         {
   3670  1.1  mrg             case Tint8:
   3671  1.1  mrg             case Tuns8:
   3672  1.1  mrg             case Tint16:
   3673  1.1  mrg             case Tuns16:
   3674  1.1  mrg             //case Tbool:       // these operations aren't allowed on bool anyway
   3675  1.1  mrg             case Tchar:
   3676  1.1  mrg             case Twchar:
   3677  1.1  mrg             case Tdchar:
   3678  1.1  mrg                 ue.deprecation("integral promotion not done for `%s`, remove '-revert=intpromote' switch or `%scast(int)(%s)`",
   3679  1.1  mrg                     ue.toChars(), EXPtoString(ue.op).ptr, ue.e1.toChars());
   3680  1.1  mrg                 break;
   3681  1.1  mrg 
   3682  1.1  mrg             default:
   3683  1.1  mrg                 break;
   3684  1.1  mrg         }
   3685  1.1  mrg     }
   3686  1.1  mrg }
   3687  1.1  mrg 
   3688  1.1  mrg /***********************************
   3689  1.1  mrg  * See if both types are arrays that can be compared
   3690  1.1  mrg  * for equality without any casting. Return true if so.
   3691  1.1  mrg  * This is to enable comparing things like an immutable
   3692  1.1  mrg  * array with a mutable one.
   3693  1.1  mrg  */
   3694  1.1  mrg extern (C++) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
   3695  1.1  mrg {
   3696  1.1  mrg     t1 = t1.toBasetype();
   3697  1.1  mrg     t2 = t2.toBasetype();
   3698  1.1  mrg 
   3699  1.1  mrg     if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && t2.ty == t1.ty)
   3700  1.1  mrg     {
   3701  1.1  mrg         if (t1.nextOf().implicitConvTo(t2.nextOf()) >= MATCH.constant || t2.nextOf().implicitConvTo(t1.nextOf()) >= MATCH.constant)
   3702  1.1  mrg             return true;
   3703  1.1  mrg     }
   3704  1.1  mrg     return false;
   3705  1.1  mrg }
   3706  1.1  mrg 
   3707  1.1  mrg /******************************************************************/
   3708  1.1  mrg /* Determine the integral ranges of an expression.
   3709  1.1  mrg  * This is used to determine if implicit narrowing conversions will
   3710  1.1  mrg  * be allowed.
   3711  1.1  mrg  */
   3712  1.1  mrg @trusted
   3713  1.1  mrg IntRange getIntRange(Expression e)
   3714  1.1  mrg {
   3715  1.1  mrg     IntRange visit(Expression e)
   3716  1.1  mrg     {
   3717  1.1  mrg         return IntRange.fromType(e.type);
   3718  1.1  mrg     }
   3719  1.1  mrg 
   3720  1.1  mrg     IntRange visitInteger(IntegerExp e)
   3721  1.1  mrg     {
   3722  1.1  mrg         return IntRange(SignExtendedNumber(e.getInteger()))._cast(e.type);
   3723  1.1  mrg     }
   3724  1.1  mrg 
   3725  1.1  mrg     IntRange visitCast(CastExp e)
   3726  1.1  mrg     {
   3727  1.1  mrg         return getIntRange(e.e1)._cast(e.type);
   3728  1.1  mrg     }
   3729  1.1  mrg 
   3730  1.1  mrg     IntRange visitAdd(AddExp e)
   3731  1.1  mrg     {
   3732  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3733  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3734  1.1  mrg         return (ir1 + ir2)._cast(e.type);
   3735  1.1  mrg     }
   3736  1.1  mrg 
   3737  1.1  mrg     IntRange visitMin(MinExp e)
   3738  1.1  mrg     {
   3739  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3740  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3741  1.1  mrg         return (ir1 - ir2)._cast(e.type);
   3742  1.1  mrg     }
   3743  1.1  mrg 
   3744  1.1  mrg     IntRange visitDiv(DivExp e)
   3745  1.1  mrg     {
   3746  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3747  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3748  1.1  mrg 
   3749  1.1  mrg         return (ir1 / ir2)._cast(e.type);
   3750  1.1  mrg     }
   3751  1.1  mrg 
   3752  1.1  mrg     IntRange visitMul(MulExp e)
   3753  1.1  mrg     {
   3754  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3755  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3756  1.1  mrg 
   3757  1.1  mrg         return (ir1 * ir2)._cast(e.type);
   3758  1.1  mrg     }
   3759  1.1  mrg 
   3760  1.1  mrg     IntRange visitMod(ModExp e)
   3761  1.1  mrg     {
   3762  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3763  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3764  1.1  mrg 
   3765  1.1  mrg         // Modding on 0 is invalid anyway.
   3766  1.1  mrg         if (!ir2.absNeg().imin.negative)
   3767  1.1  mrg         {
   3768  1.1  mrg             return visit(e);
   3769  1.1  mrg         }
   3770  1.1  mrg         return (ir1 % ir2)._cast(e.type);
   3771  1.1  mrg     }
   3772  1.1  mrg 
   3773  1.1  mrg     IntRange visitAnd(AndExp e)
   3774  1.1  mrg     {
   3775  1.1  mrg         IntRange result;
   3776  1.1  mrg         bool hasResult = false;
   3777  1.1  mrg         result.unionOrAssign(getIntRange(e.e1) & getIntRange(e.e2), hasResult);
   3778  1.1  mrg 
   3779  1.1  mrg         assert(hasResult);
   3780  1.1  mrg         return result._cast(e.type);
   3781  1.1  mrg     }
   3782  1.1  mrg 
   3783  1.1  mrg     IntRange visitOr(OrExp e)
   3784  1.1  mrg     {
   3785  1.1  mrg         IntRange result;
   3786  1.1  mrg         bool hasResult = false;
   3787  1.1  mrg         result.unionOrAssign(getIntRange(e.e1) | getIntRange(e.e2), hasResult);
   3788  1.1  mrg 
   3789  1.1  mrg         assert(hasResult);
   3790  1.1  mrg         return result._cast(e.type);
   3791  1.1  mrg     }
   3792  1.1  mrg 
   3793  1.1  mrg     IntRange visitXor(XorExp e)
   3794  1.1  mrg     {
   3795  1.1  mrg         IntRange result;
   3796  1.1  mrg         bool hasResult = false;
   3797  1.1  mrg         result.unionOrAssign(getIntRange(e.e1) ^ getIntRange(e.e2), hasResult);
   3798  1.1  mrg 
   3799  1.1  mrg         assert(hasResult);
   3800  1.1  mrg         return result._cast(e.type);
   3801  1.1  mrg     }
   3802  1.1  mrg 
   3803  1.1  mrg     IntRange visitShl(ShlExp e)
   3804  1.1  mrg     {
   3805  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3806  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3807  1.1  mrg 
   3808  1.1  mrg         return (ir1 << ir2)._cast(e.type);
   3809  1.1  mrg     }
   3810  1.1  mrg 
   3811  1.1  mrg     IntRange visitShr(ShrExp e)
   3812  1.1  mrg     {
   3813  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3814  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3815  1.1  mrg 
   3816  1.1  mrg         return (ir1 >> ir2)._cast(e.type);
   3817  1.1  mrg     }
   3818  1.1  mrg 
   3819  1.1  mrg     IntRange visitUshr(UshrExp e)
   3820  1.1  mrg     {
   3821  1.1  mrg         IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type);
   3822  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3823  1.1  mrg 
   3824  1.1  mrg         return (ir1 >>> ir2)._cast(e.type);
   3825  1.1  mrg     }
   3826  1.1  mrg 
   3827  1.1  mrg     IntRange visitAssign(AssignExp e)
   3828  1.1  mrg     {
   3829  1.1  mrg         return getIntRange(e.e2)._cast(e.type);
   3830  1.1  mrg     }
   3831  1.1  mrg 
   3832  1.1  mrg     IntRange visitCond(CondExp e)
   3833  1.1  mrg     {
   3834  1.1  mrg         // No need to check e.econd; assume caller has called optimize()
   3835  1.1  mrg         IntRange ir1 = getIntRange(e.e1);
   3836  1.1  mrg         IntRange ir2 = getIntRange(e.e2);
   3837  1.1  mrg         return ir1.unionWith(ir2)._cast(e.type);
   3838  1.1  mrg     }
   3839  1.1  mrg 
   3840  1.1  mrg     IntRange visitVar(VarExp e)
   3841  1.1  mrg     {
   3842  1.1  mrg         Expression ie;
   3843  1.1  mrg         VarDeclaration vd = e.var.isVarDeclaration();
   3844  1.1  mrg         if (vd && vd.range)
   3845  1.1  mrg             return vd.range._cast(e.type);
   3846  1.1  mrg         else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
   3847  1.1  mrg             return getIntRange(ie);
   3848  1.1  mrg         else
   3849  1.1  mrg             return visit(e);
   3850  1.1  mrg     }
   3851  1.1  mrg 
   3852  1.1  mrg     IntRange visitComma(CommaExp e)
   3853  1.1  mrg     {
   3854  1.1  mrg         return getIntRange(e.e2);
   3855  1.1  mrg     }
   3856  1.1  mrg 
   3857  1.1  mrg     IntRange visitCom(ComExp e)
   3858  1.1  mrg     {
   3859  1.1  mrg         IntRange ir = getIntRange(e.e1);
   3860  1.1  mrg         return IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative), SignExtendedNumber(~ir.imin.value, !ir.imin.negative))._cast(e.type);
   3861  1.1  mrg     }
   3862  1.1  mrg 
   3863  1.1  mrg     IntRange visitNeg(NegExp e)
   3864  1.1  mrg     {
   3865  1.1  mrg         IntRange ir = getIntRange(e.e1);
   3866  1.1  mrg         return (-ir)._cast(e.type);
   3867  1.1  mrg     }
   3868  1.1  mrg 
   3869  1.1  mrg     switch (e.op)
   3870  1.1  mrg     {
   3871  1.1  mrg         default                     : return visit(e);
   3872  1.1  mrg         case EXP.int64              : return visitInteger(e.isIntegerExp());
   3873  1.1  mrg         case EXP.cast_              : return visitCast(e.isCastExp());
   3874  1.1  mrg         case EXP.add                : return visitAdd(e.isAddExp());
   3875  1.1  mrg         case EXP.min                : return visitMin(e.isMinExp());
   3876  1.1  mrg         case EXP.div                : return visitDiv(e.isDivExp());
   3877  1.1  mrg         case EXP.mul                : return visitMul(e.isMulExp());
   3878  1.1  mrg         case EXP.mod                : return visitMod(e.isModExp());
   3879  1.1  mrg         case EXP.and                : return visitAnd(e.isAndExp());
   3880  1.1  mrg         case EXP.or                 : return visitOr(e.isOrExp());
   3881  1.1  mrg         case EXP.xor                : return visitXor(e.isXorExp());
   3882  1.1  mrg         case EXP.leftShift          : return visitShl(e.isShlExp());
   3883  1.1  mrg         case EXP.rightShift         : return visitShr(e.isShrExp());
   3884  1.1  mrg         case EXP.unsignedRightShift : return visitUshr(e.isUshrExp());
   3885  1.1  mrg         case EXP.blit               : return visitAssign(e.isBlitExp());
   3886  1.1  mrg         case EXP.construct          : return visitAssign(e.isConstructExp());
   3887  1.1  mrg         case EXP.assign             : return visitAssign(e.isAssignExp());
   3888  1.1  mrg         case EXP.question           : return visitCond(e.isCondExp());
   3889  1.1  mrg         case EXP.variable           : return visitVar(e.isVarExp());
   3890  1.1  mrg         case EXP.comma              : return visitComma(e.isCommaExp());
   3891  1.1  mrg         case EXP.tilde              : return visitCom(e.isComExp());
   3892  1.1  mrg         case EXP.negate             : return visitNeg(e.isNegExp());
   3893  1.1  mrg     }
   3894  1.1  mrg }
   3895