1
/**
2
 * Semantic analysis for cast-expressions.
3
 *
4
 * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
5
 * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
6
 * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d)
8
 * Documentation:  https://dlang.org/phobos/dmd_dcast.html
9
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dcast.d
10
 */
11

12
module dmd.dcast;
13

14
import core.stdc.stdio;
15
import core.stdc.string;
16
import dmd.aggregate;
17
import dmd.aliasthis;
18
import dmd.arrayop;
19
import dmd.arraytypes;
20
import dmd.dclass;
21
import dmd.declaration;
22
import dmd.dscope;
23
import dmd.dstruct;
24
import dmd.dsymbol;
25
import dmd.errors;
26
import dmd.escape;
27
import dmd.expression;
28
import dmd.expressionsem;
29
import dmd.func;
30
import dmd.globals;
31
import dmd.impcnvtab;
32
import dmd.id;
33
import dmd.init;
34
import dmd.intrange;
35
import dmd.mtype;
36
import dmd.opover;
37
import dmd.root.ctfloat;
38
import dmd.root.outbuffer;
39
import dmd.root.rmem;
40
import dmd.tokens;
41
import dmd.typesem;
42
import dmd.utf;
43
import dmd.visitor;
44

45
enum LOG = false;
46

47
/**************************************
48
 * Do an implicit cast.
49
 * Issue error if it can't be done.
50
 */
51
Expression implicitCastTo(Expression e, Scope* sc, Type t)
52
{
53
    extern (C++) final class ImplicitCastTo : Visitor
54
    {
55
        alias visit = Visitor.visit;
56
    public:
57
        Type t;
58
        Scope* sc;
59
        Expression result;
60

61 1
        extern (D) this(Scope* sc, Type t)
62
        {
63 1
            this.sc = sc;
64 1
            this.t = t;
65
        }
66

67
        override void visit(Expression e)
68
        {
69
            //printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
70

71 1
            if (const match = e.implicitConvTo(t))
72
            {
73 1
                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 1
                    result = e.copy();
79 1
                    result.type = t;
80 1
                    return;
81
                }
82

83 1
                auto ad = isAggregate(e.type);
84 1
                if (ad && ad.aliasthis)
85
                {
86 1
                    auto ts = ad.type.isTypeStruct();
87 1
                    const adMatch = ts
88 1
                        ? ts.implicitConvToWithoutAliasThis(t)
89 1
                        : ad.type.isTypeClass().implicitConvToWithoutAliasThis(t);
90

91 1
                    if (!adMatch)
92
                    {
93 1
                        Type tob = t.toBasetype();
94 1
                        Type t1b = e.type.toBasetype();
95 1
                        if (ad != isAggregate(tob))
96
                        {
97 1
                            if (t1b.ty == Tclass && tob.ty == Tclass)
98
                            {
99 1
                                ClassDeclaration t1cd = t1b.isClassHandle();
100 1
                                ClassDeclaration tocd = tob.isClassHandle();
101 1
                                int offset;
102 1
                                if (tocd.isBaseOf(t1cd, &offset))
103
                                {
104 0
                                    result = new CastExp(e.loc, e, t);
105 0
                                    result.type = t;
106 0
                                    return;
107
                                }
108
                            }
109

110
                            /* Forward the cast to our alias this member, rewrite to:
111
                             *   cast(to)e1.aliasthis
112
                             */
113 1
                            result = resolveAliasThis(sc, e);
114 1
                            result = result.castTo(sc, t);
115 1
                            return;
116
                       }
117
                    }
118
                }
119

120 1
                result = e.castTo(sc, t);
121 1
                return;
122
            }
123

124 1
            result = e.optimize(WANTvalue);
125 1
            if (result != e)
126
            {
127 1
                result.accept(this);
128 1
                return;
129
            }
130

131 1
            if (t.ty != Terror && e.type.ty != Terror)
132
            {
133 1
                if (!t.deco)
134
                {
135 0
                    e.error("forward reference to type `%s`", t.toChars());
136
                }
137
                else
138
                {
139
                    //printf("type %p ty %d deco %p\n", type, type.ty, type.deco);
140
                    //type = type.typeSemantic(loc, sc);
141
                    //printf("type %s t %s\n", type.deco, t.deco);
142 1
                    auto ts = toAutoQualChars(e.type, t);
143 1
                    e.error("cannot implicitly convert expression `%s` of type `%s` to `%s`",
144
                        e.toChars(), ts[0], ts[1]);
145
                }
146
            }
147 1
            result = ErrorExp.get();
148
        }
149

150
        override void visit(StringExp e)
151
        {
152
            //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
153 1
            visit(cast(Expression)e);
154 1
            if (auto se = result.isStringExp())
155
            {
156
                // Retain polysemous nature if it started out that way
157 1
                se.committed = e.committed;
158
            }
159
        }
160

161
        override void visit(ErrorExp e)
162
        {
163 1
            result = e;
164
        }
165

166
        override void visit(FuncExp e)
167
        {
168
            //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
169 1
            FuncExp fe;
170 1
            if (e.matchType(t, sc, &fe) > MATCH.nomatch)
171
            {
172 1
                result = fe;
173 1
                return;
174
            }
175 1
            visit(cast(Expression)e);
176
        }
177

178
        override void visit(ArrayLiteralExp e)
179
        {
180 1
            visit(cast(Expression)e);
181

182 1
            Type tb = result.type.toBasetype();
183 1
            if (auto ta = tb.isTypeDArray())
184 1
                if (global.params.useTypeInfo && Type.dtypeinfo)
185 1
                    semanticTypeInfo(sc, ta.next);
186
        }
187

188
        override void visit(SliceExp e)
189
        {
190 1
            visit(cast(Expression)e);
191

192 1
            if (auto se = result.isSliceExp())
193 1
                if (auto ale = se.e1.isArrayLiteralExp())
194
                {
195 1
                    Type tb = t.toBasetype();
196 1
                    Type tx = (tb.ty == Tsarray)
197 1
                        ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.dim : 0)
198 1
                        : tb.nextOf().arrayOf();
199 1
                    se.e1 = ale.implicitCastTo(sc, tx);
200
                }
201
        }
202
    }
203

204 1
    scope ImplicitCastTo v = new ImplicitCastTo(sc, t);
205 1
    e.accept(v);
206 1
    return v.result;
207
}
208

209
/*******************************************
210
 * Return MATCH level of implicitly converting e to type t.
211
 * Don't do the actual cast; don't change e.
212
 */
213
MATCH implicitConvTo(Expression e, Type t)
214
{
215
    extern (C++) final class ImplicitConvTo : Visitor
216
    {
217
        alias visit = Visitor.visit;
218
    public:
219
        Type t;
220
        MATCH result;
221

222 1
        extern (D) this(Type t)
223
        {
224 1
            this.t = t;
225 1
            result = MATCH.nomatch;
226
        }
227

228
        override void visit(Expression e)
229
        {
230
            version (none)
231
            {
232
                printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
233
            }
234
            //static int nest; if (++nest == 10) assert(0);
235 1
            if (t == Type.terror)
236 1
                return;
237 1
            if (!e.type)
238
            {
239 0
                e.error("`%s` is not an expression", e.toChars());
240 0
                e.type = Type.terror;
241
            }
242

243 1
            Expression ex = e.optimize(WANTvalue);
244 1
            if (ex.type.equals(t))
245
            {
246 1
                result = MATCH.exact;
247 1
                return;
248
            }
249 1
            if (ex != e)
250
            {
251
                //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars());
252 1
                result = ex.implicitConvTo(t);
253 1
                return;
254
            }
255

256 1
            MATCH match = e.type.implicitConvTo(t);
257 1
            if (match != MATCH.nomatch)
258
            {
259 1
                result = match;
260 1
                return;
261
            }
262

263
            /* See if we can do integral narrowing conversions
264
             */
265 1
            if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic())
266
            {
267 1
                IntRange src = getIntRange(e);
268 1
                IntRange target = IntRange.fromType(t);
269 1
                if (target.contains(src))
270
                {
271 1
                    result = MATCH.convert;
272 1
                    return;
273
                }
274
            }
275
        }
276

277
        /******
278
         * Given expression e of type t, see if we can implicitly convert e
279
         * to type tprime, where tprime is type t with mod bits added.
280
         * Returns:
281
         *      match level
282
         */
283
        static MATCH implicitMod(Expression e, Type t, MOD mod)
284
        {
285 1
            Type tprime;
286 1
            if (t.ty == Tpointer)
287 1
                tprime = t.nextOf().castMod(mod).pointerTo();
288 1
            else if (t.ty == Tarray)
289 1
                tprime = t.nextOf().castMod(mod).arrayOf();
290 1
            else if (t.ty == Tsarray)
291 0
                tprime = t.nextOf().castMod(mod).sarrayOf(t.size() / t.nextOf().size());
292
            else
293 1
                tprime = t.castMod(mod);
294

295 1
            return e.implicitConvTo(tprime);
296
        }
297

298
        static MATCH implicitConvToAddMin(BinExp e, Type t)
299
        {
300
            /* Is this (ptr +- offset)? If so, then ask ptr
301
             * if the conversion can be done.
302
             * This is to support doing things like implicitly converting a mutable unique
303
             * pointer to an immutable pointer.
304
             */
305

306 1
            Type tb = t.toBasetype();
307 1
            Type typeb = e.type.toBasetype();
308

309 1
            if (typeb.ty != Tpointer || tb.ty != Tpointer)
310 1
                return MATCH.nomatch;
311

312 1
            Type t1b = e.e1.type.toBasetype();
313 1
            Type t2b = e.e2.type.toBasetype();
314 1
            if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb))
315
            {
316
                // ptr + offset
317
                // ptr - offset
318 1
                MATCH m = e.e1.implicitConvTo(t);
319 1
                return (m > MATCH.constant) ? MATCH.constant : m;
320
            }
321 1
            if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb))
322
            {
323
                // offset + ptr
324 0
                MATCH m = e.e2.implicitConvTo(t);
325 0
                return (m > MATCH.constant) ? MATCH.constant : m;
326
            }
327

328 1
            return MATCH.nomatch;
329
        }
330

331
        override void visit(AddExp e)
