d: Merge upstream dmd, druntime f1a045928e
[official-gcc.git] / gcc / d / dmd / dcast.d
blobcfa374c970bd8d05bbf0ac0cd82415fdcb4de8be
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.dsymbolsem;
28 import dmd.errors;
29 import dmd.escape;
30 import dmd.expression;
31 import dmd.expressionsem;
32 import dmd.func;
33 import dmd.globals;
34 import dmd.hdrgen;
35 import dmd.location;
36 import dmd.impcnvtab;
37 import dmd.importc;
38 import dmd.init;
39 import dmd.intrange;
40 import dmd.mtype;
41 import dmd.opover;
42 import dmd.optimize;
43 import dmd.root.ctfloat;
44 import dmd.common.outbuffer;
45 import dmd.root.rmem;
46 import dmd.root.utf;
47 import dmd.tokens;
48 import dmd.typesem;
50 enum LOG = false;
52 /**
53 * Attempt to implicitly cast the expression into type `t`.
55 * This routine will change `e`. To check the matching level,
56 * use `implicitConvTo`.
58 * Params:
59 * e = Expression that is to be casted
60 * sc = Current scope
61 * t = Expected resulting type
63 * Returns:
64 * The resulting casted expression (mutating `e`), or `ErrorExp`
65 * if such an implicit conversion is not possible.
67 Expression implicitCastTo(Expression e, Scope* sc, Type t)
69 Expression visit(Expression e)
71 // 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 || typeb.ty == Tpointer))
806 { // Tpointer because ImportC eagerly converts Tsarray to Tpointer
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;
1491 if (tb.isTypeVector() || typeb.isTypeVector())
1492 return implicitConvTo(e, t); // permissive checking doesn't apply to vectors
1494 if ((typeb.isintegral() || typeb.isfloating()) &&
1495 (tb.isintegral() || tb.isfloating()))
1496 return MATCH.convert;
1497 if (tb.ty == Tpointer && typeb.isintegral()) // C11 6.3.2.3-5
1498 return MATCH.convert;
1499 if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
1500 return MATCH.convert;
1501 if (tb.ty == Tpointer && typeb.ty == Tpointer) // C11 6.3.2.3-7
1502 return MATCH.convert;
1504 return implicitConvTo(e, t);
1507 /*****************************************
1509 Type toStaticArrayType(SliceExp e)
1511 if (e.lwr && e.upr)
1513 // For the following code to work, e should be optimized beforehand.
1514 // (eg. $ in lwr and upr should be already resolved, if possible)
1515 Expression lwr = e.lwr.optimize(WANTvalue);
1516 Expression upr = e.upr.optimize(WANTvalue);
1517 if (lwr.isConst() && upr.isConst())
1519 size_t len = cast(size_t)(upr.toUInteger() - lwr.toUInteger());
1520 return e.type.toBasetype().nextOf().sarrayOf(len);
1523 else
1525 Type t1b = e.e1.type.toBasetype();
1526 if (t1b.ty == Tsarray)
1527 return t1b;
1529 return null;
1532 /**************************************
1533 * Do an explicit cast.
1534 * Assume that the expression `e` does not have any indirections.
1535 * (Parameter 'att' is used to stop 'alias this' recursion)
1537 Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
1539 //printf("castTo(e: %s from: %s to: %s\n", e.toChars(), e.type.toChars(), t.toChars());
1541 Expression visit(Expression e)
1543 //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
1544 version (none)
1546 printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1548 if (e.type.equals(t))
1550 return e;
1552 if (e.type.isTypeNoreturn() && e.op != EXP.type)
1554 return specialNoreturnCast(e, t);
1556 if (auto ve = e.isVarExp())
1558 VarDeclaration v = ve.var.isVarDeclaration();
1559 if (v && v.storage_class & STC.manifest)
1561 auto result = e.ctfeInterpret();
1562 /* https://issues.dlang.org/show_bug.cgi?id=18236
1564 * The expression returned by ctfeInterpret points
1565 * to the line where the manifest constant was declared
1566 * so we need to update the location before trying to cast
1568 result.loc = e.loc;
1569 return result.castTo(sc, t);
1573 Type tob = t.toBasetype();
1574 Type t1b = e.type.toBasetype();
1575 if (tob.equals(t1b))
1577 auto result = e.copy(); // because of COW for assignment to e.type
1578 result.type = t;
1579 return result;
1582 /* Make semantic error against invalid cast between concrete types.
1583 * Assume that 'e' is never be any placeholder expressions.
1584 * The result of these checks should be consistent with CastExp::toElem().
1587 // Fat Value types
1588 const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray || tob.ty == Tvector);
1589 const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray || t1b.ty == Tvector);
1591 // Fat Reference types
1592 const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate);
1593 const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate);
1595 // Reference types
1596 const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass);
1597 const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
1599 // Arithmetic types (== valueable basic types)
1600 const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
1601 const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
1603 // Try casting the alias this member.
1604 // Return the expression if it succeeds, null otherwise.
1605 Expression tryAliasThisCast()
1607 if (isRecursiveAliasThis(att, t1b))
1608 return null;
1610 /* Forward the cast to our alias this member, rewrite to:
1611 * cast(to)e1.aliasthis
1613 auto exp = resolveAliasThis(sc, e);
1614 const errors = global.startGagging();
1615 exp = castTo(exp, sc, t, att);
1616 return global.endGagging(errors) ? null : exp;
1619 bool hasAliasThis;
1620 if (AggregateDeclaration t1ad = isAggregate(t1b))
1622 AggregateDeclaration toad = isAggregate(tob);
1623 if (t1ad != toad && t1ad.aliasthis)
1625 if (t1b.ty == Tclass && tob.ty == Tclass)
1627 ClassDeclaration t1cd = t1b.isClassHandle();
1628 ClassDeclaration tocd = tob.isClassHandle();
1629 int offset;
1630 if (tocd.isBaseOf(t1cd, &offset))
1631 goto Lok;
1633 hasAliasThis = true;
1636 else if (tob.ty == Tvector && t1b.ty != Tvector)
1638 if (t1b.ty == Tsarray)
1640 // Casting static array to vector with same size, e.g. `cast(int4) int[4]`
1641 if (t1b.size(e.loc) != tob.size(e.loc))
1642 goto Lfail;
1643 return new VectorExp(e.loc, e, tob).expressionSemantic(sc);
1645 //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
1646 TypeVector tv = tob.isTypeVector();
1647 Expression result = new CastExp(e.loc, e, tv.elementType());
1648 result = new VectorExp(e.loc, result, tob);
1649 result = result.expressionSemantic(sc);
1650 return result;
1652 else if (tob.ty != Tvector && t1b.ty == Tvector)
1654 // T[n] <-- __vector(U[m])
1655 if (tob.ty == Tsarray)
1657 if (t1b.size(e.loc) == tob.size(e.loc))
1658 goto Lok;
1660 goto Lfail;
1662 else if (t1b.implicitConvTo(tob) == MATCH.constant && t.equals(e.type.constOf()))
1664 auto result = e.copy();
1665 result.type = t;
1666 return result;
1669 // arithmetic values vs. other arithmetic values
1670 // arithmetic values vs. T*
1671 if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer))
1673 goto Lok;
1676 // arithmetic values vs. references or fat values
1677 if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV))
1679 goto Lfail;
1682 // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
1683 if (tob_isFV && t1b_isFV)
1685 if (hasAliasThis)
1687 auto result = tryAliasThisCast();
1688 if (result)
1689 return result;
1692 if (t1b.size(e.loc) == tob.size(e.loc))
1693 goto Lok;
1695 auto ts = toAutoQualChars(e.type, t);
1696 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
1697 e.toChars(), ts[0], ts[1]);
1698 return ErrorExp.get();
1701 // Fat values vs. null or references
1702 if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR))
1704 if (tob.ty == Tpointer && t1b.ty == Tsarray)
1706 // T[n] sa;
1707 // cast(U*)sa; // ==> cast(U*)sa.ptr;
1708 return new AddrExp(e.loc, e, t);
1710 if (tob.ty == Tarray && t1b.ty == Tsarray)
1712 // T[n] sa;
1713 // cast(U[])sa; // ==> cast(U[])sa[];
1714 const fsize = t1b.nextOf().size();
1715 const tsize = tob.nextOf().size();
1716 if (fsize == SIZE_INVALID || tsize == SIZE_INVALID)
1718 return ErrorExp.get();
1720 if (fsize != tsize)
1722 const dim = t1b.isTypeSArray().dim.toInteger();
1723 if (tsize == 0 || (dim * fsize) % tsize != 0)
1725 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
1726 e.toChars(), e.type.toChars(), t.toChars());
1727 return ErrorExp.get();
1730 goto Lok;
1732 goto Lfail;
1735 /* For references, any reinterpret casts are allowed to same 'ty' type.
1736 * T* to U*
1737 * R1 function(P1) to R2 function(P2)
1738 * R1 delegate(P1) to R2 delegate(P2)
1739 * T[] to U[]
1740 * V1[K1] to V2[K2]
1741 * class/interface A to B (will be a dynamic cast if possible)
1743 if (tob.ty == t1b.ty && tob_isR && t1b_isR)
1744 goto Lok;
1746 // typeof(null) <-- non-null references or values
1747 if (tob.ty == Tnull && t1b.ty != Tnull)
1748 goto Lfail; // https://issues.dlang.org/show_bug.cgi?id=14629
1749 // typeof(null) --> non-null references or arithmetic values
1750 if (t1b.ty == Tnull && tob.ty != Tnull)
1751 goto Lok;
1753 // Check size mismatch of references.
1754 // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
1755 if (tob_isFR && t1b_isR || t1b_isFR && tob_isR)
1757 if (tob.ty == Tpointer && t1b.ty == Tarray)
1759 // T[] da;
1760 // cast(U*)da; // ==> cast(U*)da.ptr;
1761 goto Lok;
1763 if (tob.ty == Tpointer && t1b.ty == Tdelegate)
1765 // void delegate() dg;
1766 // cast(U*)dg; // ==> cast(U*)dg.ptr;
1767 // Note that it happens even when U is a Tfunction!
1768 deprecation(e.loc, "casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
1769 goto Lok;
1771 goto Lfail;
1774 if (t1b.ty == Tvoid && tob.ty != Tvoid)
1776 Lfail:
1777 /* if the cast cannot be performed, maybe there is an alias
1778 * this that can be used for casting.
1780 if (hasAliasThis)
1782 auto result = tryAliasThisCast();
1783 if (result)
1784 return result;
1786 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
1787 return ErrorExp.get();
1790 Lok:
1791 auto result = new CastExp(e.loc, e, t);
1792 result.type = t; // Don't call semantic()
1793 //printf("Returning: %s\n", result.toChars());
1794 return result;
1797 Expression visitError(ErrorExp e)
1799 return e;
1802 Expression visitReal(RealExp e)
1804 if (!e.type.equals(t))
1806 if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
1808 auto result = e.copy();
1809 result.type = t;
1810 return result;
1812 else
1813 return visit(e);
1815 return e;
1818 Expression visitComplex(ComplexExp e)
1820 if (!e.type.equals(t))
1822 if (e.type.iscomplex() && t.iscomplex())
1824 auto result = e.copy();
1825 result.type = t;
1826 return result;
1828 else
1829 return visit(e);
1831 return e;
1834 Expression visitStructLiteral(StructLiteralExp e)
1836 auto result = visit(e);
1837 if (auto sle = result.isStructLiteralExp())
1838 sle.stype = t; // commit type
1839 return result;
1842 Expression visitString(StringExp e)
1844 /* This follows copy-on-write; any changes to 'this'
1845 * will result in a copy.
1846 * The this.string member is considered immutable.
1848 int copied = 0;
1850 //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
1852 if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
1853 (!sc || !(sc.flags & SCOPE.Cfile)))
1855 error(e.loc, "cannot convert string literal to `void*`");
1856 return ErrorExp.get();
1859 StringExp se = e;
1861 Expression lcast()
1863 auto result = new CastExp(e.loc, se, t);
1864 result.type = t; // so semantic() won't be run on e
1865 return result;
1868 if (!e.committed)
1870 se = e.copy().isStringExp();
1871 se.committed = true;
1872 copied = 1;
1875 if (e.type.equals(t))
1877 return se;
1880 Type tb = t.toBasetype();
1881 Type typeb = e.type.toBasetype();
1883 //printf("\ttype = %s\n", e.type.toChars());
1884 if (tb.ty == Tdelegate && typeb.ty != Tdelegate)
1886 return visit(e);
1889 if (typeb.equals(tb))
1891 if (!copied)
1893 se = e.copy().isStringExp();
1894 copied = 1;
1896 se.type = t;
1897 return se;
1900 /* Handle reinterpret casts:
1901 * cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
1902 * cast(wchar[2])"abcd"c --> [\u6261, \u6463]
1903 * cast(wchar[1])"abcd"c --> [\u6261]
1904 * cast(char[4])"a" --> ['a', 0, 0, 0]
1906 if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
1908 se = e.copy().isStringExp();
1909 uinteger_t szx = tb.nextOf().size();
1910 assert(szx <= 255);
1911 se.sz = cast(ubyte)szx;
1912 se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
1913 se.committed = true;
1914 se.type = t;
1916 /* If larger than source, pad with zeros.
1918 const fullSize = (se.len + 1) * se.sz; // incl. terminating 0
1919 if (fullSize > (e.len + 1) * e.sz)
1921 void* s = mem.xmalloc(fullSize);
1922 const srcSize = e.len * e.sz;
1923 const data = se.peekData();
1924 memcpy(s, data.ptr, srcSize);
1925 memset(s + srcSize, 0, fullSize - srcSize);
1926 se.setData(s, se.len, se.sz);
1928 return se;
1931 if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer)
1933 if (!copied)
1935 se = e.copy().isStringExp();
1936 copied = 1;
1938 return lcast();
1940 if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
1942 if (!copied)
1944 se = e.copy().isStringExp();
1945 copied = 1;
1947 return lcast();
1950 const nextSz = typeb.nextOf().size();
1951 if (nextSz == SIZE_INVALID)
1953 return ErrorExp.get();
1955 if (nextSz == tb.nextOf().size())
1957 if (!copied)
1959 se = e.copy().isStringExp();
1960 copied = 1;
1962 if (tb.ty == Tsarray)
1963 goto L2; // handle possible change in static array dimension
1964 se.type = t;
1965 return se;
1968 if (e.committed)
1969 goto Lcast;
1971 auto X(T, U)(T tf, U tt)
1973 return (cast(int)tf * 256 + cast(int)tt);
1977 OutBuffer buffer;
1978 size_t newlen = 0;
1979 int tfty = typeb.nextOf().toBasetype().ty;
1980 int ttty = tb.nextOf().toBasetype().ty;
1981 switch (X(tfty, ttty))
1983 case X(Tchar, Tchar):
1984 case X(Twchar, Twchar):
1985 case X(Tdchar, Tdchar):
1986 break;
1988 case X(Tchar, Twchar):
1989 for (size_t u = 0; u < e.len;)
1991 dchar c;
1992 if (const s = utf_decodeChar(se.peekString(), u, c))
1993 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
1994 else
1995 buffer.writeUTF16(c);
1997 newlen = buffer.length / 2;
1998 buffer.writeUTF16(0);
1999 goto L1;
2001 case X(Tchar, Tdchar):
2002 for (size_t u = 0; u < e.len;)
2004 dchar c;
2005 if (const s = utf_decodeChar(se.peekString(), u, c))
2006 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
2007 buffer.write4(c);
2008 newlen++;
2010 buffer.write4(0);
2011 goto L1;
2013 case X(Twchar, Tchar):
2014 for (size_t u = 0; u < e.len;)
2016 dchar c;
2017 if (const s = utf_decodeWchar(se.peekWstring(), u, c))
2018 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
2019 else
2020 buffer.writeUTF8(c);
2022 newlen = buffer.length;
2023 buffer.writeUTF8(0);
2024 goto L1;
2026 case X(Twchar, Tdchar):
2027 for (size_t u = 0; u < e.len;)
2029 dchar c;
2030 if (const s = utf_decodeWchar(se.peekWstring(), u, c))
2031 error(e.loc, "%.*s", cast(int)s.length, s.ptr);
2032 buffer.write4(c);
2033 newlen++;
2035 buffer.write4(0);
2036 goto L1;
2038 case X(Tdchar, Tchar):
2039 for (size_t u = 0; u < e.len; u++)
2041 uint c = se.peekDstring()[u];
2042 if (!utf_isValidDchar(c))
2043 error(e.loc, "invalid UCS-32 char \\U%08x", c);
2044 else
2045 buffer.writeUTF8(c);
2046 newlen++;
2048 newlen = buffer.length;
2049 buffer.writeUTF8(0);
2050 goto L1;
2052 case X(Tdchar, Twchar):
2053 for (size_t u = 0; u < e.len; u++)
2055 uint c = se.peekDstring()[u];
2056 if (!utf_isValidDchar(c))
2057 error(e.loc, "invalid UCS-32 char \\U%08x", c);
2058 else
2059 buffer.writeUTF16(c);
2060 newlen++;
2062 newlen = buffer.length / 2;
2063 buffer.writeUTF16(0);
2064 goto L1;
2067 if (!copied)
2069 se = e.copy().isStringExp();
2070 copied = 1;
2074 uinteger_t szx = tb.nextOf().size();
2075 assert(szx <= 255);
2076 se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
2078 break;
2080 default:
2081 assert(typeb.nextOf().size() != tb.nextOf().size());
2082 goto Lcast;
2086 assert(copied);
2088 // See if need to truncate or extend the literal
2089 if (auto tsa = tb.isTypeSArray())
2091 size_t dim2 = cast(size_t)tsa.dim.toInteger();
2092 //printf("dim from = %d, to = %d\n", cast(int)se.len, cast(int)dim2);
2094 // Changing dimensions
2095 if (dim2 != se.len)
2097 // Copy when changing the string literal
2098 const newsz = se.sz;
2099 const d = (dim2 < se.len) ? dim2 : se.len;
2100 void* s = mem.xmalloc((dim2 + 1) * newsz);
2101 memcpy(s, se.peekData().ptr, d * newsz);
2102 // Extend with 0, add terminating 0
2103 memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz);
2104 se.setData(s, dim2, newsz);
2107 se.type = t;
2108 return se;
2110 Lcast:
2111 auto result = new CastExp(e.loc, se, t);
2112 result.type = t; // so semantic() won't be run on e
2113 return result;
2116 Expression visitAddr(AddrExp e)
2118 version (none)
2120 printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2122 Type tb = t.toBasetype();
2123 Type typeb = e.type.toBasetype();
2125 if (tb.equals(typeb))
2127 auto result = e.copy();
2128 result.type = t;
2129 return result;
2132 // Look for pointers to functions where the functions are overloaded.
2133 if (e.e1.isOverExp() &&
2134 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2136 OverExp eo = e.e1.isOverExp();
2137 FuncDeclaration f = null;
2138 for (size_t i = 0; i < eo.vars.a.length; i++)
2140 auto s = eo.vars.a[i];
2141 auto f2 = s.isFuncDeclaration();
2142 assert(f2);
2143 if (f2.overloadExactMatch(tb.nextOf()))
2145 if (f)
2147 /* Error if match in more than one overload set,
2148 * even if one is a 'better' match than the other.
2150 ScopeDsymbol.multiplyDefined(e.loc, f, f2);
2152 else
2153 f = f2;
2156 if (f)
2158 f.tookAddressOf++;
2159 auto se = new SymOffExp(e.loc, f, 0, false);
2160 auto se2 = se.expressionSemantic(sc);
2161 // Let SymOffExp::castTo() do the heavy lifting
2162 return visit(se2);
2166 if (e.e1.isVarExp() &&
2167 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2168 tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
2170 auto ve = e.e1.isVarExp();
2171 auto f = ve.var.isFuncDeclaration();
2172 if (f)
2174 assert(f.isImportedSymbol());
2175 f = f.overloadExactMatch(tb.nextOf());
2176 if (f)
2178 Expression result = new VarExp(e.loc, f, false);
2179 result.type = f.type;
2180 result = new AddrExp(e.loc, result, t);
2181 return result;
2186 if (auto f = isFuncAddress(e))
2188 if (f.checkForwardRef(e.loc))
2190 return ErrorExp.get();
2194 return visit(e);
2197 Expression visitTuple(TupleExp e)
2199 if (e.type.equals(t))
2201 return e;
2204 /* If target type is a tuple of same length, cast each expression to
2205 * the corresponding type in the tuple.
2207 TypeTuple totuple;
2208 if (auto tt = t.isTypeTuple())
2209 totuple = e.exps.length == tt.arguments.length ? tt : null;
2211 TupleExp te = e.copy().isTupleExp();
2212 te.e0 = e.e0 ? e.e0.copy() : null;
2213 te.exps = e.exps.copy();
2214 for (size_t i = 0; i < te.exps.length; i++)
2216 Expression ex = (*te.exps)[i];
2217 ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
2218 (*te.exps)[i] = ex;
2220 if (totuple)
2221 te.type = totuple;
2222 return te;
2224 /* Questionable behavior: In here, result.type is not set to t
2225 * if target type is not a tuple of same length.
2226 * Therefoe:
2227 * TypeTuple!(int, int) values;
2228 * auto values2 = cast(long)values;
2229 * // typeof(values2) == TypeTuple!(int, int) !!
2231 * Only when the casted tuple is immediately expanded, it would work.
2232 * auto arr = [cast(long)values];
2233 * // typeof(arr) == long[]
2237 Expression visitArrayLiteral(ArrayLiteralExp e)
2239 version (none)
2241 printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2244 ArrayLiteralExp ae = e;
2246 Type tb = t.toBasetype();
2247 if (tb.ty == Tarray)
2249 if (checkArrayLiteralEscape(sc, ae, false))
2251 return ErrorExp.get();
2255 if (e.type == t)
2257 return e;
2259 Type typeb = e.type.toBasetype();
2261 if ((tb.ty == Tarray || tb.ty == Tsarray) &&
2262 (typeb.ty == Tarray || typeb.ty == Tsarray))
2264 if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
2266 // Don't do anything to cast non-void[] to void[]
2268 else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid)
2270 // Don't do anything for casting void[n] to others
2272 else
2274 if (auto tsa = tb.isTypeSArray())
2276 if (e.elements.length != tsa.dim.toInteger())
2277 goto L1;
2280 ae = e.copy().isArrayLiteralExp();
2281 if (e.basis)
2282 ae.basis = e.basis.castTo(sc, tb.nextOf());
2283 ae.elements = e.elements.copy();
2284 for (size_t i = 0; i < e.elements.length; i++)
2286 Expression ex = (*e.elements)[i];
2287 if (!ex)
2288 continue;
2289 ex = ex.castTo(sc, tb.nextOf());
2290 (*ae.elements)[i] = ex;
2292 ae.type = t;
2293 return ae;
2296 else if (tb.ty == Tpointer && typeb.ty == Tsarray)
2298 Type tp = typeb.nextOf().pointerTo();
2299 if (!tp.equals(ae.type))
2301 ae = e.copy().isArrayLiteralExp();
2302 ae.type = tp;
2305 else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer))
2307 // Convert array literal to vector type
2308 // The Tpointer case comes from C eagerly converting Tsarray to Tpointer
2309 TypeVector tv = tb.isTypeVector();
2310 TypeSArray tbase = tv.basetype.isTypeSArray();
2311 assert(tbase.ty == Tsarray);
2312 const edim = e.elements.length;
2313 const tbasedim = tbase.dim.toInteger();
2314 if (edim > tbasedim)
2315 goto L1;
2317 ae = e.copy().isArrayLiteralExp();
2318 ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
2319 ae.elements = e.elements.copy();
2320 Type telement = tv.elementType();
2321 foreach (i; 0 .. edim)
2323 Expression ex = (*e.elements)[i];
2324 ex = ex.castTo(sc, telement);
2325 (*ae.elements)[i] = ex;
2327 // Fill in the rest with the default initializer
2328 ae.elements.setDim(cast(size_t)tbasedim);
2329 foreach (i; edim .. cast(size_t)tbasedim)
2331 Expression ex = typeb.nextOf.defaultInitLiteral(e.loc);
2332 ex = ex.castTo(sc, telement);
2333 (*ae.elements)[i] = ex;
2335 Expression ev = new VectorExp(e.loc, ae, tb);
2336 ev = ev.expressionSemantic(sc);
2337 return ev;
2340 return visit(ae);
2343 Expression visitAssocArrayLiteral(AssocArrayLiteralExp e)
2345 //printf("AssocArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2346 if (e.type == t)
2348 return e;
2351 Type tb = t.toBasetype();
2352 Type typeb = e.type.toBasetype();
2354 if (tb.ty == Taarray && typeb.ty == Taarray &&
2355 tb.nextOf().toBasetype().ty != Tvoid)
2357 AssocArrayLiteralExp ae = e.copy().isAssocArrayLiteralExp();
2358 ae.keys = e.keys.copy();
2359 ae.values = e.values.copy();
2360 assert(e.keys.length == e.values.length);
2361 for (size_t i = 0; i < e.keys.length; i++)
2363 Expression ex = (*e.values)[i];
2364 ex = ex.castTo(sc, tb.nextOf());
2365 (*ae.values)[i] = ex;
2367 ex = (*e.keys)[i];
2368 ex = ex.castTo(sc, tb.isTypeAArray().index);
2369 (*ae.keys)[i] = ex;
2371 ae.type = t;
2372 return ae;
2374 return visit(e);
2377 Expression visitSymOff(SymOffExp e)
2379 version (none)
2381 printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2383 if (e.type == t && !e.hasOverloads)
2385 return e;
2388 Type tb = t.toBasetype();
2389 Type typeb = e.type.toBasetype();
2391 if (tb.equals(typeb))
2393 auto result = e.copy();
2394 result.type = t;
2395 result.isSymOffExp().hasOverloads = false;
2396 return result;
2399 // Look for pointers to functions where the functions are overloaded.
2400 if (e.hasOverloads &&
2401 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2402 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2404 FuncDeclaration f = e.var.isFuncDeclaration();
2405 f = f ? f.overloadExactMatch(tb.nextOf()) : null;
2406 if (f)
2408 Expression result;
2409 if (tb.ty == Tdelegate)
2411 if (f.needThis() && hasThis(sc))
2413 result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false);
2414 result = result.expressionSemantic(sc);
2416 else if (f.needThis())
2418 error(e.loc, "no `this` to create delegate for `%s`", f.toChars());
2419 return ErrorExp.get();
2421 else if (f.isNested())
2423 result = new DelegateExp(e.loc, IntegerExp.literal!0, f, false);
2424 result = result.expressionSemantic(sc);
2426 else
2428 error(e.loc, "cannot cast from function pointer to delegate");
2429 return ErrorExp.get();
2432 else
2434 result = new SymOffExp(e.loc, f, 0, false);
2435 result.type = t;
2437 f.tookAddressOf++;
2438 return result;
2442 if (auto f = isFuncAddress(e))
2444 if (f.checkForwardRef(e.loc))
2446 return ErrorExp.get();
2450 return visit(e);
2453 Expression visitDelegate(DelegateExp e)
2455 version (none)
2457 printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2459 static immutable msg = "cannot form delegate due to covariant return type";
2461 Type tb = t.toBasetype();
2462 Type typeb = e.type.toBasetype();
2464 if (tb.equals(typeb) && !e.hasOverloads)
2466 int offset;
2467 e.func.tookAddressOf++;
2468 if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
2469 error(e.loc, "%s", msg.ptr);
2470 auto result = e.copy();
2471 result.type = t;
2472 return result;
2475 // Look for delegates to functions where the functions are overloaded.
2476 if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
2478 if (e.func)
2480 auto f = e.func.overloadExactMatch(tb.nextOf());
2481 if (f)
2483 int offset;
2484 if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
2485 error(e.loc, "%s", msg.ptr);
2486 if (f != e.func) // if address not already marked as taken
2487 f.tookAddressOf++;
2488 auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
2489 result.type = t;
2490 return result;
2492 if (e.func.tintro)
2493 error(e.loc, "%s", msg.ptr);
2497 if (auto f = isFuncAddress(e))
2499 if (f.checkForwardRef(e.loc))
2501 return ErrorExp.get();
2505 return visit(e);
2508 Expression visitFunc(FuncExp e)
2510 //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
2511 FuncExp fe;
2512 if (e.matchType(t, sc, &fe, global.errorSinkNull) > MATCH.nomatch)
2514 return fe;
2516 return visit(e);
2519 Expression visitCond(CondExp e)
2521 if (!e.type.equals(t))
2523 auto result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t));
2524 result.type = t;
2525 return result;
2527 return e;
2530 Expression visitComma(CommaExp e)
2532 Expression e2c = e.e2.castTo(sc, t);
2534 if (e2c != e.e2)
2536 auto result = new CommaExp(e.loc, e.e1, e2c);
2537 result.type = e2c.type;
2538 return result;
2540 else
2542 e.type = e.e2.type;
2543 return e;
2547 Expression visitSlice(SliceExp e)
2549 //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e.toChars(), e.type.toChars(), t.toChars());
2551 Type tb = t.toBasetype();
2552 Type typeb = e.type.toBasetype();
2554 if (e.type.equals(t) || typeb.ty != Tarray ||
2555 (tb.ty != Tarray && tb.ty != Tsarray))
2557 return visit(e);
2560 if (tb.ty == Tarray)
2562 if (typeb.nextOf().equivalent(tb.nextOf()))
2564 // T[] to const(T)[]
2565 auto result = e.copy();
2566 result.type = t;
2567 return result;
2569 else
2571 return visit(e);
2575 // Handle the cast from Tarray to Tsarray with CT-known slicing
2577 TypeSArray tsa;
2579 Type t = toStaticArrayType(e);
2580 tsa = t ? t.isTypeSArray() : null;
2583 if (tsa && tsa.size(e.loc) == tb.size(e.loc))
2585 /* Match if the sarray sizes are equal:
2586 * T[a .. b] to const(T)[b-a]
2587 * T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
2589 * If a SliceExp has Tsarray, it will become lvalue.
2590 * That's handled in SliceExp::isLvalue and toLvalue
2592 auto result = e.copy();
2593 result.type = t;
2594 return result;
2596 if (tsa && tsa.dim.equals(tb.isTypeSArray().dim))
2598 /* Match if the dimensions are equal
2599 * with the implicit conversion of e.e1:
2600 * cast(float[2]) [2.0, 1.0, 0.0][0..2];
2602 Type t1b = e.e1.type.toBasetype();
2603 if (t1b.ty == Tsarray)
2604 t1b = tb.nextOf().sarrayOf(t1b.isTypeSArray().dim.toInteger());
2605 else if (t1b.ty == Tarray)
2606 t1b = tb.nextOf().arrayOf();
2607 else if (t1b.ty == Tpointer)
2608 t1b = tb.nextOf().pointerTo();
2609 else
2610 assert(0);
2611 if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
2613 Expression e1x = e.e1.implicitCastTo(sc, t1b);
2614 assert(e1x.op != EXP.error);
2615 e = e.copy().isSliceExp();
2616 e.e1 = e1x;
2617 e.type = t;
2618 return e;
2621 auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
2622 error(e.loc, "cannot cast expression `%s` of type `%s` to `%s`",
2623 e.toChars(), ts[0], ts[1]);
2624 return ErrorExp.get();
2627 // Casting to noreturn isn't an actual cast
2628 // Rewrite cast(<qual> noreturn) <exp>
2629 // as <exp>, assert(false)
2630 if (t.isTypeNoreturn())
2632 // Don't generate an unreachable assert(false) if e will abort
2633 if (e.type.isTypeNoreturn())
2635 // Paint e to accomodate for different type qualifiers
2636 e.type = t;
2637 return e;
2640 auto ini = t.defaultInitLiteral(e.loc);
2641 return Expression.combine(e, ini);
2644 switch (e.op)
2646 default : return visit(e);
2647 case EXP.error : return visitError(e.isErrorExp());
2648 case EXP.float64 : return visitReal(e.isRealExp());
2649 case EXP.complex80 : return visitComplex(e.isComplexExp());
2650 case EXP.structLiteral : return visitStructLiteral(e.isStructLiteralExp());
2651 case EXP.string_ : return visitString(e.isStringExp());
2652 case EXP.address : return visitAddr(e.isAddrExp());
2653 case EXP.tuple : return visitTuple(e.isTupleExp());
2654 case EXP.arrayLiteral : return visitArrayLiteral(e.isArrayLiteralExp());
2655 case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
2656 case EXP.symbolOffset : return visitSymOff(e.isSymOffExp());
2657 case EXP.delegate_ : return visitDelegate(e.isDelegateExp());
2658 case EXP.function_ : return visitFunc(e.isFuncExp());
2659 case EXP.question : return visitCond(e.isCondExp());
2660 case EXP.comma : return visitComma(e.isCommaExp());
2661 case EXP.slice : return visitSlice(e.isSliceExp());
2665 /****************************************
2666 * Set type inference target
2667 * t Target type
2668 * flag 1: don't put an error when inference fails
2670 Expression inferType(Expression e, Type t, int flag = 0)
2672 Expression visitAle(ArrayLiteralExp ale)
2674 Type tb = t.toBasetype();
2675 if (tb.ty == Tarray || tb.ty == Tsarray)
2677 Type tn = tb.nextOf();
2678 if (ale.basis)
2679 ale.basis = inferType(ale.basis, tn, flag);
2680 for (size_t i = 0; i < ale.elements.length; i++)
2682 if (Expression e = (*ale.elements)[i])
2684 e = inferType(e, tn, flag);
2685 (*ale.elements)[i] = e;
2689 return ale;
2692 Expression visitAar(AssocArrayLiteralExp aale)
2694 Type tb = t.toBasetype();
2695 if (auto taa = tb.isTypeAArray())
2697 Type ti = taa.index;
2698 Type tv = taa.nextOf();
2699 for (size_t i = 0; i < aale.keys.length; i++)
2701 if (Expression e = (*aale.keys)[i])
2703 e = inferType(e, ti, flag);
2704 (*aale.keys)[i] = e;
2707 for (size_t i = 0; i < aale.values.length; i++)
2709 if (Expression e = (*aale.values)[i])
2711 e = inferType(e, tv, flag);
2712 (*aale.values)[i] = e;
2716 return aale;
2719 Expression visitFun(FuncExp fe)
2721 //printf("FuncExp::inferType('%s'), to=%s\n", fe.type ? fe.type.toChars() : "null", t.toChars());
2722 if (t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction)
2724 fe.fd.treq = t;
2726 return fe;
2729 Expression visitTer(CondExp ce)
2731 Type tb = t.toBasetype();
2732 ce.e1 = inferType(ce.e1, tb, flag);
2733 ce.e2 = inferType(ce.e2, tb, flag);
2734 return ce;
2737 if (t) switch (e.op)
2739 case EXP.arrayLiteral: return visitAle(e.isArrayLiteralExp());
2740 case EXP.assocArrayLiteral: return visitAar(e.isAssocArrayLiteralExp());
2741 case EXP.function_: return visitFun(e.isFuncExp());
2742 case EXP.question: return visitTer(e.isCondExp());
2743 default:
2745 return e;
2748 /****************************************
2749 * Scale addition/subtraction to/from pointer.
2751 Expression scaleFactor(BinExp be, Scope* sc)
2753 Type t1b = be.e1.type.toBasetype();
2754 Type t2b = be.e2.type.toBasetype();
2755 Expression eoff;
2757 if (t1b.ty == Tpointer && t2b.isintegral())
2759 // Need to adjust operator by the stride
2760 // Replace (ptr + int) with (ptr + (int * stride))
2761 Type t = Type.tptrdiff_t;
2763 uinteger_t stride = t1b.nextOf().size(be.loc);
2764 if (!t.equals(t2b))
2765 be.e2 = be.e2.castTo(sc, t);
2766 eoff = be.e2;
2767 be.e2 = new MulExp(be.loc, be.e2, new IntegerExp(Loc.initial, stride, t));
2768 be.e2.type = t;
2769 be.type = be.e1.type;
2771 else if (t2b.ty == Tpointer && t1b.isintegral())
2773 // Need to adjust operator by the stride
2774 // Replace (int + ptr) with (ptr + (int * stride))
2775 Type t = Type.tptrdiff_t;
2776 Expression e;
2778 uinteger_t stride = t2b.nextOf().size(be.loc);
2779 if (!t.equals(t1b))
2780 e = be.e1.castTo(sc, t);
2781 else
2782 e = be.e1;
2783 eoff = e;
2784 e = new MulExp(be.loc, e, new IntegerExp(Loc.initial, stride, t));
2785 e.type = t;
2786 be.type = be.e2.type;
2787 be.e1 = be.e2;
2788 be.e2 = e;
2790 else
2791 assert(0);
2794 eoff = eoff.optimize(WANTvalue);
2795 if (eoff.op == EXP.int64 && eoff.toInteger() == 0)
2798 else if (sc.setUnsafe(false, be.loc, "pointer arithmetic not allowed in @safe functions"))
2800 return ErrorExp.get();
2803 return be;
2806 /**************************************
2807 * Return true if e is an empty array literal with dimensionality
2808 * equal to or less than type of other array.
2809 * [], [[]], [[[]]], etc.
2810 * I.e., make sure that [1,2] is compatible with [],
2811 * [[1,2]] is compatible with [[]], etc.
2813 private bool isVoidArrayLiteral(Expression e, Type other)
2815 while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && (e.isArrayLiteralExp().elements.length == 1))
2817 auto ale = e.isArrayLiteralExp();
2818 e = ale[0];
2819 if (other.ty == Tsarray || other.ty == Tarray)
2820 other = other.nextOf();
2821 else
2822 return false;
2824 if (other.ty != Tsarray && other.ty != Tarray)
2825 return false;
2826 Type t = e.type;
2827 return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && e.isArrayLiteralExp().elements.length == 0);
2831 * Merge types of `e1` and `e2` into a common subset
2833 * Parameters `e1` and `e2` will be rewritten in place as needed.
2835 * Params:
2836 * sc = Current scope
2837 * op = Operator such as `e1 op e2`. In practice, either EXP.question
2838 * or one of the binary operator.
2839 * pe1 = The LHS of the operation, will be rewritten
2840 * pe2 = The RHS of the operation, will be rewritten
2842 * Returns:
2843 * The resulting type in case of success, `null` in case of error
2845 Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2)
2847 //printf("typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
2849 Expression e1 = pe1;
2850 Expression e2 = pe2;
2852 // ImportC: do array/function conversions
2853 if (sc)
2855 e1 = e1.arrayFuncConv(sc);
2856 e2 = e2.arrayFuncConv(sc);
2859 Type Lret(Type result)
2861 pe1 = e1;
2862 pe2 = e2;
2864 version (none)
2866 printf("-typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
2867 if (e1.type)
2868 printf("\tt1 = %s\n", e1.type.toChars());
2869 if (e2.type)
2870 printf("\tt2 = %s\n", e2.type.toChars());
2871 printf("\ttype = %s\n", result.toChars());
2873 return result;
2876 /// Converts one of the expression to the other
2877 Type convert(ref Expression from, Type to)
2879 from = from.castTo(sc, to);
2880 return Lret(to);
2883 /// Converts both expression to a third type
2884 Type coerce(Type towards)
2886 e1 = e1.castTo(sc, towards);
2887 e2 = e2.castTo(sc, towards);
2888 return Lret(towards);
2891 Type t1b = e1.type.toBasetype();
2892 Type t2b = e2.type.toBasetype();
2894 if (sc && sc.flags & SCOPE.Cfile)
2896 // Integral types can be implicitly converted to pointers
2897 if ((t1b.ty == Tpointer) != (t2b.ty == Tpointer))
2899 if (t1b.isintegral())
2901 return convert(e1, t2b);
2903 else if (t2b.isintegral())
2905 return convert(e2, t1b);
2910 if (op != EXP.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
2912 if (op == EXP.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
2914 e1 = e1.castTo(sc, Type.tdchar);
2915 e2 = e2.castTo(sc, Type.tdchar);
2917 else
2919 e1 = integralPromotions(e1, sc);
2920 e2 = integralPromotions(e2, sc);
2924 MATCH m;
2925 Type t1 = e1.type;
2926 Type t2 = e2.type;
2927 assert(t1);
2928 Type t = t1;
2930 /* The start type of alias this type recursion.
2931 * In following case, we should save A, and stop recursion
2932 * if it appears again.
2933 * X -> Y -> [A] -> B -> A -> B -> ...
2935 Type att1 = null;
2936 Type att2 = null;
2938 if (t1.mod != t2.mod &&
2939 t1.ty == Tenum && t2.ty == Tenum &&
2940 t1.isTypeEnum().sym == t2.isTypeEnum().sym)
2942 ubyte mod = MODmerge(t1.mod, t2.mod);
2943 t1 = t1.castMod(mod);
2944 t2 = t2.castMod(mod);
2945 return Lret(t1);
2948 Lagain:
2949 t1b = t1.toBasetype();
2950 t2b = t2.toBasetype();
2952 const ty = implicitConvCommonTy(t1b.ty, t2b.ty);
2953 if (ty != Terror)
2955 const ty1 = implicitConvTy1(t1b.ty, t2b.ty);
2956 const ty2 = implicitConvTy1(t2b.ty, t1b.ty);
2958 if (t1b.ty == ty1) // if no promotions
2960 if (t1.equals(t2))
2961 return Lret(t1);
2963 if (t1b.equals(t2b))
2964 return Lret(t1b);
2967 t1 = Type.basic[ty1];
2968 t2 = Type.basic[ty2];
2970 if (!(t1 && t2))
2971 return null;
2972 e1 = e1.castTo(sc, t1);
2973 e2 = e2.castTo(sc, t2);
2974 return Lret(Type.basic[ty]);
2977 t1 = t1b;
2978 t2 = t2b;
2980 if (t1.ty == Ttuple || t2.ty == Ttuple)
2981 return null;
2983 if (t1.equals(t2))
2985 // merging can not result in new enum type
2986 if (t.ty == Tenum)
2987 return Lret(t1b);
2988 return Lret(t);
2991 if ((t1.ty == Tpointer && t2.ty == Tpointer) || (t1.ty == Tdelegate && t2.ty == Tdelegate))
2993 // Bring pointers to compatible type
2994 Type t1n = t1.nextOf();
2995 Type t2n = t2.nextOf();
2997 if (t1n.equals(t2n))
2998 return Lret(t);
3000 if (t1n.ty == Tvoid) // pointers to void are always compatible
3001 return Lret(t1);
3003 if (t2n.ty == Tvoid)
3004 return Lret(t2);
3006 if (t1.implicitConvTo(t2))
3007 return convert(e1, t2);
3009 if (t2.implicitConvTo(t1))
3010 return convert(e2, t1);
3012 if (t1n.ty == Tfunction && t2n.ty == Tfunction)
3014 TypeFunction tf1 = t1n.isTypeFunction();
3015 TypeFunction tf2 = t2n.isTypeFunction();
3016 tf1.purityLevel();
3017 tf2.purityLevel();
3019 TypeFunction d = tf1.syntaxCopy();
3021 if (tf1.purity != tf2.purity)
3022 d.purity = PURE.impure;
3023 assert(d.purity != PURE.fwdref);
3025 d.isnothrow = (tf1.isnothrow && tf2.isnothrow);
3026 d.isnogc = (tf1.isnogc && tf2.isnogc);
3028 if (tf1.trust == tf2.trust)
3029 d.trust = tf1.trust;
3030 else if (tf1.trust <= TRUST.system || tf2.trust <= TRUST.system)
3031 d.trust = TRUST.system;
3032 else
3033 d.trust = TRUST.trusted;
3035 Type tx = (t1.ty == Tdelegate) ? new TypeDelegate(d) : d.pointerTo();
3036 tx = tx.typeSemantic(e1.loc, sc);
3038 if (t1.implicitConvTo(tx) && t2.implicitConvTo(tx))
3039 return coerce(tx);
3040 return null;
3043 if (t1n.mod != t2n.mod)
3045 if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
3046 return null;
3047 ubyte mod = MODmerge(t1n.mod, t2n.mod);
3048 t1 = t1n.castMod(mod).pointerTo();
3049 t2 = t2n.castMod(mod).pointerTo();
3050 t = t1;
3051 goto Lagain;
3054 if (t1n.ty == Tclass && t2n.ty == Tclass)
3056 ClassDeclaration cd1 = t1n.isClassHandle();
3057 ClassDeclaration cd2 = t2n.isClassHandle();
3058 int offset;
3059 if (cd1.isBaseOf(cd2, &offset))
3061 if (offset)
3062 e2 = e2.castTo(sc, t);
3063 return Lret(t);
3066 if (cd2.isBaseOf(cd1, &offset))
3068 if (offset)
3069 e1 = e1.castTo(sc, t2);
3070 return Lret(t2);
3073 return null;
3076 t1 = t1n.constOf().pointerTo();
3077 t2 = t2n.constOf().pointerTo();
3078 if (t1.implicitConvTo(t2))
3079 return convert(e1, t2);
3080 if (t2.implicitConvTo(t1))
3081 return convert(e2, t1);
3082 return null;
3085 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)))
3087 /* (T[n] op void*) => T[]
3088 * (T[] op void*) => T[]
3089 * (T[n] op void[0]) => T[]
3090 * (T[] op void[0]) => T[]
3091 * (T[n] op void[]) => T[]
3092 * (T[] op void[]) => T[]
3094 return coerce(t1.nextOf().arrayOf());
3097 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)))
3099 /* (void* op T[n]) => T[]
3100 * (void* op T[]) => T[]
3101 * (void[0] op T[n]) => T[]
3102 * (void[0] op T[]) => T[]
3103 * (void[] op T[n]) => T[]
3104 * (void[] op T[]) => T[]
3106 return coerce(t2.nextOf().arrayOf());
3109 if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
3111 // https://issues.dlang.org/show_bug.cgi?id=7285
3112 // Tsarray op [x, y, ...] should to be Tsarray
3113 // https://issues.dlang.org/show_bug.cgi?id=14737
3114 // Tsarray ~ [x, y, ...] should to be Tarray
3115 if (t1.ty == Tsarray && e2.op == EXP.arrayLiteral && op != EXP.concatenate)
3116 return convert(e2, t1);
3117 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))
3119 // Don't make the lvalue const
3120 return Lret(t2);
3122 return convert(e1, t2);
3125 if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
3127 // https://issues.dlang.org/show_bug.cgi?id=7285
3128 // https://issues.dlang.org/show_bug.cgi?id=14737
3129 if (t2.ty == Tsarray && e1.op == EXP.arrayLiteral && op != EXP.concatenate)
3130 return convert(e1, t2);
3131 return convert(e2, t1);
3134 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)
3136 /* If one is mutable and the other immutable, then retry
3137 * with both of them as const
3139 Type t1n = t1.nextOf();
3140 Type t2n = t2.nextOf();
3141 ubyte mod;
3142 if (e1.op == EXP.null_ && e2.op != EXP.null_)
3143 mod = t2n.mod;
3144 else if (e1.op != EXP.null_ && e2.op == EXP.null_)
3145 mod = t1n.mod;
3146 else if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
3147 return null;
3148 else
3149 mod = MODmerge(t1n.mod, t2n.mod);
3151 if (t1.ty == Tpointer)
3152 t1 = t1n.castMod(mod).pointerTo();
3153 else
3154 t1 = t1n.castMod(mod).arrayOf();
3156 if (t2.ty == Tpointer)
3157 t2 = t2n.castMod(mod).pointerTo();
3158 else
3159 t2 = t2n.castMod(mod).arrayOf();
3160 t = t1;
3161 goto Lagain;
3164 if (t1.ty == Tclass && t2.ty == Tclass)
3166 if (t1.mod != t2.mod)
3168 ubyte mod;
3169 if (e1.op == EXP.null_ && e2.op != EXP.null_)
3170 mod = t2.mod;
3171 else if (e1.op != EXP.null_ && e2.op == EXP.null_)
3172 mod = t1.mod;
3173 else if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3174 return null;
3175 else
3176 mod = MODmerge(t1.mod, t2.mod);
3177 t1 = t1.castMod(mod);
3178 t2 = t2.castMod(mod);
3179 t = t1;
3180 goto Lagain;
3182 goto Lcc;
3185 if (t1.ty == Tclass || t2.ty == Tclass)
3187 Lcc:
3188 while (1)
3190 MATCH i1woat = MATCH.exact;
3191 MATCH i2woat = MATCH.exact;
3193 if (auto t2c = t2.isTypeClass())
3194 i1woat = t2c.implicitConvToWithoutAliasThis(t1);
3195 if (auto t1c = t1.isTypeClass())
3196 i2woat = t1c.implicitConvToWithoutAliasThis(t2);
3198 MATCH i1 = e2.implicitConvTo(t1);
3199 MATCH i2 = e1.implicitConvTo(t2);
3201 if (i1 && i2)
3203 // We have the case of class vs. void*, so pick class
3204 if (t1.ty == Tpointer)
3205 i1 = MATCH.nomatch;
3206 else if (t2.ty == Tpointer)
3207 i2 = MATCH.nomatch;
3210 // Match but without 'alias this' on classes
3211 if (i2 && i2woat)
3212 return coerce(t2);
3213 if (i1 && i1woat)
3214 return coerce(t1);
3216 // Here use implicitCastTo() instead of castTo() to try 'alias this' on classes
3217 Type coerceImplicit(Type towards)
3219 e1 = e1.implicitCastTo(sc, towards);
3220 e2 = e2.implicitCastTo(sc, towards);
3221 return Lret(towards);
3224 // Implicit conversion with 'alias this'
3225 if (i2)
3226 return coerceImplicit(t2);
3227 if (i1)
3228 return coerceImplicit(t1);
3230 if (t1.ty == Tclass && t2.ty == Tclass)
3232 TypeClass tc1 = t1.isTypeClass();
3233 TypeClass tc2 = t2.isTypeClass();
3235 /* Pick 'tightest' type
3237 ClassDeclaration cd1 = tc1.sym.baseClass;
3238 ClassDeclaration cd2 = tc2.sym.baseClass;
3239 if (cd1 && cd2)
3241 t1 = cd1.type.castMod(t1.mod);
3242 t2 = cd2.type.castMod(t2.mod);
3244 else if (cd1)
3245 t1 = cd1.type;
3246 else if (cd2)
3247 t2 = cd2.type;
3248 else
3249 return null;
3251 else if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
3253 if (isRecursiveAliasThis(att1, e1.type))
3254 return null;
3255 //printf("att tmerge(c || c) e1 = %s\n", e1.type.toChars());
3256 e1 = resolveAliasThis(sc, e1);
3257 t1 = e1.type;
3258 continue;
3260 else if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
3262 if (isRecursiveAliasThis(att2, e2.type))
3263 return null;
3264 //printf("att tmerge(c || c) e2 = %s\n", e2.type.toChars());
3265 e2 = resolveAliasThis(sc, e2);
3266 t2 = e2.type;
3267 continue;
3269 else
3270 return null;
3274 if (t1.ty == Tstruct && t2.ty == Tstruct)
3276 if (t1.mod != t2.mod)
3278 if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3279 return null;
3280 ubyte mod = MODmerge(t1.mod, t2.mod);
3281 t1 = t1.castMod(mod);
3282 t2 = t2.castMod(mod);
3283 t = t1;
3284 goto Lagain;
3287 TypeStruct ts1 = t1.isTypeStruct();
3288 TypeStruct ts2 = t2.isTypeStruct();
3289 if (ts1.sym != ts2.sym)
3291 if (!ts1.sym.aliasthis && !ts2.sym.aliasthis)
3292 return null;
3294 MATCH i1 = MATCH.nomatch;
3295 MATCH i2 = MATCH.nomatch;
3297 Expression e1b = null;
3298 Expression e2b = null;
3299 if (ts2.sym.aliasthis)
3301 if (isRecursiveAliasThis(att2, e2.type))
3302 return null;
3303 //printf("att tmerge(s && s) e2 = %s\n", e2.type.toChars());
3304 e2b = resolveAliasThis(sc, e2);
3305 i1 = e2b.implicitConvTo(t1);
3307 if (ts1.sym.aliasthis)
3309 if (isRecursiveAliasThis(att1, e1.type))
3310 return null;
3311 //printf("att tmerge(s && s) e1 = %s\n", e1.type.toChars());
3312 e1b = resolveAliasThis(sc, e1);
3313 i2 = e1b.implicitConvTo(t2);
3315 if (i1 && i2)
3316 return null;
3318 if (i1)
3319 return convert(e2, t1);
3320 if (i2)
3321 return convert(e1, t2);
3323 if (e1b)
3325 e1 = e1b;
3326 t1 = e1b.type.toBasetype();
3328 if (e2b)
3330 e2 = e2b;
3331 t2 = e2b.type.toBasetype();
3333 t = t1;
3334 goto Lagain;
3338 if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
3340 if (isRecursiveAliasThis(att1, e1.type))
3341 return null;
3342 //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
3343 e1 = resolveAliasThis(sc, e1);
3344 t1 = e1.type;
3345 t = t1;
3346 goto Lagain;
3349 if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
3351 if (isRecursiveAliasThis(att2, e2.type))
3352 return null;
3353 //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
3354 e2 = resolveAliasThis(sc, e2);
3355 t2 = e2.type;
3356 t = t2;
3357 goto Lagain;
3360 if ((e1.op == EXP.string_ || e1.op == EXP.null_) && e1.implicitConvTo(t2))
3361 return convert(e1, t2);
3362 if ((e2.op == EXP.string_ || e2.op == EXP.null_) && e2.implicitConvTo(t1))
3363 return convert(e2, t1);
3364 if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf()))
3365 return coerce(t1.nextOf().arrayOf());
3366 if (t1.ty == Tsarray && t2.ty == Tsarray && e1.implicitConvTo(t2.nextOf().arrayOf()))
3367 return coerce(t2.nextOf().arrayOf());
3369 if (t1.ty == Tvector && t2.ty == Tvector)
3371 // https://issues.dlang.org/show_bug.cgi?id=13841
3372 // all vector types should have no common types between
3373 // different vectors, even though their sizes are same.
3374 auto tv1 = t1.isTypeVector();
3375 auto tv2 = t2.isTypeVector();
3376 if (!tv1.basetype.equals(tv2.basetype))
3377 return null;
3379 goto LmodCompare;
3382 if (t1.ty == Tvector && t2.ty != Tvector && e2.implicitConvTo(t1))
3384 e2 = e2.castTo(sc, t1);
3385 t2 = t1;
3386 t = t1;
3387 goto Lagain;
3390 if (t2.ty == Tvector && t1.ty != Tvector && e1.implicitConvTo(t2))
3392 e1 = e1.castTo(sc, t2);
3393 t1 = t2;
3394 t = t1;
3395 goto Lagain;
3398 if (t1.isintegral() && t2.isintegral())
3400 if (t1.ty != t2.ty)
3402 if (t1.ty == Tvector || t2.ty == Tvector)
3403 return null;
3404 e1 = integralPromotions(e1, sc);
3405 e2 = integralPromotions(e2, sc);
3406 t1 = e1.type;
3407 t2 = e2.type;
3408 goto Lagain;
3410 assert(t1.ty == t2.ty);
3411 LmodCompare:
3412 if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3413 return null;
3414 ubyte mod = MODmerge(t1.mod, t2.mod);
3416 t1 = t1.castMod(mod);
3417 t2 = t2.castMod(mod);
3418 t = t1;
3419 e1 = e1.castTo(sc, t);
3420 e2 = e2.castTo(sc, t);
3421 goto Lagain;
3424 if (t1.ty == Tnull && t2.ty == Tnull)
3426 ubyte mod = MODmerge(t1.mod, t2.mod);
3427 return coerce(t1.castMod(mod));
3430 if (t2.ty == Tnull && (t1.ty == Tpointer || t1.ty == Taarray || t1.ty == Tarray))
3431 return convert(e2, t1);
3432 if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray))
3433 return convert(e1, t2);
3435 /// Covers array operations for user-defined types
3436 Type checkArrayOpType(Expression e1, Expression e2, EXP op, Scope *sc)
3438 // scalar op scalar - we shouldn't be here
3439 if (e1.type.ty != Tarray && e1.type.ty != Tsarray && e2.type.ty != Tarray && e2.type.ty != Tsarray)
3440 return null;
3442 // only supporting slices and array literals
3443 if (!e1.isSliceExp() && !e1.isArrayLiteralExp() && !e2.isSliceExp() && !e2.isArrayLiteralExp())
3444 return null;
3446 // start with e1 op e2 and if either one of e1 or e2 is a slice or array literal,
3447 // replace it with the first element of the array
3448 Expression lhs = e1;
3449 Expression rhs = e2;
3451 // T[x .. y] op ?
3452 if (auto se1 = e1.isSliceExp())
3453 lhs = new IndexExp(Loc.initial, se1.e1, IntegerExp.literal!0);
3455 // [t1, t2, .. t3] op ?
3456 if (auto ale1 = e1.isArrayLiteralExp())
3457 lhs = ale1.opIndex(0);
3459 // ? op U[z .. t]
3460 if (auto se2 = e2.isSliceExp())
3461 rhs = new IndexExp(Loc.initial, se2.e1, IntegerExp.literal!0);
3463 // ? op [u1, u2, .. u3]
3464 if (auto ale2 = e2.isArrayLiteralExp())
3465 rhs = ale2.opIndex(0);
3467 // create a new binary expression with the new lhs and rhs (at this stage, at least
3468 // one of lhs/rhs has been replaced with the 0'th element of the array it was before)
3469 Expression exp;
3470 switch (op)
3472 case EXP.add:
3473 exp = new AddExp(Loc.initial, lhs, rhs); break;
3474 case EXP.min:
3475 exp = new MinExp(Loc.initial, lhs, rhs); break;
3476 case EXP.mul:
3477 exp = new MulExp(Loc.initial, lhs, rhs); break;
3478 case EXP.div:
3479 exp = new DivExp(Loc.initial, lhs, rhs); break;
3480 case EXP.pow:
3481 exp = new PowExp(Loc.initial, lhs, rhs); break;
3482 default:
3483 exp = null;
3486 if (exp)
3488 // if T op U is valid and has type V
3489 // then T[] op U and T op U[] should be valid and have type V[]
3490 Expression e = exp.trySemantic(sc);
3491 if (e && e.type)
3492 return e.type.arrayOf;
3495 return null;
3498 if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
3500 if (e2.implicitConvTo(t1.nextOf()))
3502 // T[] op T
3503 // T[] op cast(T)U
3504 e2 = e2.castTo(sc, t1.nextOf());
3505 return Lret(t1.nextOf().arrayOf());
3507 if (t1.nextOf().implicitConvTo(e2.type))
3509 // (cast(T)U)[] op T (https://issues.dlang.org/show_bug.cgi?id=12780)
3510 // e1 is left as U[], it will be handled in arrayOp() later.
3511 return Lret(e2.type.arrayOf());
3513 if (t2.ty == Tarray && isArrayOpOperand(e2))
3515 if (t1.nextOf().implicitConvTo(t2.nextOf()))
3517 // (cast(T)U)[] op T[] (https://issues.dlang.org/show_bug.cgi?id=12780)
3518 t = t2.nextOf().arrayOf();
3519 // if cast won't be handled in arrayOp() later
3520 if (!isArrayOpImplicitCast(t1.isTypeDArray(), t2.isTypeDArray()))
3521 e1 = e1.castTo(sc, t);
3522 return Lret(t);
3524 if (t2.nextOf().implicitConvTo(t1.nextOf()))
3526 // T[] op (cast(T)U)[] (https://issues.dlang.org/show_bug.cgi?id=12780)
3527 // e2 is left as U[], it will be handled in arrayOp() later.
3528 t = t1.nextOf().arrayOf();
3529 // if cast won't be handled in arrayOp() later
3530 if (!isArrayOpImplicitCast(t2.isTypeDArray(), t1.isTypeDArray()))
3531 e2 = e2.castTo(sc, t);
3532 return Lret(t);
3536 t = checkArrayOpType(e1, e2, op, sc);
3537 if (t !is null)
3538 return Lret(t);
3540 return null;
3542 else if (t2.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2))
3544 if (e1.implicitConvTo(t2.nextOf()))
3546 // T op T[]
3547 // cast(T)U op T[]
3548 e1 = e1.castTo(sc, t2.nextOf());
3549 t = t2.nextOf().arrayOf();
3551 else if (t2.nextOf().implicitConvTo(e1.type))
3553 // T op (cast(T)U)[] (https://issues.dlang.org/show_bug.cgi?id=12780)
3554 // e2 is left as U[], it will be handled in arrayOp() later.
3555 t = e1.type.arrayOf();
3557 else
3559 t = checkArrayOpType(e1, e2, op, sc);
3560 if (t is null)
3561 return null;
3564 //printf("test %s\n", EXPtoString(op).ptr);
3565 e1 = e1.optimize(WANTvalue);
3566 if (isCommutative(op) && e1.isConst())
3568 /* Swap operands to minimize number of functions generated
3570 //printf("swap %s\n", EXPtoString(op).ptr);
3571 Expression tmp = e1;
3572 e1 = e2;
3573 e2 = tmp;
3575 return Lret(t);
3578 return null;
3581 /************************************
3582 * Bring leaves to common type.
3583 * Returns:
3584 * null on success, ErrorExp if error occurs
3586 Expression typeCombine(BinExp be, Scope* sc)
3588 Expression errorReturn()
3590 Expression ex = be.incompatibleTypes();
3591 if (ex.op == EXP.error)
3592 return ex;
3593 return ErrorExp.get();
3596 Type t1 = be.e1.type.toBasetype();
3597 Type t2 = be.e2.type.toBasetype();
3599 if (be.op == EXP.min || be.op == EXP.add)
3601 // struct+struct, and class+class are errors
3602 if (t1.ty == Tstruct && t2.ty == Tstruct)
3603 return errorReturn();
3604 else if (t1.ty == Tclass && t2.ty == Tclass)
3605 return errorReturn();
3606 else if (t1.ty == Taarray && t2.ty == Taarray)
3607 return errorReturn();
3610 if (auto result = typeMerge(sc, be.op, be.e1, be.e2))
3612 if (be.type is null)
3613 be.type = result;
3615 else
3616 return errorReturn();
3618 // If the types have no value, return an error
3619 if (be.e1.op == EXP.error)
3620 return be.e1;
3621 if (be.e2.op == EXP.error)
3622 return be.e2;
3623 return null;
3626 /***********************************
3627 * Do integral promotions (convertchk).
3628 * Don't convert <array of> to <pointer to>
3630 Expression integralPromotions(Expression e, Scope* sc)
3632 //printf("integralPromotions %s %s\n", e.toChars(), e.type.toChars());
3633 switch (e.type.toBasetype().ty)
3635 case Tvoid:
3636 error(e.loc, "void has no value");
3637 return ErrorExp.get();
3639 case Tint8:
3640 case Tuns8:
3641 case Tint16:
3642 case Tuns16:
3643 case Tbool:
3644 case Tchar:
3645 case Twchar:
3646 e = e.castTo(sc, Type.tint32);
3647 break;
3649 case Tdchar:
3650 e = e.castTo(sc, Type.tuns32);
3651 break;
3653 default:
3654 break;
3656 return e;
3659 /******************************************************
3660 * This provides a transition from the non-promoting behavior
3661 * of unary + - ~ to the C-like integral promotion behavior.
3662 * Params:
3663 * sc = context
3664 * ue = NegExp, UAddExp, or ComExp which is revised per rules
3665 * References:
3666 * https://issues.dlang.org/show_bug.cgi?id=16997
3669 void fix16997(Scope* sc, UnaExp ue)
3671 if (global.params.fix16997 || sc.flags & SCOPE.Cfile)
3672 ue.e1 = integralPromotions(ue.e1, sc); // desired C-like behavor
3673 else
3675 switch (ue.e1.type.toBasetype.ty)
3677 case Tint8:
3678 case Tuns8:
3679 case Tint16:
3680 case Tuns16:
3681 //case Tbool: // these operations aren't allowed on bool anyway
3682 case Tchar:
3683 case Twchar:
3684 case Tdchar:
3685 deprecation(ue.loc, "integral promotion not done for `%s`, remove '-revert=intpromote' switch or `%scast(int)(%s)`",
3686 ue.toChars(), EXPtoString(ue.op).ptr, ue.e1.toChars());
3687 break;
3689 default:
3690 break;
3695 /***********************************
3696 * See if both types are arrays that can be compared
3697 * for equality without any casting. Return true if so.
3698 * This is to enable comparing things like an immutable
3699 * array with a mutable one.
3701 extern (D) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
3703 t1 = t1.toBasetype();
3704 t2 = t2.toBasetype();
3706 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && t2.ty == t1.ty)
3708 if (t1.nextOf().implicitConvTo(t2.nextOf()) >= MATCH.constant || t2.nextOf().implicitConvTo(t1.nextOf()) >= MATCH.constant)
3709 return true;
3711 return false;
3714 /******************************************************************/
3715 /* Determine the integral ranges of an expression.
3716 * This is used to determine if implicit narrowing conversions will
3717 * be allowed.
3719 @trusted
3720 IntRange getIntRange(Expression e)
3722 IntRange visit(Expression e)
3724 return IntRange.fromType(e.type);
3727 IntRange visitInteger(IntegerExp e)
3729 return IntRange(SignExtendedNumber(e.getInteger()))._cast(e.type);
3732 IntRange visitCast(CastExp e)
3734 return getIntRange(e.e1)._cast(e.type);
3737 IntRange visitAdd(AddExp e)
3739 IntRange ir1 = getIntRange(e.e1);
3740 IntRange ir2 = getIntRange(e.e2);
3741 return (ir1 + ir2)._cast(e.type);
3744 IntRange visitMin(MinExp e)
3746 IntRange ir1 = getIntRange(e.e1);
3747 IntRange ir2 = getIntRange(e.e2);
3748 return (ir1 - ir2)._cast(e.type);
3751 IntRange visitDiv(DivExp e)
3753 IntRange ir1 = getIntRange(e.e1);
3754 IntRange ir2 = getIntRange(e.e2);
3756 return (ir1 / ir2)._cast(e.type);
3759 IntRange visitMul(MulExp e)
3761 IntRange ir1 = getIntRange(e.e1);
3762 IntRange ir2 = getIntRange(e.e2);
3764 return (ir1 * ir2)._cast(e.type);
3767 IntRange visitMod(ModExp e)
3769 IntRange ir1 = getIntRange(e.e1);
3770 IntRange ir2 = getIntRange(e.e2);
3772 // Modding on 0 is invalid anyway.
3773 if (!ir2.absNeg().imin.negative)
3775 return visit(e);
3777 return (ir1 % ir2)._cast(e.type);
3780 IntRange visitAnd(AndExp e)
3782 IntRange result;
3783 bool hasResult = false;
3784 result.unionOrAssign(getIntRange(e.e1) & getIntRange(e.e2), hasResult);
3786 assert(hasResult);
3787 return result._cast(e.type);
3790 IntRange visitOr(OrExp e)
3792 IntRange result;
3793 bool hasResult = false;
3794 result.unionOrAssign(getIntRange(e.e1) | getIntRange(e.e2), hasResult);
3796 assert(hasResult);
3797 return result._cast(e.type);
3800 IntRange visitXor(XorExp e)
3802 IntRange result;
3803 bool hasResult = false;
3804 result.unionOrAssign(getIntRange(e.e1) ^ getIntRange(e.e2), hasResult);
3806 assert(hasResult);
3807 return result._cast(e.type);
3810 IntRange visitShl(ShlExp e)
3812 IntRange ir1 = getIntRange(e.e1);
3813 IntRange ir2 = getIntRange(e.e2);
3815 return (ir1 << ir2)._cast(e.type);
3818 IntRange visitShr(ShrExp e)
3820 IntRange ir1 = getIntRange(e.e1);
3821 IntRange ir2 = getIntRange(e.e2);
3823 return (ir1 >> ir2)._cast(e.type);
3826 IntRange visitUshr(UshrExp e)
3828 IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type);
3829 IntRange ir2 = getIntRange(e.e2);
3831 return (ir1 >>> ir2)._cast(e.type);
3834 IntRange visitAssign(AssignExp e)
3836 return getIntRange(e.e2)._cast(e.type);
3839 IntRange visitCond(CondExp e)
3841 // No need to check e.econd; assume caller has called optimize()
3842 IntRange ir1 = getIntRange(e.e1);
3843 IntRange ir2 = getIntRange(e.e2);
3844 return ir1.unionWith(ir2)._cast(e.type);
3847 IntRange visitVar(VarExp e)
3849 Expression ie;
3850 VarDeclaration vd = e.var.isVarDeclaration();
3851 if (vd && vd.range)
3852 return vd.range._cast(e.type);
3853 else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
3854 return getIntRange(ie);
3855 else
3856 return visit(e);
3859 IntRange visitComma(CommaExp e)
3861 return getIntRange(e.e2);
3864 IntRange visitCom(ComExp e)
3866 IntRange ir = getIntRange(e.e1);
3867 return IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative), SignExtendedNumber(~ir.imin.value, !ir.imin.negative))._cast(e.type);
3870 IntRange visitNeg(NegExp e)
3872 IntRange ir = getIntRange(e.e1);
3873 return (-ir)._cast(e.type);
3876 switch (e.op)
3878 default : return visit(e);
3879 case EXP.int64 : return visitInteger(e.isIntegerExp());
3880 case EXP.cast_ : return visitCast(e.isCastExp());
3881 case EXP.add : return visitAdd(e.isAddExp());
3882 case EXP.min : return visitMin(e.isMinExp());
3883 case EXP.div : return visitDiv(e.isDivExp());
3884 case EXP.mul : return visitMul(e.isMulExp());
3885 case EXP.mod : return visitMod(e.isModExp());
3886 case EXP.and : return visitAnd(e.isAndExp());
3887 case EXP.or : return visitOr(e.isOrExp());
3888 case EXP.xor : return visitXor(e.isXorExp());
3889 case EXP.leftShift : return visitShl(e.isShlExp());
3890 case EXP.rightShift : return visitShr(e.isShrExp());
3891 case EXP.unsignedRightShift : return visitUshr(e.isUshrExp());
3892 case EXP.blit : return visitAssign(e.isBlitExp());
3893 case EXP.construct : return visitAssign(e.isConstructExp());
3894 case EXP.assign : return visitAssign(e.isAssignExp());
3895 case EXP.question : return visitCond(e.isCondExp());
3896 case EXP.variable : return visitVar(e.isVarExp());
3897 case EXP.comma : return visitComma(e.isCommaExp());
3898 case EXP.tilde : return visitCom(e.isComExp());
3899 case EXP.negate : return visitNeg(e.isNegExp());
3903 * A helper function to "cast" from expressions of type noreturn to
3904 * any other type - noreturn is implicitly convertible to any other type.
3905 * However, the dmd backend does not like a naive cast from a noreturn expression
3906 * (particularly an `assert(0)`) so this function generates:
3908 * `(assert(0), value)` instead of `cast(to)(assert(0))`.
3910 * `value` is currently `to.init` however it cannot be read so could be made simpler.
3911 * Params:
3912 * toBeCasted = Expression of type noreturn to cast
3913 * to = Type to cast the expression to.
3914 * Returns: A CommaExp, upon any failure ErrorExp will be returned.
3916 Expression specialNoreturnCast(Expression toBeCasted, Type to)
3918 return Expression.combine(toBeCasted, to.defaultInitLiteral(toBeCasted.loc));