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