332
        {
333
            version (none)
334
            {
335
                printf("AddExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
336
            }
337 1
            visit(cast(Expression)e);
338 1
            if (result == MATCH.nomatch)
339 1
                result = implicitConvToAddMin(e, t);
340
        }
341

342
        override void visit(MinExp e)
343
        {
344
            version (none)
345
            {
346
                printf("MinExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
347
            }
348 1
            visit(cast(Expression)e);
349 1
            if (result == MATCH.nomatch)
350 1
                result = implicitConvToAddMin(e, t);
351
        }
352

353
        override void visit(IntegerExp e)
354
        {
355
            version (none)
356
            {
357
                printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
358
            }
359 1
            MATCH m = e.type.implicitConvTo(t);
360 1
            if (m >= MATCH.constant)
361
            {
362 1
                result = m;
363 1
                return;
364
            }
365

366 1
            TY ty = e.type.toBasetype().ty;
367 1
            TY toty = t.toBasetype().ty;
368 1
            TY oldty = ty;
369

370 1
            if (m == MATCH.nomatch && t.ty == Tenum)
371 1
                return;
372

373 1
            if (auto tv = t.isTypeVector())
374
            {
375 1
                TypeBasic tb = tv.elementType();
376 1
                if (tb.ty == Tvoid)
377 1
                    return;
378 1
                toty = tb.ty;
379
            }
380

381 1
            switch (ty)
382
            {
383 1
            case Tbool:
384 1
            case Tint8:
385 1
            case Tchar:
386 1
            case Tuns8:
387 1
            case Tint16:
388 1
            case Tuns16:
389 1
            case Twchar:
390 1
                ty = Tint32;
391 1
                break;
392

393 1
            case Tdchar:
394 1
                ty = Tuns32;
395 1
                break;
396

397 1
            default:
398 1
                break;
399
            }
400

401
            // Only allow conversion if no change in value
402 1
            immutable dinteger_t value = e.toInteger();
403

404
            bool isLosslesslyConvertibleToFP(T)()
405
            {
406 1
                if (e.type.isunsigned())
407
                {
408 1
                    const f = cast(T) value;
409 1
                    return cast(dinteger_t) f == value;
410
                }
411

412 1
                const f = cast(T) cast(sinteger_t) value;
413 1
                return cast(sinteger_t) f == cast(sinteger_t) value;
414
            }
415

416 1
            switch (toty)
417
            {
418 1
            case Tbool:
419 1
                if ((value & 1) != value)
420 1
                    return;
421 1
                break;
422

423 1
            case Tint8:
424 1
                if (ty == Tuns64 && value & ~0x7FU)
425 1
                    return;
426 1
                else if (cast(byte)value != value)
427 1
                    return;
428 1
                break;
429

430 1
            case Tchar:
431 1
                if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
432 0
                    return;
433 1
                goto case Tuns8;
434 1
            case Tuns8:
435
                //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
436 1
                if (cast(ubyte)value != value)
437 1
                    return;
438 1
                break;
439

440 1
            case Tint16:
441 1
                if (ty == Tuns64 && value & ~0x7FFFU)
442 1
                    return;
443 1
                else if (cast(short)value != value)
444 1
                    return;
445 1
                break;
446

447 1
            case Twchar:
448 1
                if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
449 0
                    return;
450 1
                goto case Tuns16;
451 1
            case Tuns16:
452 1
                if (cast(ushort)value != value)
453 1
                    return;
454 1
                break;
455

456 1
            case Tint32:
457 1
                if (ty == Tuns32)
458
                {
459
                }
460 1
                else if (ty == Tuns64 && value & ~0x7FFFFFFFU)
461 1
                    return;
462 1
                else if (cast(int)value != value)
463 1
                    return;
464 1
                break;
465

466 1
            case Tuns32:
467 1
                if (ty == Tint32)
468
                {
469
                }
470 1
                else if (cast(uint)value != value)
471 1
                    return;
472 1
                break;
473

474 1
            case Tdchar:
475 1
                if (value > 0x10FFFFU)
476 1
                    return;
477 1
                break;
478

479 1
            case Tfloat32:
480 1
                if (!isLosslesslyConvertibleToFP!float)
481 0
                    return;
482 1
                break;
483

484 1
            case Tfloat64:
485 1
                if (!isLosslesslyConvertibleToFP!double)
486 0
                    return;
487 1
                break;
488

489 1
            case Tfloat80:
490 1
                if (!isLosslesslyConvertibleToFP!real_t)
491 0
                    return;
492 1
                break;
493

494 1
            case Tpointer:
495
                //printf("type = %s\n", type.toBasetype()->toChars());
496
                //printf("t = %s\n", t.toBasetype()->toChars());
497 1
                if (ty == Tpointer && e.type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty)
498
                {
499
                    /* Allow things like:
500
                     *      const char* P = cast(char *)3;
501
                     *      char* q = P;
502
                     */
503 1
                    break;
504
                }
505 1
                goto default;
506

507 1
            default:
508 1
                visit(cast(Expression)e);
509 1
                return;
510
            }
511

512
            //printf("MATCH.convert\n");
513 1
            result = MATCH.convert;
514
        }
515

516
        override void visit(ErrorExp e)
517
        {
518
            // no match
519
        }
520

521
        override void visit(NullExp e)
522
        {
523
            version (none)
524
            {
525
                printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n", e.toChars(), e.type.toChars(), t.toChars(), e.committed);
526
            }
527 1
            if (e.type.equals(t))
528
            {
529 1
                result = MATCH.exact;
530 1
                return;
531
            }
532

533
            /* Allow implicit conversions from immutable to mutable|const,
534
             * and mutable to immutable. It works because, after all, a null
535
             * doesn't actually point to anything.
536
             */
537 1
            if (t.equivalent(e.type))
538
            {
539 1
                result = MATCH.constant;
540 1
                return;
541
            }
542

543 1
            visit(cast(Expression)e);
544
        }
545

546
        override void visit(StructLiteralExp e)
547
        {
548
            version (none)
549
            {
550
                printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
551
            }
552 1
            visit(cast(Expression)e);
553 1
            if (result != MATCH.nomatch)
554 1
                return;
555 1
            if (e.type.ty == t.ty && e.type.ty == Tstruct && (cast(TypeStruct)e.type).sym == (cast(TypeStruct)t).sym)
556
            {
557 1
                result = MATCH.constant;
558 1
                foreach (i, el; (*e.elements)[])
559
                {
560 1
                    if (!el)
561 0
                        continue;
562 1
                    Type te = e.sd.fields[i].type.addMod(t.mod);
563 1
                    MATCH m2 = el.implicitConvTo(te);
564
                    //printf("\t%s => %s, match = %d\n", el.toChars(), te.toChars(), m2);
565 1
                    if (m2 < result)
566 1
                        result = m2;
567
                }
568
            }
569
        }
570

571
        override void visit(StringExp e)
572
        {
573
            version (none)
574
            {
575
                printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", e.toChars(), e.committed, e.type.toChars(), t.toChars());
576
            }
577 1
            if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
578 1
                return;
579

580 1
            if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
581 1
                return visit(cast(Expression)e);
582

583 1
            TY tyn = e.type.nextOf().ty;
584

585 1
            if (!tyn.isSomeChar)
586 1
                return visit(cast(Expression)e);
587

588 1
            switch (t.ty)
589
            {
590 1
            case Tsarray:
591 1
                if (e.type.ty == Tsarray)
592
                {
593 1
                    TY tynto = t.nextOf().ty;
594 1
                    if (tynto == tyn)
595
                    {
596 1
                        if ((cast(TypeSArray)e.type).dim.toInteger() == (cast(TypeSArray)t).dim.toInteger())
597
                        {
598 1
                            result = MATCH.exact;
599
                        }
600 1
                        return;
601
                    }
602 1
                    if (tynto.isSomeChar)
603
                    {
604 0
                        if (e.committed && tynto != tyn)
605 0
                            return;
606 0
                        size_t fromlen = e.numberOfCodeUnits(tynto);
607 0
                        size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger();
608 0
                        if (tolen < fromlen)
609 0
                            return;
610 0
                        if (tolen != fromlen)
611
                        {
612
                            // implicit length extending
613 0
                            result = MATCH.convert;
614 0
                            return;
615
                        }
616
                    }
617 1
                    if (!e.committed && tynto.isSomeChar)
618
                    {
619 0
                        result = MATCH.exact;
620 0
                        return;
621
                    }
622
                }
623 1
                else if (e.type.ty == Tarray)
624
                {
625 1
                    TY tynto = t.nextOf().ty;
626 1
                    if (tynto.isSomeChar)
627
                    {
628 1
                        if (e.committed && tynto != tyn)
629 1
                            return;
630 1
                        size_t fromlen = e.numberOfCodeUnits(tynto);
631 1
                        size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger();
632 1
                        if (tolen < fromlen)
633 1
                            return;
634 1
                        if (tolen != fromlen)
635
                        {
636
                            // implicit length extending
637 1
                            result = MATCH.convert;
638 1
                            return;
639
                        }
640
                    }
641 1
                    if (tynto == tyn)
642
                    {
643 1
                        result = MATCH.exact;
644 1
                        return;
645
                    }
646 1
                    if (!e.committed && tynto.isSomeChar)
647
                    {
648 1
                        result = MATCH.exact;
649 1
                        return;
650
                    }
651
                }
652 1
                goto case; /+ fall through +/
653 1
            case Tarray:
654 1
            case Tpointer:
655 1
                Type tn = t.nextOf();
656 1
                MATCH m = MATCH.exact;
657 1
                if (e.type.nextOf().mod != tn.mod)
658
                {
659
                    // https://issues.dlang.org/show_bug.cgi?id=16183
660 1
                    if (!tn.isConst() && !tn.isImmutable())
661 1
                        return;
662 1
                    m = MATCH.constant;
663
                }
664 1
                if (!e.committed)
665
                {
666 1
                    switch (tn.ty)
667
                    {
668 1
                    case Tchar:
669 1
                        if (e.postfix == 'w' || e.postfix == 'd')
670 0
                            m = MATCH.convert;
671 1
                        result = m;
672 1
                        return;
673 1
                    case Twchar:
674 1
                        if (e.postfix != 'w')
675 1
                            m = MATCH.convert;
676 1
                        result = m;
677 1
                        return;
678 1
                    case Tdchar:
679 1
                        if (e.postfix != 'd')
680 1
                            m = MATCH.convert;
681 1
                        result = m;
682 1
                        return;
683 1
                    case Tenum:
684 1
                        if ((cast(TypeEnum)tn).sym.isSpecial())
685
                        {
686
                            /* Allow string literal -> const(wchar_t)[]
687
                             */
688 1
                            if (TypeBasic tob = tn.toBasetype().isTypeBasic())
689 1
                            result = tn.implicitConvTo(tob);
690 1
                            return;
691
                        }
692 0
                        break;
693 1
                    default:
694 1
                        break;
695
                    }
696
                }
697 1
                break;
698

699 1
            default:
700 1
                break;
701
            }
702

703 1
            visit(cast(Expression)e);
704
        }
705

706
        override void visit(ArrayLiteralExp e)
707
        {
708
            version (none)
709
            {
710
                printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
711
            }
712 1
            Type tb = t.toBasetype();
713 1
            Type typeb = e.type.toBasetype();
714

715 1
            if ((tb.ty == Tarray || tb.ty == Tsarray) &&
716 1
                (typeb.ty == Tarray || typeb.ty == Tsarray))
717
            {
718 1
                result = MATCH.exact;
719 1
                Type typen = typeb.nextOf().toBasetype();
720

721 1
                if (auto tsa = tb.isTypeSArray())
722
                {
723 1
                    if (e.elements.dim != tsa.dim.toInteger())
724 1
                        result = MATCH.nomatch;
725
                }
726

727 1
                Type telement = tb.nextOf();
728 1
                if (!e.elements.dim)
729
                {
730 1
                    if (typen.ty != Tvoid)
731 1
                        result = typen.implicitConvTo(telement);
732
                }
733
                else
734
                {
735 1
                    if (e.basis)
736
                    {
737 1
                        MATCH m = e.basis.implicitConvTo(telement);
738 1
                        if (m < result)
739 1
                            result = m;
740
                    }
741 1
                    for (size_t i = 0; i < e.elements.dim; i++)
742
                    {
743 1
                        Expression el = (*e.elements)[i];
744 1
                        if (result == MATCH.nomatch)
745 1
                            break;
746 1
                        if (!el)
747 1
                            continue;
748 1
                        MATCH m = el.implicitConvTo(telement);
749 1
                        if (m < result)
750 1
                            result = m; // remember worst match
751
                    }
752
                }
753

754 1
                if (!result)
755 1
                    result = e.type.implicitConvTo(t);
756

757 1
                return;
758
            }
759 1
            else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
760
            {
761 1
                result = MATCH.exact;
762
                // Convert array literal to vector type
763 1
                TypeVector tv = tb.isTypeVector();
764 1
                TypeSArray tbase = tv.basetype.isTypeSArray();
765 1
                assert(tbase);
766 1
                const edim = e.elements.dim;
767 1
                const tbasedim = tbase.dim.toInteger();
768 1
                if (edim > tbasedim)
769
                {
770 0
                    result = MATCH.nomatch;
771 0
                    return;
772
                }
773

774 1
                Type telement = tv.elementType();
775 1
                if (edim < tbasedim)
776
                {
777 1
                    Expression el = typeb.nextOf.defaultInitLiteral(e.loc);
778 1
                    MATCH m = el.implicitConvTo(telement);
779 1
                    if (m < result)
780 1
                        result = m; // remember worst match
781
                }
782 1
                foreach (el; (*e.elements)[])
783
                {
784 1
                    MATCH m = el.implicitConvTo(telement);
785 1
                    if (m < result)
786 1
                        result = m; // remember worst match
787 1
                    if (result == MATCH.nomatch)
788 0
                        break; // no need to check for worse
789
                }
790 1
                return;
791
            }
792

793 1
            visit(cast(Expression)e);
794
        }
795

796
        override void visit(AssocArrayLiteralExp e)
797
        {
798 1
            auto taa = t.toBasetype().isTypeAArray();
799 1
            Type typeb = e.type.toBasetype();
800

801 1
            if (!(taa && typeb.ty == Taarray))
802 1
                return visit(cast(Expression)e);
803

804 1
            result = MATCH.exact;
805 1
            foreach (i, el; (*e.keys)[])
806
            {
807 1
                MATCH m = el.implicitConvTo(taa.index);
808 1
                if (m < result)
809 1
                    result = m; // remember worst match
810 1
                if (result == MATCH.nomatch)
811 0
                    break; // no need to check for worse
812 1
                el = (*e.values)[i];
813 1
                m = el.implicitConvTo(taa.nextOf());
814 1
                if (m < result)
815 1
                    result = m; // remember worst match
816 1
                if (result == MATCH.nomatch)
817 0
                    break; // no need to check for worse
818
            }
819
        }
820

821
        override void visit(CallExp e)
822
        {
823
            enum LOG = false;
824
            static if (LOG)
825
            {
826
                printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
827
            }
828

829 1
            visit(cast(Expression)e);
830 1
            if (result != MATCH.nomatch)
831 1
                return;
832

833
            /* Allow the result of strongly pure functions to
834
             * convert to immutable
835
             */
836 1
            if (e.f && e.f.isReturnIsolated() &&
837 1
                (!global.params.vsafe ||        // lots of legacy code breaks with the following purity check
838 1
                 e.f.isPure() >= PURE.strong ||
839
                 // Special case exemption for Object.dup() which we assume is implemented correctly
840 1
                 e.f.ident == Id.dup &&
841 0
                 e.f.toParent2() == ClassDeclaration.object.toParent())
842
               )
843
            {
844 1
                result = e.type.immutableOf().implicitConvTo(t);
845 1
                if (result > MATCH.constant) // Match level is MATCH.constant at best.
846 1
                    result = MATCH.constant;
847 1
                return;
848
            }
849

850
            /* Conversion is 'const' conversion if:
851
             * 1. function is pure (weakly pure is ok)
852
             * 2. implicit conversion only fails because of mod bits
853
             * 3. each function parameter can be implicitly converted to the mod bits
854
             */
855 1
            auto tf = (e.f ? e.f.type : e.e1.type).toBasetype().isTypeFunction();
856 1
            if (!tf)
857 0
                return;
858

859 1
            if (tf.purity == PURE.impure)
860 1
                return;
861 1
            if (e.f && e.f.isNested())
862 1
                return;
863

864
            /* See if fail only because of mod bits.
865
             *
866
             * https://issues.dlang.org/show_bug.cgi?id=14155
867
             * All pure functions can access global immutable data.
868
             * So the returned pointer may refer an immutable global data,
869
             * and then the returned pointer that points non-mutable object
870
             * cannot be unique pointer.
871
             *
872
             * Example:
873
             *  immutable g;
874
             *  static this() { g = 1; }
875
             *  const(int*) foo() pure { return &g; }
876
             *  void test() {
877
             *    immutable(int*) ip = foo(); // OK
878
             *    int* mp = foo();            // should be disallowed
879
             *  }
880
             */
881 1
            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)
882
            {
883 1
                return;
884
            }
885
            // Allow a conversion to immutable type, or
886
            // conversions of mutable types between thread-local and shared.
887

888
            /* Get mod bits of what we're converting to
889
             */
890 1
            Type tb = t.toBasetype();
891 1
            MOD mod = tb.mod;
892 1
            if (tf.isref)
893
            {
894
            }
895
            else
896
            {
897 1
                if (Type ti = getIndirection(t))
898 1
                    mod = ti.mod;
899
            }
900
            static if (LOG)
901
            {
902
                printf("mod = x%x\n", mod);
903
            }
904 1
            if (mod & MODFlags.wild)
905 0
                return; // not sure what to do with this
906

907
            /* Apply mod bits to each function parameter,
908
             * and see if we can convert the function argument to the modded type
909
             */
910

911 1
            size_t nparams = tf.parameterList.length;
912 1
            size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
913 1
            if (auto dve = e.e1.isDotVarExp())
914
            {
915
                /* Treat 'this' as just another function argument
916
                 */
917 1
                Type targ = dve.e1.type;
918 1
                if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
919 1
                    return;
920
            }
921 1
            foreach (const i; j .. e.arguments.dim)
922
            {
923 1
                Expression earg = (*e.arguments)[i];
924 1
                Type targ = earg.type.toBasetype();
925
                static if (LOG)
926
                {
927
                    printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
928
                }
929 1
                if (i - j < nparams)
930
                {
931 1
                    Parameter fparam = tf.parameterList[i - j];
932 1
                    if (fparam.storageClass & STC.lazy_)
933 0
                        return; // not sure what to do with this
934 1
                    Type tparam = fparam.type;
935 1
                    if (!tparam)
936 0
                        continue;
937 1
                    if (fparam.isReference())
938
                    {
939 1
                        if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
940 1
                            return;
941 0
                        continue;
942
                    }
943
                }
944
                static if (LOG)
945
                {
946
                    printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
947
                }
948 1
                if (implicitMod(earg, targ, mod) == MATCH.nomatch)
949 1
                    return;
950
            }
951

952
            /* Success
953
             */
954 1
            result = MATCH.constant;
955
        }
956

957
        override void visit(AddrExp e)
958
        {
959
            version (none)
960
            {
961
                printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
962
            }
963 1
            result = e.type.implicitConvTo(t);
964
            //printf("\tresult = %d\n", result);
965

966 1
            if (result != MATCH.nomatch)
967 1
                return;
968

969 1
            Type tb = t.toBasetype();
970 1
            Type typeb = e.type.toBasetype();
971

972
            // Look for pointers to functions where the functions are overloaded.
973 1
            if (e.e1.op == TOK.overloadSet &&
974 1
                (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
975
            {
976 1
                OverExp eo = e.e1.isOverExp();
977 1
                FuncDeclaration f = null;
978 1
                foreach (s; eo.vars.a[])
979
                {
980 1
                    FuncDeclaration f2 = s.isFuncDeclaration();
981 1
                    assert(f2);
982 1
                    if (f2.overloadExactMatch(tb.nextOf()))
983
                    {
984 1
                        if (f)
985
                        {
986
                            /* Error if match in more than one overload set,
987
                             * even if one is a 'better' match than the other.
988
                             */
989 0
                            ScopeDsymbol.multiplyDefined(e.loc, f, f2);
990
                        }
991
                        else
992 1
                            f = f2;
993 1
                        result = MATCH.exact;
994
                    }
995
                }
996
            }
997

998 1
            if (e.e1.op == TOK.variable &&
999 1
                typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
1000 0
                tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
1001
            {
1002
                /* I don't think this can ever happen -
1003
                 * it should have been
1004
                 * converted to a SymOffExp.
1005
                 */
1006 0
                assert(0);
1007
            }
1008

1009
            //printf("\tresult = %d\n", result);
1010
        }
1011

1012
        override void visit(SymOffExp e)
1013
        {
1014
            version (none)
1015
            {
1016
                printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1017
            }
1018 1
            result = e.type.implicitConvTo(t);
1019
            //printf("\tresult = %d\n", result);
1020 1
            if (result != MATCH.nomatch)
1021 1
                return;
1022

1023 1
            Type tb = t.toBasetype();
1024 1
            Type typeb = e.type.toBasetype();
1025

1026
            // Look for pointers to functions where the functions are overloaded.
1027 1
            if (typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
1028 1
                (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
1029
            {
1030 1
                if (FuncDeclaration f = e.var.isFuncDeclaration())
1031
                {
1032 1
                    f = f.overloadExactMatch(tb.nextOf());
1033 1
                    if (f)
1034
                    {
1035 1
                        if ((tb.ty == Tdelegate && (f.needThis() || f.isNested())) ||
1036 1
                            (tb.ty == Tpointer && !(f.needThis() || f.isNested())))
1037
                        {
1038 1
                            result = MATCH.exact;
1039
                        }
1040
                    }
1041
                }
1042
            }
1043
            //printf("\tresult = %d\n", result);
1044
        }
1045

1046
        override void visit(DelegateExp e)
1047
        {
1048
            version (none)
1049
            {
1050
                printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1051
            }
1052 1
            result = e.type.implicitConvTo(t);
1053 1
            if (result != MATCH.nomatch)
1054 1
                return;
1055

1056 1
            Type tb = t.toBasetype();
1057 1
            Type typeb = e.type.toBasetype();
1058

1059
            // Look for pointers to functions where the functions are overloaded.
1060 1
            if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
1061
            {
1062 1
                if (e.func && e.func.overloadExactMatch(tb.nextOf()))
1063 1
                    result = MATCH.exact;
1064
            }
1065
        }
1066

1067
        override void visit(FuncExp e)
1068
        {
1069
            //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
1070 1
            MATCH m = e.matchType(t, null, null, 1);
1071 1
            if (m > MATCH.nomatch)
1072
            {
1073 1
                result = m;
1074 1
                return;
1075
            }
1076 1
            visit(cast(Expression)e);
1077
        }
1078

1079
        override void visit(AndExp e)
1080
        {
1081 1
            visit(cast(Expression)e);
1082 1
            if (result != MATCH.nomatch)
1083 1
                return;
1084

1085 1
            MATCH m1 = e.e1.implicitConvTo(t);
1086 1
            MATCH m2 = e.e2.implicitConvTo(t);
1087

1088
            // Pick the worst match
1089 1
            result = (m1 < m2) ? m1 : m2;
1090
        }
1091

1092
        override void visit(OrExp e)
1093
        {
1094 1
            visit(cast(Expression)e);
1095 1
            if (result != MATCH.nomatch)
1096 1
                return;
1097

1098 1
            MATCH m1 = e.e1.implicitConvTo(t);
1099 1
            MATCH m2 = e.e2.implicitConvTo(t);
1100

1101
            // Pick the worst match
1102 1
            result = (m1 < m2) ? m1 : m2;
1103
        }
1104

1105
        override void visit(XorExp e)
1106
        {
1107 1
            visit(cast(Expression)e);
1108 1
            if (result != MATCH.nomatch)
1109 1
                return;
1110

1111 1
            MATCH m1 = e.e1.implicitConvTo(t);
1112 1
            MATCH m2 = e.e2.implicitConvTo(t);
1113

1114
            // Pick the worst match
1115 1
            result = (m1 < m2) ? m1 : m2;
1116
        }
1117

1118
        override void visit(CondExp e)
1119
        {
1120 1
            MATCH m1 = e.e1.implicitConvTo(t);
1121 1
            MATCH m2 = e.e2.implicitConvTo(t);
1122
            //printf("CondExp: m1 %d m2 %d\n", m1, m2);
1123

1124
            // Pick the worst match
1125 1
            result = (m1 < m2) ? m1 : m2;
1126
        }
1127

1128
        override void visit(CommaExp e)
1129
        {
1130 1
            e.e2.accept(this);
1131
        }
1132

1133
        override void visit(CastExp e)
1134
        {
1135
            version (none)
1136
            {
1137
                printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1138
            }
1139 1
            result = e.type.implicitConvTo(t);
1140 1
            if (result != MATCH.nomatch)
1141 1
                return;
1142

1143 1
            if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
1144 1
                result = MATCH.convert;
1145
            else
1146 1
                visit(cast(Expression)e);
1147
        }
1148

1149
        override void visit(NewExp e)
1150
        {
1151
            version (none)
1152
            {
1153
                printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1154
            }
1155 1
            visit(cast(Expression)e);
1156 1
            if (result != MATCH.nomatch)
1157 1
                return;
1158

1159
            /* Calling new() is like calling a pure function. We can implicitly convert the
1160
             * return from new() to t using the same algorithm as in CallExp, with the function
1161
             * 'arguments' being:
1162
             *    thisexp
1163
             *    newargs
1164
             *    arguments
1165
             *    .init
1166
             * 'member' and 'allocator' need to be pure.
1167
             */
1168

1169
            /* See if fail only because of mod bits
1170
             */
1171 1
            if (e.type.immutableOf().implicitConvTo(t.immutableOf()) == MATCH.nomatch)
1172 1
                return;
1173

1174
            /* Get mod bits of what we're converting to
1175
             */
1176 1
            Type tb = t.toBasetype();
1177 1
            MOD mod = tb.mod;
1178 1
            if (Type ti = getIndirection(t))
1179 1
                mod = ti.mod;
1180
            static if (LOG)
1181
            {
1182
                printf("mod = x%x\n", mod);
1183
            }
1184 1
            if (mod & MODFlags.wild)
1185 1
                return; // not sure what to do with this
1186

1187
            /* Apply mod bits to each argument,
1188
             * and see if we can convert the argument to the modded type
1189
             */
1190

1191 1
            if (e.thisexp)
1192
            {
1193
                /* Treat 'this' as just another function argument
1194
                 */
1195 0
                Type targ = e.thisexp.type;
1196 0
                if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
1197 0
                    return;
1198
            }
1199

1200
            /* Check call to 'allocator', then 'member'
1201
             */
1202 1
            FuncDeclaration fd = e.allocator;
1203 1
            for (int count = 0; count < 2; ++count, (fd = e.member))
1204
            {
1205 1
                if (!fd)
1206 1
                    continue;
1207 1
                if (fd.errors || fd.type.ty != Tfunction)
1208 0
                    return; // error
1209 1
                TypeFunction tf = cast(TypeFunction)fd.type;
1210 1
                if (tf.purity == PURE.impure)
1211 1
                    return; // impure
1212

1213 1
                if (fd == e.member)
1214
                {
1215 1
                    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)
1216
                    {
1217 1
                        return;
1218
                    }
1219
                    // Allow a conversion to immutable type, or
1220
                    // conversions of mutable types between thread-local and shared.
1221
                }
1222

1223 1
                Expressions* args = (fd == e.allocator) ? e.newargs : e.arguments;
1224

1225 1
                size_t nparams = tf.parameterList.length;
1226
                // if TypeInfoArray was prepended
1227 1
                size_t j = tf.isDstyleVariadic();
1228 1
                for (size_t i = j; i < e.arguments.dim; ++i)
1229
                {
1230 1
                    Expression earg = (*args)[i];
1231 1
                    Type targ = earg.type.toBasetype();
1232
                    static if (LOG)
1233
                    {
1234
                        printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
1235
                    }
1236 1
                    if (i - j < nparams)
1237
                    {
1238 1
                        Parameter fparam = tf.parameterList[i - j];
1239 1
                        if (fparam.storageClass & STC.lazy_)
1240 0
                            return; // not sure what to do with this
1241 1
                        Type tparam = fparam.type;
1242 1
                        if (!tparam)
1243 0
                            continue;
1244 1
                        if (fparam.isReference())
1245
                        {
1246 0
                            if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
1247 0
                                return;
1248 0
                            continue;
1249
                        }
1250
                    }
1251
                    static if (LOG)
1252
                    {
1253
                        printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
1254
                    }
1255 1
                    if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1256 1
                        return;
1257
                }
1258
            }
1259

1260
            /* If no 'member', then construction is by simple assignment,
1261
             * and just straight check 'arguments'
1262
             */
1263 1
            if (!e.member && e.arguments)
1264
            {
1265 1
                for (size_t i = 0; i < e.arguments.dim; ++i)
1266
                {
1267 1
                    Expression earg = (*e.arguments)[i];
1268 1
                    if (!earg) // https://issues.dlang.org/show_bug.cgi?id=14853
1269
                               // if it's on overlapped field
1270 1
                        continue;
1271 1
                    Type targ = earg.type.toBasetype();
1272
                    static if (LOG)
1273
                    {
1274
                        printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
1275
                        printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
1276
                    }
1277 1
                    if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1278 1
                        return;
1279
                }
1280
            }
1281

1282
            /* Consider the .init expression as an argument
1283
             */
1284 1
            Type ntb = e.newtype.toBasetype();
1285 1
            if (ntb.ty == Tarray)
1286 1
                ntb = ntb.nextOf().toBasetype();
1287 1
            if (ntb.ty == Tstruct)
1288
            {
1289
                // Don't allow nested structs - uplevel reference may not be convertible
1290 1
                StructDeclaration sd = (cast(TypeStruct)ntb).sym;
1291 1
                sd.size(e.loc); // resolve any forward references
1292 1
                if (sd.isNested())
1293 1
                    return;
1294
            }
1295 1
            if (ntb.isZeroInit(e.loc))
1296
            {
1297
                /* Zeros are implicitly convertible, except for special cases.
1298
                 */
1299 1
                if (ntb.ty == Tclass)
1300
                {
1301
                    /* With new() must look at the class instance initializer.
1302
                     */
1303 1
                    ClassDeclaration cd = (cast(TypeClass)ntb).sym;
1304

1305 1
                    cd.size(e.loc); // resolve any forward references
1306

1307 1
                    if (cd.isNested())
1308 1
                        return; // uplevel reference may not be convertible
1309

1310 1
                    assert(!cd.isInterfaceDeclaration());
1311

1312
                    struct ClassCheck
1313
                    {
1314
                        extern (C++) static bool convertible(Loc loc, ClassDeclaration cd, MOD mod)
1315
                        {
1316 1
                            for (size_t i = 0; i < cd.fields.dim; i++)
1317
                            {
1318 1
                                VarDeclaration v = cd.fields[i];
1319 1
                                Initializer _init = v._init;
1320 1
                                if (_init)
1321
                                {
1322 1
                                    if (_init.isVoidInitializer())
1323
                                    {
1324
                                    }
1325 1
                                    else if (ExpInitializer ei = _init.isExpInitializer())
1326
                                    {
1327 1
                                        Type tb = v.type.toBasetype();
1328 1
                                        if (implicitMod(ei.exp, tb, mod) == MATCH.nomatch)
1329 1
                                            return false;
1330
                                    }
1331
                                    else
1332
                                    {
1333
                                        /* Enhancement: handle StructInitializer and ArrayInitializer
1334
                                         */
1335 1
                                        return false;
1336
                                    }
1337
                                }
1338 1
                                else if (!v.type.isZeroInit(loc))
1339 0
                                    return false;
1340
                            }
1341 1
                            return cd.baseClass ? convertible(loc, cd.baseClass, mod) : true;
1342
                        }
1343
                    }
1344

1345 1
                    if (!ClassCheck.convertible(e.loc, cd, mod))
1346 1
                        return;
1347
                }
1348
            }
1349
            else
1350
            {
1351 0
                Expression earg = e.newtype.defaultInitLiteral(e.loc);
1352 0
                Type targ = e.newtype.toBasetype();
1353

1354 0
                if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1355 0
                    return;
1356
            }
1357

1358
            /* Success
1359
             */
1360 1
            result = MATCH.constant;
1361
        }
1362

1363
        override void visit(SliceExp e)
1364
        {
1365
            //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e.toChars(), e.type.toChars());
1366 1
            visit(cast(Expression)e);
1367 1
            if (result != MATCH.nomatch)
1368 1
                return;
1369

1370 1
            Type tb = t.toBasetype();
1371 1
            Type typeb = e.type.toBasetype();
1372

1373 1
            if (tb.ty == Tsarray && typeb.ty == Tarray)
1374
            {
1375 1
                typeb = toStaticArrayType(e);
1376 1
                if (typeb)
1377 1
                    result = typeb.implicitConvTo(t);
1378 1
                return;
1379
            }
1380

1381
            /* If the only reason it won't convert is because of the mod bits,
1382
             * then test for conversion by seeing if e1 can be converted with those
1383
             * same mod bits.
1384
             */
1385 1
            Type t1b = e.e1.type.toBasetype();
1386 1
            if (tb.ty == Tarray && typeb.equivalent(tb))
1387
            {
1388 1
                Type tbn = tb.nextOf();
1389 1
                Type tx = null;
1390

1391
                /* If e.e1 is dynamic array or pointer, the uniqueness of e.e1
1392
                 * is equivalent with the uniqueness of the referred data. And in here
1393
                 * we can have arbitrary typed reference for that.
1394
                 */
1395 1
                if (t1b.ty == Tarray)
1396 1
                    tx = tbn.arrayOf();
1397 1
                if (t1b.ty == Tpointer)
1398 1
                    tx = tbn.pointerTo();
1399

1400
                /* If e.e1 is static array, at least it should be an rvalue.
1401
                 * If not, e.e1 is a reference, and its uniqueness does not link
1402
                 * to the uniqueness of the referred data.
1403
                 */
1404 1
                if (t1b.ty == Tsarray && !e.e1.isLvalue())
1405 1
                    tx = tbn.sarrayOf(t1b.size() / tbn.size());
1406

1407 1
                if (tx)
1408
                {
1409 1
                    result = e.e1.implicitConvTo(tx);
1410 1
                    if (result > MATCH.constant) // Match level is MATCH.constant at best.
1411 0
                        result = MATCH.constant;
1412
                }
1413
            }
1414

1415
            // Enhancement 10724
1416 1
            if (tb.ty == Tpointer && e.e1.op == TOK.string_)
1417 1
                e.e1.accept(this);
1418
        }
1419
    }
1420

1421 1
    scope ImplicitConvTo v = new ImplicitConvTo(t);
1422 1
    e.accept(v);
1423 1
    return v.result;
1424
}
1425

1426
Type toStaticArrayType(SliceExp e)
1427
{
1428 1
    if (e.lwr && e.upr)
1429
    {
1430
        // For the following code to work, e should be optimized beforehand.
1431
        // (eg. $ in lwr and upr should be already resolved, if possible)
1432 1
        Expression lwr = e.lwr.optimize(WANTvalue);
1433 1
        Expression upr = e.upr.optimize(WANTvalue);
1434 1
        if (lwr.isConst() && upr.isConst())
1435
        {
1436 1
            size_t len = cast(size_t)(upr.toUInteger() - lwr.toUInteger());
1437 1
            return e.type.toBasetype().nextOf().sarrayOf(len);
1438
        }
1439
    }
1440
    else
1441
    {
1442 1
        Type t1b = e.e1.type.toBasetype();
1443 1
        if (t1b.ty == Tsarray)
1444 1
            return t1b;
1445
    }
1446 1
    return null;
1447
}
1448

1449
// Try casting the alias this member. Return the expression if it succeeds, null otherwise.
1450
private Expression tryAliasThisCast(Expression e, Scope* sc, Type tob, Type t1b, Type t)
1451
{
1452 1
    Expression result;
1453 1
    AggregateDeclaration t1ad = isAggregate(t1b);
1454 1
    if (!t1ad)
1455 0
        return null;
1456

1457 1
    AggregateDeclaration toad = isAggregate(tob);
1458 1
    if (t1ad == toad || !t1ad.aliasthis)
1459 0
        return null;
1460

1461
    /* Forward the cast to our alias this member, rewrite to:
1462
     *   cast(to)e1.aliasthis
1463
     */
1464 1
    result = resolveAliasThis(sc, e);
1465 1
    const errors = global.startGagging();
1466 1
    result = result.castTo(sc, t);
1467 1
    return global.endGagging(errors) ? null : result;
1468
}
1469

1470
/**************************************
1471
 * Do an explicit cast.
1472
 * Assume that the 'this' expression does not have any indirections.
1473
 */
1474
Expression castTo(Expression e, Scope* sc, Type t)
1475
{
1476
    extern (C++) final class CastTo : Visitor
1477
    {
1478
        alias visit = Visitor.visit;
1479
    public:
1480
        Type t;
1481
        Scope* sc;
1482
        Expression result;
1483

1484 1
        extern (D) this(Scope* sc, Type t)
1485
        {
1486 1
            this.sc = sc;
1487 1
            this.t = t;
1488
        }
1489

1490
        override void visit(Expression e)
1491
        {
1492
            //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
1493
            version (none)
1494
            {
1495
                printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1496
            }
1497 1
            if (e.type.equals(t))
1498
            {
1499 1
                result = e;
1500 1
                return;
1501
            }
1502 1
            if (e.op == TOK.variable)
1503
            {
1504 1
                VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
1505 1
                if (v && v.storage_class & STC.manifest)
1506
                {
1507 1
                    result = e.ctfeInterpret();
1508
                    /* https://issues.dlang.org/show_bug.cgi?id=18236
1509
                     *
1510
                     * The expression returned by ctfeInterpret points
1511
                     * to the line where the manifest constant was declared
1512
                     * so we need to update the location before trying to cast
1513
                     */
1514 1
                    result.loc = e.loc;
1515 1
                    result = result.castTo(sc, t);
1516 1
                    return;
1517
                }
1518
            }
1519

1520 1
            Type tob = t.toBasetype();
1521 1
            Type t1b = e.type.toBasetype();
1522 1
            if (tob.equals(t1b))
1523
            {
1524 1
                result = e.copy(); // because of COW for assignment to e.type
1525 1
                result.type = t;
1526 1
                return;
1527
            }
1528

1529
            /* Make semantic error against invalid cast between concrete types.
1530
             * Assume that 'e' is never be any placeholder expressions.
1531
             * The result of these checks should be consistent with CastExp::toElem().
1532
             */
1533

1534
            // Fat Value types
1535 1
            const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray || tob.ty == Tvector);
1536 1
            const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray || t1b.ty == Tvector);
1537

1538
            // Fat Reference types
1539 1
            const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate);
1540 1
            const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate);
1541

1542
            // Reference types
1543 1
            const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass);
1544 1
            const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
1545

1546
            // Arithmetic types (== valueable basic types)
1547 1
            const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
1548 1
            const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
1549

1550 1
            bool hasAliasThis;
1551 1
            if (AggregateDeclaration t1ad = isAggregate(t1b))
1552
            {
1553 1
                AggregateDeclaration toad = isAggregate(tob);
1554 1
                if (t1ad != toad && t1ad.aliasthis)
1555
                {
1556 1
                    if (t1b.ty == Tclass && tob.ty == Tclass)
1557
                    {
1558 1
                        ClassDeclaration t1cd = t1b.isClassHandle();
1559 1
                        ClassDeclaration tocd = tob.isClassHandle();
1560 1
                        int offset;
1561 1
                        if (tocd.isBaseOf(t1cd, &offset))
1562 1
                            goto Lok;
1563
                    }
1564 1
                    hasAliasThis = true;
1565
                }
1566
            }
1567 1
            else if (tob.ty == Tvector && t1b.ty != Tvector)
1568
            {
1569
                //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
1570 1
                TypeVector tv = cast(TypeVector)tob;
1571 1
                result = new CastExp(e.loc, e, tv.elementType());
1572 1
                result = new VectorExp(e.loc, result, tob);
1573 1
                result = result.expressionSemantic(sc);
1574 1
                return;
1575
            }
1576 1
            else if (tob.ty != Tvector && t1b.ty == Tvector)
1577
            {
1578
                // T[n] <-- __vector(U[m])
1579 1
                if (tob.ty == Tsarray)
1580
                {
1581 1
                    if (t1b.size(e.loc) == tob.size(e.loc))
1582 1
                        goto Lok;
1583
                }
1584 1
                goto Lfail;
1585
            }
1586 1
            else if (t1b.implicitConvTo(tob) == MATCH.constant && t.equals(e.type.constOf()))
1587
            {
1588 1
                result = e.copy();
1589 1
                result.type = t;
1590 1
                return;
1591
            }
1592

1593
            // arithmetic values vs. other arithmetic values
1594
            // arithmetic values vs. T*
1595 1
            if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer))
