d: Merge upstream dmd ff57fec515, druntime ff57fec515, phobos 17bafda79.
[official-gcc.git] / gcc / d / dmd / dcast.d
blob14c67f062a3247c690708963c02cb0d771d904b0
1 /**
2 * Semantic analysis for cast-expressions.
4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d)
8 * Documentation: https://dlang.org/phobos/dmd_dcast.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dcast.d
12 module dmd.dcast;
14 import core.stdc.stdio;
15 import core.stdc.string;
16 import dmd.aggregate;
17 import dmd.aliasthis;
18 import dmd.arrayop;
19 import dmd.arraytypes;
20 import dmd.astenums;
21 import dmd.dclass;
22 import dmd.declaration;
23 import dmd.dinterpret;
24 import dmd.dscope;
25 import dmd.dstruct;
26 import dmd.dsymbol;
27 import dmd.errors;
28 import dmd.escape;
29 import dmd.expression;
30 import dmd.expressionsem;
31 import dmd.func;
32 import dmd.globals;
33 import dmd.hdrgen;
34 import dmd.location;
35 import dmd.impcnvtab;
36 import dmd.importc;
37 import dmd.init;
38 import dmd.intrange;
39 import dmd.mtype;
40 import dmd.opover;
41 import dmd.optimize;
42 import dmd.root.ctfloat;
43 import dmd.common.outbuffer;
44 import dmd.root.rmem;
45 import dmd.root.utf;
46 import dmd.tokens;
47 import dmd.typesem;
49 enum LOG = false;
51 /**
52 * Attempt to implicitly cast the expression into type `t`.
54 * This routine will change `e`. To check the matching level,
55 * use `implicitConvTo`.
57 * Params:
58 * e = Expression that is to be casted
59 * sc = Current scope
60 * t = Expected resulting type
62 * Returns:
63 * The resulting casted expression (mutating `e`), or `ErrorExp`
64 * if such an implicit conversion is not possible.
66 Expression implicitCastTo(Expression e, Scope* sc, Type t)
68 Expression visit(Expression e)
70 // printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
72 if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t))
74 // no need for an extra cast when matching is exact
76 if (match == MATCH.convert && e.type.isTypeNoreturn() && e.op != EXP.type)
78 return specialNoreturnCast(e, t);
80 if (match == MATCH.constant && (e.type.constConv(t) || !e.isLvalue() && e.type.equivalent(t)))
82 /* Do not emit CastExp for const conversions and
83 * unique conversions on rvalue.
85 auto result = e.copy();
86 result.type = t;
87 return result;
90 auto ad = isAggregate(e.type);
91 if (ad && ad.aliasthis)
93 if (!ad.type || ad.type.isTypeError())
94 return e;
95 auto ts = ad.type.isTypeStruct();
96 const adMatch = ts
97 ? ts.implicitConvToWithoutAliasThis(t)
98 : ad.type.isTypeClass().implicitConvToWithoutAliasThis(t);
100 if (!adMatch)
102 Type tob = t.toBasetype();
103 Type t1b = e.type.toBasetype();
104 if (ad != isAggregate(tob))
106 if (t1b.ty == Tclass && tob.ty == Tclass)
108 ClassDeclaration t1cd = t1b.isClassHandle();
109 ClassDeclaration tocd = tob.isClassHandle();
110 int offset;
111 if (tocd.isBaseOf(t1cd, &offset))
113 auto result = new CastExp(e.loc, e, t);
114 result.type = t;
115 return result;
119 /* Forward the cast to our alias this member, rewrite to:
120 * cast(to)e1.aliasthis
122 auto result = resolveAliasThis(sc, e);
123 return result.castTo(sc, t);
128 return e.castTo(sc, t);
131 auto result = e.optimize(WANTvalue);
132 if (result != e)
134 return implicitCastTo(result, sc, t);
137 if (t.ty != Terror && e.type.ty != Terror)
139 if (!t.deco)
141 error(e.loc, "forward reference to type `%s`", t.toChars());
143 else
145 //printf("type %p ty %d deco %p\n", type, type.ty, type.deco);
146 //type = type.typeSemantic(loc, sc);
147 //printf("type %s t %s\n", type.deco, t.deco);
148 auto ts = toAutoQualChars(e.type, t);
149 error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
150 e.toChars(), ts[0], ts[1]);
153 return ErrorExp.get();
156 Expression visitString(StringExp e)
158 //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
159 auto result = visit(e);
160 if (auto se = result.isStringExp())
162 // Retain polysemous nature if it started out that way
163 se.committed = e.committed;
165 return result;
168 Expression visitError(ErrorExp e)
170 return e;
173 Expression visitFunc(FuncExp e)
175 //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
176 FuncExp fe;
177 if (e.matchType(t, sc, &fe, global.errorSink) > MATCH.nomatch)
179 return fe;
181 return visit(e);
184 Expression visitArrayLiteral(ArrayLiteralExp e)
186 auto result = visit(e);
188 Type tb = result.type.toBasetype();
189 if (auto ta = tb.isTypeDArray())
190 if (global.params.useTypeInfo && Type.dtypeinfo)
191 semanticTypeInfo(sc, ta.next);
192 return result;
195 Expression visitSlice(SliceExp e)
197 auto result = visit(e);
199 if (auto se = result.isSliceExp())
200 if (auto ale = se.e1.isArrayLiteralExp())
202 Type tb = t.toBasetype();
203 Type tx = (tb.ty == Tsarray)
204 ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0)
205 : tb.nextOf().arrayOf();
206 se.e1 = ale.implicitCastTo(sc, tx);
209 return result;
212 switch (e.op)
214 default : return visit (e);
215 case EXP.string_ : return visitString (e.isStringExp());
216 case EXP.error : return visitError (e.isErrorExp());
217 case EXP.function_ : return visitFunc (e.isFuncExp());
218 case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
219 case EXP.slice : return visitSlice (e.isSliceExp());
224 * Checks whether or not an expression can be implicitly converted
225 * to type `t`.
227 * Unlike `implicitCastTo`, this routine does not perform the actual cast,
228 * but only checks up to what `MATCH` level the conversion would be possible.
230 * Params:
231 * e = Expression that is to be casted
232 * t = Expected resulting type
234 * Returns:
235 * The `MATCH` level between `e.type` and `t`.
237 extern(C++) MATCH implicitConvTo(Expression e, Type t)
239 MATCH visit(Expression e)
241 version (none)
243 printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
245 //static int nest; if (++nest == 10) assert(0);
246 if (t == Type.terror)
247 return MATCH.nomatch;
248 if (!e.type)
250 error(e.loc, "`%s` is not an expression", e.toChars());
251 e.type = Type.terror;
254 Expression ex = e.optimize(WANTvalue);
255 if (ex.type.equals(t))
257 return MATCH.exact;
259 if (ex != e)
261 //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars());
262 return ex.implicitConvTo(t);
265 MATCH match = e.type.implicitConvTo(t);
266 if (match != MATCH.nomatch)
268 return match;
271 /* See if we can do integral narrowing conversions
273 if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic())
275 IntRange src = getIntRange(e);
276 IntRange target = IntRange.fromType(t);
277 if (target.contains(src))
279 return MATCH.convert;
282 return MATCH.nomatch;
285 /******
286 * Given expression e of type t, see if we can implicitly convert e
287 * to type tprime, where tprime is type t with mod bits added.
288 * Returns:
289 * match level
291 static MATCH implicitMod(Expression e, Type t, MOD mod)
293 Type tprime;
294 if (t.ty == Tpointer)
295 tprime = t.nextOf().castMod(mod).pointerTo();
296 else if (t.ty == Tarray)
297 tprime = t.nextOf().castMod(mod).arrayOf();
298 else if (t.ty == Tsarray)
299 tprime = t.nextOf().castMod(mod).sarrayOf(t.size() / t.nextOf().size());
300 else
301 tprime = t.castMod(mod);
303 return e.implicitConvTo(tprime);
306 static MATCH implicitConvToAddMin(BinExp e, Type t)
308 /* Is this (ptr +- offset)? If so, then ask ptr
309 * if the conversion can be done.
310 * This is to support doing things like implicitly converting a mutable unique
311 * pointer to an immutable pointer.
314 Type tb = t.toBasetype();
315 Type typeb = e.type.toBasetype();
317 if (typeb.ty != Tpointer || tb.ty != Tpointer)
318 return MATCH.nomatch;
320 Type t1b = e.e1.type.toBasetype();
321 Type t2b = e.e2.type.toBasetype();
322 if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb))
324 // ptr + offset
325 // ptr - offset
326 MATCH m = e.e1.implicitConvTo(t);
327 return (m > MATCH.constant) ? MATCH.constant : m;
329 if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb))
331 // offset + ptr
332 MATCH m = e.e2.implicitConvTo(t);
333 return (m > MATCH.constant) ? MATCH.constant : m;
336 return MATCH.nomatch;
339 // Apply mod bits to each function parameter,
340 // and see if we can convert the function argument to the modded type
341 static bool parametersModMatch(Expressions* args, TypeFunction tf, MOD mod)
343 const size_t nparams = tf.parameterList.length;
344 const size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
345 foreach (const i; j .. args.length)
347 Expression earg = (*args)[i];
348 Type targ = earg.type.toBasetype();
349 static if (LOG)
351 printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
353 if (i - j < nparams)
355 Parameter fparam = tf.parameterList[i - j];
356 if (fparam.isLazy())
357 return false; // not sure what to do with this
358 Type tparam = fparam.type;
359 if (!tparam)
360 continue;
361 if (fparam.isReference())
363 if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
364 return false;
365 continue;
368 static if (LOG)
370 printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
372 if (implicitMod(earg, targ, mod) == MATCH.nomatch)
373 return false;
375 return true;
378 MATCH visitAdd(AddExp e)
380 version (none)
382 printf("AddExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
384 auto result = visit(e);
385 if (result == MATCH.nomatch)
386 result = implicitConvToAddMin(e, t);
387 return result;
390 MATCH visitMin(MinExp e)
392 version (none)
394 printf("MinExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
396 auto result = visit(e);
397 if (result == MATCH.nomatch)
398 result = implicitConvToAddMin(e, t);
399 return result;
402 MATCH visitInteger(IntegerExp e)
404 version (none)
406 printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
408 MATCH m = e.type.implicitConvTo(t);
409 if (m >= MATCH.constant)
411 return m;
414 TY ty = e.type.toBasetype().ty;
415 TY toty = t.toBasetype().ty;
416 TY oldty = ty;
418 if (m == MATCH.nomatch && t.ty == Tenum)
419 return MATCH.nomatch;
421 if (auto tv = t.isTypeVector())
423 TypeBasic tb = tv.elementType();
424 if (tb.ty == Tvoid)
425 return MATCH.nomatch;
426 toty = tb.ty;
429 switch (ty)
431 case Tbool:
432 case Tint8:
433 case Tchar:
434 case Tuns8:
435 case Tint16:
436 case Tuns16:
437 case Twchar:
438 ty = Tint32;
439 break;
441 case Tdchar:
442 ty = Tuns32;
443 break;
445 default:
446 break;
449 // Only allow conversion if no change in value
450 immutable dinteger_t value = e.toInteger();
452 bool isLosslesslyConvertibleToFP(T)()
454 if (e.type.isunsigned())
456 const f = cast(T) value;
457 return cast(dinteger_t) f == value;
460 const f = cast(T) cast(sinteger_t) value;
461 return cast(sinteger_t) f == cast(sinteger_t) value;
464 switch (toty)
466 case Tbool:
467 if ((value & 1) != value)
468 return MATCH.nomatch;
469 break;
471 case Tint8:
472 if (ty == Tuns64 && value & ~0x7FU)
473 return MATCH.nomatch;
474 else if (cast(byte)value != value)
475 return MATCH.nomatch;
476 break;
478 case Tchar:
479 if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
480 return MATCH.nomatch;
481 goto case Tuns8;
482 case Tuns8:
483 //printf("value = %llu %llu\n", cast(dinteger_t)cast(ubyte)value, value);
484 if (cast(ubyte)value != value)
485 return MATCH.nomatch;
486 break;
488 case Tint16:
489 if (ty == Tuns64 && value & ~0x7FFFU)
490 return MATCH.nomatch;
491 else if (cast(short)value != value)
492 return MATCH.nomatch;
493 break;
495 case Twchar:
496 if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
497 return MATCH.nomatch;
498 goto case Tuns16;
499 case Tuns16:
500 if (cast(ushort)value != value)
501 return MATCH.nomatch;
502 break;
504 case Tint32:
505 if (ty == Tuns32)
508 else if (ty == Tuns64 && value & ~0x7FFFFFFFU)
509 return MATCH.nomatch;
510 else if (cast(int)value != value)
511 return MATCH.nomatch;
512 break;
514 case Tuns32:
515 if (ty == Tint32)
518 else if (cast(uint)value != value)
519 return MATCH.nomatch;
520 break;
522 case Tdchar:
523 if (value > 0x10FFFFU)
524 return MATCH.nomatch;
525 break;
527 case Tfloat32:
528 if (!isLosslesslyConvertibleToFP!float)
529 return MATCH.nomatch;
530 break;
532 case Tfloat64:
533 if (!isLosslesslyConvertibleToFP!double)
534 return MATCH.nomatch;
535 break;
537 case Tfloat80:
538 if (!isLosslesslyConvertibleToFP!real_t)
539 return MATCH.nomatch;
540 break;
542 case Tpointer:
543 //printf("type = %s\n", type.toBasetype().toChars());
544 //printf("t = %s\n", t.toBasetype().toChars());
545 if (ty == Tpointer && e.type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty)
547 /* Allow things like:
548 * const char* P = cast(char *)3;
549 * char* q = P;
551 break;
553 goto default;
555 default:
556 return visit(e);
559 //printf("MATCH.convert\n");
560 return MATCH.convert;
563 MATCH visitError(ErrorExp e)
565 return MATCH.nomatch;
568 MATCH visitNull(NullExp e)
570 version (none)
572 printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
574 if (e.type.equals(t))
576 return MATCH.exact;
579 /* Allow implicit conversions from immutable to mutable|const,
580 * and mutable to immutable. It works because, after all, a null
581 * doesn't actually point to anything.
583 if (t.equivalent(e.type))
585 return MATCH.constant;
588 return visit(e);
591 MATCH visitStructLiteral(StructLiteralExp e)
593 version (none)
595 printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
597 auto result = visit(e);
598 if (result != MATCH.nomatch)
599 return result;
600 if (e.type.ty == t.ty && e.type.isTypeStruct() && e.type.isTypeStruct().sym == t.isTypeStruct().sym)
602 result = MATCH.constant;
603 foreach (i, el; (*e.elements)[])
605 if (!el)
606 continue;
607 Type te = e.sd.fields[i].type.addMod(t.mod);
608 MATCH m2 = el.implicitConvTo(te);
609 //printf("\t%s => %s, match = %d\n", el.toChars(), te.toChars(), m2);
610 if (m2 < result)
611 result = m2;
614 return result;
617 MATCH visitString(StringExp e)
619 version (none)
621 printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", e.toChars(), e.committed, e.type.toChars(), t.toChars());
623 if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
624 return MATCH.nomatch;
626 if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
627 return visit(e);
629 TY tyn = e.type.nextOf().ty;
631 if (!tyn.isSomeChar)
632 return visit(e);
634 switch (t.ty)
636 case Tsarray:
637 if (e.type.ty == Tsarray)
639 TY tynto = t.nextOf().ty;
640 if (tynto == tyn)
642 if (e.type.isTypeSArray().dim.toInteger() == t.isTypeSArray().dim.toInteger())
644 return MATCH.exact;
646 return MATCH.nomatch;
648 if (tynto.isSomeChar)
650 if (e.committed && tynto != tyn)
651 return MATCH.nomatch;
652 size_t fromlen = e.numberOfCodeUnits(tynto);
653 size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
654 if (tolen < fromlen)
655 return MATCH.nomatch;
656 if (tolen != fromlen)
658 // implicit length extending
659 return MATCH.convert;
662 if (!e.committed && tynto.isSomeChar)
664 return MATCH.exact;
667 else if (e.type.ty == Tarray)
669 TY tynto = t.nextOf().ty;
670 if (tynto.isSomeChar)
672 if (e.committed && tynto != tyn)
673 return MATCH.nomatch;
674 size_t fromlen = e.numberOfCodeUnits(tynto);
675 size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
676 if (tolen < fromlen)
677 return MATCH.nomatch;
678 if (tolen != fromlen)
680 // implicit length extending
681 return MATCH.convert;
684 if (tynto == tyn)
686 return MATCH.exact;
688 if (!e.committed && tynto.isSomeChar)
690 return MATCH.exact;
693 goto case; /+ fall through +/
694 case Tarray:
695 case Tpointer:
696 Type tn = t.nextOf();
697 MATCH m = MATCH.exact;
698 if (e.type.nextOf().mod != tn.mod)
700 // https://issues.dlang.org/show_bug.cgi?id=16183
701 if (!tn.isConst() && !tn.isImmutable())
702 return MATCH.nomatch;
703 m = MATCH.constant;
705 if (!e.committed)
707 switch (tn.ty)
709 case Tchar:
710 if (e.postfix == 'w' || e.postfix == 'd')
711 m = MATCH.convert;
712 return m;
713 case Twchar:
714 if (e.postfix != 'w')
715 m = MATCH.convert;
716 return m;
717 case Tdchar:
718 if (e.postfix != 'd')
719 m = MATCH.convert;
720 return m;
721 case Tint8:
722 case Tuns8:
723 if (e.hexString)
725 m = MATCH.convert;
726 return m;
728 break;
729 case Tenum:
730 if (tn.isTypeEnum().sym.isSpecial())
732 /* Allow string literal -> const(wchar_t)[]
734 if (TypeBasic tob = tn.toBasetype().isTypeBasic())
735 return tn.implicitConvTo(tob);
737 break;
738 default:
739 break;
742 break;
744 default:
745 break;
748 return visit(e);
751 MATCH visitArrayLiteral(ArrayLiteralExp e)
753 version (none)
755 printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
757 Type tb = t.toBasetype();
758 Type typeb = e.type.toBasetype();
760 auto result = MATCH.nomatch;
761 if ((tb.ty == Tarray || tb.ty == Tsarray) &&
762 (typeb.ty == Tarray || typeb.ty == Tsarray))
764 result = MATCH.exact;
765 Type typen = typeb.nextOf().toBasetype();
767 if (auto tsa = tb.isTypeSArray())
769 if (e.elements.length != tsa.dim.toInteger())
770 result = MATCH.nomatch;
773 Type telement = tb.nextOf();
774 if (!e.elements.length)
776 if (typen.ty != Tvoid)
777 result = typen.implicitConvTo(telement);
779 else
781 if (e.basis)
783 MATCH m = e.basis.implicitConvTo(telement);
784 if (m < result)
785 result = m;
787 for (size_t i = 0; i < e.elements.length; i++)
789 Expression el = (*e.elements)[i];
790 if (result == MATCH.nomatch)
791 break;
792 if (!el)
793 continue;
794 MATCH m = el.implicitConvTo(telement);
795 if (m < result)
796 result = m; // remember worst match
800 if (!result)
801 result = e.type.implicitConvTo(t);
803 return result;
805 else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
807 result = MATCH.exact;
808 // Convert array literal to vector type
809 TypeVector tv = tb.isTypeVector();
810 TypeSArray tbase = tv.basetype.isTypeSArray();
811 assert(tbase);
812 const edim = e.elements.length;
813 const tbasedim = tbase.dim.toInteger();
814 if (edim > tbasedim)
816 return MATCH.nomatch;
819 Type telement = tv.elementType();
820 if (edim < tbasedim)
822 Expression el = typeb.nextOf.defaultInitLiteral(e.loc);
823 MATCH m = el.implicitConvTo(telement);
824 if (m < result)
825 result = m; // remember worst match
827 foreach (el; (*e.elements)[])
829 MATCH m = el.implicitConvTo(telement);
830 if (m < result)
831 result = m; // remember worst match
832 if (result == MATCH.nomatch)
833 break; // no need to check for worse
835 return result;
838 return visit(e);
841 MATCH visitAssocArrayLiteral(AssocArrayLiteralExp e)
843 auto taa = t.toBasetype().isTypeAArray();
844 Type typeb = e.type.toBasetype();
846 if (!(taa && typeb.ty == Taarray))
847 return visit(e);
849 auto result = MATCH.exact;
850 foreach (i, el; (*e.keys)[])
852 MATCH m = el.implicitConvTo(taa.index);
853 if (m < result)
854 result = m; // remember worst match
855 if (result == MATCH.nomatch)
856 break; // no need to check for worse
857 el = (*e.values)[i];
858 m = el.implicitConvTo(taa.nextOf());
859 if (m < result)
860 result = m; // remember worst match
861 if (result == MATCH.nomatch)
862 break; // no need to check for worse
864 return result;
867 MATCH visitCall(CallExp e)
869 enum LOG = false;
870 static if (LOG)
872 printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
875 auto result = visit(e);
876 if (result != MATCH.nomatch)
877 return result;
879 /* Allow the result of strongly pure functions to
880 * convert to immutable
882 if (e.f &&
883 (!global.params.fixImmutableConv || e.f.isPure() >= PURE.const_) &&
884 e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive.
887 result = e.type.immutableOf().implicitConvTo(t);
888 if (result > MATCH.constant) // Match level is MATCH.constant at best.
889 result = MATCH.constant;
890 return result;
893 /* Conversion is 'const' conversion if:
894 * 1. function is pure (weakly pure is ok)
895 * 2. implicit conversion only fails because of mod bits
896 * 3. each function parameter can be implicitly converted to the mod bits
898 auto tf = (e.f ? e.f.type : e.e1.type).toBasetype().isTypeFunction();
899 if (!tf)
900 return result;
902 if (tf.purity == PURE.impure)
903 return result;
904 if (e.f && e.f.isNested())
905 return result;
907 /* See if fail only because of mod bits.
909 * https://issues.dlang.org/show_bug.cgi?id=14155
910 * All pure functions can access global immutable data.
911 * So the returned pointer may refer an immutable global data,
912 * and then the returned pointer that points non-mutable object
913 * cannot be unique pointer.
915 * Example:
916 * immutable g;
917 * static this() { g = 1; }
918 * const(int*) foo() pure { return &g; }
919 * void test() {
920 * immutable(int*) ip = foo(); // OK
921 * int* mp = foo(); // should be disallowed
924 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)
926 return result;
928 // Allow a conversion to immutable type, or
929 // conversions of mutable types between thread-local and shared.
931 /* Get mod bits of what we're converting to
933 Type tb = t.toBasetype();
934 MOD mod = tb.mod;
935 if (tf.isref)
938 else
940 if (Type ti = getIndirection(t))
941 mod = ti.mod;
943 static if (LOG)
945 printf("mod = x%x\n", mod);
947 if (mod & MODFlags.wild)
948 return result; // not sure what to do with this
950 /* Apply mod bits to each function parameter,
951 * and see if we can convert the function argument to the modded type
953 if (auto dve = e.e1.isDotVarExp())
955 /* Treat 'this' as just another function argument
957 Type targ = dve.e1.type;
958 if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
959 return result;
962 if (!parametersModMatch(e.arguments, tf, mod))
963 return result;
965 /* Success
967 return MATCH.constant;
970 MATCH visitAddr(AddrExp e)
972 version (none)
974 printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
976 auto result = e.type.implicitConvTo(t);
977 //printf("\tresult = %d\n", result);
979 if (result != MATCH.nomatch)
980 return result;
982 Type tb = t.toBasetype();
983 Type typeb = e.type.toBasetype();
985 // Look for pointers to functions where the functions are overloaded.
986 if (e.e1.op == EXP.overloadSet &&
987 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
989 OverExp eo = e.e1.isOverExp();
990 FuncDeclaration f = null;
991 foreach (s; eo.vars.a[])
993 FuncDeclaration f2 = s.isFuncDeclaration();
994 assert(f2);
995 if (f2.overloadExactMatch(tb.nextOf()))
997 if (f)
999 /* Error if match in more than one overload set,
1000 * even if one is a 'better' match than the other.
1002 ScopeDsymbol.multiplyDefined(e.loc, f, f2);
1004 else
1005 f = f2;
1006 result = MATCH.exact;
1011 if (e.e1.op == EXP.variable &&
1012 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
1013 tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
1015 /* I don't think this can ever happen -
1016 * it should have been
1017 * converted to a SymOffExp.
1019 assert(0);
1022 //printf("\tresult = %d\n", result);
1023 return result;
1026 MATCH visitSymOff(SymOffExp e)
1028 version (none)
1030 printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1032 auto result = e.type.implicitConvTo(t);
1033 //printf("\tresult = %d\n", result);
1034 if (result != MATCH.nomatch)
1035 return result;
1037 Type tb = t.toBasetype();
1038 Type typeb = e.type.toBasetype();
1040 // Look for pointers to functions where the functions are overloaded.
1041 if (typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
1042 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
1044 if (FuncDeclaration f = e.var.isFuncDeclaration())
1046 f = f.overloadExactMatch(tb.nextOf());
1047 if (f)
1049 if ((tb.ty == Tdelegate && (f.needThis() || f.isNested())) ||
1050 (tb.ty == Tpointer && !(f.needThis() || f.isNested())))
1052 result = MATCH.exact;
1057 //printf("\tresult = %d\n", result);
1058 return result;
1061 MATCH visitDelegate(DelegateExp e)
1063 version (none)
1065 printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1067 auto result = e.type.implicitConvTo(t);
1068 if (result != MATCH.nomatch)
1069 return result;
1071 Type tb = t.toBasetype();
1072 Type typeb = e.type.toBasetype();
1074 // Look for pointers to functions where the functions are overloaded.
1075 if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
1077 if (e.func && e.func.overloadExactMatch(tb.nextOf()))
1078 result = MATCH.exact;
1080 return result;
1083 MATCH visitFunc(FuncExp e)
1085 //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
1086 MATCH m = e.matchType(t, null, null, global.errorSinkNull);
1087 if (m > MATCH.nomatch)
1089 return m;
1091 return visit(e);
1094 MATCH visitAnd(AndExp e)
1096 auto result = visit(e);
1097 if (result != MATCH.nomatch)
1098 return result;
1100 MATCH m1 = e.e1.implicitConvTo(t);
1101 MATCH m2 = e.e2.implicitConvTo(t);
1103 // Pick the worst match
1104 return (m1 < m2) ? m1 : m2;
1107 MATCH visitOr(OrExp e)
1109 auto result = visit(e);
1110 if (result != MATCH.nomatch)
1111 return result;
1113 MATCH m1 = e.e1.implicitConvTo(t);
1114 MATCH m2 = e.e2.implicitConvTo(t);
1116 // Pick the worst match
1117 return (m1 < m2) ? m1 : m2;
1120 MATCH visitXor(XorExp e)
1122 auto result = visit(e);
1123 if (result != MATCH.nomatch)
1124 return result;
1126 MATCH m1 = e.e1.implicitConvTo(t);
1127 MATCH m2 = e.e2.implicitConvTo(t);
1129 // Pick the worst match
1130 return (m1 < m2) ? m1 : m2;
1133 MATCH visitCond(CondExp e)
1135 e.econd = e.econd.optimize(WANTvalue);
1136 const opt = e.econd.toBool();
1137 if (opt.isPresent())
1139 auto result = visit(e);
1140 if (result != MATCH.nomatch)
1141 return result;
1144 MATCH m1 = e.e1.implicitConvTo(t);
1145 MATCH m2 = e.e2.implicitConvTo(t);
1146 //printf("CondExp: m1 %d m2 %d\n", m1, m2);
1148 // Pick the worst match
1149 return (m1 < m2) ? m1 : m2;
1152 MATCH visitComma(CommaExp e)
1154 return e.e2.implicitConvTo(t);
1157 MATCH visitCast(CastExp e)
1159 version (none)
1161 printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1163 auto result = e.type.implicitConvTo(t);
1164 if (result != MATCH.nomatch)
1165 return result;
1167 if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
1168 result = MATCH.convert;
1169 else
1170 result = visit(e);
1171 return result;
1174 MATCH visitNew(NewExp e)
1176 version (none)
1178 printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1180 auto result = visit(e);
1181 if (result != MATCH.nomatch)
1182 return result;
1184 /* Calling new() is like calling a pure function. We can implicitly convert the
1185 * return from new() to t using the same algorithm as in CallExp, with the function
1186 * 'arguments' being:
1187 * thisexp
1188 * arguments
1189 * .init
1190 * 'member' need to be pure.
1193 /* See if fail only because of mod bits
1195 if (e.type.immutableOf().implicitConvTo(t.immutableOf()) == MATCH.nomatch)
1196 return MATCH.nomatch;
1198 /* Get mod bits of what we're converting to
1200 Type tb = t.toBasetype();
1201 MOD mod = tb.mod;
1202 if (Type ti = getIndirection(t))
1203 mod = ti.mod;
1204 static if (LOG)
1206 printf("mod = x%x\n", mod);
1208 if (mod & MODFlags.wild)
1209 return MATCH.nomatch; // not sure what to do with this
1211 /* Apply mod bits to each argument,
1212 * and see if we can convert the argument to the modded type
1215 if (e.thisexp)
1217 /* Treat 'this' as just another function argument
1219 Type targ = e.thisexp.type;
1220 if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
1221 return MATCH.nomatch;
1224 /* Check call to 'member'
1226 if (e.member)
1228 FuncDeclaration fd = e.member;
1229 if (fd.errors || fd.type.ty != Tfunction)
1230 return MATCH.nomatch; // error
1231 TypeFunction tf = fd.type.isTypeFunction();
1232 if (tf.purity == PURE.impure)
1233 return MATCH.nomatch; // impure
1235 // Allow a conversion to immutable type, or
1236 // conversions of mutable types between thread-local and shared.
1237 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)
1239 return MATCH.nomatch;
1242 if (!parametersModMatch(e.arguments, tf, mod))
1244 return MATCH.nomatch;
1248 /* If no 'member', then construction is by simple assignment,
1249 * and just straight check 'arguments'
1251 if (!e.member && e.arguments)
1253 for (size_t i = 0; i < e.arguments.length; ++i)
1255 Expression earg = (*e.arguments)[i];
1256 if (!earg) // https://issues.dlang.org/show_bug.cgi?id=14853
1257 // if it's on overlapped field
1258 continue;
1259 Type targ = earg.type.toBasetype();
1260 static if (LOG)
1262 printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
1263 printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
1265 if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1266 return MATCH.nomatch;
1270 /* Consider the .init expression as an argument
1272 Type ntb = e.newtype.toBasetype();
1273 if (ntb.ty == Tarray)
1274 ntb = ntb.nextOf().toBasetype();
1275 if (auto ts = ntb.isTypeStruct())
1277 // Don't allow nested structs - uplevel reference may not be convertible
1278 StructDeclaration sd = ts.sym;
1279 sd.size(e.loc); // resolve any forward references
1280 if (sd.isNested())
1281 return MATCH.nomatch;
1283 if (ntb.isZeroInit(e.loc))
1285 /* Zeros are implicitly convertible, except for special cases.
1287 if (auto tc = ntb.isTypeClass())
1289 /* With new() must look at the class instance initializer.
1291 ClassDeclaration cd = tc.sym;
1293 cd.size(e.loc); // resolve any forward references
1295 if (cd.isNested())
1296 return MATCH.nomatch; // uplevel reference may not be convertible
1298 assert(!cd.isInterfaceDeclaration());
1300 struct ClassCheck
1302 extern (C++) static bool convertible(Expression e, ClassDeclaration cd, MOD mod)
1304 for (size_t i = 0; i < cd.fields.length; i++)
1306 VarDeclaration v = cd.fields[i];
1307 Initializer _init = v._init;
1308 if (_init)
1310 if (_init.isVoidInitializer())
1313 else if (ExpInitializer ei = _init.isExpInitializer())
1315 // https://issues.dlang.org/show_bug.cgi?id=21319
1316 // This is to prevent re-analyzing the same expression
1317 // over and over again.
1318 if (ei.exp == e)
1319 return false;
1320 Type tb = v.type.toBasetype();
1321 if (implicitMod(ei.exp, tb, mod) == MATCH.nomatch)
1322 return false;
1324 else
1326 /* Enhancement: handle StructInitializer and ArrayInitializer
1328 return false;
1331 else if (!v.type.isZeroInit(e.loc))
1332 return false;
1334 return cd.baseClass ? convertible(e, cd.baseClass, mod) : true;
1338 if (!ClassCheck.convertible(e, cd, mod))
1339 return MATCH.nomatch;
1342 else
1344 Expression earg = e.newtype.defaultInitLiteral(e.loc);
1345 Type targ = e.newtype.toBasetype();
1347 if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1348 return MATCH.nomatch;
1351 /* Success
1353 return MATCH.constant;
1356 MATCH visitSlice(SliceExp e)
1358 //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e.toChars(), e.type.toChars());
1359 auto result = visit(e);
1360 if (result != MATCH.nomatch)
1361 return result;
1363 Type tb = t.toBasetype();
1364 Type typeb = e.type.toBasetype();
1366 if (tb.ty == Tsarray && typeb.ty == Tarray)
1368 typeb = toStaticArrayType(e);
1369 if (typeb)
1371 // Try: T[] -> T[dim]
1372 // (Slice with compile-time known boundaries to static array)
1373 result = typeb.implicitConvTo(t);
1374 if (result > MATCH.convert)
1375 result = MATCH.convert; // match with implicit conversion at most
1377 return result;
1380 /* If the only reason it won't convert is because of the mod bits,
1381 * then test for conversion by seeing if e1 can be converted with those
1382 * same mod bits.
1384 Type t1b = e.e1.type.toBasetype();
1385 if (tb.ty == Tarray && typeb.equivalent(tb))
1387 Type tbn = tb.nextOf();
1388 Type tx = null;
1390 /* If e.e1 is dynamic array or pointer, the uniqueness of e.e1
1391 * is equivalent with the uniqueness of the referred data. And in here
1392 * we can have arbitrary typed reference for that.
1394 if (t1b.ty == Tarray)
1395 tx = tbn.arrayOf();
1396 if (t1b.ty == Tpointer)
1397 tx = tbn.pointerTo();
1399 /* If e.e1 is static array, at least it should be an rvalue.
1400 * If not, e.e1 is a reference, and its uniqueness does not link
1401 * to the uniqueness of the referred data.
1403 if (t1b.ty == Tsarray && !e.e1.isLvalue())
1404 tx = tbn.sarrayOf(t1b.size() / tbn.size());
1406 if (tx)
1408 result = e.e1.implicitConvTo(tx);
1409 if (result > MATCH.constant) // Match level is MATCH.constant at best.
1410 result = MATCH.constant;
1414 // Enhancement 10724
1415 if (tb.ty == Tpointer && e.e1.op == EXP.string_)
1416 result = e.e1.implicitConvTo(t);
1417 return result;
1420 MATCH visitTuple(TupleExp e)
1422 auto result = e.type.implicitConvTo(t);
1423 if (result != MATCH.nomatch)
1424 return result;
1426 /* If target type is a tuple of same length, test conversion of
1427 * each expression to the corresponding type in the tuple.
1429 TypeTuple totuple = t.isTypeTuple();
1430 if (totuple && e.exps.length == totuple.arguments.length)
1432 result = MATCH.exact;
1433 foreach (i, ex; *e.exps)
1435 auto to = (*totuple.arguments)[i].type;
1436 MATCH mi = ex.implicitConvTo(to);
1437 if (mi < result)
1438 result = mi;
1441 return result;
1444 switch (e.op)
1446 default : return visit(e);
1447 case EXP.add : return visitAdd(e.isAddExp());
1448 case EXP.min : return visitMin(e.isMinExp());
1449 case EXP.int64 : return visitInteger(e.isIntegerExp());
1450 case EXP.error : return visitError(e.isErrorExp());
1451 case EXP.null_ : return visitNull(e.isNullExp());
1452 case EXP.structLiteral : return visitStructLiteral(e.isStructLiteralExp());
1453 case EXP.string_ : return visitString(e.isStringExp());
1454 case EXP.arrayLiteral : return visitArrayLiteral(e.isArrayLiteralExp());
1455 case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
1456 case EXP.call : return visitCall(e.isCallExp());
1457 case EXP.address : return visitAddr(e.isAddrExp());
1458 case EXP.symbolOffset : return visitSymOff(e.isSymOffExp());
1459 case EXP.delegate_ : return visitDelegate(e.isDelegateExp());
1460 case EXP.function_ : return visitFunc(e.isFuncExp());
1461 case EXP.and : return visitAnd(e.isAndExp());
1462 case EXP.or : return visitOr(e.isOrExp());
1463 case EXP.xor : return visitXor(e.isXorExp());
1464 case EXP.question : return visitCond(e.isCondExp());
1465 case EXP.comma : return visitComma(e.isCommaExp());
1466 case EXP.cast_ : return visitCast(e.isCastExp());
1467 case EXP.new_ : return visitNew(e.isNewExp());
1468 case EXP.slice : return visitSlice(e.isSliceExp());
1469 case EXP.tuple : return visitTuple(e.isTupleExp());
1474 * Same as implicitConvTo(); except follow C11 rules, which are quite a bit
1475 * more permissive than D.
1476 * C11 6.3 and 6.5.16.1
1477 * Params:
1478 * e = Expression that is to be casted
1479 * t = Expected resulting type
1480 * Returns:
1481 * The `MATCH` level between `e.type` and `t`.
1483 MATCH cimplicitConvTo(Expression e, Type t)
1485 Type tb = t.toBasetype();
1486 Type typeb = e.type.toBasetype();
1488 if (tb.equals(typeb))
1489 return MATCH.exact;
1490 if ((typeb.isintegral() || typeb.isfloating()) &&
1491 (tb.isintegral() || tb.isfloating()))
1492 return MATCH.convert;
1493 if (tb.ty == Tpointer && typeb.isintegral()) // C11 6.3.2.3-5
1494 return MATCH.convert;
1495 if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
1496 return MATCH.convert;
1497 if (tb.ty == Tpointer && typeb.ty == Tpointer) // C11 6.3.2.3-7
1498 return MATCH.convert;
1500 return implicitConvTo(e, t);
1503 /*****************************************
1505 Type toStaticArrayType(SliceExp e)
1507 if (e.lwr && e.upr)
1509 // For the following code to work, e should be optimized beforehand.
1510 // (eg. $ in lwr and upr should be already resolved, if possible)
1511 Expression lwr = e.lwr.optimize(WANTvalue);
1512 Expression upr = e.upr.optimize(WANTvalue);
1513 if (lwr.isConst() && upr.isConst())
1515 size_t len = cast(size_t)(upr.toUInteger() - lwr.toUInteger());
1516 return e.type.toBasetype().nextOf().sarrayOf(len);
1519 else
1521 Type t1b = e.e1.type.toBasetype();
1522 if (t1b.ty == Tsarray)
1523 return t1b;
1525 return null;
1528 /**************************************
1529 * Do an explicit cast.
1530 * Assume that the expression `e` does not have any indirections.
1531 * (Parameter 'att' is used to stop 'alias this' recursion)
1533 Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
1535 //printf("castTo(e: %s from: %s to: %s\n", e.toChars(), e.type.toChars(), t.toChars());
1537 Expression visit(Expression e)
1539 //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
1540 version (none)
1542 printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1544 if (e.type.equals(t))
1546 return e;
1548 if (e.type.isTypeNoreturn() && e.op != EXP.type)
1550 return specialNoreturnCast(e, t);
1552 if (auto ve = e.isVarExp())
1554 VarDeclaration v = ve.var.isVarDeclaration();
1555 if (v && v.storage_class & STC.manifest)
1557 auto result = e.ctfeInterpret();
1558 /* https://issues.dlang.org/show_bug.cgi?id=18236
1560 * The expression returned by ctfeInterpret points
1561 * to the line where the manifest constant was declared
1562 * so we need to update the location before trying to cast
1564 result.loc = e.loc;
1565 return result.castTo(sc, t);
1569 Type tob = t.toBasetype();
1570 Type t1b = e.type.toBasetype();
1571 if (tob.equals(t1b))
1573 auto result = e.copy(); // because of COW for assignment to e.type
1574 result.type = t;
1575 return result;
1578 /* Make semantic error against invalid cast between concrete types.
1579 * Assume that 'e' is never be any placeholder expressions.
1580 * The result of these checks should be consistent with CastExp::toElem().
1583 // Fat Value types
1584 const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray || tob.ty == Tvector);
1585 const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray || t1b.ty == Tvector);
1587 // Fat Reference types
1588 const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate);
1589 const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate);
1591 // Reference types
1592 const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass);
1593 const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
1595 // Arithmetic types (== valueable basic types)
1596 const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
1597 const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
1599 // Try casting the alias this member.
1600 // Return the expression if it succeeds, null otherwise.
1601 Expression tryAliasThisCast()
1603 if (isRecursiveAliasThis(att, t1b))
1604 return null;
1606 /* Forward the cast to our alias this member, rewrite to:
1607 * cast(to)e1.aliasthis
1609 auto exp = resolveAliasThis(sc, e);
1610 const errors = global.startGagging();
1611 exp = castTo(exp, sc, t, att);
1612 return global.endGagging(errors) ? null : exp;
1615 bool hasAliasThis;
1616 if (AggregateDeclaration t1ad = isAggregate(t1b))
1618 AggregateDeclaration toad = isAggregate(tob);
1619 if (t1ad != toad && t1ad.aliasthis)
1621 if (t1b.ty == Tclass && tob.ty == Tclass)
1623 ClassDeclaration t1cd = t1b.isClassHandle();
1624 ClassDeclaration tocd = tob.isClassHandle();
1625 int offset;
1626 if (tocd.isBaseOf(t1cd, &offset))
1627 goto Lok;
1629 hasAliasThis = true;
1632 else if (tob.ty == Tvector && t1b.ty != Tvector)
1634 if (t1b.ty == Tsarray)
1636 // Casting static array to vector with same size, e.g. `cast(int4) int[4]`
1637 if (t1b.size(e.loc) != tob.size(e.loc))
1638 goto Lfail;
1639 return new VectorExp(e.loc, e, tob).expressionSemantic(sc);
1641 //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
1642 TypeVector tv = tob.isTypeVector();
1643 Expression result = new CastExp(e.loc, e, tv.elementType());
1644 result = new VectorExp(e.loc, result, tob);
1645 result = result.expressionSemantic(sc);
1646 return result;
1648 else if (tob.ty != Tvector && t1b.ty == Tvector)
1650 // T[n] <-- __vector(U[m])
1651 if (tob.ty == Tsarray)
1653 if (t1b.size(e.loc) == tob.size(e.loc))
1654 goto Lok;
1656 goto Lfail;
1658 else if (t1b.implicitConvTo(tob) == MATCH.constant && t.equals(e.type.constOf()))
1660 auto result = e.copy();
1661 result.type = t;
1662 return result;
1665 // arithmetic values vs. other arithmetic values
1666 // arithmetic values vs. T*
1667 if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer))
1669 goto Lok;
1672 // arithmetic values vs. references or fat values
1673 if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV))
1675 goto Lfail;
1678 // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
1679 if (tob_isFV && t1b_isFV)
1681 if (hasAliasThis)
1683 auto result = tryAliasThisCast();
1684 if (result)
1685 return result;
1688 if (t1b.size(e.loc) == tob.size(e.loc))
1689 goto Lok;
1691 auto ts = toAutoQualChars(e.type, t);
1692 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
1693 e.toChars(), ts[0], ts[1]);
1694 return ErrorExp.get();
1697 // Fat values vs. null or references
1698 if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR))
1700 if (tob.ty == Tpointer && t1b.ty == Tsarray)
1702 // T[n] sa;
1703 // cast(U*)sa; // ==> cast(U*)sa.ptr;
1704 return new AddrExp(e.loc, e, t);
1706 if (tob.ty == Tarray && t1b.ty == Tsarray)
1708 // T[n] sa;
1709 // cast(U[])sa; // ==> cast(U[])sa[];
1710 const fsize = t1b.nextOf().size();
1711 const tsize = tob.nextOf().size();
1712 if (fsize == SIZE_INVALID || tsize == SIZE_INVALID)
1714 return ErrorExp.get();
1716 if (fsize != tsize)
1718 const dim = t1b.isTypeSArray().dim.toInteger();
1719 if (tsize == 0 || (dim * fsize) % tsize != 0)
1721 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
1722 e.toChars(), e.type.toChars(), t.toChars());
1723 return ErrorExp.get();
1726 goto Lok;
1728 goto Lfail;
1731 /* For references, any reinterpret casts are allowed to same 'ty' type.
1732 * T* to U*
1733 * R1 function(P1) to R2 function(P2)
1734 * R1 delegate(P1) to R2 delegate(P2)
1735 * T[] to U[]
1736 * V1[K1] to V2[K2]
1737 * class/interface A to B (will be a dynamic cast if possible)
1739 if (tob.ty == t1b.ty && tob_isR && t1b_isR)
1740 goto Lok;
1742 // typeof(null) <-- non-null references or values
1743 if (tob.ty == Tnull && t1b.ty != Tnull)
1744 goto Lfail; // https://issues.dlang.org/show_bug.cgi?id=14629
1745 // typeof(null) --> non-null references or arithmetic values
1746 if (t1b.ty == Tnull && tob.ty != Tnull)
1747 goto Lok;
1749 // Check size mismatch of references.
1750 // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
1751 if (tob_isFR && t1b_isR || t1b_isFR && tob_isR)
1753 if (tob.ty == Tpointer && t1b.ty == Tarray)
1755 // T[] da;
1756 // cast(U*)da; // ==> cast(U*)da.ptr;
1757 goto Lok;
1759 if (tob.ty == Tpointer && t1b.ty == Tdelegate)
1761 // void delegate() dg;
1762 // cast(U*)dg; // ==> cast(U*)dg.ptr;
1763 // Note that it happens even when U is a Tfunction!
1764 deprecation(e.loc, "casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
1765 goto Lok;
1767 goto Lfail;
1770 if (t1b.ty == Tvoid && tob.ty != Tvoid)
1772 Lfail:
1773 /* if the cast cannot be performed, maybe there is an alias
1774 * this that can be used for casting.
1776 if (hasAliasThis)
1778 auto result = tryAliasThisCast();
1779 if (result)
1780 return result;
1782 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
1783 return ErrorExp.get();
1786 Lok:
1787 auto result = new CastExp(e.loc, e, t);
1788 result.type = t; // Don't call semantic()
1789 //printf("Returning: %s\n", result.toChars());
1790 return result;
1793 Expression visitError(ErrorExp e)
1795 return e;
1798 Expression visitReal(RealExp e)
1800 if (!e.type.equals(t))
1802 if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
1804 auto result = e.copy();
1805 result.type = t;
1806 return result;
1808 else
1809 return visit(e);
1811 return e;
1814 Expression visitComplex(ComplexExp e)
1816 if (!e.type.equals(t))
1818 if (e.type.iscomplex() && t.iscomplex())
1820 auto result = e.copy();
1821 result.type = t;
1822 return result;
1824 else
1825 return visit(e);
1827 return e;
1830 Expression visitStructLiteral(StructLiteralExp e)
1832 auto result = visit(e);
1833 if (auto sle = result.isStructLiteralExp())
1834 sle.stype = t; // commit type
1835 return result;
1838 Expression visitString(StringExp e)
1840 /* This follows copy-on-write; any changes to 'this'
1841 * will result in a copy.
1842 * The this.string member is considered immutable.
1844 int copied = 0;
1846 //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
1848 if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
1849 (!sc || !(sc.flags & SCOPE.Cfile)))
1851 error(e.loc, "cannot convert string literal to `void*`");
1852 return ErrorExp.get();
1855 StringExp se = e;
1857 Expression lcast()
1859 auto result = new CastExp(e.loc, se, t);
1860 result.type = t; // so semantic() won't be run on e
1861 return result;
1864 if (!e.committed)
1866 se = e.copy().isStringExp();
1867 se.committed = true;
1868 copied = 1;
1871 if (e.type.equals(t))
1873 return se;
1876 Type tb = t.toBasetype();
1877 Type typeb = e.type.toBasetype();
1879 //printf("\ttype = %s\n", e.type.toChars());
1880 if (tb.ty == Tdelegate && typeb.ty != Tdelegate)
1882 return visit(e);
1885 if (typeb.equals(tb))
1887 if (!copied)
1889 se = e.copy().isStringExp();
1890 copied = 1;
1892 se.type = t;
1893 return se;
1896 /* Handle reinterpret casts:
1897 * cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
1898 * cast(wchar[2])"abcd"c --> [\u6261, \u6463]
1899 * cast(wchar[1])"abcd"c --> [\u6261]
1900 * cast(char[4])"a" --> ['a', 0, 0, 0]
1902 if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
1904 se = e.copy().isStringExp();
1905 uinteger_t szx = tb.nextOf().size();
1906 assert(szx <= 255);
1907 se.sz = cast(ubyte)szx;
1908 se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
1909 se.committed = true;
1910 se.type = t;
1912 /* If larger than source, pad with zeros.
1914 const fullSize = (se.len + 1) * se.sz; // incl. terminating 0
1915 if (fullSize > (e.len + 1) * e.sz)
1917 void* s = mem.xmalloc(fullSize);
1918 const srcSize = e.len * e.sz;
1919 const data = se.peekData();
1920 memcpy(s, data.ptr, srcSize);
1921 memset(s + srcSize, 0, fullSize - srcSize);
1922 se.setData(s, se.len, se.sz);
1924 return se;
1927 if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer)
1929 if (!copied)
1931 se = e.copy().isStringExp();
1932 copied = 1;
1934 return lcast();
1936 if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
1938 if (!copied)
1940 se = e.copy().isStringExp();
1941 copied = 1;
1943 return lcast();
1946 const nextSz = typeb.nextOf().size();
1947 if (nextSz == SIZE_INVALID)
1949 return ErrorExp.get();
1951 if (nextSz == tb.nextOf().size())
1953 if (!copied)
1955 se = e.copy().isStringExp();
1956 copied = 1;
1958 if (tb.ty == Tsarray)
1959 goto L2; // handle possible change in static array dimension
1960 se.type = t;
1961 return se;
1964 if (e.committed)
1965 goto Lcast;
1967 auto X(T, U)(T tf, U tt)
1969 return (cast(int)tf * 256 + cast(int)tt);
1973 OutBuffer buffer;
1974 size_t newlen = 0;
1975 int tfty = typeb.nextOf().toBasetype().ty;
1976 int ttty = tb.nextOf().toBasetype().ty;
1977 switch (X(tfty, ttty))
1979 case X(Tchar, Tchar):
1980 case X(Twchar, Twchar):
1981 case X(Tdchar, Tdchar):
1982 break;
1984 case X(Tchar, Twchar):
1985 for (size_t u = 0; u < e.len;)
1987 dchar c;
1988 if (const s = utf_decodeChar(se.peekString(), u, c))
1989 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
1990 else
1991 buffer.writeUTF16(c);
1993 newlen = buffer.length / 2;
1994 buffer.writeUTF16(0);
1995 goto L1;
1997 case X(Tchar, Tdchar):
1998 for (size_t u = 0; u < e.len;)
2000 dchar c;
2001 if (const s = utf_decodeChar(se.peekString(), u, c))
2002 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
2003 buffer.write4(c);
2004 newlen++;
2006 buffer.write4(0);
2007 goto L1;
2009 case X(Twchar, Tchar):
2010 for (size_t u = 0; u < e.len;)
2012 dchar c;
2013 if (const s = utf_decodeWchar(se.peekWstring(), u, c))
2014 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
2015 else
2016 buffer.writeUTF8(c);
2018 newlen = buffer.length;
2019 buffer.writeUTF8(0);
2020 goto L1;
2022 case X(Twchar, Tdchar):
2023 for (size_t u = 0; u < e.len;)
2025 dchar c;
2026 if (const s = utf_decodeWchar(se.peekWstring(), u, c))
2027 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
2028 buffer.write4(c);
2029 newlen++;
2031 buffer.write4(0);
2032 goto L1;
2034 case X(Tdchar, Tchar):
2035 for (size_t u = 0; u < e.len; u++)
2037 uint c = se.peekDstring()[u];
2038 if (!utf_isValidDchar(c))
2039 error(e.loc, "invalid UCS-32 char \\U%08x", c);
2040 else
2041 buffer.writeUTF8(c);
2042 newlen++;
2044 newlen = buffer.length;
2045 buffer.writeUTF8(0);
2046 goto L1;
2048 case X(Tdchar, Twchar):
2049 for (size_t u = 0; u < e.len; u++)
2051 uint c = se.peekDstring()[u];
2052 if (!utf_isValidDchar(c))
2053 error(e.loc, "invalid UCS-32 char \\U%08x", c);
2054 else
2055 buffer.writeUTF16(c);
2056 newlen++;
2058 newlen = buffer.length / 2;
2059 buffer.writeUTF16(0);
2060 goto L1;
2063 if (!copied)
2065 se = e.copy().isStringExp();
2066 copied = 1;
2070 uinteger_t szx = tb.nextOf().size();
2071 assert(szx <= 255);
2072 se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
2074 break;
2076 default:
2077 assert(typeb.nextOf().size() != tb.nextOf().size());
2078 goto Lcast;
2082 assert(copied);
2084 // See if need to truncate or extend the literal
2085 if (auto tsa = tb.isTypeSArray())
2087 size_t dim2 = cast(size_t)tsa.dim.toInteger();
2088 //printf("dim from = %d, to = %d\n", cast(int)se.len, cast(int)dim2);
2090 // Changing dimensions
2091 if (dim2 != se.len)
2093 // Copy when changing the string literal
2094 const newsz = se.sz;
2095 const d = (dim2 < se.len) ? dim2 : se.len;
2096 void* s = mem.xmalloc((dim2 + 1) * newsz);
2097 memcpy(s, se.peekData().ptr, d * newsz);
2098 // Extend with 0, add terminating 0
2099 memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz);
2100 se.setData(s, dim2, newsz);
2103 se.type = t;
2104 return se;
2106 Lcast:
2107 auto result = new CastExp(e.loc, se, t);
2108 result.type = t; // so semantic() won't be run on e
2109 return result;
2112 Expression visitAddr(AddrExp e)
2114 version (none)
2116 printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2118 Type tb = t.toBasetype();
2119 Type typeb = e.type.toBasetype();
2121 if (tb.equals(typeb))
2123 auto result = e.copy();
2124 result.type = t;
2125 return result;
2128 // Look for pointers to functions where the functions are overloaded.
2129 if (e.e1.isOverExp() &&
2130 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2132 OverExp eo = e.e1.isOverExp();
2133 FuncDeclaration f = null;
2134 for (size_t i = 0; i < eo.vars.a.length; i++)
2136 auto s = eo.vars.a[i];
2137 auto f2 = s.isFuncDeclaration();
2138 assert(f2);
2139 if (f2.overloadExactMatch(tb.nextOf()))
2141 if (f)
2143 /* Error if match in more than one overload set,
2144 * even if one is a 'better' match than the other.
2146 ScopeDsymbol.multiplyDefined(e.loc, f, f2);
2148 else
2149 f = f2;
2152 if (f)
2154 f.tookAddressOf++;
2155 auto se = new SymOffExp(e.loc, f, 0, false);
2156 auto se2 = se.expressionSemantic(sc);
2157 // Let SymOffExp::castTo() do the heavy lifting
2158 return visit(se2);
2162 if (e.e1.isVarExp() &&
2163 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2164 tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
2166 auto ve = e.e1.isVarExp();
2167 auto f = ve.var.isFuncDeclaration();
2168 if (f)
2170 assert(f.isImportedSymbol());
2171 f = f.overloadExactMatch(tb.nextOf());
2172 if (f)
2174 Expression result = new VarExp(e.loc, f, false);
2175 result.type = f.type;
2176 result = new AddrExp(e.loc, result, t);
2177 return result;
2182 if (auto f = isFuncAddress(e))
2184 if (f.checkForwardRef(e.loc))
2186 return ErrorExp.get();
2190 return visit(e);
2193 Expression visitTuple(TupleExp e)
2195 if (e.type.equals(t))
2197 return e;
2200 /* If target type is a tuple of same length, cast each expression to
2201 * the corresponding type in the tuple.
2203 TypeTuple totuple;
2204 if (auto tt = t.isTypeTuple())
2205 totuple = e.exps.length == tt.arguments.length ? tt : null;
2207 TupleExp te = e.copy().isTupleExp();
2208 te.e0 = e.e0 ? e.e0.copy() : null;
2209 te.exps = e.exps.copy();
2210 for (size_t i = 0; i < te.exps.length; i++)
2212 Expression ex = (*te.exps)[i];
2213 ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
2214 (*te.exps)[i] = ex;
2216 if (totuple)
2217 te.type = totuple;
2218 return te;
2220 /* Questionable behavior: In here, result.type is not set to t
2221 * if target type is not a tuple of same length.
2222 * Therefoe:
2223 * TypeTuple!(int, int) values;
2224 * auto values2 = cast(long)values;
2225 * // typeof(values2) == TypeTuple!(int, int) !!
2227 * Only when the casted tuple is immediately expanded, it would work.
2228 * auto arr = [cast(long)values];
2229 * // typeof(arr) == long[]
2233 Expression visitArrayLiteral(ArrayLiteralExp e)
2235 version (none)
2237 printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2240 ArrayLiteralExp ae = e;
2242 Type tb = t.toBasetype();
2243 if (tb.ty == Tarray)
2245 if (checkArrayLiteralEscape(sc, ae, false))
2247 return ErrorExp.get();
2251 if (e.type == t)
2253 return e;
2255 Type typeb = e.type.toBasetype();
2257 if ((tb.ty == Tarray || tb.ty == Tsarray) &&
2258 (typeb.ty == Tarray || typeb.ty == Tsarray))
2260 if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
2262 // Don't do anything to cast non-void[] to void[]
2264 else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid)
2266 // Don't do anything for casting void[n] to others
2268 else
2270 if (auto tsa = tb.isTypeSArray())
2272 if (e.elements.length != tsa.dim.toInteger())
2273 goto L1;
2276 ae = e.copy().isArrayLiteralExp();
2277 if (e.basis)
2278 ae.basis = e.basis.castTo(sc, tb.nextOf());
2279 ae.elements = e.elements.copy();
2280 for (size_t i = 0; i < e.elements.length; i++)
2282 Expression ex = (*e.elements)[i];
2283 if (!ex)
2284 continue;
2285 ex = ex.castTo(sc, tb.nextOf());
2286 (*ae.elements)[i] = ex;
2288 ae.type = t;
2289 return ae;
2292 else if (tb.ty == Tpointer && typeb.ty == Tsarray)
2294 Type tp = typeb.nextOf().pointerTo();
2295 if (!tp.equals(ae.type))
2297 ae = e.copy().isArrayLiteralExp();
2298 ae.type = tp;
2301 else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
2303 // Convert array literal to vector type
2304 TypeVector tv = tb.isTypeVector();
2305 TypeSArray tbase = tv.basetype.isTypeSArray();
2306 assert(tbase.ty == Tsarray);
2307 const edim = e.elements.length;
2308 const tbasedim = tbase.dim.toInteger();
2309 if (edim > tbasedim)
2310 goto L1;
2312 ae = e.copy().isArrayLiteralExp();
2313 ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
2314 ae.elements = e.elements.copy();
2315 Type telement = tv.elementType();
2316 foreach (i; 0 .. edim)
2318 Expression ex = (*e.elements)[i];
2319 ex = ex.castTo(sc, telement);
2320 (*ae.elements)[i] = ex;
2322 // Fill in the rest with the default initializer
2323 ae.elements.setDim(cast(size_t)tbasedim);
2324 foreach (i; edim .. cast(size_t)tbasedim)
2326 Expression ex = typeb.nextOf.defaultInitLiteral(e.loc);
2327 ex = ex.castTo(sc, telement);
2328 (*ae.elements)[i] = ex;
2330 Expression ev = new VectorExp(e.loc, ae, tb);
2331 ev = ev.expressionSemantic(sc);
2332 return ev;
2335 return visit(ae);
2338 Expression visitAssocArrayLiteral(AssocArrayLiteralExp e)
2340 //printf("AssocArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2341 if (e.type == t)
2343 return e;
2346 Type tb = t.toBasetype();
2347 Type typeb = e.type.toBasetype();
2349 if (tb.ty == Taarray && typeb.ty == Taarray &&
2350 tb.nextOf().toBasetype().ty != Tvoid)
2352 AssocArrayLiteralExp ae = e.copy().isAssocArrayLiteralExp();
2353 ae.keys = e.keys.copy();
2354 ae.values = e.values.copy();
2355 assert(e.keys.length == e.values.length);
2356 for (size_t i = 0; i < e.keys.length; i++)
2358 Expression ex = (*e.values)[i];
2359 ex = ex.castTo(sc, tb.nextOf());
2360 (*ae.values)[i] = ex;
2362 ex = (*e.keys)[i];
2363 ex = ex.castTo(sc, tb.isTypeAArray().index);
2364 (*ae.keys)[i] = ex;
2366 ae.type = t;
2367 return ae;
2369 return visit(e);
2372 Expression visitSymOff(SymOffExp e)
2374 version (none)
2376 printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2378 if (e.type == t && !e.hasOverloads)
2380 return e;
2383 Type tb = t.toBasetype();
2384 Type typeb = e.type.toBasetype();
2386 if (tb.equals(typeb))
2388 auto result = e.copy();
2389 result.type = t;
2390 result.isSymOffExp().hasOverloads = false;
2391 return result;
2394 // Look for pointers to functions where the functions are overloaded.
2395 if (e.hasOverloads &&
2396 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2397 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2399 FuncDeclaration f = e.var.isFuncDeclaration();
2400 f = f ? f.overloadExactMatch(tb.nextOf()) : null;
2401 if (f)
2403 Expression result;
2404 if (tb.ty == Tdelegate)
2406 if (f.needThis() && hasThis(sc))
2408 result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false);
2409 result = result.expressionSemantic(sc);
2411 else if (f.needThis())
2413 error(e.loc, "no `this` to create delegate for `%s`", f.toChars());
2414 return ErrorExp.get();
2416 else if (f.isNested())
2418 result = new DelegateExp(e.loc, IntegerExp.literal!0, f, false);
2419 result = result.expressionSemantic(sc);
2421 else
2423 error(e.loc, "cannot cast from function pointer to delegate");
2424 return ErrorExp.get();
2427 else
2429 result = new SymOffExp(e.loc, f, 0, false);
2430 result.type = t;
2432 f.tookAddressOf++;
2433 return result;
2437 if (auto f = isFuncAddress(e))
2439 if (f.checkForwardRef(e.loc))
2441 return ErrorExp.get();
2445 return visit(e);
2448 Expression visitDelegate(DelegateExp e)
2450 version (none)
2452 printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2454 static immutable msg = "cannot form delegate due to covariant return type";
2456 Type tb = t.toBasetype();
2457 Type typeb = e.type.toBasetype();
2459 if (tb.equals(typeb) && !e.hasOverloads)
2461 int offset;
2462 e.func.tookAddressOf++;
2463 if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
2464 error(e.loc, "%s", msg.ptr);
2465 auto result = e.copy();
2466 result.type = t;
2467 return result;
2470 // Look for delegates to functions where the functions are overloaded.
2471 if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
2473 if (e.func)
2475 auto f = e.func.overloadExactMatch(tb.nextOf());
2476 if (f)
2478 int offset;
2479 if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
2480 error(e.loc, "%s", msg.ptr);
2481 if (f != e.func) // if address not already marked as taken
2482 f.tookAddressOf++;
2483 auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
2484 result.type = t;
2485 return result;
2487 if (e.func.tintro)
2488 error(e.loc, "%s", msg.ptr);
2492 if (auto f = isFuncAddress(e))
2494 if (f.checkForwardRef(e.loc))
2496 return ErrorExp.get();
2500 return visit(e);
2503 Expression visitFunc(FuncExp e)
2505 //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
2506 FuncExp fe;
2507 if (e.matchType(t, sc, &fe, global.errorSinkNull) > MATCH.nomatch)
2509 return fe;
2511 return visit(e);
2514 Expression visitCond(CondExp e)
2516 if (!e.type.equals(t))
2518 auto result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t));
2519 result.type = t;
2520 return result;
2522 return e;
2525 Expression visitComma(CommaExp e)
2527 Expression e2c = e.e2.castTo(sc, t);
2529 if (e2c != e.e2)
2531 auto result = new CommaExp(e.loc, e.e1, e2c);
2532 result.type = e2c.type;
2533 return result;
2535 else
2537 e.type = e.e2.type;
2538 return e;
2542 Expression visitSlice(SliceExp e)
2544 //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e.toChars(), e.type.toChars(), t.toChars());
2546 Type tb = t.toBasetype();
2547 Type typeb = e.type.toBasetype();
2549 if (e.type.equals(t) || typeb.ty != Tarray ||
2550 (tb.ty != Tarray && tb.ty != Tsarray))
2552 return visit(e);
2555 if (tb.ty == Tarray)
2557 if (typeb.nextOf().equivalent(tb.nextOf()))
2559 // T[] to const(T)[]
2560 auto result = e.copy();
2561 result.type = t;
2562 return result;
2564 else
2566 return visit(e);
2570 // Handle the cast from Tarray to Tsarray with CT-known slicing
2572 TypeSArray tsa;
2574 Type t = toStaticArrayType(e);
2575 tsa = t ? t.isTypeSArray() : null;
2578 if (tsa && tsa.size(e.loc) == tb.size(e.loc))
2580 /* Match if the sarray sizes are equal:
2581 * T[a .. b] to const(T)[b-a]
2582 * T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
2584 * If a SliceExp has Tsarray, it will become lvalue.
2585 * That's handled in SliceExp::isLvalue and toLvalue
2587 auto result = e.copy();
2588 result.type = t;
2589 return result;
2591 if (tsa && tsa.dim.equals(tb.isTypeSArray().dim))
2593 /* Match if the dimensions are equal
2594 * with the implicit conversion of e.e1:
2595 * cast(float[2]) [2.0, 1.0, 0.0][0..2];
2597 Type t1b = e.e1.type.toBasetype();
2598 if (t1b.ty == Tsarray)
2599 t1b = tb.nextOf().sarrayOf(t1b.isTypeSArray().dim.toInteger());
2600 else if (t1b.ty == Tarray)
2601 t1b = tb.nextOf().arrayOf();
2602 else if (t1b.ty == Tpointer)
2603 t1b = tb.nextOf().pointerTo();
2604 else
2605 assert(0);
2606 if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
2608 Expression e1x = e.e1.implicitCastTo(sc, t1b);
2609 assert(e1x.op != EXP.error);
2610 e = e.copy().isSliceExp();
2611 e.e1 = e1x;
2612 e.type = t;
2613 return e;
2616 auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
2617 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s`",
2618 e.toChars(), ts[0], ts[1]);
2619 return ErrorExp.get();
2622 // Casting to noreturn isn't an actual cast
2623 // Rewrite cast(<qual> noreturn) <exp>
2624 // as <exp>, assert(false)
2625 if (t.isTypeNoreturn())
2627 // Don't generate an unreachable assert(false) if e will abort
2628 if (e.type.isTypeNoreturn())
2630 // Paint e to accomodate for different type qualifiers
2631 e.type = t;
2632 return e;
2635 auto ini = t.defaultInitLiteral(e.loc);
2636 return Expression.combine(e, ini);
2639 switch (e.op)
2641 default : return visit(e);
2642 case EXP.error : return visitError(e.isErrorExp());
2643 case EXP.float64 : return visitReal(e.isRealExp());
2644 case EXP.complex80 : return visitComplex(e.isComplexExp());
2645 case EXP.structLiteral : return visitStructLiteral(e.isStructLiteralExp());
2646 case EXP.string_ : return visitString(e.isStringExp());
2647 case EXP.address : return visitAddr(e.isAddrExp());
2648 case EXP.tuple : return visitTuple(e.isTupleExp());
2649 case EXP.arrayLiteral : return visitArrayLiteral(e.isArrayLiteralExp());
2650 case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
2651 case EXP.symbolOffset : return visitSymOff(e.isSymOffExp());
2652 case EXP.delegate_ : return visitDelegate(e.isDelegateExp());
2653 case EXP.function_ : return visitFunc(e.isFuncExp());
2654 case EXP.question : return visitCond(e.isCondExp());
2655 case EXP.comma : return visitComma(e.isCommaExp());
2656 case EXP.slice : return visitSlice(e.isSliceExp());
2660 /****************************************
2661 * Set type inference target
2662 * t Target type
2663 * flag 1: don't put an error when inference fails
2665 Expression inferType(Expression e, Type t, int flag = 0)
2667 Expression visitAle(ArrayLiteralExp ale)
2669 Type tb = t.toBasetype();
2670 if (tb.ty == Tarray || tb.ty == Tsarray)
2672 Type tn = tb.nextOf();
2673 if (ale.basis)
2674 ale.basis = inferType(ale.basis, tn, flag);
2675 for (size_t i = 0; i < ale.elements.length; i++)
2677 if (Expression e = (*ale.elements)[i])
2679 e = inferType(e, tn, flag);
2680 (*ale.elements)[i] = e;
2684 return ale;
2687 Expression visitAar(AssocArrayLiteralExp aale)
2689 Type tb = t.toBasetype();
2690 if (auto taa = tb.isTypeAArray())
2692 Type ti = taa.index;
2693 Type tv = taa.nextOf();
2694 for (size_t i = 0; i < aale.keys.length; i++)
2696 if (Expression e = (*aale.keys)[i])
2698 e = inferType(e, ti, flag);
2699 (*aale.keys)[i] = e;
2702 for (size_t i = 0; i < aale.values.length; i++)
2704 if (Expression e = (*aale.values)[i])
2706 e = inferType(e, tv, flag);
2707 (*aale.values)[i] = e;
2711 return aale;
2714 Expression visitFun(FuncExp fe)
2716 //printf("FuncExp::inferType('%s'), to=%s\n", fe.type ? fe.type.toChars() : "null", t.toChars());
2717 if (t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction)
2719 fe.fd.treq = t;
2721 return fe;
2724 Expression visitTer(CondExp ce)
2726 Type tb = t.toBasetype();
2727 ce.e1 = inferType(ce.e1, tb, flag);
2728 ce.e2 = inferType(ce.e2, tb, flag);
2729 return ce;
2732 if (t) switch (e.op)
2734 case EXP.arrayLiteral: return visitAle(e.isArrayLiteralExp());
2735 case EXP.assocArrayLiteral: return visitAar(e.isAssocArrayLiteralExp());
2736 case EXP.function_: return visitFun(e.isFuncExp());
2737 case EXP.question: return visitTer(e.isCondExp());
2738 default:
2740 return e;
2743 /****************************************
2744 * Scale addition/subtraction to/from pointer.
2746 Expression scaleFactor(BinExp be, Scope* sc)
2748 Type t1b = be.e1.type.toBasetype();
2749 Type t2b = be.e2.type.toBasetype();
2750 Expression eoff;
2752 if (t1b.ty == Tpointer && t2b.isintegral())
2754 // Need to adjust operator by the stride
2755 // Replace (ptr + int) with (ptr + (int * stride))
2756 Type t = Type.tptrdiff_t;
2758 uinteger_t stride = t1b.nextOf().size(be.loc);
2759 if (!t.equals(t2b))
2760 be.e2 = be.e2.castTo(sc, t);
2761 eoff = be.e2;
2762 be.e2 = new MulExp(be.loc, be.e2, new IntegerExp(Loc.initial, stride, t));
2763 be.e2.type = t;
2764 be.type = be.e1.type;
2766 else if (t2b.ty == Tpointer && t1b.isintegral())
2768 // Need to adjust operator by the stride
2769 // Replace (int + ptr) with (ptr + (int * stride))
2770 Type t = Type.tptrdiff_t;
2771 Expression e;
2773 uinteger_t stride = t2b.nextOf().size(be.loc);
2774 if (!t.equals(t1b))
2775 e = be.e1.castTo(sc, t);
2776 else
2777 e = be.e1;
2778 eoff = e;
2779 e = new MulExp(be.loc, e, new IntegerExp(Loc.initial, stride, t));
2780 e.type = t;
2781 be.type = be.e2.type;
2782 be.e1 = be.e2;
2783 be.e2 = e;
2785 else
2786 assert(0);
2789 eoff = eoff.optimize(WANTvalue);
2790 if (eoff.op == EXP.int64 && eoff.toInteger() == 0)
2793 else if (sc.setUnsafe(false, be.loc, "pointer arithmetic not allowed in @safe functions"))
2795 return ErrorExp.get();
2798 return be;
2801 /**************************************
2802 * Return true if e is an empty array literal with dimensionality
2803 * equal to or less than type of other array.
2804 * [], [[]], [[[]]], etc.
2805 * I.e., make sure that [1,2] is compatible with [],
2806 * [[1,2]] is compatible with [[]], etc.
2808 private bool isVoidArrayLiteral(Expression e, Type other)
2810 while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && (e.isArrayLiteralExp().elements.length == 1))
2812 auto ale = e.isArrayLiteralExp();
2813 e = ale[0];
2814 if (other.ty == Tsarray || other.ty == Tarray)
2815 other = other.nextOf();
2816 else
2817 return false;
2819 if (other.ty != Tsarray && other.ty != Tarray)
2820 return false;
2821 Type t = e.type;
2822 return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && e.isArrayLiteralExp().elements.length == 0);
2826 * Merge types of `e1` and `e2` into a common subset
2828 * Parameters `e1` and `e2` will be rewritten in place as needed.
2830 * Params:
2831 * sc = Current scope
2832 * op = Operator such as `e1 op e2`. In practice, either EXP.question
2833 * or one of the binary operator.
2834 * pe1 = The LHS of the operation, will be rewritten
2835 * pe2 = The RHS of the operation, will be rewritten
2837 * Returns:
2838 * The resulting type in case of success, `null` in case of error
2840 Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2)
2842 //printf("typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
2844 Expression e1 = pe1;
2845 Expression e2 = pe2;
2847 // ImportC: do array/function conversions
2848 if (sc)
2850 e1 = e1.arrayFuncConv(sc);
2851 e2 = e2.arrayFuncConv(sc);
2854 Type Lret(Type result)
2856 pe1 = e1;
2857 pe2 = e2;
2859 version (none)
2861 printf("-typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
2862 if (e1.type)
2863 printf("\tt1 = %s\n", e1.type.toChars());
2864 if (e2.type)
2865 printf("\tt2 = %s\n", e2.type.toChars());
2866 printf("\ttype = %s\n", result.toChars());
2868 return result;
2871 /// Converts one of the expression to the other
2872 Type convert(ref Expression from, Type to)
2874 from = from.castTo(sc, to);
2875 return Lret(to);
2878 /// Converts both expression to a third type
2879 Type coerce(Type towards)
2881 e1 = e1.castTo(sc, towards);
2882 e2 = e2.castTo(sc, towards);
2883 return Lret(towards);
2886 Type t1b = e1.type.toBasetype();
2887 Type t2b = e2.type.toBasetype();
2889 if (sc && sc.flags & SCOPE.Cfile)
2891 // Integral types can be implicitly converted to pointers
2892 if ((t1b.ty == Tpointer) != (t2b.ty == Tpointer))
2894 if (t1b.isintegral())
2896 return convert(e1, t2b);
2898 else if (t2b.isintegral())
2900 return convert(e2, t1b);
2905 if (op != EXP.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
2907 if (op == EXP.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
2909 e1 = e1.castTo(sc, Type.tdchar);
2910 e2 = e2.castTo(sc, Type.tdchar);
2912 else
2914 e1 = integralPromotions(e1, sc);
2915 e2 = integralPromotions(e2, sc);
2919 MATCH m;
2920 Type t1 = e1.type;
2921 Type t2 = e2.type;
2922 assert(t1);
2923 Type t = t1;
2925 /* The start type of alias this type recursion.
2926 * In following case, we should save A, and stop recursion
2927 * if it appears again.
2928 * X -> Y -> [A] -> B -> A -> B -> ...
2930 Type att1 = null;
2931 Type att2 = null;
2933 if (t1.mod != t2.mod &&
2934 t1.ty == Tenum && t2.ty == Tenum &&
2935 t1.isTypeEnum().sym == t2.isTypeEnum().sym)
2937 ubyte mod = MODmerge(t1.mod, t2.mod);
2938 t1 = t1.castMod(mod);
2939 t2 = t2.castMod(mod);
2940 return Lret(t1);
2943 Lagain:
2944 t1b = t1.toBasetype();
2945 t2b = t2.toBasetype();
2947 const ty = implicitConvCommonTy(t1b.ty, t2b.ty);
2948 if (ty != Terror)
2950 const ty1 = implicitConvTy1(t1b.ty, t2b.ty);
2951 const ty2 = implicitConvTy1(t2b.ty, t1b.ty);
2953 if (t1b.ty == ty1) // if no promotions
2955 if (t1.equals(t2))
2956 return Lret(t1);
2958 if (t1b.equals(t2b))
2959 return Lret(t1b);
2962 t1 = Type.basic[ty1];
2963 t2 = Type.basic[ty2];
2965 if (!(t1 && t2))
2966 return null;
2967 e1 = e1.castTo(sc, t1);
2968 e2 = e2.castTo(sc, t2);
2969 return Lret(Type.basic[ty]);
2972 t1 = t1b;
2973 t2 = t2b;
2975 if (t1.ty == Ttuple || t2.ty == Ttuple)
2976 return null;
2978 if (t1.equals(t2))
2980 // merging can not result in new enum type
2981 if (t.ty == Tenum)
2982 return Lret(t1b);
2983 return Lret(t);
2986 if ((t1.ty == Tpointer && t2.ty == Tpointer) || (t1.ty == Tdelegate && t2.ty == Tdelegate))
2988 // Bring pointers to compatible type
2989 Type t1n = t1.nextOf();
2990 Type t2n = t2.nextOf();
2992 if (t1n.equals(t2n))
2993 return Lret(t);
2995 if (t1n.ty == Tvoid) // pointers to void are always compatible
2996 return Lret(t1);
2998 if (t2n.ty == Tvoid)
2999 return Lret(t2);
3001 if (t1.implicitConvTo(t2))
3002 return convert(e1, t2);
3004 if (t2.implicitConvTo(t1))
3005 return convert(e2, t1);
3007 if (t1n.ty == Tfunction && t2n.ty == Tfunction)
3009 TypeFunction tf1 = t1n.isTypeFunction();
3010 TypeFunction tf2 = t2n.isTypeFunction();
3011 tf1.purityLevel();
3012 tf2.purityLevel();
3014 TypeFunction d = tf1.syntaxCopy();
3016 if (tf1.purity != tf2.purity)
3017 d.purity = PURE.impure;
3018 assert(d.purity != PURE.fwdref);
3020 d.isnothrow = (tf1.isnothrow && tf2.isnothrow);
3021 d.isnogc = (tf1.isnogc && tf2.isnogc);
3023 if (tf1.trust == tf2.trust)
3024 d.trust = tf1.trust;
3025 else if (tf1.trust <= TRUST.system || tf2.trust <= TRUST.system)
3026 d.trust = TRUST.system;
3027 else
3028 d.trust = TRUST.trusted;
3030 Type tx = (t1.ty == Tdelegate) ? new TypeDelegate(d) : d.pointerTo();
3031 tx = tx.typeSemantic(e1.loc, sc);
3033 if (t1.implicitConvTo(tx) && t2.implicitConvTo(tx))
3034 return coerce(tx);
3035 return null;
3038 if (t1n.mod != t2n.mod)
3040 if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
3041 return null;
3042 ubyte mod = MODmerge(t1n.mod, t2n.mod);
3043 t1 = t1n.castMod(mod).pointerTo();
3044 t2 = t2n.castMod(mod).pointerTo();
3045 t = t1;
3046 goto Lagain;
3049 if (t1n.ty == Tclass && t2n.ty == Tclass)
3051 ClassDeclaration cd1 = t1n.isClassHandle();
3052 ClassDeclaration cd2 = t2n.isClassHandle();
3053 int offset;
3054 if (cd1.isBaseOf(cd2, &offset))
3056 if (offset)
3057 e2 = e2.castTo(sc, t);
3058 return Lret(t);
3061 if (cd2.isBaseOf(cd1, &offset))
3063 if (offset)
3064 e1 = e1.castTo(sc, t2);
3065 return Lret(t2);
3068 return null;
3071 t1 = t1n.constOf().pointerTo();
3072 t2 = t2n.constOf().pointerTo();
3073 if (t1.implicitConvTo(t2))
3074 return convert(e1, t2);
3075 if (t2.implicitConvTo(t1))
3076 return convert(e2, t1);
3077 return null;
3080 if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
3082 /* (T[n] op void*) => T[]
3083 * (T[] op void*) => T[]
3084 * (T[n] op void[0]) => T[]
3085 * (T[] op void[0]) => T[]
3086 * (T[n] op void[]) => T[]
3087 * (T[] op void[]) => T[]
3089 return coerce(t1.nextOf().arrayOf());
3092 if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
3094 /* (void* op T[n]) => T[]
3095 * (void* op T[]) => T[]
3096 * (void[0] op T[n]) => T[]
3097 * (void[0] op T[]) => T[]
3098 * (void[] op T[n]) => T[]
3099 * (void[] op T[]) => T[]
3101 return coerce(t2.nextOf().arrayOf());
3104 if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
3106 // https://issues.dlang.org/show_bug.cgi?id=7285
3107 // Tsarray op [x, y, ...] should to be Tsarray
3108 // https://issues.dlang.org/show_bug.cgi?id=14737
3109 // Tsarray ~ [x, y, ...] should to be Tarray
3110 if (t1.ty == Tsarray && e2.op == EXP.arrayLiteral && op != EXP.concatenate)
3111 return convert(e2, t1);
3112 if (m == MATCH.constant && (op == EXP.addAssign || op == EXP.minAssign || op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign || op == EXP.powAssign || op == EXP.andAssign || op == EXP.orAssign || op == EXP.xorAssign))
3114 // Don't make the lvalue const
3115 return Lret(t2);
3117 return convert(e1, t2);
3120 if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
3122 // https://issues.dlang.org/show_bug.cgi?id=7285
3123 // https://issues.dlang.org/show_bug.cgi?id=14737
3124 if (t2.ty == Tsarray && e1.op == EXP.arrayLiteral && op != EXP.concatenate)
3125 return convert(e1, t2);
3126 return convert(e2, t1);
3129 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)
3131 /* If one is mutable and the other immutable, then retry
3132 * with both of them as const
3134 Type t1n = t1.nextOf();
3135 Type t2n = t2.nextOf();
3136 ubyte mod;
3137 if (e1.op == EXP.null_ && e2.op != EXP.null_)
3138 mod = t2n.mod;
3139 else if (e1.op != EXP.null_ && e2.op == EXP.null_)
3140 mod = t1n.mod;
3141 else if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
3142 return null;
3143 else
3144 mod = MODmerge(t1n.mod, t2n.mod);
3146 if (t1.ty == Tpointer)
3147 t1 = t1n.castMod(mod).pointerTo();
3148 else
3149 t1 = t1n.castMod(mod).arrayOf();
3151 if (t2.ty == Tpointer)
3152 t2 = t2n.castMod(mod).pointerTo();
3153 else
3154 t2 = t2n.castMod(mod).arrayOf();
3155 t = t1;
3156 goto Lagain;
3159 if (t1.ty == Tclass && t2.ty == Tclass)
3161 if (t1.mod != t2.mod)
3163 ubyte mod;
3164 if (e1.op == EXP.null_ && e2.op != EXP.null_)
3165 mod = t2.mod;
3166 else if (e1.op != EXP.null_ && e2.op == EXP.null_)
3167 mod = t1.mod;
3168 else if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3169 return null;
3170 else
3171 mod = MODmerge(t1.mod, t2.mod);
3172 t1 = t1.castMod(mod);
3173 t2 = t2.castMod(mod);
3174 t = t1;
3175 goto Lagain;
3177 goto Lcc;
3180 if (t1.ty == Tclass || t2.ty == Tclass)
3182 Lcc:
3183 while (1)
3185 MATCH i1woat = MATCH.exact;
3186 MATCH i2woat = MATCH.exact;
3188 if (auto t2c = t2.isTypeClass())
3189 i1woat = t2c.implicitConvToWithoutAliasThis(t1);
3190 if (auto t1c = t1.isTypeClass())
3191 i2woat = t1c.implicitConvToWithoutAliasThis(t2);
3193 MATCH i1 = e2.implicitConvTo(t1);
3194 MATCH i2 = e1.implicitConvTo(t2);
3196 if (i1 && i2)
3198 // We have the case of class vs. void*, so pick class
3199 if (t1.ty == Tpointer)
3200 i1 = MATCH.nomatch;
3201 else if (t2.ty == Tpointer)
3202 i2 = MATCH.nomatch;
3205 // Match but without 'alias this' on classes
3206 if (i2 && i2woat)
3207 return coerce(t2);
3208 if (i1 && i1woat)
3209 return coerce(t1);
3211 // Here use implicitCastTo() instead of castTo() to try 'alias this' on classes
3212 Type coerceImplicit(Type towards)
3214 e1 = e1.implicitCastTo(sc, towards);
3215 e2 = e2.implicitCastTo(sc, towards);
3216 return Lret(towards);
3219 // Implicit conversion with 'alias this'
3220 if (i2)
3221 return coerceImplicit(t2);
3222 if (i1)
3223 return coerceImplicit(t1);
3225 if (t1.ty == Tclass && t2.ty == Tclass)
3227 TypeClass tc1 = t1.isTypeClass();
3228 TypeClass tc2 = t2.isTypeClass();
3230 /* Pick 'tightest' type
3232 ClassDeclaration cd1 = tc1.sym.baseClass;
3233 ClassDeclaration cd2 = tc2.sym.baseClass;
3234 if (cd1 && cd2)
3236 t1 = cd1.type.castMod(t1.mod);
3237 t2 = cd2.type.castMod(t2.mod);
3239 else if (cd1)
3240 t1 = cd1.type;
3241 else if (cd2)
3242 t2 = cd2.type;
3243 else
3244 return null;
3246 else if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
3248 if (isRecursiveAliasThis(att1, e1.type))
3249 return null;
3250 //printf("att tmerge(c || c) e1 = %s\n", e1.type.toChars());
3251 e1 = resolveAliasThis(sc, e1);
3252 t1 = e1.type;
3253 continue;
3255 else if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
3257 if (isRecursiveAliasThis(att2, e2.type))
3258 return null;
3259 //printf("att tmerge(c || c) e2 = %s\n", e2.type.toChars());
3260 e2 = resolveAliasThis(sc, e2);
3261 t2 = e2.type;
3262 continue;
3264 else
3265 return null;
3269 if (t1.ty == Tstruct && t2.ty == Tstruct)
3271 if (t1.mod != t2.mod)
3273 if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3274 return null;
3275 ubyte mod = MODmerge(t1.mod, t2.mod);
3276 t1 = t1.castMod(mod);
3277 t2 = t2.castMod(mod);
3278 t = t1;
3279 goto Lagain;
3282 TypeStruct ts1 = t1.isTypeStruct();
3283 TypeStruct ts2 = t2.isTypeStruct();
3284 if (ts1.sym != ts2.sym)
3286 if (!ts1.sym.aliasthis && !ts2.sym.aliasthis)
3287 return null;
3289 MATCH i1 = MATCH.nomatch;
3290 MATCH i2 = MATCH.nomatch;
3292 Expression e1b = null;
3293 Expression e2b = null;
3294 if (ts2.sym.aliasthis)
3296 if (isRecursiveAliasThis(att2, e2.type))
3297 return null;
3298 //printf("att tmerge(s && s) e2 = %s\n", e2.type.toChars());
3299 e2b = resolveAliasThis(sc, e2);
3300 i1 = e2b.implicitConvTo(t1);
3302 if (ts1.sym.aliasthis)
3304 if (isRecursiveAliasThis(att1, e1.type))
3305 return null;
3306 //printf("att tmerge(s && s) e1 = %s\n", e1.type.toChars());
3307 e1b = resolveAliasThis(sc, e1);
3308 i2 = e1b.implicitConvTo(t2);
3310 if (i1 && i2)
3311 return null;
3313 if (i1)
3314 return convert(e2, t1);
3315 if (i2)
3316 return convert(e1, t2);
3318 if (e1b)
3320 e1 = e1b;
3321 t1 = e1b.type.toBasetype();
3323 if (e2b)
3325 e2 = e2b;
3326 t2 = e2b.type.toBasetype();
3328 t = t1;
3329 goto Lagain;
3333 if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
3335 if (isRecursiveAliasThis(att1, e1.type))
3336 return null;
3337 //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
3338 e1 = resolveAliasThis(sc, e1);
3339 t1 = e1.type;
3340 t = t1;
3341 goto Lagain;
3344 if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
3346 if (isRecursiveAliasThis(att2, e2.type))
3347 return null;
3348 //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
3349 e2 = resolveAliasThis(sc, e2);
3350 t2 = e2.type;
3351 t = t2;
3352 goto Lagain;
3355 if ((e1.op == EXP.string_ || e1.op == EXP.null_) && e1.implicitConvTo(t2))
3356 return convert(e1, t2);
3357 if ((e2.op == EXP.string_ || e2.op == EXP.null_) && e2.implicitConvTo(t1))
3358 return convert(e2, t1);
3359 if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf()))
3360 return coerce(t1.nextOf().arrayOf());
3361 if (t1.ty == Tsarray && t2.ty == Tsarray && e1.implicitConvTo(t2.nextOf().arrayOf()))
3362 return coerce(t2.nextOf().arrayOf());
3364 if (t1.ty == Tvector && t2.ty == Tvector)
3366 // https://issues.dlang.org/show_bug.cgi?id=13841
3367 // all vector types should have no common types between
3368 // different vectors, even though their sizes are same.
3369 auto tv1 = t1.isTypeVector();
3370 auto tv2 = t2.isTypeVector();
3371 if (!tv1.basetype.equals(tv2.basetype))
3372 return null;
3374 goto LmodCompare;
3377 if (t1.ty == Tvector && t2.ty != Tvector && e2.implicitConvTo(t1))
3379 e2 = e2.castTo(sc, t1);
3380 t2 = t1;
3381 t = t1;
3382 goto Lagain;
3385 if (t2.ty == Tvector && t1.ty != Tvector && e1.implicitConvTo(t2))
3387 e1 = e1.castTo(sc, t2);
3388 t1 = t2;
3389 t = t1;
3390 goto Lagain;
3393 if (t1.isintegral() && t2.isintegral())
3395 if (t1.ty != t2.ty)
3397 if (t1.ty == Tvector || t2.ty == Tvector)
3398 return null;
3399 e1 = integralPromotions(e1, sc);
3400 e2 = integralPromotions(e2, sc);
3401 t1 = e1.type;
3402 t2 = e2.type;
3403 goto Lagain;
3405 assert(t1.ty == t2.ty);
3406 LmodCompare:
3407 if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3408 return null;
3409 ubyte mod = MODmerge(t1.mod, t2.mod);
3411 t1 = t1.castMod(mod);
3412 t2 = t2.castMod(mod);
3413 t = t1;
3414 e1 = e1.castTo(sc, t);
3415 e2 = e2.castTo(sc, t);
3416 goto Lagain;
3419 if (t1.ty == Tnull && t2.ty == Tnull)
3421 ubyte mod = MODmerge(t1.mod, t2.mod);
3422 return coerce(t1.castMod(mod));
3425 if (t2.ty == Tnull && (t1.ty == Tpointer || t1.ty == Taarray || t1.ty == Tarray))
3426 return convert(e2, t1);
3427 if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray))
3428 return convert(e1, t2);
3430 /// Covers array operations for user-defined types
3431 Type checkArrayOpType(Expression e1, Expression e2, EXP op, Scope *sc)
3433 // scalar op scalar - we shouldn't be here
3434 if (e1.type.ty != Tarray && e1.type.ty != Tsarray && e2.type.ty != Tarray && e2.type.ty != Tsarray)
3435 return null;
3437 // only supporting slices and array literals
3438 if (!e1.isSliceExp() && !e1.isArrayLiteralExp() && !e2.isSliceExp() && !e2.isArrayLiteralExp())
3439 return null;
3441 // start with e1 op e2 and if either one of e1 or e2 is a slice or array literal,
3442 // replace it with the first element of the array
3443 Expression lhs = e1;
3444 Expression rhs = e2;
3446 // T[x .. y] op ?
3447 if (auto se1 = e1.isSliceExp())
3448 lhs = new IndexExp(Loc.initial, se1.e1, IntegerExp.literal!0);
3450 // [t1, t2, .. t3] op ?
3451 if (auto ale1 = e1.isArrayLiteralExp())
3452 lhs = ale1.opIndex(0);
3454 // ? op U[z .. t]
3455 if (auto se2 = e2.isSliceExp())
3456 rhs = new IndexExp(Loc.initial, se2.e1, IntegerExp.literal!0);
3458 // ? op [u1, u2, .. u3]
3459 if (auto ale2 = e2.isArrayLiteralExp())
3460 rhs = ale2.opIndex(0);
3462 // create a new binary expression with the new lhs and rhs (at this stage, at least
3463 // one of lhs/rhs has been replaced with the 0'th element of the array it was before)
3464 Expression exp;
3465 switch (op)
3467 case EXP.add:
3468 exp = new AddExp(Loc.initial, lhs, rhs); break;
3469 case EXP.min:
3470 exp = new MinExp(Loc.initial, lhs, rhs); break;
3471 case EXP.mul:
3472 exp = new MulExp(Loc.initial, lhs, rhs); break;
3473 case EXP.div:
3474 exp = new DivExp(Loc.initial, lhs, rhs); break;
3475 case EXP.pow:
3476 exp = new PowExp(Loc.initial, lhs, rhs); break;
3477 default:
3478 exp = null;
3481 if (exp)
3483 // if T op U is valid and has type V
3484 // then T[] op U and T op U[] should be valid and have type V[]
3485 Expression e = exp.trySemantic(sc);
3486 if (e && e.type)
3487 return e.type.arrayOf;
3490 return null;
3493 if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
3495 if (e2.implicitConvTo(t1.nextOf()))
3497 // T[] op T
3498 // T[] op cast(T)U
3499 e2 = e2.castTo(sc, t1.nextOf());
3500 return Lret(t1.nextOf().arrayOf());
3502 if (t1.nextOf().implicitConvTo(e2.type))
3504 // (cast(T)U)[] op T (https://issues.dlang.org/show_bug.cgi?id=12780)
3505 // e1 is left as U[], it will be handled in arrayOp() later.
3506 return Lret(e2.type.arrayOf());
3508 if (t2.ty == Tarray && isArrayOpOperand(e2))
3510 if (t1.nextOf().implicitConvTo(t2.nextOf()))
3512 // (cast(T)U)[] op T[] (https://issues.dlang.org/show_bug.cgi?id=12780)
3513 t = t2.nextOf().arrayOf();
3514 // if cast won't be handled in arrayOp() later
3515 if (!isArrayOpImplicitCast(t1.isTypeDArray(), t2.isTypeDArray()))
3516 e1 = e1.castTo(sc, t);
3517 return Lret(t);
3519 if (t2.nextOf().implicitConvTo(t1.nextOf()))
3521 // T[] op (cast(T)U)[] (https://issues.dlang.org/show_bug.cgi?id=12780)
3522 // e2 is left as U[], it will be handled in arrayOp() later.
3523 t = t1.nextOf().arrayOf();
3524 // if cast won't be handled in arrayOp() later
3525 if (!isArrayOpImplicitCast(t2.isTypeDArray(), t1.isTypeDArray()))
3526 e2 = e2.castTo(sc, t);
3527 return Lret(t);
3531 t = checkArrayOpType(e1, e2, op, sc);
3532 if (t !is null)
3533 return Lret(t);
3535 return null;
3537 else if (t2.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2))
3539 if (e1.implicitConvTo(t2.nextOf()))
3541 // T op T[]
3542 // cast(T)U op T[]
3543 e1 = e1.castTo(sc, t2.nextOf());
3544 t = t2.nextOf().arrayOf();
3546 else if (t2.nextOf().implicitConvTo(e1.type))
3548 // T op (cast(T)U)[] (https://issues.dlang.org/show_bug.cgi?id=12780)
3549 // e2 is left as U[], it will be handled in arrayOp() later.
3550 t = e1.type.arrayOf();
3552 else
3554 t = checkArrayOpType(e1, e2, op, sc);
3555 if (t is null)
3556 return null;
3559 //printf("test %s\n", EXPtoString(op).ptr);
3560 e1 = e1.optimize(WANTvalue);
3561 if (isCommutative(op) && e1.isConst())
3563 /* Swap operands to minimize number of functions generated
3565 //printf("swap %s\n", EXPtoString(op).ptr);
3566 Expression tmp = e1;
3567 e1 = e2;
3568 e2 = tmp;
3570 return Lret(t);
3573 return null;
3576 /************************************
3577 * Bring leaves to common type.
3578 * Returns:
3579 * null on success, ErrorExp if error occurs
3581 Expression typeCombine(BinExp be, Scope* sc)
3583 Expression errorReturn()
3585 Expression ex = be.incompatibleTypes();
3586 if (ex.op == EXP.error)
3587 return ex;
3588 return ErrorExp.get();
3591 Type t1 = be.e1.type.toBasetype();
3592 Type t2 = be.e2.type.toBasetype();
3594 if (be.op == EXP.min || be.op == EXP.add)
3596 // struct+struct, and class+class are errors
3597 if (t1.ty == Tstruct && t2.ty == Tstruct)
3598 return errorReturn();
3599 else if (t1.ty == Tclass && t2.ty == Tclass)
3600 return errorReturn();
3601 else if (t1.ty == Taarray && t2.ty == Taarray)
3602 return errorReturn();
3605 if (auto result = typeMerge(sc, be.op, be.e1, be.e2))
3607 if (be.type is null)
3608 be.type = result;
3610 else
3611 return errorReturn();
3613 // If the types have no value, return an error
3614 if (be.e1.op == EXP.error)
3615 return be.e1;
3616 if (be.e2.op == EXP.error)
3617 return be.e2;
3618 return null;
3621 /***********************************
3622 * Do integral promotions (convertchk).
3623 * Don't convert <array of> to <pointer to>
3625 Expression integralPromotions(Expression e, Scope* sc)
3627 //printf("integralPromotions %s %s\n", e.toChars(), e.type.toChars());
3628 switch (e.type.toBasetype().ty)
3630 case Tvoid:
3631 error(e.loc, "void has no value");
3632 return ErrorExp.get();
3634 case Tint8:
3635 case Tuns8:
3636 case Tint16:
3637 case Tuns16:
3638 case Tbool:
3639 case Tchar:
3640 case Twchar:
3641 e = e.castTo(sc, Type.tint32);
3642 break;
3644 case Tdchar:
3645 e = e.castTo(sc, Type.tuns32);
3646 break;
3648 default:
3649 break;
3651 return e;
3654 /******************************************************
3655 * This provides a transition from the non-promoting behavior
3656 * of unary + - ~ to the C-like integral promotion behavior.
3657 * Params:
3658 * sc = context
3659 * ue = NegExp, UAddExp, or ComExp which is revised per rules
3660 * References:
3661 * https://issues.dlang.org/show_bug.cgi?id=16997
3664 void fix16997(Scope* sc, UnaExp ue)
3666 if (global.params.fix16997 || sc.flags & SCOPE.Cfile)
3667 ue.e1 = integralPromotions(ue.e1, sc); // desired C-like behavor
3668 else
3670 switch (ue.e1.type.toBasetype.ty)
3672 case Tint8:
3673 case Tuns8:
3674 case Tint16:
3675 case Tuns16:
3676 //case Tbool: // these operations aren't allowed on bool anyway
3677 case Tchar:
3678 case Twchar:
3679 case Tdchar:
3680 deprecation(ue.loc, "integral promotion not done for `%s`, remove '-revert=intpromote' switch or `%scast(int)(%s)`",
3681 ue.toChars(), EXPtoString(ue.op).ptr, ue.e1.toChars());
3682 break;
3684 default:
3685 break;
3690 /***********************************
3691 * See if both types are arrays that can be compared
3692 * for equality without any casting. Return true if so.
3693 * This is to enable comparing things like an immutable
3694 * array with a mutable one.
3696 extern (D) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
3698 t1 = t1.toBasetype();
3699 t2 = t2.toBasetype();
3701 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && t2.ty == t1.ty)
3703 if (t1.nextOf().implicitConvTo(t2.nextOf()) >= MATCH.constant || t2.nextOf().implicitConvTo(t1.nextOf()) >= MATCH.constant)
3704 return true;
3706 return false;
3709 /******************************************************************/
3710 /* Determine the integral ranges of an expression.
3711 * This is used to determine if implicit narrowing conversions will
3712 * be allowed.
3714 @trusted
3715 IntRange getIntRange(Expression e)
3717 IntRange visit(Expression e)
3719 return IntRange.fromType(e.type);
3722 IntRange visitInteger(IntegerExp e)
3724 return IntRange(SignExtendedNumber(e.getInteger()))._cast(e.type);
3727 IntRange visitCast(CastExp e)
3729 return getIntRange(e.e1)._cast(e.type);
3732 IntRange visitAdd(AddExp e)
3734 IntRange ir1 = getIntRange(e.e1);
3735 IntRange ir2 = getIntRange(e.e2);
3736 return (ir1 + ir2)._cast(e.type);
3739 IntRange visitMin(MinExp e)
3741 IntRange ir1 = getIntRange(e.e1);
3742 IntRange ir2 = getIntRange(e.e2);
3743 return (ir1 - ir2)._cast(e.type);
3746 IntRange visitDiv(DivExp e)
3748 IntRange ir1 = getIntRange(e.e1);
3749 IntRange ir2 = getIntRange(e.e2);
3751 return (ir1 / ir2)._cast(e.type);
3754 IntRange visitMul(MulExp e)
3756 IntRange ir1 = getIntRange(e.e1);
3757 IntRange ir2 = getIntRange(e.e2);
3759 return (ir1 * ir2)._cast(e.type);
3762 IntRange visitMod(ModExp e)
3764 IntRange ir1 = getIntRange(e.e1);
3765 IntRange ir2 = getIntRange(e.e2);
3767 // Modding on 0 is invalid anyway.
3768 if (!ir2.absNeg().imin.negative)
3770 return visit(e);
3772 return (ir1 % ir2)._cast(e.type);
3775 IntRange visitAnd(AndExp e)
3777 IntRange result;
3778 bool hasResult = false;
3779 result.unionOrAssign(getIntRange(e.e1) & getIntRange(e.e2), hasResult);
3781 assert(hasResult);
3782 return result._cast(e.type);
3785 IntRange visitOr(OrExp e)
3787 IntRange result;
3788 bool hasResult = false;
3789 result.unionOrAssign(getIntRange(e.e1) | getIntRange(e.e2), hasResult);
3791 assert(hasResult);
3792 return result._cast(e.type);
3795 IntRange visitXor(XorExp e)
3797 IntRange result;
3798 bool hasResult = false;
3799 result.unionOrAssign(getIntRange(e.e1) ^ getIntRange(e.e2), hasResult);
3801 assert(hasResult);
3802 return result._cast(e.type);
3805 IntRange visitShl(ShlExp e)
3807 IntRange ir1 = getIntRange(e.e1);
3808 IntRange ir2 = getIntRange(e.e2);
3810 return (ir1 << ir2)._cast(e.type);
3813 IntRange visitShr(ShrExp e)
3815 IntRange ir1 = getIntRange(e.e1);
3816 IntRange ir2 = getIntRange(e.e2);
3818 return (ir1 >> ir2)._cast(e.type);
3821 IntRange visitUshr(UshrExp e)
3823 IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type);
3824 IntRange ir2 = getIntRange(e.e2);
3826 return (ir1 >>> ir2)._cast(e.type);
3829 IntRange visitAssign(AssignExp e)
3831 return getIntRange(e.e2)._cast(e.type);
3834 IntRange visitCond(CondExp e)
3836 // No need to check e.econd; assume caller has called optimize()
3837 IntRange ir1 = getIntRange(e.e1);
3838 IntRange ir2 = getIntRange(e.e2);
3839 return ir1.unionWith(ir2)._cast(e.type);
3842 IntRange visitVar(VarExp e)
3844 Expression ie;
3845 VarDeclaration vd = e.var.isVarDeclaration();
3846 if (vd && vd.range)
3847 return vd.range._cast(e.type);
3848 else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
3849 return getIntRange(ie);
3850 else
3851 return visit(e);
3854 IntRange visitComma(CommaExp e)
3856 return getIntRange(e.e2);
3859 IntRange visitCom(ComExp e)
3861 IntRange ir = getIntRange(e.e1);
3862 return IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative), SignExtendedNumber(~ir.imin.value, !ir.imin.negative))._cast(e.type);
3865 IntRange visitNeg(NegExp e)
3867 IntRange ir = getIntRange(e.e1);
3868 return (-ir)._cast(e.type);
3871 switch (e.op)
3873 default : return visit(e);
3874 case EXP.int64 : return visitInteger(e.isIntegerExp());
3875 case EXP.cast_ : return visitCast(e.isCastExp());
3876 case EXP.add : return visitAdd(e.isAddExp());
3877 case EXP.min : return visitMin(e.isMinExp());
3878 case EXP.div : return visitDiv(e.isDivExp());
3879 case EXP.mul : return visitMul(e.isMulExp());
3880 case EXP.mod : return visitMod(e.isModExp());
3881 case EXP.and : return visitAnd(e.isAndExp());
3882 case EXP.or : return visitOr(e.isOrExp());
3883 case EXP.xor : return visitXor(e.isXorExp());
3884 case EXP.leftShift : return visitShl(e.isShlExp());
3885 case EXP.rightShift : return visitShr(e.isShrExp());
3886 case EXP.unsignedRightShift : return visitUshr(e.isUshrExp());
3887 case EXP.blit : return visitAssign(e.isBlitExp());
3888 case EXP.construct : return visitAssign(e.isConstructExp());
3889 case EXP.assign : return visitAssign(e.isAssignExp());
3890 case EXP.question : return visitCond(e.isCondExp());
3891 case EXP.variable : return visitVar(e.isVarExp());
3892 case EXP.comma : return visitComma(e.isCommaExp());
3893 case EXP.tilde : return visitCom(e.isComExp());
3894 case EXP.negate : return visitNeg(e.isNegExp());
3898 * A helper function to "cast" from expressions of type noreturn to
3899 * any other type - noreturn is implicitly convertible to any other type.
3900 * However, the dmd backend does not like a naive cast from a noreturn expression
3901 * (particularly an `assert(0)`) so this function generates:
3903 * `(assert(0), value)` instead of `cast(to)(assert(0))`.
3905 * `value` is currently `to.init` however it cannot be read so could be made simpler.
3906 * Params:
3907 * toBeCasted = Expression of type noreturn to cast
3908 * to = Type to cast the expression to.
3909 * Returns: A CommaExp, upon any failure ErrorExp will be returned.
3911 Expression specialNoreturnCast(Expression toBeCasted, Type to)
3913 return Expression.combine(toBeCasted, to.defaultInitLiteral(toBeCasted.loc));