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