1596
            {
1597 1
                goto Lok;
1598
            }
1599

1600
            // arithmetic values vs. references or fat values
1601 1
            if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV))
1602
            {
1603 1
                goto Lfail;
1604
            }
1605

1606
            // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
1607 1
            if (tob_isFV && t1b_isFV)
1608
            {
1609 1
                if (hasAliasThis)
1610
                {
1611 1
                    result = tryAliasThisCast(e, sc, tob, t1b, t);
1612 1
                    if (result)
1613 1
                        return;
1614
                }
1615

1616 1
                if (t1b.size(e.loc) == tob.size(e.loc))
1617 1
                    goto Lok;
1618

1619 1
                auto ts = toAutoQualChars(e.type, t);
1620 1
                e.error("cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
1621
                    e.toChars(), ts[0], ts[1]);
1622 1
                result = ErrorExp.get();
1623 1
                return;
1624
            }
1625

1626
            // Fat values vs. null or references
1627 1
            if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR))
1628
            {
1629 1
                if (tob.ty == Tpointer && t1b.ty == Tsarray)
1630
                {
1631
                    // T[n] sa;
1632
                    // cast(U*)sa; // ==> cast(U*)sa.ptr;
1633 1
                    result = new AddrExp(e.loc, e, t);
1634 1
                    return;
1635
                }
1636 1
                if (tob.ty == Tarray && t1b.ty == Tsarray)
1637
                {
1638
                    // T[n] sa;
1639
                    // cast(U[])sa; // ==> cast(U[])sa[];
1640 1
                    d_uns64 fsize = t1b.nextOf().size();
1641 1
                    d_uns64 tsize = tob.nextOf().size();
1642 1
                    if (((cast(TypeSArray)t1b).dim.toInteger() * fsize) % tsize != 0)
1643
                    {
1644
                        // copied from sarray_toDarray() in e2ir.c
1645 1
                        e.error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up", e.toChars(), e.type.toChars(), t.toChars());
1646 1
                        result = ErrorExp.get();
1647 1
                        return;
1648
                    }
1649 1
                    goto Lok;
1650
                }
1651 1
                goto Lfail;
1652
            }
