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