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