1653

1654
            /* For references, any reinterpret casts are allowed to same 'ty' type.
1655
             *      T* to U*
1656
             *      R1 function(P1) to R2 function(P2)
1657
             *      R1 delegate(P1) to R2 delegate(P2)
1658
             *      T[] to U[]
1659
             *      V1[K1] to V2[K2]
1660
             *      class/interface A to B  (will be a dynamic cast if possible)
1661
             */
1662 1
            if (tob.ty == t1b.ty && tob_isR && t1b_isR)
1663 1
                goto Lok;
1664

1665
            // typeof(null) <-- non-null references or values
1666 1
            if (tob.ty == Tnull && t1b.ty != Tnull)
1667 1
                goto Lfail; // https://issues.dlang.org/show_bug.cgi?id=14629
1668
            // typeof(null) --> non-null references or arithmetic values
1669 1
            if (t1b.ty == Tnull && tob.ty != Tnull)
1670 1
                goto Lok;
1671

1672
            // Check size mismatch of references.
1673
            // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
1674 1
            if (tob_isFR && t1b_isR || t1b_isFR && tob_isR)
1675
            {
1676 1
                if (tob.ty == Tpointer && t1b.ty == Tarray)
1677
                {
1678
                    // T[] da;
1679
                    // cast(U*)da; // ==> cast(U*)da.ptr;
1680 1
                    goto Lok;
1681
                }
1682 1
                if (tob.ty == Tpointer && t1b.ty == Tdelegate)
1683
                {
1684
                    // void delegate() dg;
1685
                    // cast(U*)dg; // ==> cast(U*)dg.ptr;
1686
                    // Note that it happens even when U is a Tfunction!
1687 1
                    e.deprecation("casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
1688 1
                    goto Lok;
1689
                }
1690 1
                goto Lfail;
1691
            }
1692

1693 1
            if (t1b.ty == Tvoid && tob.ty != Tvoid)
1694
            {
1695
            Lfail:
1696
                /* if the cast cannot be performed, maybe there is an alias
1697
                 * this that can be used for casting.
1698
                 */
1699 1
                if (hasAliasThis)
1700
                {
1701 1
                    result = tryAliasThisCast(e, sc, tob, t1b, t);
1702 1
                    if (result)
1703 1
                        return;
1704
                }
1705 1
                e.error("cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
1706 1
                result = ErrorExp.get();
1707 1
                return;
1708
            }
1709

1710
        Lok:
1711 1
            result = new CastExp(e.loc, e, t);
1712 1
            result.type = t; // Don't call semantic()
1713
            //printf("Returning: %s\n", result.toChars());
1714
        }
1715

1716
        override void visit(ErrorExp e)
1717
        {
1718 1
            result = e;
1719
        }
1720

1721
        override void visit(RealExp e)
1722
        {
1723 1
            if (!e.type.equals(t))
1724
            {
1725 1
                if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
1726
                {
1727 1
                    result = e.copy();
1728 1
                    result.type = t;
1729
                }
1730
                else
1731 1
                    visit(cast(Expression)e);
1732 1
                return;
1733
            }
1734 1
            result = e;
1735
        }
1736

1737
        override void visit(ComplexExp e)
1738
        {
1739 1
            if (!e.type.equals(t))
1740
            {
1741 0
                if (e.type.iscomplex() && t.iscomplex())
1742
                {
1743 0
                    result = e.copy();
1744 0
                    result.type = t;
1745
                }
1746
                else
1747 0
                    visit(cast(Expression)e);
1748 0
                return;
1749
            }
1750 1
            result = e;
1751
        }
1752

1753
        override void visit(StructLiteralExp e)
1754
        {
1755 1
            visit(cast(Expression)e);
1756 1
            if (result.op == TOK.structLiteral)
1757 1
                (cast(StructLiteralExp)result).stype = t; // commit type
1758
        }
1759

1760
        override void visit(StringExp e)
1761
        {
1762
            /* This follows copy-on-write; any changes to 'this'
1763
             * will result in a copy.
1764
             * The this.string member is considered immutable.
1765
             */
1766 1
            int copied = 0;
1767

1768
            //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
1769

1770 1
            if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
1771
            {
1772 0
                e.error("cannot convert string literal to `void*`");
1773 0
                result = ErrorExp.get();
1774 0
                return;
1775
            }
1776

1777 1
            StringExp se = e;
1778 1
            if (!e.committed)
1779
            {
1780 1
                se = cast(StringExp)e.copy();
1781 1
                se.committed = 1;
1782 1
                copied = 1;
1783
            }
1784

1785 1
            if (e.type.equals(t))
1786
            {
1787 1
                result = se;
1788 1
                return;
1789
            }
1790

1791 1
            Type tb = t.toBasetype();
1792 1
            Type typeb = e.type.toBasetype();
1793

1794
            //printf("\ttype = %s\n", e.type.toChars());
1795 1
            if (tb.ty == Tdelegate && typeb.ty != Tdelegate)
1796
            {
1797 0
                visit(cast(Expression)e);
1798 0
                return;
1799
            }
1800

1801 1
            if (typeb.equals(tb))
1802
            {
1803 1
                if (!copied)
1804
                {
1805 1
                    se = cast(StringExp)e.copy();
1806 1
                    copied = 1;
1807
                }
1808 1
                se.type = t;
1809 1
                result = se;
1810 1
                return;
1811
            }
1812

1813
            /* Handle reinterpret casts:
1814
             *  cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
1815
             *  cast(wchar[2])"abcd"c --> [\u6261, \u6463]
1816
             *  cast(wchar[1])"abcd"c --> [\u6261]
1817
             *  cast(char[4])"a" --> ['a', 0, 0, 0]
1818
             */
1819 1
            if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
1820
            {
1821 1
                se = cast(StringExp)e.copy();
1822 1
                d_uns64 szx = tb.nextOf().size();
1823 1
                assert(szx <= 255);
1824 1
                se.sz = cast(ubyte)szx;
1825 1
                se.len = cast(size_t)(cast(TypeSArray)tb).dim.toInteger();
1826 1
                se.committed = 1;
1827 1
                se.type = t;
1828

1829
                /* If larger than source, pad with zeros.
1830
                 */
1831 1
                const fullSize = (se.len + 1) * se.sz; // incl. terminating 0
1832 1
                if (fullSize > (e.len + 1) * e.sz)
1833
                {
1834 1
                    void* s = mem.xmalloc(fullSize);
1835 1
                    const srcSize = e.len * e.sz;
1836 1
                    const data = se.peekData();
1837 1
                    memcpy(s, data.ptr, srcSize);
1838 1
                    memset(s + srcSize, 0, fullSize - srcSize);
1839 1
                    se.setData(s, se.len, se.sz);
1840
                }
1841 1
                result = se;
1842 1
                return;
1843
            }
1844

1845 1
            if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer)
1846
            {
1847 1
                if (!copied)
1848
                {
1849 1
                    se = cast(StringExp)e.copy();
1850 1
                    copied = 1;
1851
                }
1852 1
                goto Lcast;
1853
            }
1854 1
            if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
1855
            {
1856 0
                if (!copied)
1857
                {
1858 0
                    se = cast(StringExp)e.copy();
1859 0
                    copied = 1;
1860
                }
1861 0
                goto Lcast;
1862
            }
1863

1864 1
            if (typeb.nextOf().size() == tb.nextOf().size())
1865
            {
1866 1
                if (!copied)
1867
                {
1868 1
                    se = cast(StringExp)e.copy();
1869 1
                    copied = 1;
1870
                }
1871 1
                if (tb.ty == Tsarray)
1872 1
                    goto L2; // handle possible change in static array dimension
1873 1
                se.type = t;
1874 1
                result = se;
1875 1
                return;
1876
            }
1877

1878 1
            if (e.committed)
1879 1
                goto Lcast;
1880

1881
            auto X(T, U)(T tf, U tt)
1882
            {
1883 1
                return (cast(int)tf * 256 + cast(int)tt);
1884
            }
1885

1886
            {
1887 1
                OutBuffer buffer;
1888 1
                size_t newlen = 0;
1889 1
                int tfty = typeb.nextOf().toBasetype().ty;
1890 1
                int ttty = tb.nextOf().toBasetype().ty;
1891 1
                switch (X(tfty, ttty))
1892
                {
1893 0
                case X(Tchar, Tchar):
1894 0
                case X(Twchar, Twchar):
1895 0
                case X(Tdchar, Tdchar):
1896 0
                    break;
1897

1898 1
                case X(Tchar, Twchar):
1899 1
                    for (size_t u = 0; u < e.len;)
1900
                    {
1901 1
                        dchar c;
1902 1
                        if (const s = utf_decodeChar(se.peekString(), u, c))
1903 0
                            e.error("%.*s", cast(int)s.length, s.ptr);
1904
                        else
1905 1
                            buffer.writeUTF16(c);
1906
                    }
1907 1
                    newlen = buffer.length / 2;
1908 1
                    buffer.writeUTF16(0);
1909 1
                    goto L1;
1910

1911 1
                case X(Tchar, Tdchar):
1912 1
                    for (size_t u = 0; u < e.len;)
1913
                    {
1914 1
                        dchar c;
1915 1
                        if (const s = utf_decodeChar(se.peekString(), u, c))
1916 0
                            e.error("%.*s", cast(int)s.length, s.ptr);
1917 1
                        buffer.write4(c);
1918 1
                        newlen++;
1919
                    }
1920 1
                    buffer.write4(0);
1921 1
                    goto L1;
1922

1923 1
                case X(Twchar, Tchar):
1924 1
                    for (size_t u = 0; u < e.len;)
1925
                    {
1926 1
                        dchar c;
1927 1
                        if (const s = utf_decodeWchar(se.peekWstring(), u, c))
1928 0
                            e.error("%.*s", cast(int)s.length, s.ptr);
1929
                        else
1930 1
                            buffer.writeUTF8(c);
1931
                    }
1932 1
                    newlen = buffer.length;
1933 1
                    buffer.writeUTF8(0);
1934 1
                    goto L1;
1935

1936 0
                case X(Twchar, Tdchar):
1937 0
                    for (size_t u = 0; u < e.len;)
1938
                    {
1939 0
                        dchar c;
1940 0
                        if (const s = utf_decodeWchar(se.peekWstring(), u, c))
1941 0
                            e.error("%.*s", cast(int)s.length, s.ptr);
1942 0
                        buffer.write4(c);
1943 0
                        newlen++;
1944
                    }
1945 0
                    buffer.write4(0);
1946 0
                    goto L1;
1947

1948 1
                case X(Tdchar, Tchar):
1949 1
                    for (size_t u = 0; u < e.len; u++)
1950
                    {
1951 1
                        uint c = se.peekDstring()[u];
1952 1
                        if (!utf_isValidDchar(c))
1953 0
                            e.error("invalid UCS-32 char \\U%08x", c);
1954
                        else
1955 1
                            buffer.writeUTF8(c);
1956 1
                        newlen++;
1957
                    }
1958 1
                    newlen = buffer.length;
1959 1
                    buffer.writeUTF8(0);
1960 1
                    goto L1;
1961

1962 0
                case X(Tdchar, Twchar):
1963 0
                    for (size_t u = 0; u < e.len; u++)
1964
                    {
1965 0
                        uint c = se.peekDstring()[u];
1966 0
                        if (!utf_isValidDchar(c))
1967 0
                            e.error("invalid UCS-32 char \\U%08x", c);
1968
                        else
1969 0
                            buffer.writeUTF16(c);
1970 0
                        newlen++;
1971
                    }
1972 0
                    newlen = buffer.length / 2;
1973 0
                    buffer.writeUTF16(0);
1974 0
                    goto L1;
1975

1976
                L1:
1977 1
                    if (!copied)
1978
                    {
1979 0
                        se = cast(StringExp)e.copy();
1980 0
                        copied = 1;
1981
                    }
1982

1983
                    {
1984 1
                        d_uns64 szx = tb.nextOf().size();
1985 1
                        assert(szx <= 255);
1986 1
                        se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
1987
                    }
1988 1
                    break;
1989

1990 1
                default:
1991 1
                    assert(typeb.nextOf().size() != tb.nextOf().size());
1992 1
                    goto Lcast;
1993
                }
1994
            }
1995
        L2:
1996 1
            assert(copied);
1997

1998
            // See if need to truncate or extend the literal
1999 1
            if (tb.ty == Tsarray)
2000
            {
2001 1
                size_t dim2 = cast(size_t)(cast(TypeSArray)tb).dim.toInteger();
2002
                //printf("dim from = %d, to = %d\n", (int)se.len, (int)dim2);
2003

2004
                // Changing dimensions
2005 1
                if (dim2 != se.len)
2006
                {
2007
                    // Copy when changing the string literal
2008 1
                    const newsz = se.sz;
2009 1
                    const d = (dim2 < se.len) ? dim2 : se.len;
2010 1
                    void* s = mem.xmalloc((dim2 + 1) * newsz);
2011 1
                    memcpy(s, se.peekData().ptr, d * newsz);
2012
                    // Extend with 0, add terminating 0
2013 1
                    memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz);
2014 1
                    se.setData(s, dim2, newsz);
2015
                }
2016
            }
