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