2017 1
            se.type = t;
2018 1
            result = se;
2019 1
            return;
2020

2021
        Lcast:
2022 1
            result = new CastExp(e.loc, se, t);
2023 1
            result.type = t; // so semantic() won't be run on e
2024
        }
2025

2026
        override void visit(AddrExp e)
2027
        {
2028
            version (none)
2029
            {
2030
                printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2031
            }
2032 1
            result = e;
2033

2034 1
            Type tb = t.toBasetype();
2035 1
            Type typeb = e.type.toBasetype();
2036

2037 1
            if (tb.equals(typeb))
2038
            {
2039 1
                result = e.copy();
2040 1
                result.type = t;
2041 1
                return;
2042
            }
2043

2044
            // Look for pointers to functions where the functions are overloaded.
2045 1
            if (e.e1.op == TOK.overloadSet &&
2046 1
                (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2047
            {
2048 1
                OverExp eo = cast(OverExp)e.e1;
2049 1
                FuncDeclaration f = null;
2050 1
                for (size_t i = 0; i < eo.vars.a.dim; i++)
2051
                {
2052 1
                    auto s = eo.vars.a[i];
2053 1
                    auto f2 = s.isFuncDeclaration();
2054 1
                    assert(f2);
2055 1
                    if (f2.overloadExactMatch(tb.nextOf()))
2056
                    {
2057 1
                        if (f)
2058
                        {
2059
                            /* Error if match in more than one overload set,
2060
                             * even if one is a 'better' match than the other.
2061
                             */
2062 0
                            ScopeDsymbol.multiplyDefined(e.loc, f, f2);
2063
                        }
2064
                        else
2065 1
                            f = f2;
2066
                    }
2067
                }
2068 1
                if (f)
2069
                {
2070 1
                    f.tookAddressOf++;
2071 1
                    auto se = new SymOffExp(e.loc, f, 0, false);
2072 1
                    se.expressionSemantic(sc);
2073
                    // Let SymOffExp::castTo() do the heavy lifting
2074 1
                    visit(se);
2075 1
                    return;
2076
                }
2077
            }
2078

2079 1
            if (e.e1.op == TOK.variable &&
2080 1
                typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2081 1
                tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
2082
            {
2083 1
                auto ve = cast(VarExp)e.e1;
2084 1
                auto f = ve.var.isFuncDeclaration();
2085 1
                if (f)
2086
                {
2087 1
                    assert(f.isImportedSymbol());
2088 1
                    f = f.overloadExactMatch(tb.nextOf());
2089 1
                    if (f)
2090
                    {
2091 1
                        result = new VarExp(e.loc, f, false);
2092 1
                        result.type = f.type;
2093 1
                        result = new AddrExp(e.loc, result, t);
2094 1
                        return;
2095
                    }
2096
                }
2097
            }
2098

2099 1
            if (auto f = isFuncAddress(e))
2100
            {
2101 0
                if (f.checkForwardRef(e.loc))
2102
                {
2103 0
                    result = ErrorExp.get();
2104 0
                    return;
2105
                }
2106
            }
2107

2108 1
            visit(cast(Expression)e);
2109
        }
2110

2111
        override void visit(TupleExp e)
2112
        {
2113 1
            if (e.type.equals(t))
2114
            {
2115 1
                result = e;
2116 1
                return;
2117
            }
2118

2119 1
            TupleExp te = cast(TupleExp)e.copy();
2120 1
            te.e0 = e.e0 ? e.e0.copy() : null;
2121 1
            te.exps = e.exps.copy();
2122 1
            for (size_t i = 0; i < te.exps.dim; i++)
2123
            {
2124 1
                Expression ex = (*te.exps)[i];
2125 1
                ex = ex.castTo(sc, t);
2126 1
                (*te.exps)[i] = ex;
2127
            }
2128 1
            result = te;
2129

2130
            /* Questionable behavior: In here, result.type is not set to t.
2131
             * Therefoe:
2132
             *  TypeTuple!(int, int) values;
2133
             *  auto values2 = cast(long)values;
2134
             *  // typeof(values2) == TypeTuple!(int, int) !!
2135
             *
2136
             * Only when the casted tuple is immediately expanded, it would work.
2137
             *  auto arr = [cast(long)values];
2138
             *  // typeof(arr) == long[]
2139
             */
2140
        }
2141

2142
        override void visit(ArrayLiteralExp e)
2143
        {
2144
            version (none)
2145
            {
2146
                printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2147
            }
2148

2149 1
            ArrayLiteralExp ae = e;
2150

2151 1
            Type tb = t.toBasetype();
2152 1
            if (tb.ty == Tarray && global.params.vsafe)
2153
            {
2154 1
                if (checkArrayLiteralEscape(sc, ae, false))
2155
                {
2156 1
                    result = ErrorExp.get();
2157 1
                    return;
2158
                }
2159
            }
2160

2161 1
            if (e.type == t)
2162
            {
2163 1
                result = e;
2164 1
                return;
2165
            }
2166 1
            Type typeb = e.type.toBasetype();
2167

2168 1
            if ((tb.ty == Tarray || tb.ty == Tsarray) &&
2169 1
                (typeb.ty == Tarray || typeb.ty == Tsarray))
2170
            {
2171 1
                if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
2172
                {
2173
                    // Don't do anything to cast non-void[] to void[]
2174
                }
2175 1
                else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid)
2176
                {
2177
                    // Don't do anything for casting void[n] to others
2178
                }
2179
                else
2180
                {
2181 1
                    if (tb.ty == Tsarray)
2182
                    {
2183 1
                        TypeSArray tsa = cast(TypeSArray)tb;
2184 1
                        if (e.elements.dim != tsa.dim.toInteger())
2185 1
                            goto L1;
2186
                    }
2187

2188 1
                    ae = cast(ArrayLiteralExp)e.copy();
2189 1
                    if (e.basis)
2190 1
                        ae.basis = e.basis.castTo(sc, tb.nextOf());
2191 1
                    ae.elements = e.elements.copy();
2192 1
                    for (size_t i = 0; i < e.elements.dim; i++)
2193
                    {
2194 1
                        Expression ex = (*e.elements)[i];
2195 1
                        if (!ex)
2196 1
                            continue;
2197 1
                        ex = ex.castTo(sc, tb.nextOf());
2198 1
                        (*ae.elements)[i] = ex;
2199
                    }
2200 1
                    ae.type = t;
2201 1
                    result = ae;
2202 1
                    return;
2203
                }
2204
            }
2205 1
            else if (tb.ty == Tpointer && typeb.ty == Tsarray)
2206
            {
2207 1
                Type tp = typeb.nextOf().pointerTo();
2208 1
                if (!tp.equals(ae.type))
2209
                {
2210 1
                    ae = cast(ArrayLiteralExp)e.copy();
2211 1
                    ae.type = tp;
2212
                }
2213
            }
2214 1
            else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
2215
            {
2216
                // Convert array literal to vector type
2217 1
                TypeVector tv = cast(TypeVector)tb;
2218 1
                TypeSArray tbase = cast(TypeSArray)tv.basetype;
2219 1
                assert(tbase.ty == Tsarray);
2220 1
                const edim = e.elements.dim;
2221 1
                const tbasedim = tbase.dim.toInteger();
2222 1
                if (edim > tbasedim)
2223 0
                    goto L1;
2224

2225 1
                ae = cast(ArrayLiteralExp)e.copy();
2226 1
                ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
2227 1
                ae.elements = e.elements.copy();
2228 1
                Type telement = tv.elementType();
2229 1
                foreach (i; 0 .. edim)
2230
                {
2231 1
                    Expression ex = (*e.elements)[i];
2232 1
                    ex = ex.castTo(sc, telement);
2233 1
                    (*ae.elements)[i] = ex;
2234
                }
2235
                // Fill in the rest with the default initializer
2236 1
                ae.elements.setDim(cast(size_t)tbasedim);
2237 1
                foreach (i; edim .. cast(size_t)tbasedim)
2238
                {
2239 1
                    Expression ex = typeb.nextOf.defaultInitLiteral(e.loc);
2240 1
                    ex = ex.castTo(sc, telement);
2241 1
                    (*ae.elements)[i] = ex;
2242
                }
2243 1
                Expression ev = new VectorExp(e.loc, ae, tb);
2244 1
                ev = ev.expressionSemantic(sc);
2245 1
                result = ev;
2246 1
                return;
2247
            }
2248
        L1:
2249 1
            visit(cast(Expression)ae);
2250
        }
2251

2252
        override void visit(AssocArrayLiteralExp e)
2253
        {
2254
            //printf("AssocArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2255 1
            if (e.type == t)
2256
            {
2257 1
                result = e;
2258 1
                return;
2259
            }
2260

2261 1
            Type tb = t.toBasetype();
2262 1
            Type typeb = e.type.toBasetype();
2263

2264 1
            if (tb.ty == Taarray && typeb.ty == Taarray &&
2265 1
                tb.nextOf().toBasetype().ty != Tvoid)
2266
            {
2267 1
                AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e.copy();
2268 1
                ae.keys = e.keys.copy();
2269 1
                ae.values = e.values.copy();
2270 1
                assert(e.keys.dim == e.values.dim);
2271 1
                for (size_t i = 0; i < e.keys.dim; i++)
2272
                {
2273 1
                    Expression ex = (*e.values)[i];
2274 1
                    ex = ex.castTo(sc, tb.nextOf());
2275 1
                    (*ae.values)[i] = ex;
2276

2277 1
                    ex = (*e.keys)[i];
2278 1
                    ex = ex.castTo(sc, (cast(TypeAArray)tb).index);
2279 1
                    (*ae.keys)[i] = ex;
2280
                }
2281 1
                ae.type = t;
2282 1
                result = ae;
2283 1
                return;
2284
            }
2285 0
            visit(cast(Expression)e);
2286
        }
2287

2288
        override void visit(SymOffExp e)
2289
        {
2290
            version (none)
2291
            {
2292
                printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2293
            }
2294 1
            if (e.type == t && !e.hasOverloads)
2295
            {
2296 1
                result = e;
2297 1
                return;
2298
            }
2299

2300 1
            Type tb = t.toBasetype();
2301 1
            Type typeb = e.type.toBasetype();
2302

2303 1
            if (tb.equals(typeb))
2304
            {
2305 1
                result = e.copy();
2306 1
                result.type = t;
2307 1
                (cast(SymOffExp)result).hasOverloads = false;
2308 1
                return;
2309
            }
2310

2311
            // Look for pointers to functions where the functions are overloaded.
2312 1
            if (e.hasOverloads &&
2313 1
                typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2314 1
                (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2315
            {
2316 1
                FuncDeclaration f = e.var.isFuncDeclaration();
2317 1
                f = f ? f.overloadExactMatch(tb.nextOf()) : null;
2318 1
                if (f)
2319
                {
2320 1
                    if (tb.ty == Tdelegate)
2321
                    {
2322 1
                        if (f.needThis() && hasThis(sc))
2323
                        {
2324 0
                            result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false);
2325 0
                            result = result.expressionSemantic(sc);
2326
                        }
2327 1
                        else if (f.needThis())
2328
                        {
2329 1
                            e.error("no `this` to create delegate for `%s`", f.toChars());
2330 1
                            result = ErrorExp.get();
2331 1
                            return;
2332
                        }
2333 1
                        else if (f.isNested())
2334
                        {
2335 0
                            result = new DelegateExp(e.loc, IntegerExp.literal!0, f, false);
2336 0
                            result = result.expressionSemantic(sc);
2337
                        }
2338
                        else
2339
                        {
2340 1
                            e.error("cannot cast from function pointer to delegate");
2341 1
                            result = ErrorExp.get();
2342 1
                            return;
2343
                        }
2344
                    }
2345
                    else
2346
                    {
2347 1
                        result = new SymOffExp(e.loc, f, 0, false);
2348 1
                        result.type = t;
2349
                    }
2350 1
                    f.tookAddressOf++;
2351 1
                    return;
2352
                }
2353
            }
2354

2355 1
            if (auto f = isFuncAddress(e))
2356
            {
2357 1
                if (f.checkForwardRef(e.loc))
2358
                {
2359 1
                    result = ErrorExp.get();
2360 1
                    return;
2361
                }
2362
            }
2363

2364 1
            visit(cast(Expression)e);
2365
        }
2366

2367
        override void visit(DelegateExp e)
2368
        {
2369
            version (none)
2370
            {
2371
                printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2372
            }
2373 1
            __gshared const(char)* msg = "cannot form delegate due to covariant return type";
2374

2375 1
            Type tb = t.toBasetype();
2376 1
            Type typeb = e.type.toBasetype();
2377

2378 1
            if (tb.equals(typeb) && !e.hasOverloads)
2379
            {
2380 1
                int offset;
2381 1
                e.func.tookAddressOf++;
2382 1
                if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
2383 0
                    e.error("%s", msg);
2384 1
                result = e.copy();
2385 1
                result.type = t;
2386 1
                return;
2387
            }
2388

2389
            // Look for delegates to functions where the functions are overloaded.
2390 1
            if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
2391
            {
2392 1
                if (e.func)
2393
                {
2394 1
                    auto f = e.func.overloadExactMatch(tb.nextOf());
2395 1
                    if (f)
2396
                    {
2397 1
                        int offset;
2398 1
                        if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
2399 0
                            e.error("%s", msg);
2400 1
                        if (f != e.func)    // if address not already marked as taken
2401 1
                            f.tookAddressOf++;
2402 1
                        result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
2403 1
                        result.type = t;
2404 1
                        return;
2405
                    }
2406 1
                    if (e.func.tintro)
2407 0
                        e.error("%s", msg);
2408
                }
2409
            }
2410

2411 1
            if (auto f = isFuncAddress(e))
2412
            {
2413 1
                if (f.checkForwardRef(e.loc))
2414
                {
2415 1
                    result = ErrorExp.get();
2416 1
                    return;
2417
                }
2418
            }
2419

2420 1
            visit(cast(Expression)e);
2421
        }
2422

2423
        override void visit(FuncExp e)
2424
        {
2425
            //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
2426 1
            FuncExp fe;
2427 1
            if (e.matchType(t, sc, &fe, 1) > MATCH.nomatch)
2428
            {
2429 1
                result = fe;
2430 1
                return;
2431
            }
2432 1
            visit(cast(Expression)e);
2433
        }
2434

2435
        override void visit(CondExp e)
2436
        {
2437 1
            if (!e.type.equals(t))
2438
            {
2439 1
                result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t));
2440 1
                result.type = t;
2441 1
                return;
2442
            }
2443 1
            result = e;
2444
        }
2445

2446
        override void visit(CommaExp e)
2447
        {
2448 1
            Expression e2c = e.e2.castTo(sc, t);
2449

2450 1
            if (e2c != e.e2)
2451
            {
2452 1
                result = new CommaExp(e.loc, e.e1, e2c);
2453 1
                result.type = e2c.type;
2454
            }
2455
            else
2456
            {
2457 1
                result = e;
2458 1
                result.type = e.e2.type;
2459
            }
2460
        }
2461

2462
        override void visit(SliceExp e)
2463
        {
2464
            //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e.toChars(), e.type.toChars(), t.toChars());
2465

2466 1
            Type tb = t.toBasetype();
2467 1
            Type typeb = e.type.toBasetype();
2468

2469 1
            if (e.type.equals(t) || typeb.ty != Tarray ||
2470 1
                (tb.ty != Tarray && tb.ty != Tsarray))
2471
            {
2472 1
                visit(cast(Expression)e);
2473 1
                return;
2474
            }
2475

2476 1
            if (tb.ty == Tarray)
2477
            {
2478 1
                if (typeb.nextOf().equivalent(tb.nextOf()))
2479
                {
2480
                    // T[] to const(T)[]
2481 1
                    result = e.copy();
2482 1
                    result.type = t;
2483
                }
2484
                else
2485
                {
2486 1
                    visit(cast(Expression)e);
2487
                }
2488 1
                return;
2489
            }
2490

2491
            // Handle the cast from Tarray to Tsarray with CT-known slicing
2492

2493 1
            TypeSArray tsa = cast(TypeSArray)toStaticArrayType(e);
2494 1
            if (tsa && tsa.size(e.loc) == tb.size(e.loc))
2495
            {
2496
                /* Match if the sarray sizes are equal:
2497
                 *  T[a .. b] to const(T)[b-a]
2498
                 *  T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
2499
                 *
2500
                 * If a SliceExp has Tsarray, it will become lvalue.
2501
                 * That's handled in SliceExp::isLvalue and toLvalue
2502
                 */
2503 1
                result = e.copy();
2504 1
                result.type = t;
2505 1
                return;
2506
            }
2507 1
            if (tsa && tsa.dim.equals((cast(TypeSArray)tb).dim))
2508
            {
2509
                /* Match if the dimensions are equal
2510
                 * with the implicit conversion of e.e1:
2511
                 *  cast(float[2]) [2.0, 1.0, 0.0][0..2];
2512
                 */
2513 1
                Type t1b = e.e1.type.toBasetype();
2514 1
                if (t1b.ty == Tsarray)
2515 0
                    t1b = tb.nextOf().sarrayOf((cast(TypeSArray)t1b).dim.toInteger());
2516 1
                else if (t1b.ty == Tarray)
2517 1
                    t1b = tb.nextOf().arrayOf();
2518 0
                else if (t1b.ty == Tpointer)
2519 0
                    t1b = tb.nextOf().pointerTo();
2520
                else
2521 0
                    assert(0);
2522 1
                if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
2523
                {
2524 1
                    Expression e1x = e.e1.implicitCastTo(sc, t1b);
2525 1
                    assert(e1x.op != TOK.error);
2526 1
                    e = cast(SliceExp)e.copy();
2527 1
                    e.e1 = e1x;
2528 1
                    e.type = t;
2529 1
                    result = e;
2530 1
                    return;
2531
                }
2532
            }
2533 1
            auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
2534 1
            e.error("cannot cast expression `%s` of type `%s` to `%s`",
2535
                e.toChars(), ts[0], ts[1]);
2536 1
            result = ErrorExp.get();
2537
        }
2538
    }
2539

2540 1
    scope CastTo v = new CastTo(sc, t);
2541 1
    e.accept(v);
2542 1
    return v.result;
2543
}
2544

2545
/****************************************
2546
 * Set type inference target
2547
 *      t       Target type
2548
 *      flag    1: don't put an error when inference fails
2549
 */
2550
Expression inferType(Expression e, Type t, int flag = 0)
2551
{
2552
    Expression visitAle(ArrayLiteralExp ale)
2553
    {
2554 1
        Type tb = t.toBasetype();
2555 1
        if (tb.ty == Tarray || tb.ty == Tsarray)
2556
        {
2557 1
            Type tn = tb.nextOf();
2558 1
            if (ale.basis)
2559 1
                ale.basis = inferType(ale.basis, tn, flag);
2560 1
            for (size_t i = 0; i < ale.elements.dim; i++)
2561
            {
2562 1
                if (Expression e = (*ale.elements)[i])
2563
                {
2564 1
                    e = inferType(e, tn, flag);
2565 1
                    (*ale.elements)[i] = e;
2566
                }
2567
            }
2568
        }
2569 1
        return ale;
2570
    }
2571

2572
    Expression visitAar(AssocArrayLiteralExp aale)
2573
    {
2574 1
        Type tb = t.toBasetype();
2575 1
        if (tb.ty == Taarray)
2576
        {
2577 1
            TypeAArray taa = cast(TypeAArray)tb;
2578 1
            Type ti = taa.index;
2579 1
            Type tv = taa.nextOf();
2580 1
            for (size_t i = 0; i < aale.keys.dim; i++)
2581
            {
2582 1
                if (Expression e = (*aale.keys)[i])
2583
                {
2584 1
                    e = inferType(e, ti, flag);
2585 1
                    (*aale.keys)[i] = e;
2586
                }
2587
            }
2588 1
            for (size_t i = 0; i < aale.values.dim; i++)
2589
            {
2590 1
                if (Expression e = (*aale.values)[i])
2591
                {
2592 1
                    e = inferType(e, tv, flag);
2593 1
                    (*aale.values)[i] = e;
2594
                }
2595
            }
2596
        }
2597 1
        return aale;
2598
    }
2599

2600
    Expression visitFun(FuncExp fe)
2601
    {
2602
        //printf("FuncExp::inferType('%s'), to=%s\n", fe.type ? fe.type.toChars() : "null", t.toChars());
2603 1
        if (t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction)
2604
        {
2605 1
            fe.fd.treq = t;
2606
        }
2607 1
        return fe;
2608
    }
2609

2610
    Expression visitTer(CondExp ce)
2611
    {
2612 1
        Type tb = t.toBasetype();
2613 1
        ce.e1 = inferType(ce.e1, tb, flag);
2614 1
        ce.e2 = inferType(ce.e2, tb, flag);
2615 1
        return ce;
2616
    }
2617

2618 1
    if (t) switch (e.op)
2619
    {
2620 1
        case TOK.arrayLiteral:      return visitAle(cast(ArrayLiteralExp) e);
2621 1
        case TOK.assocArrayLiteral: return visitAar(cast(AssocArrayLiteralExp) e);
2622 1
        case TOK.function_:         return visitFun(cast(FuncExp) e);
2623 1
        case TOK.question:          return visitTer(cast(CondExp) e);
2624 1
        default:
2625
    }
2626 1
    return e;
2627
}
2628

2629
/****************************************
2630
 * Scale addition/subtraction to/from pointer.
2631
 */
2632
Expression scaleFactor(BinExp be, Scope* sc)
2633
{
2634 1
    Type t1b = be.e1.type.toBasetype();
2635 1
    Type t2b = be.e2.type.toBasetype();
2636 1
    Expression eoff;
2637

2638 1
    if (t1b.ty == Tpointer && t2b.isintegral())
2639
    {
2640
        // Need to adjust operator by the stride
2641
        // Replace (ptr + int) with (ptr + (int * stride))
2642 1
        Type t = Type.tptrdiff_t;
2643

2644 1
        d_uns64 stride = t1b.nextOf().size(be.loc);
2645 1
        if (!t.equals(t2b))
2646 1
            be.e2 = be.e2.castTo(sc, t);
2647 1
        eoff = be.e2;
2648 1
        be.e2 = new MulExp(be.loc, be.e2, new IntegerExp(Loc.initial, stride, t));
2649 1
        be.e2.type = t;
2650 1
        be.type = be.e1.type;
2651
    }
2652 1
    else if (t2b.ty == Tpointer && t1b.isintegral())
2653
    {
2654
        // Need to adjust operator by the stride
2655
        // Replace (int + ptr) with (ptr + (int * stride))
2656 1
        Type t = Type.tptrdiff_t;
2657 1
        Expression e;
2658

2659 1
        d_uns64 stride = t2b.nextOf().size(be.loc);
2660 1
        if (!t.equals(t1b))
2661 1
            e = be.e1.castTo(sc, t);
2662
        else
2663 0
            e = be.e1;
2664 1
        eoff = e;
2665 1
        e = new MulExp(be.loc, e, new IntegerExp(Loc.initial, stride, t));
2666 1
        e.type = t;
2667 1
        be.type = be.e2.type;
2668 1
        be.e1 = be.e2;
2669 1
        be.e2 = e;
2670
    }
2671
    else
2672 0
        assert(0);
2673

2674 1
    if (sc.func && !sc.intypeof)
2675
    {
2676 1
        eoff = eoff.optimize(WANTvalue);
2677 1
        if (eoff.op == TOK.int64 && eoff.toInteger() == 0)
2678
        {
2679
        }
2680 1
        else if (sc.func.setUnsafe())
2681
        {
2682 1
            be.error("pointer arithmetic not allowed in @safe functions");
2683 1
            return ErrorExp.get();
2684
        }
2685
    }
2686

2687 1
    return be;
2688
}
2689

2690
/**************************************
2691
 * Return true if e is an empty array literal with dimensionality
2692
 * equal to or less than type of other array.
2693
 * [], [[]], [[[]]], etc.
2694
 * I.e., make sure that [1,2] is compatible with [],
2695
 * [[1,2]] is compatible with [[]], etc.
2696
 */
2697
private bool isVoidArrayLiteral(Expression e, Type other)
2698
{
2699 1
    while (e.op == TOK.arrayLiteral && e.type.ty == Tarray && ((cast(ArrayLiteralExp)e).elements.dim == 1))
2700
    {
2701 1
        auto ale = cast(ArrayLiteralExp)e;
2702 1
        e = ale[0];
2703 1
        if (other.ty == Tsarray || other.ty == Tarray)
2704 1
            other = other.nextOf();
2705
        else
2706 1
            return false;
2707
    }
2708 1
    if (other.ty != Tsarray && other.ty != Tarray)
2709 1
        return false;
2710 1
    Type t = e.type;
2711 1
    return (e.op == TOK.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && (cast(ArrayLiteralExp)e).elements.dim == 0);
2712
}
2713

2714
/**************************************
2715
 * Combine types.
2716
 * Output:
2717
 *      *pt     merged type, if *pt is not NULL
2718
 *      *pe1    rewritten e1
2719
 *      *pe2    rewritten e2
2720
 * Returns:
2721
 *      true    success
2722
 *      false   failed
2723
 */
2724
bool typeMerge(Scope* sc, TOK op, Type* pt, Expression* pe1, Expression* pe2)
2725
{
2726
    //printf("typeMerge() %s op %s\n", pe1.toChars(), pe2.toChars());
2727

2728 1
    MATCH m;
2729 1
    Expression e1 = *pe1;
2730 1
    Expression e2 = *pe2;
2731

2732 1
    Type t1 = e1.type;
2733 1
    Type t2 = e2.type;
2734

2735 1
    Type t1b = e1.type.toBasetype();
2736 1
    Type t2b = e2.type.toBasetype();
2737

2738 1
    Type t;
2739

2740
    bool Lret()
2741
    {
2742 1
        if (!*pt)
2743 1
            *pt = t;
2744 1
        *pe1 = e1;
2745 1
        *pe2 = e2;
2746

2747
        version (none)
2748
        {
2749
            printf("-typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
2750
            if (e1.type)
2751
                printf("\tt1 = %s\n", e1.type.toChars());
2752
            if (e2.type)
2753
                printf("\tt2 = %s\n", e2.type.toChars());
2754
            printf("\ttype = %s\n", t.toChars());
2755
        }
2756 1
        return true;
2757
    }
2758

2759
    bool Lt1()
2760
    {
2761 1
        e2 = e2.castTo(sc, t1);
2762 1
        t = t1;
2763 1
        return Lret();
2764
    }
2765

2766
    bool Lt2()
2767
    {
2768 1
        e1 = e1.castTo(sc, t2);
2769 1
        t = t2;
2770 1
        return Lret();
2771
    }
2772

2773 1
    bool Lincompatible() { return false; }
2774

2775 1
    if (op != TOK.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
2776
    {
2777 1
        if (op == TOK.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
2778
        {
2779 1
            e1 = e1.castTo(sc, Type.tdchar);
2780 1
            e2 = e2.castTo(sc, Type.tdchar);
2781
        }
2782
        else
2783
        {
2784 1
            e1 = integralPromotions(e1, sc);
2785 1
            e2 = integralPromotions(e2, sc);
2786
        }
2787