xref: /netbsd/external/gpl3/gcc/dist/gcc/d/dmd/dcast.c (revision 7327edaf)
181418a27Smrg 
281418a27Smrg /* Compiler implementation of the D programming language
381418a27Smrg  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
481418a27Smrg  * written by Walter Bright
581418a27Smrg  * http://www.digitalmars.com
681418a27Smrg  * Distributed under the Boost Software License, Version 1.0.
781418a27Smrg  * http://www.boost.org/LICENSE_1_0.txt
881418a27Smrg  * https://github.com/D-Programming-Language/dmd/blob/master/src/cast.c
981418a27Smrg  */
1081418a27Smrg 
1181418a27Smrg #include "root/dsystem.h"               // mem{set|cpy}()
1281418a27Smrg #include "root/rmem.h"
1381418a27Smrg 
1481418a27Smrg #include "mars.h"
1581418a27Smrg #include "expression.h"
1681418a27Smrg #include "mtype.h"
1781418a27Smrg #include "utf.h"
1881418a27Smrg #include "declaration.h"
1981418a27Smrg #include "aggregate.h"
2081418a27Smrg #include "template.h"
2181418a27Smrg #include "scope.h"
2281418a27Smrg #include "id.h"
2381418a27Smrg #include "init.h"
2481418a27Smrg #include "tokens.h"
2581418a27Smrg 
2681418a27Smrg FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
2781418a27Smrg bool isCommutative(TOK op);
2881418a27Smrg MOD MODmerge(MOD mod1, MOD mod2);
2981418a27Smrg Expression *semantic(Expression *e, Scope *sc);
3081418a27Smrg 
3181418a27Smrg /* ==================== implicitCast ====================== */
3281418a27Smrg 
3381418a27Smrg /**************************************
3481418a27Smrg  * Do an implicit cast.
3581418a27Smrg  * Issue error if it can't be done.
3681418a27Smrg  */
3781418a27Smrg 
3881418a27Smrg 
implicitCastTo(Expression * e,Scope * sc,Type * t)3981418a27Smrg Expression *implicitCastTo(Expression *e, Scope *sc, Type *t)
4081418a27Smrg {
4181418a27Smrg     class ImplicitCastTo : public Visitor
4281418a27Smrg     {
4381418a27Smrg     public:
4481418a27Smrg         Type *t;
4581418a27Smrg         Scope *sc;
4681418a27Smrg         Expression *result;
4781418a27Smrg 
4881418a27Smrg         ImplicitCastTo(Scope *sc, Type *t)
4981418a27Smrg             : t(t), sc(sc)
5081418a27Smrg         {
5181418a27Smrg             result = NULL;
5281418a27Smrg         }
5381418a27Smrg 
5481418a27Smrg         void visit(Expression *e)
5581418a27Smrg         {
5681418a27Smrg             //printf("Expression::implicitCastTo(%s of type %s) => %s\n", e->toChars(), e->type->toChars(), t->toChars());
5781418a27Smrg 
5881418a27Smrg             MATCH match = e->implicitConvTo(t);
5981418a27Smrg             if (match)
6081418a27Smrg             {
6181418a27Smrg                 if (match == MATCHconst &&
6281418a27Smrg                     (e->type->constConv(t) ||
6381418a27Smrg                      (!e->isLvalue() && e->type->equivalent(t))))
6481418a27Smrg                 {
6581418a27Smrg                     /* Do not emit CastExp for const conversions and
6681418a27Smrg                      * unique conversions on rvalue.
6781418a27Smrg                      */
6881418a27Smrg                     result = e->copy();
6981418a27Smrg                     result->type = t;
7081418a27Smrg                     return;
7181418a27Smrg                 }
7281418a27Smrg                 result = e->castTo(sc, t);
7381418a27Smrg                 return;
7481418a27Smrg             }
7581418a27Smrg 
7681418a27Smrg             result = e->optimize(WANTvalue);
7781418a27Smrg             if (result != e)
7881418a27Smrg             {
7981418a27Smrg                 result->accept(this);
8081418a27Smrg                 return;
8181418a27Smrg             }
8281418a27Smrg 
8381418a27Smrg             if (t->ty != Terror && e->type->ty != Terror)
8481418a27Smrg             {
8581418a27Smrg                 if (!t->deco)
8681418a27Smrg                 {
8781418a27Smrg                     e->error("forward reference to type %s", t->toChars());
8881418a27Smrg                 }
8981418a27Smrg                 else
9081418a27Smrg                 {
9181418a27Smrg                     //printf("type %p ty %d deco %p\n", type, type->ty, type->deco);
9281418a27Smrg                     //type = type->semantic(loc, sc);
9381418a27Smrg                     //printf("type %s t %s\n", type->deco, t->deco);
9481418a27Smrg                     e->error("cannot implicitly convert expression (%s) of type %s to %s",
9581418a27Smrg                         e->toChars(), e->type->toChars(), t->toChars());
9681418a27Smrg                 }
9781418a27Smrg             }
9881418a27Smrg             result = new ErrorExp();
9981418a27Smrg         }
10081418a27Smrg 
10181418a27Smrg         void visit(StringExp *e)
10281418a27Smrg         {
10381418a27Smrg             //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e->toChars(), e->type->toChars(), t->toChars());
10481418a27Smrg             visit((Expression *)e);
10581418a27Smrg             if (result->op == TOKstring)
10681418a27Smrg             {
10781418a27Smrg                 // Retain polysemous nature if it started out that way
10881418a27Smrg                 ((StringExp *)result)->committed = e->committed;
10981418a27Smrg             }
11081418a27Smrg         }
11181418a27Smrg 
11281418a27Smrg         void visit(ErrorExp *e)
11381418a27Smrg         {
11481418a27Smrg             result = e;
11581418a27Smrg         }
11681418a27Smrg 
11781418a27Smrg         void visit(FuncExp *e)
11881418a27Smrg         {
11981418a27Smrg             //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e->type, e->type ? e->type->toChars() : NULL, t->toChars());
12081418a27Smrg             FuncExp *fe;
12181418a27Smrg             if (e->matchType(t, sc, &fe) > MATCHnomatch)
12281418a27Smrg             {
12381418a27Smrg                 result = fe;
12481418a27Smrg                 return;
12581418a27Smrg             }
12681418a27Smrg             visit((Expression *)e);
12781418a27Smrg         }
12881418a27Smrg 
12981418a27Smrg         void visit(ArrayLiteralExp *e)
13081418a27Smrg         {
13181418a27Smrg             visit((Expression *)e);
13281418a27Smrg 
13381418a27Smrg             Type *tb = result->type->toBasetype();
13481418a27Smrg             if (tb->ty == Tarray && global.params.useTypeInfo && Type::dtypeinfo)
13581418a27Smrg                 semanticTypeInfo(sc, ((TypeDArray *)tb)->next);
13681418a27Smrg         }
13781418a27Smrg 
13881418a27Smrg         void visit(SliceExp *e)
13981418a27Smrg         {
14081418a27Smrg             visit((Expression *)e);
14181418a27Smrg             if (result->op != TOKslice)
14281418a27Smrg                 return;
14381418a27Smrg 
14481418a27Smrg             e = (SliceExp *)result;
14581418a27Smrg             if (e->e1->op == TOKarrayliteral)
14681418a27Smrg             {
14781418a27Smrg                 ArrayLiteralExp *ale = (ArrayLiteralExp *)e->e1;
14881418a27Smrg                 Type *tb = t->toBasetype();
14981418a27Smrg                 Type *tx;
15081418a27Smrg                 if (tb->ty == Tsarray)
15181418a27Smrg                     tx = tb->nextOf()->sarrayOf(ale->elements ? ale->elements->dim : 0);
15281418a27Smrg                 else
15381418a27Smrg                     tx = tb->nextOf()->arrayOf();
15481418a27Smrg                 e->e1 = ale->implicitCastTo(sc, tx);
15581418a27Smrg             }
15681418a27Smrg         }
15781418a27Smrg     };
15881418a27Smrg 
15981418a27Smrg     ImplicitCastTo v(sc, t);
16081418a27Smrg     e->accept(&v);
16181418a27Smrg     return v.result;
16281418a27Smrg }
16381418a27Smrg 
16481418a27Smrg /*******************************************
16581418a27Smrg  * Return MATCH level of implicitly converting e to type t.
16681418a27Smrg  * Don't do the actual cast; don't change e.
16781418a27Smrg  */
16881418a27Smrg 
implicitConvTo(Expression * e,Type * t)16981418a27Smrg MATCH implicitConvTo(Expression *e, Type *t)
17081418a27Smrg {
17181418a27Smrg     class ImplicitConvTo : public Visitor
17281418a27Smrg     {
17381418a27Smrg     public:
17481418a27Smrg         Type *t;
17581418a27Smrg         MATCH result;
17681418a27Smrg 
17781418a27Smrg         ImplicitConvTo(Type *t)
17881418a27Smrg             : t(t)
17981418a27Smrg         {
18081418a27Smrg             result = MATCHnomatch;
18181418a27Smrg         }
18281418a27Smrg 
18381418a27Smrg         void visit(Expression *e)
18481418a27Smrg         {
18581418a27Smrg             //static int nest; if (++nest == 10) halt();
18681418a27Smrg             if (t == Type::terror)
18781418a27Smrg                 return;
18881418a27Smrg             if (!e->type)
18981418a27Smrg             {
19081418a27Smrg                 e->error("%s is not an expression", e->toChars());
19181418a27Smrg                 e->type = Type::terror;
19281418a27Smrg             }
19381418a27Smrg             Expression *ex = e->optimize(WANTvalue);
19481418a27Smrg             if (ex->type->equals(t))
19581418a27Smrg             {
19681418a27Smrg                 result = MATCHexact;
19781418a27Smrg                 return;
19881418a27Smrg             }
19981418a27Smrg             if (ex != e)
20081418a27Smrg             {
20181418a27Smrg                 //printf("\toptimized to %s of type %s\n", e->toChars(), e->type->toChars());
20281418a27Smrg                 result = ex->implicitConvTo(t);
20381418a27Smrg                 return;
20481418a27Smrg             }
20581418a27Smrg             MATCH match = e->type->implicitConvTo(t);
20681418a27Smrg             if (match != MATCHnomatch)
20781418a27Smrg             {
20881418a27Smrg                 result = match;
20981418a27Smrg                 return;
21081418a27Smrg             }
21181418a27Smrg 
21281418a27Smrg             /* See if we can do integral narrowing conversions
21381418a27Smrg              */
21481418a27Smrg             if (e->type->isintegral() && t->isintegral() &&
21581418a27Smrg                 e->type->isTypeBasic() && t->isTypeBasic())
21681418a27Smrg             {
21781418a27Smrg                 IntRange src = getIntRange(e);
21881418a27Smrg                 IntRange target = IntRange::fromType(t);
21981418a27Smrg                 if (target.contains(src))
22081418a27Smrg                 {
22181418a27Smrg                     result = MATCHconvert;
22281418a27Smrg                     return;
22381418a27Smrg                 }
22481418a27Smrg             }
22581418a27Smrg         }
22681418a27Smrg 
22781418a27Smrg         /******
22881418a27Smrg          * Given expression e of type t, see if we can implicitly convert e
22981418a27Smrg          * to type tprime, where tprime is type t with mod bits added.
23081418a27Smrg          * Returns:
23181418a27Smrg          *      match level
23281418a27Smrg          */
23381418a27Smrg         static MATCH implicitMod(Expression *e, Type *t, MOD mod)
23481418a27Smrg         {
23581418a27Smrg             Type *tprime;
23681418a27Smrg             if (t->ty == Tpointer)
23781418a27Smrg                 tprime = t->nextOf()->castMod(mod)->pointerTo();
23881418a27Smrg             else if (t->ty == Tarray)
23981418a27Smrg                 tprime = t->nextOf()->castMod(mod)->arrayOf();
24081418a27Smrg             else if (t->ty == Tsarray)
24181418a27Smrg                 tprime = t->nextOf()->castMod(mod)->sarrayOf(t->size() / t->nextOf()->size());
24281418a27Smrg             else
24381418a27Smrg                 tprime = t->castMod(mod);
24481418a27Smrg 
24581418a27Smrg             return e->implicitConvTo(tprime);
24681418a27Smrg         }
24781418a27Smrg 
24881418a27Smrg         static MATCH implicitConvToAddMin(BinExp *e, Type *t)
24981418a27Smrg         {
25081418a27Smrg             /* Is this (ptr +- offset)? If so, then ask ptr
25181418a27Smrg              * if the conversion can be done.
25281418a27Smrg              * This is to support doing things like implicitly converting a mutable unique
25381418a27Smrg              * pointer to an immutable pointer.
25481418a27Smrg              */
25581418a27Smrg 
25681418a27Smrg             Type *typeb = e->type->toBasetype();
25781418a27Smrg             Type *tb = t->toBasetype();
25881418a27Smrg             if (typeb->ty != Tpointer || tb->ty != Tpointer)
25981418a27Smrg                 return MATCHnomatch;
26081418a27Smrg 
26181418a27Smrg             Type *t1b = e->e1->type->toBasetype();
26281418a27Smrg             Type *t2b = e->e2->type->toBasetype();
26381418a27Smrg             if (t1b->ty == Tpointer && t2b->isintegral() &&
26481418a27Smrg                 t1b->equivalent(tb))
26581418a27Smrg             {
26681418a27Smrg                 // ptr + offset
26781418a27Smrg                 // ptr - offset
26881418a27Smrg                 MATCH m = e->e1->implicitConvTo(t);
26981418a27Smrg                 return (m > MATCHconst) ? MATCHconst : m;
27081418a27Smrg             }
27181418a27Smrg             if (t2b->ty == Tpointer && t1b->isintegral() &&
27281418a27Smrg                 t2b->equivalent(tb))
27381418a27Smrg             {
27481418a27Smrg                 // offset + ptr
27581418a27Smrg                 MATCH m = e->e2->implicitConvTo(t);
27681418a27Smrg                 return (m > MATCHconst) ? MATCHconst : m;
27781418a27Smrg             }
27881418a27Smrg 
27981418a27Smrg             return MATCHnomatch;
28081418a27Smrg         }
28181418a27Smrg 
28281418a27Smrg         void visit(AddExp *e)
28381418a27Smrg         {
28481418a27Smrg             visit((Expression *)e);
28581418a27Smrg             if (result == MATCHnomatch)
28681418a27Smrg                 result = implicitConvToAddMin(e, t);
28781418a27Smrg         }
28881418a27Smrg 
28981418a27Smrg         void visit(MinExp *e)
29081418a27Smrg         {
29181418a27Smrg             visit((Expression *)e);
29281418a27Smrg             if (result == MATCHnomatch)
29381418a27Smrg                 result = implicitConvToAddMin(e, t);
29481418a27Smrg         }
29581418a27Smrg 
29681418a27Smrg         void visit(IntegerExp *e)
29781418a27Smrg         {
29881418a27Smrg             MATCH m = e->type->implicitConvTo(t);
29981418a27Smrg             if (m >= MATCHconst)
30081418a27Smrg             {
30181418a27Smrg                 result = m;
30281418a27Smrg                 return;
30381418a27Smrg             }
30481418a27Smrg 
30581418a27Smrg             TY ty = e->type->toBasetype()->ty;
30681418a27Smrg             TY toty = t->toBasetype()->ty;
30781418a27Smrg             TY oldty = ty;
30881418a27Smrg 
30981418a27Smrg             if (m == MATCHnomatch && t->ty == Tenum)
31081418a27Smrg                 return;
31181418a27Smrg 
31281418a27Smrg             if (t->ty == Tvector)
31381418a27Smrg             {
31481418a27Smrg                 TypeVector *tv = (TypeVector *)t;
31581418a27Smrg                 TypeBasic *tb = tv->elementType();
31681418a27Smrg                 if (tb->ty == Tvoid)
31781418a27Smrg                     return;
31881418a27Smrg                 toty = tb->ty;
31981418a27Smrg             }
32081418a27Smrg 
32181418a27Smrg             switch (ty)
32281418a27Smrg             {
32381418a27Smrg                 case Tbool:
32481418a27Smrg                 case Tint8:
32581418a27Smrg                 case Tchar:
32681418a27Smrg                 case Tuns8:
32781418a27Smrg                 case Tint16:
32881418a27Smrg                 case Tuns16:
32981418a27Smrg                 case Twchar:
33081418a27Smrg                     ty = Tint32;
33181418a27Smrg                     break;
33281418a27Smrg 
33381418a27Smrg                 case Tdchar:
33481418a27Smrg                     ty = Tuns32;
33581418a27Smrg                     break;
33681418a27Smrg 
33781418a27Smrg                 default:
33881418a27Smrg                     break;
33981418a27Smrg             }
34081418a27Smrg 
34181418a27Smrg             // Only allow conversion if no change in value
34281418a27Smrg             dinteger_t value = e->toInteger();
34381418a27Smrg             switch (toty)
34481418a27Smrg             {
34581418a27Smrg                 case Tbool:
34681418a27Smrg                     if ((value & 1) != value)
34781418a27Smrg                         return;
34881418a27Smrg                     break;
34981418a27Smrg 
35081418a27Smrg                 case Tint8:
35181418a27Smrg                     if (ty == Tuns64 && value & ~0x7FUL)
35281418a27Smrg                         return;
35381418a27Smrg                     else if ((signed char)value != (sinteger_t)value)
35481418a27Smrg                         return;
35581418a27Smrg                     break;
35681418a27Smrg 
35781418a27Smrg                 case Tchar:
35881418a27Smrg                     if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
35981418a27Smrg                         return;
36081418a27Smrg                     /* fall through */
36181418a27Smrg                 case Tuns8:
36281418a27Smrg                     //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
36381418a27Smrg                     if ((unsigned char)value != value)
36481418a27Smrg                         return;
36581418a27Smrg                     break;
36681418a27Smrg 
36781418a27Smrg                 case Tint16:
36881418a27Smrg                     if (ty == Tuns64 && value & ~0x7FFFUL)
36981418a27Smrg                         return;
37081418a27Smrg                     else if ((short)value != (sinteger_t)value)
37181418a27Smrg                         return;
37281418a27Smrg                     break;
37381418a27Smrg 
37481418a27Smrg                 case Twchar:
37581418a27Smrg                     if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
37681418a27Smrg                         return;
37781418a27Smrg                     /* fall through */
37881418a27Smrg                 case Tuns16:
37981418a27Smrg                     if ((unsigned short)value != value)
38081418a27Smrg                         return;
38181418a27Smrg                     break;
38281418a27Smrg 
38381418a27Smrg                 case Tint32:
38481418a27Smrg                     if (ty == Tuns32)
38581418a27Smrg                     {
38681418a27Smrg                     }
38781418a27Smrg                     else if (ty == Tuns64 && value & ~0x7FFFFFFFUL)
38881418a27Smrg                         return;
38981418a27Smrg                     else if ((int)value != (sinteger_t)value)
39081418a27Smrg                         return;
39181418a27Smrg                     break;
39281418a27Smrg 
39381418a27Smrg                 case Tuns32:
39481418a27Smrg                     if (ty == Tint32)
39581418a27Smrg                     {
39681418a27Smrg                     }
39781418a27Smrg                     else if ((unsigned)value != value)
39881418a27Smrg                         return;
39981418a27Smrg                     break;
40081418a27Smrg 
40181418a27Smrg                 case Tdchar:
40281418a27Smrg                     if (value > 0x10FFFFUL)
40381418a27Smrg                         return;
40481418a27Smrg                     break;
40581418a27Smrg 
40681418a27Smrg                 case Tfloat32:
40781418a27Smrg                 {
40881418a27Smrg                     volatile float f;
40981418a27Smrg                     if (e->type->isunsigned())
41081418a27Smrg                     {
41181418a27Smrg                         f = (float)value;
41281418a27Smrg                         if (f != value)
41381418a27Smrg                             return;
41481418a27Smrg                     }
41581418a27Smrg                     else
41681418a27Smrg                     {
41781418a27Smrg                         f = (float)(sinteger_t)value;
41881418a27Smrg                         if (f != (sinteger_t)value)
41981418a27Smrg                             return;
42081418a27Smrg                     }
42181418a27Smrg                     break;
42281418a27Smrg                 }
42381418a27Smrg 
42481418a27Smrg                 case Tfloat64:
42581418a27Smrg                 {
42681418a27Smrg                     volatile double f;
42781418a27Smrg                     if (e->type->isunsigned())
42881418a27Smrg                     {
42981418a27Smrg                         f = (double)value;
43081418a27Smrg                         if (f != value)
43181418a27Smrg                             return;
43281418a27Smrg                     }
43381418a27Smrg                     else
43481418a27Smrg                     {
43581418a27Smrg                         f = (double)(sinteger_t)value;
43681418a27Smrg                         if (f != (sinteger_t)value)
43781418a27Smrg                             return;
43881418a27Smrg                     }
43981418a27Smrg                     break;
44081418a27Smrg                 }
44181418a27Smrg 
44281418a27Smrg                 case Tfloat80:
44381418a27Smrg                 {
44481418a27Smrg                     volatile_longdouble f;
44581418a27Smrg                     if (e->type->isunsigned())
44681418a27Smrg                     {
44781418a27Smrg                         f = ldouble(value);
44881418a27Smrg                         if ((dinteger_t)f != value) // isn't this a noop, because the compiler prefers ld
44981418a27Smrg                             return;
45081418a27Smrg                     }
45181418a27Smrg                     else
45281418a27Smrg                     {
45381418a27Smrg                         f = ldouble((sinteger_t)value);
45481418a27Smrg                         if ((sinteger_t)f != (sinteger_t)value)
45581418a27Smrg                             return;
45681418a27Smrg                     }
45781418a27Smrg                     break;
45881418a27Smrg                 }
45981418a27Smrg 
46081418a27Smrg                 case Tpointer:
46181418a27Smrg                     //printf("type = %s\n", type->toBasetype()->toChars());
46281418a27Smrg                     //printf("t = %s\n", t->toBasetype()->toChars());
46381418a27Smrg                     if (ty == Tpointer &&
46481418a27Smrg                         e->type->toBasetype()->nextOf()->ty == t->toBasetype()->nextOf()->ty)
46581418a27Smrg                     {
46681418a27Smrg                         /* Allow things like:
46781418a27Smrg                          *      const char* P = cast(char *)3;
46881418a27Smrg                          *      char* q = P;
46981418a27Smrg                          */
47081418a27Smrg                         break;
47181418a27Smrg                     }
47281418a27Smrg                     /* fall through */
47381418a27Smrg 
47481418a27Smrg                 default:
47581418a27Smrg                     visit((Expression *)e);
47681418a27Smrg                 return;
47781418a27Smrg             }
47881418a27Smrg 
47981418a27Smrg             //printf("MATCHconvert\n");
48081418a27Smrg             result = MATCHconvert;
48181418a27Smrg         }
48281418a27Smrg 
48381418a27Smrg         void visit(ErrorExp *)
48481418a27Smrg         {
48581418a27Smrg             // no match
48681418a27Smrg         }
48781418a27Smrg 
48881418a27Smrg         void visit(NullExp *e)
48981418a27Smrg         {
49081418a27Smrg             if (e->type->equals(t))
49181418a27Smrg             {
49281418a27Smrg                 result = MATCHexact;
49381418a27Smrg                 return;
49481418a27Smrg             }
49581418a27Smrg 
49681418a27Smrg             /* Allow implicit conversions from immutable to mutable|const,
49781418a27Smrg              * and mutable to immutable. It works because, after all, a null
49881418a27Smrg              * doesn't actually point to anything.
49981418a27Smrg              */
50081418a27Smrg             if (t->equivalent(e->type))
50181418a27Smrg             {
50281418a27Smrg                 result = MATCHconst;
50381418a27Smrg                 return;
50481418a27Smrg             }
50581418a27Smrg 
50681418a27Smrg             visit((Expression *)e);
50781418a27Smrg         }
50881418a27Smrg 
50981418a27Smrg         void visit(StructLiteralExp *e)
51081418a27Smrg         {
51181418a27Smrg             visit((Expression *)e);
51281418a27Smrg             if (result != MATCHnomatch)
51381418a27Smrg                 return;
51481418a27Smrg             if (e->type->ty == t->ty && e->type->ty == Tstruct &&
51581418a27Smrg                 ((TypeStruct *)e->type)->sym == ((TypeStruct *)t)->sym)
51681418a27Smrg             {
51781418a27Smrg                 result = MATCHconst;
51881418a27Smrg                 for (size_t i = 0; i < e->elements->dim; i++)
51981418a27Smrg                 {
52081418a27Smrg                     Expression *el = (*e->elements)[i];
52181418a27Smrg                     if (!el)
52281418a27Smrg                         continue;
52381418a27Smrg                     Type *te = el->type;
52481418a27Smrg                     te = e->sd->fields[i]->type->addMod(t->mod);
52581418a27Smrg                     MATCH m2 = el->implicitConvTo(te);
52681418a27Smrg                     //printf("\t%s => %s, match = %d\n", el->toChars(), te->toChars(), m2);
52781418a27Smrg                     if (m2 < result)
52881418a27Smrg                         result = m2;
52981418a27Smrg                 }
53081418a27Smrg             }
53181418a27Smrg         }
53281418a27Smrg 
53381418a27Smrg         void visit(StringExp *e)
53481418a27Smrg         {
53581418a27Smrg             if (!e->committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
53681418a27Smrg                 return;
53781418a27Smrg 
53881418a27Smrg             if (e->type->ty == Tsarray || e->type->ty == Tarray || e->type->ty == Tpointer)
53981418a27Smrg             {
54081418a27Smrg                 TY tyn = e->type->nextOf()->ty;
54181418a27Smrg                 if (tyn == Tchar || tyn == Twchar || tyn == Tdchar)
54281418a27Smrg                 {
54381418a27Smrg                     switch (t->ty)
54481418a27Smrg                     {
54581418a27Smrg                         case Tsarray:
54681418a27Smrg                             if (e->type->ty == Tsarray)
54781418a27Smrg                             {
54881418a27Smrg                                 TY tynto = t->nextOf()->ty;
54981418a27Smrg                                 if (tynto == tyn)
55081418a27Smrg                                 {
55181418a27Smrg                                     if (((TypeSArray *)e->type)->dim->toInteger() ==
55281418a27Smrg                                         ((TypeSArray *)t)->dim->toInteger())
55381418a27Smrg                                     {
55481418a27Smrg                                         result = MATCHexact;
55581418a27Smrg                                     }
55681418a27Smrg                                     return;
55781418a27Smrg                                 }
55881418a27Smrg                                 if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
55981418a27Smrg                                 {
56081418a27Smrg                                     if (e->committed && tynto != tyn)
56181418a27Smrg                                         return;
56281418a27Smrg                                     size_t fromlen = e->numberOfCodeUnits(tynto);
56381418a27Smrg                                     size_t tolen = (size_t)((TypeSArray *)t)->dim->toInteger();
56481418a27Smrg                                     if (tolen < fromlen)
56581418a27Smrg                                         return;
56681418a27Smrg                                     if (tolen != fromlen)
56781418a27Smrg                                     {
56881418a27Smrg                                         // implicit length extending
56981418a27Smrg                                         result = MATCHconvert;
57081418a27Smrg                                         return;
57181418a27Smrg                                     }
57281418a27Smrg                                 }
57381418a27Smrg                                 if (!e->committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar))
57481418a27Smrg                                 {
57581418a27Smrg                                     result = MATCHexact;
57681418a27Smrg                                     return;
57781418a27Smrg                                 }
57881418a27Smrg                             }
57981418a27Smrg                             else if (e->type->ty == Tarray)
58081418a27Smrg                             {
58181418a27Smrg                                 TY tynto = t->nextOf()->ty;
58281418a27Smrg                                 if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
58381418a27Smrg                                 {
58481418a27Smrg                                     if (e->committed && tynto != tyn)
58581418a27Smrg                                         return;
58681418a27Smrg                                     size_t fromlen = e->numberOfCodeUnits(tynto);
58781418a27Smrg                                     size_t tolen = (size_t)((TypeSArray *)t)->dim->toInteger();
58881418a27Smrg                                     if (tolen < fromlen)
58981418a27Smrg                                         return;
59081418a27Smrg                                     if (tolen != fromlen)
59181418a27Smrg                                     {
59281418a27Smrg                                         // implicit length extending
59381418a27Smrg                                         result = MATCHconvert;
59481418a27Smrg                                         return;
59581418a27Smrg                                     }
59681418a27Smrg                                 }
59781418a27Smrg                                 if (tynto == tyn)
59881418a27Smrg                                 {
59981418a27Smrg                                     result = MATCHexact;
60081418a27Smrg                                     return;
60181418a27Smrg                                 }
60281418a27Smrg                                 if (!e->committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar))
60381418a27Smrg                                 {
60481418a27Smrg                                     result = MATCHexact;
60581418a27Smrg                                     return;
60681418a27Smrg                                 }
60781418a27Smrg                             }
60881418a27Smrg                             /* fall through */
60981418a27Smrg                         case Tarray:
61081418a27Smrg                         case Tpointer:
61181418a27Smrg                             Type *tn = t->nextOf();
61281418a27Smrg                             MATCH m = MATCHexact;
61381418a27Smrg                             if (e->type->nextOf()->mod != tn->mod)
61481418a27Smrg                             {
61581418a27Smrg                                 if (!tn->isConst())
61681418a27Smrg                                     return;
61781418a27Smrg                                 m = MATCHconst;
61881418a27Smrg                             }
61981418a27Smrg                             if (!e->committed)
62081418a27Smrg                             {
62181418a27Smrg                                 switch (tn->ty)
62281418a27Smrg                                 {
62381418a27Smrg                                     case Tchar:
62481418a27Smrg                                         if (e->postfix == 'w' || e->postfix == 'd')
62581418a27Smrg                                             m = MATCHconvert;
62681418a27Smrg                                         result = m;
62781418a27Smrg                                         return;
62881418a27Smrg                                     case Twchar:
62981418a27Smrg                                         if (e->postfix != 'w')
63081418a27Smrg                                             m = MATCHconvert;
63181418a27Smrg                                         result = m;
63281418a27Smrg                                         return;
63381418a27Smrg                                     case Tdchar:
63481418a27Smrg                                         if (e->postfix != 'd')
63581418a27Smrg                                             m = MATCHconvert;
63681418a27Smrg                                         result = m;
63781418a27Smrg                                         return;
63881418a27Smrg                                 }
63981418a27Smrg                             }
64081418a27Smrg                             break;
64181418a27Smrg                     }
64281418a27Smrg                 }
64381418a27Smrg             }
64481418a27Smrg 
64581418a27Smrg             visit((Expression *)e);
64681418a27Smrg         }
64781418a27Smrg 
64881418a27Smrg         void visit(ArrayLiteralExp *e)
64981418a27Smrg         {
65081418a27Smrg             Type *typeb = e->type->toBasetype();
65181418a27Smrg             Type *tb = t->toBasetype();
65281418a27Smrg             if ((tb->ty == Tarray || tb->ty == Tsarray) &&
65381418a27Smrg                 (typeb->ty == Tarray || typeb->ty == Tsarray))
65481418a27Smrg             {
65581418a27Smrg                 result = MATCHexact;
65681418a27Smrg                 Type *typen = typeb->nextOf()->toBasetype();
65781418a27Smrg 
65881418a27Smrg                 if (tb->ty == Tsarray)
65981418a27Smrg                 {
66081418a27Smrg                     TypeSArray *tsa = (TypeSArray *)tb;
66181418a27Smrg                     if (e->elements->dim != tsa->dim->toInteger())
66281418a27Smrg                         result = MATCHnomatch;
66381418a27Smrg                 }
66481418a27Smrg 
66581418a27Smrg                 Type *telement = tb->nextOf();
66681418a27Smrg                 if (!e->elements->dim)
66781418a27Smrg                 {
66881418a27Smrg                     if (typen->ty != Tvoid)
66981418a27Smrg                         result = typen->implicitConvTo(telement);
67081418a27Smrg                 }
67181418a27Smrg                 else
67281418a27Smrg                 {
67381418a27Smrg                     if (e->basis)
67481418a27Smrg                     {
67581418a27Smrg                         MATCH m = e->basis->implicitConvTo(telement);
67681418a27Smrg                         if (m < result)
67781418a27Smrg                             result = m;
67881418a27Smrg                     }
67981418a27Smrg                     for (size_t i = 0; i < e->elements->dim; i++)
68081418a27Smrg                     {
68181418a27Smrg                         Expression *el = (*e->elements)[i];
68281418a27Smrg                         if (result == MATCHnomatch)
68381418a27Smrg                             break;
68481418a27Smrg                         if (!el)
68581418a27Smrg                             continue;
68681418a27Smrg                         MATCH m = el->implicitConvTo(telement);
68781418a27Smrg                         if (m < result)
68881418a27Smrg                             result = m;                     // remember worst match
68981418a27Smrg                     }
69081418a27Smrg                 }
69181418a27Smrg 
69281418a27Smrg                 if (!result)
69381418a27Smrg                     result = e->type->implicitConvTo(t);
69481418a27Smrg 
69581418a27Smrg                 return;
69681418a27Smrg             }
69781418a27Smrg             else if (tb->ty == Tvector &&
69881418a27Smrg                 (typeb->ty == Tarray || typeb->ty == Tsarray))
69981418a27Smrg             {
70081418a27Smrg                 result = MATCHexact;
70181418a27Smrg                 // Convert array literal to vector type
70281418a27Smrg                 TypeVector *tv = (TypeVector *)tb;
70381418a27Smrg                 TypeSArray *tbase = (TypeSArray *)tv->basetype;
70481418a27Smrg                 assert(tbase->ty == Tsarray);
70581418a27Smrg                 const size_t edim = e->elements->dim;
70681418a27Smrg                 const size_t tbasedim = tbase->dim->toInteger();
70781418a27Smrg                 if (edim > tbasedim)
70881418a27Smrg                 {
70981418a27Smrg                     result = MATCHnomatch;
71081418a27Smrg                     return;
71181418a27Smrg                 }
71281418a27Smrg 
71381418a27Smrg                 Type *telement = tv->elementType();
71481418a27Smrg                 if (edim < tbasedim)
71581418a27Smrg                 {
71681418a27Smrg                     Expression *el = typeb->nextOf()->defaultInitLiteral(e->loc);
71781418a27Smrg                     MATCH m = el->implicitConvTo(telement);
71881418a27Smrg                     if (m < result)
71981418a27Smrg                         result = m; // remember worst match
72081418a27Smrg                 }
72181418a27Smrg                 for (size_t i = 0; i < edim; i++)
72281418a27Smrg                 {
72381418a27Smrg                     Expression *el = (*e->elements)[i];
72481418a27Smrg                     MATCH m = el->implicitConvTo(telement);
72581418a27Smrg                     if (m < result)
72681418a27Smrg                         result = m;                     // remember worst match
72781418a27Smrg                     if (result == MATCHnomatch)
72881418a27Smrg                         break;                          // no need to check for worse
72981418a27Smrg                 }
73081418a27Smrg                 return;
73181418a27Smrg             }
73281418a27Smrg 
73381418a27Smrg             visit((Expression *)e);
73481418a27Smrg         }
73581418a27Smrg 
73681418a27Smrg         void visit(AssocArrayLiteralExp *e)
73781418a27Smrg         {
73881418a27Smrg             Type *typeb = e->type->toBasetype();
73981418a27Smrg             Type *tb = t->toBasetype();
74081418a27Smrg             if (tb->ty == Taarray && typeb->ty == Taarray)
74181418a27Smrg             {
74281418a27Smrg                 result = MATCHexact;
74381418a27Smrg                 for (size_t i = 0; i < e->keys->dim; i++)
74481418a27Smrg                 {
74581418a27Smrg                     Expression *el = (*e->keys)[i];
74681418a27Smrg                     MATCH m = el->implicitConvTo(((TypeAArray *)tb)->index);
74781418a27Smrg                     if (m < result)
74881418a27Smrg                         result = m;                     // remember worst match
74981418a27Smrg                     if (result == MATCHnomatch)
75081418a27Smrg                         break;                          // no need to check for worse
75181418a27Smrg                     el = (*e->values)[i];
75281418a27Smrg                     m = el->implicitConvTo(tb->nextOf());
75381418a27Smrg                     if (m < result)
75481418a27Smrg                         result = m;                     // remember worst match
75581418a27Smrg                     if (result == MATCHnomatch)
75681418a27Smrg                         break;                          // no need to check for worse
75781418a27Smrg                 }
75881418a27Smrg                 return;
75981418a27Smrg             }
76081418a27Smrg             else
76181418a27Smrg                 visit((Expression *)e);
76281418a27Smrg         }
76381418a27Smrg 
76481418a27Smrg         void visit(CallExp *e)
76581418a27Smrg         {
76681418a27Smrg             visit((Expression *)e);
76781418a27Smrg             if (result != MATCHnomatch)
76881418a27Smrg                 return;
76981418a27Smrg 
77081418a27Smrg             /* Allow the result of strongly pure functions to
77181418a27Smrg              * convert to immutable
77281418a27Smrg              */
77381418a27Smrg             if (e->f && e->f->isolateReturn())
77481418a27Smrg             {
77581418a27Smrg                 result = e->type->immutableOf()->implicitConvTo(t);
77681418a27Smrg                 if (result > MATCHconst)    // Match level is MATCHconst at best.
77781418a27Smrg                     result = MATCHconst;
77881418a27Smrg                 return;
77981418a27Smrg             }
78081418a27Smrg 
78181418a27Smrg             /* Conversion is 'const' conversion if:
78281418a27Smrg              * 1. function is pure (weakly pure is ok)
78381418a27Smrg              * 2. implicit conversion only fails because of mod bits
78481418a27Smrg              * 3. each function parameter can be implicitly converted to the mod bits
78581418a27Smrg              */
78681418a27Smrg             Type *tx = e->f ? e->f->type : e->e1->type;
78781418a27Smrg             tx = tx->toBasetype();
78881418a27Smrg             if (tx->ty != Tfunction)
78981418a27Smrg                 return;
79081418a27Smrg             TypeFunction *tf = (TypeFunction *)tx;
79181418a27Smrg 
79281418a27Smrg             if (tf->purity == PUREimpure)
79381418a27Smrg                 return;
79481418a27Smrg             if (e->f && e->f->isNested())
79581418a27Smrg                 return;
79681418a27Smrg 
79781418a27Smrg             /* See if fail only because of mod bits.
79881418a27Smrg              *
79981418a27Smrg              * Bugzilla 14155: All pure functions can access global immutable data.
80081418a27Smrg              * So the returned pointer may refer an immutable global data,
80181418a27Smrg              * and then the returned pointer that points non-mutable object
80281418a27Smrg              * cannot be unique pointer.
80381418a27Smrg              *
80481418a27Smrg              * Example:
80581418a27Smrg              *  immutable g;
80681418a27Smrg              *  static this() { g = 1; }
80781418a27Smrg              *  const(int*) foo() pure { return &g; }
80881418a27Smrg              *  void test() {
80981418a27Smrg              *    immutable(int*) ip = foo(); // OK
81081418a27Smrg              *    int* mp = foo();            // should be disallowed
81181418a27Smrg              *  }
81281418a27Smrg              */
81381418a27Smrg             if (e->type->immutableOf()->implicitConvTo(t) < MATCHconst &&
81481418a27Smrg                 e->type->addMod(MODshared)->implicitConvTo(t) < MATCHconst &&
81581418a27Smrg                 e->type->implicitConvTo(t->addMod(MODshared)) < MATCHconst)
81681418a27Smrg             {
81781418a27Smrg                 return;
81881418a27Smrg             }
81981418a27Smrg             // Allow a conversion to immutable type, or
82081418a27Smrg             // conversions of mutable types between thread-local and shared.
82181418a27Smrg 
82281418a27Smrg             /* Get mod bits of what we're converting to
82381418a27Smrg              */
82481418a27Smrg             Type *tb = t->toBasetype();
82581418a27Smrg             MOD mod = tb->mod;
82681418a27Smrg             if (tf->isref)
82781418a27Smrg                 ;
82881418a27Smrg             else
82981418a27Smrg             {
83081418a27Smrg                 Type *ti = getIndirection(t);
83181418a27Smrg                 if (ti)
83281418a27Smrg                     mod = ti->mod;
83381418a27Smrg             }
83481418a27Smrg             if (mod & MODwild)
83581418a27Smrg                 return;                 // not sure what to do with this
83681418a27Smrg 
83781418a27Smrg             /* Apply mod bits to each function parameter,
83881418a27Smrg              * and see if we can convert the function argument to the modded type
83981418a27Smrg              */
84081418a27Smrg 
84181418a27Smrg             size_t nparams = Parameter::dim(tf->parameters);
84281418a27Smrg             size_t j = (tf->linkage == LINKd && tf->varargs == 1); // if TypeInfoArray was prepended
84381418a27Smrg             if (e->e1->op == TOKdotvar)
84481418a27Smrg             {
84581418a27Smrg                 /* Treat 'this' as just another function argument
84681418a27Smrg                  */
84781418a27Smrg                 DotVarExp *dve = (DotVarExp *)e->e1;
84881418a27Smrg                 Type *targ = dve->e1->type;
84981418a27Smrg                 if (targ->constConv(targ->castMod(mod)) == MATCHnomatch)
85081418a27Smrg                     return;
85181418a27Smrg             }
85281418a27Smrg             for (size_t i = j; i < e->arguments->dim; ++i)
85381418a27Smrg             {
85481418a27Smrg                 Expression *earg = (*e->arguments)[i];
85581418a27Smrg                 Type *targ = earg->type->toBasetype();
85681418a27Smrg                 if (i - j < nparams)
85781418a27Smrg                 {
85881418a27Smrg                     Parameter *fparam = Parameter::getNth(tf->parameters, i - j);
85981418a27Smrg                     if (fparam->storageClass & STClazy)
86081418a27Smrg                         return;                 // not sure what to do with this
86181418a27Smrg                     Type *tparam = fparam->type;
86281418a27Smrg                     if (!tparam)
86381418a27Smrg                         continue;
86481418a27Smrg                     if (fparam->storageClass & (STCout | STCref))
86581418a27Smrg                     {
86681418a27Smrg                         if (targ->constConv(tparam->castMod(mod)) == MATCHnomatch)
86781418a27Smrg                             return;
86881418a27Smrg                         continue;
86981418a27Smrg                     }
87081418a27Smrg                 }
87181418a27Smrg 
87281418a27Smrg                 if (implicitMod(earg, targ, mod) == MATCHnomatch)
87381418a27Smrg                     return;
87481418a27Smrg             }
87581418a27Smrg 
87681418a27Smrg             /* Success
87781418a27Smrg              */
87881418a27Smrg             result = MATCHconst;
87981418a27Smrg         }
88081418a27Smrg 
88181418a27Smrg         void visit(AddrExp *e)
88281418a27Smrg         {
88381418a27Smrg             result = e->type->implicitConvTo(t);
88481418a27Smrg             //printf("\tresult = %d\n", result);
88581418a27Smrg 
88681418a27Smrg             if (result != MATCHnomatch)
88781418a27Smrg                 return;
88881418a27Smrg 
88981418a27Smrg             // Look for pointers to functions where the functions are overloaded.
89081418a27Smrg 
89181418a27Smrg             t = t->toBasetype();
89281418a27Smrg 
89381418a27Smrg             if (e->e1->op == TOKoverloadset &&
89481418a27Smrg                 (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
89581418a27Smrg             {
89681418a27Smrg                 OverExp *eo = (OverExp *)e->e1;
89781418a27Smrg                 FuncDeclaration *f = NULL;
89881418a27Smrg                 for (size_t i = 0; i < eo->vars->a.dim; i++)
89981418a27Smrg                 {
90081418a27Smrg                     Dsymbol *s = eo->vars->a[i];
90181418a27Smrg                     FuncDeclaration *f2 = s->isFuncDeclaration();
90281418a27Smrg                     assert(f2);
90381418a27Smrg                     if (f2->overloadExactMatch(t->nextOf()))
90481418a27Smrg                     {
90581418a27Smrg                         if (f)
90681418a27Smrg                         {
90781418a27Smrg                             /* Error if match in more than one overload set,
90881418a27Smrg                              * even if one is a 'better' match than the other.
90981418a27Smrg                              */
91081418a27Smrg                             ScopeDsymbol::multiplyDefined(e->loc, f, f2);
91181418a27Smrg                         }
91281418a27Smrg                         else
91381418a27Smrg                             f = f2;
91481418a27Smrg                         result = MATCHexact;
91581418a27Smrg                     }
91681418a27Smrg                 }
91781418a27Smrg             }
91881418a27Smrg 
91981418a27Smrg             if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tfunction &&
92081418a27Smrg                 t->ty == Tpointer && t->nextOf()->ty == Tfunction &&
92181418a27Smrg                 e->e1->op == TOKvar)
92281418a27Smrg             {
92381418a27Smrg                 /* I don't think this can ever happen -
92481418a27Smrg                  * it should have been
92581418a27Smrg                  * converted to a SymOffExp.
92681418a27Smrg                  */
92781418a27Smrg                 assert(0);
92881418a27Smrg             }
92981418a27Smrg 
93081418a27Smrg             //printf("\tresult = %d\n", result);
93181418a27Smrg         }
93281418a27Smrg 
93381418a27Smrg         void visit(SymOffExp *e)
93481418a27Smrg         {
93581418a27Smrg             result = e->type->implicitConvTo(t);
93681418a27Smrg             //printf("\tresult = %d\n", result);
93781418a27Smrg             if (result != MATCHnomatch)
93881418a27Smrg                 return;
93981418a27Smrg 
94081418a27Smrg             // Look for pointers to functions where the functions are overloaded.
94181418a27Smrg             t = t->toBasetype();
94281418a27Smrg             if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tfunction &&
94381418a27Smrg                 (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
94481418a27Smrg             {
94581418a27Smrg                 if (FuncDeclaration *f = e->var->isFuncDeclaration())
94681418a27Smrg                 {
94781418a27Smrg                     f = f->overloadExactMatch(t->nextOf());
94881418a27Smrg                     if (f)
94981418a27Smrg                     {
95081418a27Smrg                         if ((t->ty == Tdelegate && (f->needThis() || f->isNested())) ||
95181418a27Smrg                             (t->ty == Tpointer && !(f->needThis() || f->isNested())))
95281418a27Smrg                         {
95381418a27Smrg                             result = MATCHexact;
95481418a27Smrg                         }
95581418a27Smrg                     }
95681418a27Smrg                 }
95781418a27Smrg             }
95881418a27Smrg             //printf("\tresult = %d\n", result);
95981418a27Smrg         }
96081418a27Smrg 
96181418a27Smrg         void visit(DelegateExp *e)
96281418a27Smrg         {
96381418a27Smrg             result = e->type->implicitConvTo(t);
96481418a27Smrg             if (result != MATCHnomatch)
96581418a27Smrg                 return;
96681418a27Smrg 
96781418a27Smrg             // Look for pointers to functions where the functions are overloaded.
96881418a27Smrg             t = t->toBasetype();
96981418a27Smrg             if (e->type->ty == Tdelegate &&
97081418a27Smrg                 t->ty == Tdelegate)
97181418a27Smrg             {
97281418a27Smrg                 if (e->func && e->func->overloadExactMatch(t->nextOf()))
97381418a27Smrg                     result = MATCHexact;
97481418a27Smrg             }
97581418a27Smrg         }
97681418a27Smrg 
97781418a27Smrg         void visit(FuncExp *e)
97881418a27Smrg         {
97981418a27Smrg             //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e->type, e->type ? e->type->toChars() : NULL, t->toChars());
98081418a27Smrg             MATCH m = e->matchType(t, NULL, NULL, 1);
98181418a27Smrg             if (m > MATCHnomatch)
98281418a27Smrg             {
98381418a27Smrg                 result = m;
98481418a27Smrg                 return;
98581418a27Smrg             }
98681418a27Smrg             visit((Expression *)e);
98781418a27Smrg         }
98881418a27Smrg 
98981418a27Smrg         void visit(AndExp *e)
99081418a27Smrg         {
99181418a27Smrg             visit((Expression *)e);
99281418a27Smrg             if (result != MATCHnomatch)
99381418a27Smrg                 return;
99481418a27Smrg 
99581418a27Smrg             MATCH m1 = e->e1->implicitConvTo(t);
99681418a27Smrg             MATCH m2 = e->e2->implicitConvTo(t);
99781418a27Smrg 
99881418a27Smrg             // Pick the worst match
99981418a27Smrg             result = (m1 < m2) ? m1 : m2;
100081418a27Smrg         }
100181418a27Smrg 
100281418a27Smrg         void visit(OrExp *e)
100381418a27Smrg         {
100481418a27Smrg             visit((Expression *)e);
100581418a27Smrg             if (result != MATCHnomatch)
100681418a27Smrg                 return;
100781418a27Smrg 
100881418a27Smrg             MATCH m1 = e->e1->implicitConvTo(t);
100981418a27Smrg             MATCH m2 = e->e2->implicitConvTo(t);
101081418a27Smrg 
101181418a27Smrg             // Pick the worst match
101281418a27Smrg             result = (m1 < m2) ? m1 : m2;
101381418a27Smrg         }
101481418a27Smrg 
101581418a27Smrg         void visit(XorExp *e)
101681418a27Smrg         {
101781418a27Smrg             visit((Expression *)e);
101881418a27Smrg             if (result != MATCHnomatch)
101981418a27Smrg                 return;
102081418a27Smrg 
102181418a27Smrg             MATCH m1 = e->e1->implicitConvTo(t);
102281418a27Smrg             MATCH m2 = e->e2->implicitConvTo(t);
102381418a27Smrg 
102481418a27Smrg             // Pick the worst match
102581418a27Smrg             result = (m1 < m2) ? m1 : m2;
102681418a27Smrg         }
102781418a27Smrg 
102881418a27Smrg         void visit(CondExp *e)
102981418a27Smrg         {
103081418a27Smrg             MATCH m1 = e->e1->implicitConvTo(t);
103181418a27Smrg             MATCH m2 = e->e2->implicitConvTo(t);
103281418a27Smrg             //printf("CondExp: m1 %d m2 %d\n", m1, m2);
103381418a27Smrg 
103481418a27Smrg             // Pick the worst match
103581418a27Smrg             result = (m1 < m2) ? m1 : m2;
103681418a27Smrg         }
103781418a27Smrg 
103881418a27Smrg         void visit(CommaExp *e)
103981418a27Smrg         {
104081418a27Smrg             e->e2->accept(this);
104181418a27Smrg         }
104281418a27Smrg 
104381418a27Smrg         void visit(CastExp *e)
104481418a27Smrg         {
104581418a27Smrg             result = e->type->implicitConvTo(t);
104681418a27Smrg             if (result != MATCHnomatch)
104781418a27Smrg                 return;
104881418a27Smrg 
104981418a27Smrg             if (t->isintegral() &&
105081418a27Smrg                 e->e1->type->isintegral() &&
105181418a27Smrg                 e->e1->implicitConvTo(t) != MATCHnomatch)
105281418a27Smrg                 result = MATCHconvert;
105381418a27Smrg             else
105481418a27Smrg                 visit((Expression *)e);
105581418a27Smrg         }
105681418a27Smrg 
105781418a27Smrg         void visit(NewExp *e)
105881418a27Smrg         {
105981418a27Smrg             visit((Expression *)e);
106081418a27Smrg             if (result != MATCHnomatch)
106181418a27Smrg                 return;
106281418a27Smrg 
106381418a27Smrg             /* Calling new() is like calling a pure function. We can implicitly convert the
106481418a27Smrg              * return from new() to t using the same algorithm as in CallExp, with the function
106581418a27Smrg              * 'arguments' being:
106681418a27Smrg              *    thisexp
106781418a27Smrg              *    newargs
106881418a27Smrg              *    arguments
106981418a27Smrg              *    .init
107081418a27Smrg              * 'member' and 'allocator' need to be pure.
107181418a27Smrg              */
107281418a27Smrg 
107381418a27Smrg             /* See if fail only because of mod bits
107481418a27Smrg              */
107581418a27Smrg             if (e->type->immutableOf()->implicitConvTo(t->immutableOf()) == MATCHnomatch)
107681418a27Smrg                 return;
107781418a27Smrg 
107881418a27Smrg             /* Get mod bits of what we're converting to
107981418a27Smrg              */
108081418a27Smrg             Type *tb = t->toBasetype();
108181418a27Smrg             MOD mod = tb->mod;
108281418a27Smrg             if (Type *ti = getIndirection(t))
108381418a27Smrg                 mod = ti->mod;
108481418a27Smrg             if (mod & MODwild)
108581418a27Smrg                 return;                 // not sure what to do with this
108681418a27Smrg 
108781418a27Smrg             /* Apply mod bits to each argument,
108881418a27Smrg              * and see if we can convert the argument to the modded type
108981418a27Smrg              */
109081418a27Smrg 
109181418a27Smrg             if (e->thisexp)
109281418a27Smrg             {
109381418a27Smrg                 /* Treat 'this' as just another function argument
109481418a27Smrg                  */
109581418a27Smrg                 Type *targ = e->thisexp->type;
109681418a27Smrg                 if (targ->constConv(targ->castMod(mod)) == MATCHnomatch)
109781418a27Smrg                     return;
109881418a27Smrg             }
109981418a27Smrg 
110081418a27Smrg             /* Check call to 'allocator', then 'member'
110181418a27Smrg              */
110281418a27Smrg             FuncDeclaration *fd = e->allocator;
110381418a27Smrg             for (int count = 0; count < 2; ++count, (fd = e->member))
110481418a27Smrg             {
110581418a27Smrg                 if (!fd)
110681418a27Smrg                     continue;
110781418a27Smrg                 if (fd->errors || fd->type->ty != Tfunction)
110881418a27Smrg                     return;     // error
110981418a27Smrg                 TypeFunction *tf = (TypeFunction *)fd->type;
111081418a27Smrg                 if (tf->purity == PUREimpure)
111181418a27Smrg                     return;     // impure
111281418a27Smrg 
111381418a27Smrg                 if (fd == e->member)
111481418a27Smrg                 {
111581418a27Smrg                     if (e->type->immutableOf()->implicitConvTo(t) < MATCHconst &&
111681418a27Smrg                         e->type->addMod(MODshared)->implicitConvTo(t) < MATCHconst &&
111781418a27Smrg                         e->type->implicitConvTo(t->addMod(MODshared)) < MATCHconst)
111881418a27Smrg                     {
111981418a27Smrg                         return;
112081418a27Smrg                     }
112181418a27Smrg                     // Allow a conversion to immutable type, or
112281418a27Smrg                     // conversions of mutable types between thread-local and shared.
112381418a27Smrg                 }
112481418a27Smrg 
112581418a27Smrg                 Expressions *args = (fd == e->allocator) ? e->newargs : e->arguments;
112681418a27Smrg 
112781418a27Smrg                 size_t nparams = Parameter::dim(tf->parameters);
112881418a27Smrg                 size_t j = (tf->linkage == LINKd && tf->varargs == 1); // if TypeInfoArray was prepended
112981418a27Smrg                 for (size_t i = j; i < e->arguments->dim; ++i)
113081418a27Smrg                 {
113181418a27Smrg                     Expression *earg = (*args)[i];
113281418a27Smrg                     Type *targ = earg->type->toBasetype();
113381418a27Smrg                     if (i - j < nparams)
113481418a27Smrg                     {
113581418a27Smrg                         Parameter *fparam = Parameter::getNth(tf->parameters, i - j);
113681418a27Smrg                         if (fparam->storageClass & STClazy)
113781418a27Smrg                             return;                 // not sure what to do with this
113881418a27Smrg                         Type *tparam = fparam->type;
113981418a27Smrg                         if (!tparam)
114081418a27Smrg                             continue;
114181418a27Smrg                         if (fparam->storageClass & (STCout | STCref))
114281418a27Smrg                         {
114381418a27Smrg                             if (targ->constConv(tparam->castMod(mod)) == MATCHnomatch)
114481418a27Smrg                                 return;
114581418a27Smrg                             continue;
114681418a27Smrg                         }
114781418a27Smrg                     }
114881418a27Smrg 
114981418a27Smrg                     if (implicitMod(earg, targ, mod) == MATCHnomatch)
115081418a27Smrg                         return;
115181418a27Smrg                 }
115281418a27Smrg             }
115381418a27Smrg 
115481418a27Smrg             /* If no 'member', then construction is by simple assignment,
115581418a27Smrg              * and just straight check 'arguments'
115681418a27Smrg              */
115781418a27Smrg             if (!e->member && e->arguments)
115881418a27Smrg             {
115981418a27Smrg                 for (size_t i = 0; i < e->arguments->dim; ++i)
116081418a27Smrg                 {
116181418a27Smrg                     Expression *earg = (*e->arguments)[i];
116281418a27Smrg                     if (!earg)  // Bugzilla 14853: if it's on overlapped field
116381418a27Smrg                         continue;
116481418a27Smrg                     Type *targ = earg->type->toBasetype();
116581418a27Smrg                     if (implicitMod(earg, targ, mod) == MATCHnomatch)
116681418a27Smrg                         return;
116781418a27Smrg                 }
116881418a27Smrg             }
116981418a27Smrg 
117081418a27Smrg             /* Consider the .init expression as an argument
117181418a27Smrg              */
117281418a27Smrg             Type *ntb = e->newtype->toBasetype();
117381418a27Smrg             if (ntb->ty == Tarray)
117481418a27Smrg                 ntb = ntb->nextOf()->toBasetype();
117581418a27Smrg             if (ntb->ty == Tstruct)
117681418a27Smrg             {
117781418a27Smrg                 // Don't allow nested structs - uplevel reference may not be convertible
117881418a27Smrg                 StructDeclaration *sd = ((TypeStruct *)ntb)->sym;
117981418a27Smrg                 sd->size(e->loc);              // resolve any forward references
118081418a27Smrg                 if (sd->isNested())
118181418a27Smrg                     return;
118281418a27Smrg             }
118381418a27Smrg             if (ntb->isZeroInit(e->loc))
118481418a27Smrg             {
118581418a27Smrg                 /* Zeros are implicitly convertible, except for special cases.
118681418a27Smrg                  */
118781418a27Smrg                 if (ntb->ty == Tclass)
118881418a27Smrg                 {
118981418a27Smrg                     /* With new() must look at the class instance initializer.
119081418a27Smrg                      */
119181418a27Smrg                     ClassDeclaration *cd = ((TypeClass *)ntb)->sym;
119281418a27Smrg 
119381418a27Smrg                     cd->size(e->loc);          // resolve any forward references
119481418a27Smrg 
119581418a27Smrg                     if (cd->isNested())
119681418a27Smrg                         return;                 // uplevel reference may not be convertible
119781418a27Smrg 
119881418a27Smrg                     assert(!cd->isInterfaceDeclaration());
119981418a27Smrg 
120081418a27Smrg                     struct ClassCheck
120181418a27Smrg                     {
120281418a27Smrg                         static bool convertible(Loc loc, ClassDeclaration *cd, MOD mod)
120381418a27Smrg                         {
120481418a27Smrg                             for (size_t i = 0; i < cd->fields.dim; i++)
120581418a27Smrg                             {
120681418a27Smrg                                 VarDeclaration *v = cd->fields[i];
120781418a27Smrg                                 Initializer *init = v->_init;
120881418a27Smrg                                 if (init)
120981418a27Smrg                                 {
121081418a27Smrg                                     if (init->isVoidInitializer())
121181418a27Smrg                                         ;
121281418a27Smrg                                     else if (ExpInitializer *ei = init->isExpInitializer())
121381418a27Smrg                                     {
121481418a27Smrg                                         Type *tb = v->type->toBasetype();
121581418a27Smrg                                         if (implicitMod(ei->exp, tb, mod) == MATCHnomatch)
121681418a27Smrg                                             return false;
121781418a27Smrg                                     }
121881418a27Smrg                                     else
121981418a27Smrg                                     {
122081418a27Smrg                                         /* Enhancement: handle StructInitializer and ArrayInitializer
122181418a27Smrg                                          */
122281418a27Smrg                                         return false;
122381418a27Smrg                                     }
122481418a27Smrg                                 }
122581418a27Smrg                                 else if (!v->type->isZeroInit(loc))
122681418a27Smrg                                     return false;
122781418a27Smrg                             }
122881418a27Smrg                             return cd->baseClass ? convertible(loc, cd->baseClass, mod) : true;
122981418a27Smrg                         }
123081418a27Smrg                     };
123181418a27Smrg 
123281418a27Smrg                     if (!ClassCheck::convertible(e->loc, cd, mod))
123381418a27Smrg                         return;
123481418a27Smrg                 }
123581418a27Smrg             }
123681418a27Smrg             else
123781418a27Smrg             {
123881418a27Smrg                 Expression *earg = e->newtype->defaultInitLiteral(e->loc);
123981418a27Smrg                 Type *targ = e->newtype->toBasetype();
124081418a27Smrg 
124181418a27Smrg                 if (implicitMod(earg, targ, mod) == MATCHnomatch)
124281418a27Smrg                     return;
124381418a27Smrg             }
124481418a27Smrg 
124581418a27Smrg             /* Success
124681418a27Smrg              */
124781418a27Smrg             result = MATCHconst;
124881418a27Smrg         }
124981418a27Smrg 
125081418a27Smrg         void visit(SliceExp *e)
125181418a27Smrg         {
125281418a27Smrg             //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e->toChars(), e->type->toChars());
125381418a27Smrg             visit((Expression *)e);
125481418a27Smrg             if (result != MATCHnomatch)
125581418a27Smrg                 return;
125681418a27Smrg 
125781418a27Smrg             Type *tb = t->toBasetype();
125881418a27Smrg             Type *typeb = e->type->toBasetype();
125981418a27Smrg             if (tb->ty == Tsarray && typeb->ty == Tarray)
126081418a27Smrg             {
126181418a27Smrg                 typeb = toStaticArrayType(e);
126281418a27Smrg                 if (typeb)
126381418a27Smrg                     result = typeb->implicitConvTo(t);
126481418a27Smrg                 return;
126581418a27Smrg             }
126681418a27Smrg 
126781418a27Smrg             /* If the only reason it won't convert is because of the mod bits,
126881418a27Smrg              * then test for conversion by seeing if e1 can be converted with those
126981418a27Smrg              * same mod bits.
127081418a27Smrg              */
127181418a27Smrg             Type *t1b = e->e1->type->toBasetype();
127281418a27Smrg             if (tb->ty == Tarray && typeb->equivalent(tb))
127381418a27Smrg             {
127481418a27Smrg                 Type *tbn = tb->nextOf();
127581418a27Smrg                 Type *tx = NULL;
127681418a27Smrg 
127781418a27Smrg                 /* If e->e1 is dynamic array or pointer, the uniqueness of e->e1
127881418a27Smrg                  * is equivalent with the uniqueness of the referred data. And in here
127981418a27Smrg                  * we can have arbitrary typed reference for that.
128081418a27Smrg                  */
128181418a27Smrg                 if (t1b->ty == Tarray)
128281418a27Smrg                     tx = tbn->arrayOf();
128381418a27Smrg                 if (t1b->ty == Tpointer)
128481418a27Smrg                     tx = tbn->pointerTo();
128581418a27Smrg 
128681418a27Smrg                 /* If e->e1 is static array, at least it should be an rvalue.
128781418a27Smrg                  * If not, e->e1 is a reference, and its uniqueness does not link
128881418a27Smrg                  * to the uniqueness of the referred data.
128981418a27Smrg                  */
129081418a27Smrg                 if (t1b->ty == Tsarray && !e->e1->isLvalue())
129181418a27Smrg                     tx = tbn->sarrayOf(t1b->size() / tbn->size());
129281418a27Smrg 
129381418a27Smrg                 if (tx)
129481418a27Smrg                 {
129581418a27Smrg                     result = e->e1->implicitConvTo(tx);
129681418a27Smrg                     if (result > MATCHconst)    // Match level is MATCHconst at best.
129781418a27Smrg                         result = MATCHconst;
129881418a27Smrg                 }
129981418a27Smrg             }
130081418a27Smrg 
130181418a27Smrg             // Enhancement 10724
130281418a27Smrg             if (tb->ty == Tpointer && e->e1->op == TOKstring)
130381418a27Smrg                 e->e1->accept(this);
130481418a27Smrg         }
130581418a27Smrg     };
130681418a27Smrg 
130781418a27Smrg     ImplicitConvTo v(t);
130881418a27Smrg     e->accept(&v);
130981418a27Smrg     return v.result;
131081418a27Smrg }
131181418a27Smrg 
toStaticArrayType(SliceExp * e)131281418a27Smrg Type *toStaticArrayType(SliceExp *e)
131381418a27Smrg {
131481418a27Smrg     if (e->lwr && e->upr)
131581418a27Smrg     {
131681418a27Smrg         // For the following code to work, e should be optimized beforehand.
131781418a27Smrg         // (eg. $ in lwr and upr should be already resolved, if possible)
131881418a27Smrg         Expression *lwr = e->lwr->optimize(WANTvalue);
131981418a27Smrg         Expression *upr = e->upr->optimize(WANTvalue);
132081418a27Smrg         if (lwr->isConst() && upr->isConst())
132181418a27Smrg         {
132281418a27Smrg             size_t len = (size_t)(upr->toUInteger() - lwr->toUInteger());
132381418a27Smrg             return e->type->toBasetype()->nextOf()->sarrayOf(len);
132481418a27Smrg         }
132581418a27Smrg     }
132681418a27Smrg     else
132781418a27Smrg     {
132881418a27Smrg         Type *t1b = e->e1->type->toBasetype();
132981418a27Smrg         if (t1b->ty == Tsarray)
133081418a27Smrg             return t1b;
133181418a27Smrg     }
133281418a27Smrg     return NULL;
133381418a27Smrg }
133481418a27Smrg 
133581418a27Smrg /* ==================== castTo ====================== */
133681418a27Smrg 
133781418a27Smrg /**************************************
133881418a27Smrg  * Do an explicit cast.
133981418a27Smrg  * Assume that the 'this' expression does not have any indirections.
134081418a27Smrg  */
134181418a27Smrg 
castTo(Expression * e,Scope * sc,Type * t)134281418a27Smrg Expression *castTo(Expression *e, Scope *sc, Type *t)
134381418a27Smrg {
134481418a27Smrg     class CastTo : public Visitor
134581418a27Smrg     {
134681418a27Smrg     public:
134781418a27Smrg         Type *t;
134881418a27Smrg         Scope *sc;
134981418a27Smrg         Expression *result;
135081418a27Smrg 
135181418a27Smrg         CastTo(Scope *sc, Type *t)
135281418a27Smrg             : t(t), sc(sc)
135381418a27Smrg         {
135481418a27Smrg             result = NULL;
135581418a27Smrg         }
135681418a27Smrg 
135781418a27Smrg         void visit(Expression *e)
135881418a27Smrg         {
135981418a27Smrg             //printf("Expression::castTo(this=%s, t=%s)\n", e->toChars(), t->toChars());
136081418a27Smrg             if (e->type->equals(t))
136181418a27Smrg             {
136281418a27Smrg                 result = e;
136381418a27Smrg                 return;
136481418a27Smrg             }
136581418a27Smrg             if (e->op == TOKvar)
136681418a27Smrg             {
136781418a27Smrg                 VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
136881418a27Smrg                 if (v && v->storage_class & STCmanifest)
136981418a27Smrg                 {
137081418a27Smrg                     result = e->ctfeInterpret();
137181418a27Smrg                     result = result->castTo(sc, t);
137281418a27Smrg                     return;
137381418a27Smrg                 }
137481418a27Smrg             }
137581418a27Smrg 
137681418a27Smrg             Type *tob = t->toBasetype();
137781418a27Smrg             Type *t1b = e->type->toBasetype();
137881418a27Smrg             if (tob->equals(t1b))
137981418a27Smrg             {
138081418a27Smrg                 result = e->copy();  // because of COW for assignment to e->type
138181418a27Smrg                 result->type = t;
138281418a27Smrg                 return;
138381418a27Smrg             }
138481418a27Smrg 
138581418a27Smrg             /* Make semantic error against invalid cast between concrete types.
138681418a27Smrg              * Assume that 'e' is never be any placeholder expressions.
138781418a27Smrg              * The result of these checks should be consistent with CastExp::toElem().
138881418a27Smrg              */
138981418a27Smrg 
139081418a27Smrg             // Fat Value types
139181418a27Smrg             const bool tob_isFV = (tob->ty == Tstruct || tob->ty == Tsarray || tob->ty == Tvector);
139281418a27Smrg             const bool t1b_isFV = (t1b->ty == Tstruct || t1b->ty == Tsarray || t1b->ty == Tvector);
139381418a27Smrg 
139481418a27Smrg             // Fat Reference types
139581418a27Smrg             const bool tob_isFR = (tob->ty == Tarray || tob->ty == Tdelegate);
139681418a27Smrg             const bool t1b_isFR = (t1b->ty == Tarray || t1b->ty == Tdelegate);
139781418a27Smrg 
139881418a27Smrg             // Reference types
139981418a27Smrg             const bool tob_isR = (tob_isFR || tob->ty == Tpointer || tob->ty == Taarray || tob->ty == Tclass);
140081418a27Smrg             const bool t1b_isR = (t1b_isFR || t1b->ty == Tpointer || t1b->ty == Taarray || t1b->ty == Tclass);
140181418a27Smrg 
140281418a27Smrg             // Arithmetic types (== valueable basic types)
140381418a27Smrg             const bool tob_isA = ((tob->isintegral() || tob->isfloating()) && tob->ty != Tvector);
140481418a27Smrg             const bool t1b_isA = ((t1b->isintegral() || t1b->isfloating()) && t1b->ty != Tvector);
140581418a27Smrg 
140681418a27Smrg             if (AggregateDeclaration *t1ad = isAggregate(t1b))
140781418a27Smrg             {
140881418a27Smrg                 AggregateDeclaration *toad = isAggregate(tob);
140981418a27Smrg                 if (t1ad != toad && t1ad->aliasthis)
141081418a27Smrg                 {
141181418a27Smrg                     if (t1b->ty == Tclass && tob->ty == Tclass)
141281418a27Smrg                     {
141381418a27Smrg                         ClassDeclaration *t1cd = t1b->isClassHandle();
141481418a27Smrg                         ClassDeclaration *tocd = tob->isClassHandle();
141581418a27Smrg                         int offset;
141681418a27Smrg                         if (tocd->isBaseOf(t1cd, &offset))
141781418a27Smrg                              goto Lok;
141881418a27Smrg                     }
141981418a27Smrg 
142081418a27Smrg                     /* Forward the cast to our alias this member, rewrite to:
142181418a27Smrg                      *   cast(to)e1.aliasthis
142281418a27Smrg                      */
142381418a27Smrg                     result = resolveAliasThis(sc, e);
142481418a27Smrg                     result = result->castTo(sc, t);
142581418a27Smrg                     return;
142681418a27Smrg                 }
142781418a27Smrg             }
142881418a27Smrg             else if (tob->ty == Tvector && t1b->ty != Tvector)
142981418a27Smrg             {
143081418a27Smrg                 //printf("test1 e = %s, e->type = %s, tob = %s\n", e->toChars(), e->type->toChars(), tob->toChars());
143181418a27Smrg                 TypeVector *tv = (TypeVector *)tob;
143281418a27Smrg                 result = new CastExp(e->loc, e, tv->elementType());
143381418a27Smrg                 result = new VectorExp(e->loc, result, tob);
143481418a27Smrg                 result = ::semantic(result, sc);
143581418a27Smrg                 return;
143681418a27Smrg             }
143781418a27Smrg             else if (tob->ty != Tvector && t1b->ty == Tvector)
143881418a27Smrg             {
143981418a27Smrg                 // T[n] <-- __vector(U[m])
144081418a27Smrg                 if (tob->ty == Tsarray)
144181418a27Smrg                 {
144281418a27Smrg                     if (t1b->size(e->loc) == tob->size(e->loc))
144381418a27Smrg                         goto Lok;
144481418a27Smrg                 }
144581418a27Smrg                 goto Lfail;
144681418a27Smrg             }
144781418a27Smrg             else if (t1b->implicitConvTo(tob) == MATCHconst && t->equals(e->type->constOf()))
144881418a27Smrg             {
144981418a27Smrg                 result = e->copy();
145081418a27Smrg                 result->type = t;
145181418a27Smrg                 return;
145281418a27Smrg             }
145381418a27Smrg 
145481418a27Smrg             // arithmetic values vs. other arithmetic values
145581418a27Smrg             // arithmetic values vs. T*
145681418a27Smrg             if ((tob_isA && (t1b_isA || t1b->ty == Tpointer)) ||
145781418a27Smrg                 (t1b_isA && (tob_isA || tob->ty == Tpointer)))
145881418a27Smrg             {
145981418a27Smrg                 goto Lok;
146081418a27Smrg             }
146181418a27Smrg 
146281418a27Smrg             // arithmetic values vs. references or fat values
146381418a27Smrg             if ((tob_isA && (t1b_isR || t1b_isFV)) ||
146481418a27Smrg                 (t1b_isA && (tob_isR || tob_isFV)))
146581418a27Smrg             {
146681418a27Smrg                 goto Lfail;
146781418a27Smrg             }
146881418a27Smrg 
146981418a27Smrg             // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
147081418a27Smrg             if (tob_isFV && t1b_isFV)
147181418a27Smrg             {
147281418a27Smrg                 if (t1b->size(e->loc) == tob->size(e->loc))
147381418a27Smrg                     goto Lok;
147481418a27Smrg                 e->error("cannot cast expression %s of type %s to %s because of different sizes",
147581418a27Smrg                     e->toChars(), e->type->toChars(), t->toChars());
147681418a27Smrg                 result = new ErrorExp();
147781418a27Smrg                 return;
147881418a27Smrg             }
147981418a27Smrg 
148081418a27Smrg             // Fat values vs. null or references
148181418a27Smrg             if ((tob_isFV && (t1b->ty == Tnull || t1b_isR)) ||
148281418a27Smrg                 (t1b_isFV && (tob->ty == Tnull || tob_isR)))
148381418a27Smrg             {
148481418a27Smrg                 if (tob->ty == Tpointer && t1b->ty == Tsarray)
148581418a27Smrg                 {
148681418a27Smrg                     // T[n] sa;
148781418a27Smrg                     // cast(U*)sa; // ==> cast(U*)sa.ptr;
148881418a27Smrg                     result = new AddrExp(e->loc, e, t);
148981418a27Smrg                     return;
149081418a27Smrg                 }
149181418a27Smrg                 if (tob->ty == Tarray && t1b->ty == Tsarray)
149281418a27Smrg                 {
149381418a27Smrg                     // T[n] sa;
149481418a27Smrg                     // cast(U[])sa; // ==> cast(U[])sa[];
149581418a27Smrg                     d_uns64 fsize = t1b->nextOf()->size();
149681418a27Smrg                     d_uns64 tsize = tob->nextOf()->size();
1497*7327edafSmrg                     if (fsize != tsize)
149881418a27Smrg                     {
1499*7327edafSmrg                         dinteger_t dim = ((TypeSArray *)t1b)->dim->toInteger();
1500*7327edafSmrg                         if (tsize == 0 || (dim * fsize) % tsize != 0)
1501*7327edafSmrg                         {
1502*7327edafSmrg                             e->error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
150381418a27Smrg                                      e->toChars(), e->type->toChars(), t->toChars());
150481418a27Smrg                             result = new ErrorExp();
150581418a27Smrg                             return;
150681418a27Smrg                         }
1507*7327edafSmrg                     }
150881418a27Smrg                     goto Lok;
150981418a27Smrg                 }
151081418a27Smrg                 goto Lfail;
151181418a27Smrg             }
151281418a27Smrg 
151381418a27Smrg             /* For references, any reinterpret casts are allowed to same 'ty' type.
151481418a27Smrg              *      T* to U*
151581418a27Smrg              *      R1 function(P1) to R2 function(P2)
151681418a27Smrg              *      R1 delegate(P1) to R2 delegate(P2)
151781418a27Smrg              *      T[] to U[]
151881418a27Smrg              *      V1[K1] to V2[K2]
151981418a27Smrg              *      class/interface A to B  (will be a dynamic cast if possible)
152081418a27Smrg              */
152181418a27Smrg             if (tob->ty == t1b->ty && tob_isR && t1b_isR)
152281418a27Smrg                 goto Lok;
152381418a27Smrg 
152481418a27Smrg             // typeof(null) <-- non-null references or values
152581418a27Smrg             if (tob->ty == Tnull && t1b->ty != Tnull)
152681418a27Smrg                 goto Lfail;     // Bugzilla 14629
152781418a27Smrg             // typeof(null) --> non-null references or arithmetic values
152881418a27Smrg             if (t1b->ty == Tnull && tob->ty != Tnull)
152981418a27Smrg                 goto Lok;
153081418a27Smrg 
153181418a27Smrg             // Check size mismatch of references.
153281418a27Smrg             // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
153381418a27Smrg             if ((tob_isFR && t1b_isR) || (t1b_isFR && tob_isR))
153481418a27Smrg             {
153581418a27Smrg                 if (tob->ty == Tpointer && t1b->ty == Tarray)
153681418a27Smrg                 {
153781418a27Smrg                     // T[] da;
153881418a27Smrg                     // cast(U*)da; // ==> cast(U*)da.ptr;
153981418a27Smrg                     goto Lok;
154081418a27Smrg                 }
154181418a27Smrg                 if (tob->ty == Tpointer && t1b->ty == Tdelegate)
154281418a27Smrg                 {
154381418a27Smrg                     // void delegate() dg;
154481418a27Smrg                     // cast(U*)dg; // ==> cast(U*)dg.ptr;
154581418a27Smrg                     // Note that it happens even when U is a Tfunction!
154681418a27Smrg                     e->deprecation("casting from %s to %s is deprecated", e->type->toChars(), t->toChars());
154781418a27Smrg                     goto Lok;
154881418a27Smrg                 }
154981418a27Smrg                 goto Lfail;
155081418a27Smrg             }
155181418a27Smrg 
155281418a27Smrg             if (t1b->ty == Tvoid && tob->ty != Tvoid)
155381418a27Smrg             {
155481418a27Smrg             Lfail:
155581418a27Smrg                 e->error("cannot cast expression %s of type %s to %s",
155681418a27Smrg                     e->toChars(), e->type->toChars(), t->toChars());
155781418a27Smrg                 result = new ErrorExp();
155881418a27Smrg                 return;
155981418a27Smrg             }
156081418a27Smrg 
156181418a27Smrg         Lok:
156281418a27Smrg             result = new CastExp(e->loc, e, t);
156381418a27Smrg             result->type = t;       // Don't call semantic()
156481418a27Smrg             //printf("Returning: %s\n", result->toChars());
156581418a27Smrg         }
156681418a27Smrg 
156781418a27Smrg         void visit(ErrorExp *e)
156881418a27Smrg         {
156981418a27Smrg             result = e;
157081418a27Smrg         }
157181418a27Smrg 
157281418a27Smrg         void visit(RealExp *e)
157381418a27Smrg         {
157481418a27Smrg             if (!e->type->equals(t))
157581418a27Smrg             {
157681418a27Smrg                 if ((e->type->isreal() && t->isreal()) ||
157781418a27Smrg                     (e->type->isimaginary() && t->isimaginary())
157881418a27Smrg                    )
157981418a27Smrg                 {
158081418a27Smrg                     result = e->copy();
158181418a27Smrg                     result->type = t;
158281418a27Smrg                 }
158381418a27Smrg                 else
158481418a27Smrg                     visit((Expression *)e);
158581418a27Smrg                 return;
158681418a27Smrg             }
158781418a27Smrg             result = e;
158881418a27Smrg         }
158981418a27Smrg 
159081418a27Smrg         void visit(ComplexExp *e)
159181418a27Smrg         {
159281418a27Smrg             if (!e->type->equals(t))
159381418a27Smrg             {
159481418a27Smrg                 if (e->type->iscomplex() && t->iscomplex())
159581418a27Smrg                 {
159681418a27Smrg                     result = e->copy();
159781418a27Smrg                     result->type = t;
159881418a27Smrg                 }
159981418a27Smrg                 else
160081418a27Smrg                     visit((Expression *)e);
160181418a27Smrg                 return;
160281418a27Smrg             }
160381418a27Smrg             result = e;
160481418a27Smrg         }
160581418a27Smrg 
160681418a27Smrg         void visit(NullExp *e)
160781418a27Smrg         {
160881418a27Smrg             //printf("NullExp::castTo(t = %s) %s\n", t->toChars(), toChars());
160981418a27Smrg             visit((Expression *)e);
161081418a27Smrg             if (result->op == TOKnull)
161181418a27Smrg             {
161281418a27Smrg                 NullExp *ex = (NullExp *)result;
161381418a27Smrg                 ex->committed = 1;
161481418a27Smrg                 return;
161581418a27Smrg             }
161681418a27Smrg         }
161781418a27Smrg 
161881418a27Smrg         void visit(StructLiteralExp *e)
161981418a27Smrg         {
162081418a27Smrg             visit((Expression *)e);
162181418a27Smrg             if (result->op == TOKstructliteral)
162281418a27Smrg                 ((StructLiteralExp *)result)->stype = t; // commit type
162381418a27Smrg         }
162481418a27Smrg 
162581418a27Smrg         void visit(StringExp *e)
162681418a27Smrg         {
162781418a27Smrg             /* This follows copy-on-write; any changes to 'this'
162881418a27Smrg              * will result in a copy.
162981418a27Smrg              * The this->string member is considered immutable.
163081418a27Smrg              */
163181418a27Smrg             int copied = 0;
163281418a27Smrg 
163381418a27Smrg             //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), e->toChars(), e->committed);
163481418a27Smrg 
163581418a27Smrg             if (!e->committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
163681418a27Smrg             {
163781418a27Smrg                 e->error("cannot convert string literal to void*");
163881418a27Smrg                 result = new ErrorExp();
163981418a27Smrg                 return;
164081418a27Smrg             }
164181418a27Smrg 
164281418a27Smrg             StringExp *se = e;
164381418a27Smrg             if (!e->committed)
164481418a27Smrg             {
164581418a27Smrg                 se = (StringExp *)e->copy();
164681418a27Smrg                 se->committed = 1;
164781418a27Smrg                 copied = 1;
164881418a27Smrg             }
164981418a27Smrg 
165081418a27Smrg             if (e->type->equals(t))
165181418a27Smrg             {
165281418a27Smrg                 result = se;
165381418a27Smrg                 return;
165481418a27Smrg             }
165581418a27Smrg 
165681418a27Smrg             Type *tb = t->toBasetype();
165781418a27Smrg             //printf("\ttype = %s\n", e->type->toChars());
165881418a27Smrg             if (tb->ty == Tdelegate && e->type->toBasetype()->ty != Tdelegate)
165981418a27Smrg             {
166081418a27Smrg                 visit((Expression *)e);
166181418a27Smrg                 return;
166281418a27Smrg             }
166381418a27Smrg 
166481418a27Smrg             Type *typeb = e->type->toBasetype();
166581418a27Smrg             if (typeb->equals(tb))
166681418a27Smrg             {
166781418a27Smrg                 if (!copied)
166881418a27Smrg                 {
166981418a27Smrg                     se = (StringExp *)e->copy();
167081418a27Smrg                     copied = 1;
167181418a27Smrg                 }
167281418a27Smrg                 se->type = t;
167381418a27Smrg                 result = se;
167481418a27Smrg                 return;
167581418a27Smrg             }
167681418a27Smrg 
167781418a27Smrg             /* Handle reinterpret casts:
167881418a27Smrg              *  cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
167981418a27Smrg              *  cast(wchar[2])"abcd"c --> [\u6261, \u6463]
168081418a27Smrg              *  cast(wchar[1])"abcd"c --> [\u6261]
168181418a27Smrg              */
168281418a27Smrg             if (e->committed && tb->ty == Tsarray && typeb->ty == Tarray)
168381418a27Smrg             {
168481418a27Smrg                 se = (StringExp *)e->copy();
168581418a27Smrg                 d_uns64 szx = tb->nextOf()->size();
168681418a27Smrg                 assert(szx <= 255);
168781418a27Smrg                 se->sz = (unsigned char)szx;
168881418a27Smrg                 se->len = (size_t)((TypeSArray *)tb)->dim->toInteger();
168981418a27Smrg                 se->committed = 1;
169081418a27Smrg                 se->type = t;
169181418a27Smrg 
169281418a27Smrg                 /* Assure space for terminating 0
169381418a27Smrg                  */
169481418a27Smrg                 if ((se->len + 1) * se->sz > (e->len + 1) * e->sz)
169581418a27Smrg                 {
169681418a27Smrg                     void *s = (void *)mem.xmalloc((se->len + 1) * se->sz);
169781418a27Smrg                     memcpy(s, se->string, se->len * se->sz);
169881418a27Smrg                     memset((char *)s + se->len * se->sz, 0, se->sz);
169981418a27Smrg                     se->string = s;
170081418a27Smrg                 }
170181418a27Smrg                 result = se;
170281418a27Smrg                 return;
170381418a27Smrg             }
170481418a27Smrg 
170581418a27Smrg             if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
170681418a27Smrg             {
170781418a27Smrg                 if (!copied)
170881418a27Smrg                 {
170981418a27Smrg                     se = (StringExp *)e->copy();
171081418a27Smrg                     copied = 1;
171181418a27Smrg                 }
171281418a27Smrg                 goto Lcast;
171381418a27Smrg             }
171481418a27Smrg             if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer)
171581418a27Smrg             {
171681418a27Smrg                 if (!copied)
171781418a27Smrg                 {
171881418a27Smrg                     se = (StringExp *)e->copy();
171981418a27Smrg                     copied = 1;
172081418a27Smrg                 }
172181418a27Smrg                 goto Lcast;
172281418a27Smrg             }
172381418a27Smrg 
172481418a27Smrg             if (typeb->nextOf()->size() == tb->nextOf()->size())
172581418a27Smrg             {
172681418a27Smrg                 if (!copied)
172781418a27Smrg                 {
172881418a27Smrg                     se = (StringExp *)e->copy();
172981418a27Smrg                     copied = 1;
173081418a27Smrg                 }
173181418a27Smrg                 if (tb->ty == Tsarray)
173281418a27Smrg                     goto L2;    // handle possible change in static array dimension
173381418a27Smrg                 se->type = t;
173481418a27Smrg                 result = se;
173581418a27Smrg                 return;
173681418a27Smrg             }
173781418a27Smrg 
173881418a27Smrg             if (e->committed)
173981418a27Smrg                 goto Lcast;
174081418a27Smrg 
174181418a27Smrg         #define X(tf,tt)        ((int)(tf) * 256 + (int)(tt))
174281418a27Smrg             {
174381418a27Smrg             OutBuffer buffer;
174481418a27Smrg             size_t newlen = 0;
174581418a27Smrg             int tfty = typeb->nextOf()->toBasetype()->ty;
174681418a27Smrg             int ttty = tb->nextOf()->toBasetype()->ty;
174781418a27Smrg             switch (X(tfty, ttty))
174881418a27Smrg             {
174981418a27Smrg                 case X(Tchar, Tchar):
175081418a27Smrg                 case X(Twchar,Twchar):
175181418a27Smrg                 case X(Tdchar,Tdchar):
175281418a27Smrg                     break;
175381418a27Smrg 
175481418a27Smrg                 case X(Tchar, Twchar):
175581418a27Smrg                     for (size_t u = 0; u < e->len;)
175681418a27Smrg                     {
175781418a27Smrg                         unsigned c;
175881418a27Smrg                         const char *p = utf_decodeChar((utf8_t *)se->string, e->len, &u, &c);
175981418a27Smrg                         if (p)
176081418a27Smrg                             e->error("%s", p);
176181418a27Smrg                         else
176281418a27Smrg                             buffer.writeUTF16(c);
176381418a27Smrg                     }
176481418a27Smrg                     newlen = buffer.offset / 2;
176581418a27Smrg                     buffer.writeUTF16(0);
176681418a27Smrg                     goto L1;
176781418a27Smrg 
176881418a27Smrg                 case X(Tchar, Tdchar):
176981418a27Smrg                     for (size_t u = 0; u < e->len;)
177081418a27Smrg                     {
177181418a27Smrg                         unsigned c;
177281418a27Smrg                         const char *p = utf_decodeChar((utf8_t *)se->string, e->len, &u, &c);
177381418a27Smrg                         if (p)
177481418a27Smrg                             e->error("%s", p);
177581418a27Smrg                         buffer.write4(c);
177681418a27Smrg                         newlen++;
177781418a27Smrg                     }
177881418a27Smrg                     buffer.write4(0);
177981418a27Smrg                     goto L1;
178081418a27Smrg 
178181418a27Smrg                 case X(Twchar,Tchar):
178281418a27Smrg                     for (size_t u = 0; u < e->len;)
178381418a27Smrg                     {
178481418a27Smrg                         unsigned c;
178581418a27Smrg                         const char *p = utf_decodeWchar((unsigned short *)se->string, e->len, &u, &c);
178681418a27Smrg                         if (p)
178781418a27Smrg                             e->error("%s", p);
178881418a27Smrg                         else
178981418a27Smrg                             buffer.writeUTF8(c);
179081418a27Smrg                     }
179181418a27Smrg                     newlen = buffer.offset;
179281418a27Smrg                     buffer.writeUTF8(0);
179381418a27Smrg                     goto L1;
179481418a27Smrg 
179581418a27Smrg                 case X(Twchar,Tdchar):
179681418a27Smrg                     for (size_t u = 0; u < e->len;)
179781418a27Smrg                     {
179881418a27Smrg                         unsigned c;
179981418a27Smrg                         const char *p = utf_decodeWchar((unsigned short *)se->string, e->len, &u, &c);
180081418a27Smrg                         if (p)
180181418a27Smrg                             e->error("%s", p);
180281418a27Smrg                         buffer.write4(c);
180381418a27Smrg                         newlen++;
180481418a27Smrg                     }
180581418a27Smrg                     buffer.write4(0);
180681418a27Smrg                     goto L1;
180781418a27Smrg 
180881418a27Smrg                 case X(Tdchar,Tchar):
180981418a27Smrg                     for (size_t u = 0; u < e->len; u++)
181081418a27Smrg                     {
181181418a27Smrg                         unsigned c = ((unsigned *)se->string)[u];
181281418a27Smrg                         if (!utf_isValidDchar(c))
181381418a27Smrg                             e->error("invalid UCS-32 char \\U%08x", c);
181481418a27Smrg                         else
181581418a27Smrg                             buffer.writeUTF8(c);
181681418a27Smrg                         newlen++;
181781418a27Smrg                     }
181881418a27Smrg                     newlen = buffer.offset;
181981418a27Smrg                     buffer.writeUTF8(0);
182081418a27Smrg                     goto L1;
182181418a27Smrg 
182281418a27Smrg                 case X(Tdchar,Twchar):
182381418a27Smrg                     for (size_t u = 0; u < e->len; u++)
182481418a27Smrg                     {
182581418a27Smrg                         unsigned c = ((unsigned *)se->string)[u];
182681418a27Smrg                         if (!utf_isValidDchar(c))
182781418a27Smrg                             e->error("invalid UCS-32 char \\U%08x", c);
182881418a27Smrg                         else
182981418a27Smrg                             buffer.writeUTF16(c);
183081418a27Smrg                         newlen++;
183181418a27Smrg                     }
183281418a27Smrg                     newlen = buffer.offset / 2;
183381418a27Smrg                     buffer.writeUTF16(0);
183481418a27Smrg                     goto L1;
183581418a27Smrg 
183681418a27Smrg                 L1:
183781418a27Smrg                     if (!copied)
183881418a27Smrg                     {
183981418a27Smrg                         se = (StringExp *)e->copy();
184081418a27Smrg                         copied = 1;
184181418a27Smrg                     }
184281418a27Smrg                     se->string = buffer.extractData();
184381418a27Smrg                     se->len = newlen;
184481418a27Smrg 
184581418a27Smrg                     {
184681418a27Smrg                         d_uns64 szx = tb->nextOf()->size();
184781418a27Smrg                         assert(szx <= 255);
184881418a27Smrg                         se->sz = (unsigned char)szx;
184981418a27Smrg                     }
185081418a27Smrg                     break;
185181418a27Smrg 
185281418a27Smrg                 default:
185381418a27Smrg                     assert(typeb->nextOf()->size() != tb->nextOf()->size());
185481418a27Smrg                     goto Lcast;
185581418a27Smrg             }
185681418a27Smrg             }
185781418a27Smrg         #undef X
185881418a27Smrg         L2:
185981418a27Smrg             assert(copied);
186081418a27Smrg 
186181418a27Smrg             // See if need to truncate or extend the literal
186281418a27Smrg             if (tb->ty == Tsarray)
186381418a27Smrg             {
186481418a27Smrg                 size_t dim2 = (size_t)((TypeSArray *)tb)->dim->toInteger();
186581418a27Smrg 
186681418a27Smrg                 //printf("dim from = %d, to = %d\n", (int)se->len, (int)dim2);
186781418a27Smrg 
186881418a27Smrg                 // Changing dimensions
186981418a27Smrg                 if (dim2 != se->len)
187081418a27Smrg                 {
187181418a27Smrg                     // Copy when changing the string literal
187281418a27Smrg                     size_t newsz = se->sz;
187381418a27Smrg                     size_t d = (dim2 < se->len) ? dim2 : se->len;
187481418a27Smrg                     void *s = (void *)mem.xmalloc((dim2 + 1) * newsz);
187581418a27Smrg                     memcpy(s, se->string, d * newsz);
187681418a27Smrg                     // Extend with 0, add terminating 0
187781418a27Smrg                     memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
187881418a27Smrg                     se->string = s;
187981418a27Smrg                     se->len = dim2;
188081418a27Smrg                 }
188181418a27Smrg             }
188281418a27Smrg             se->type = t;
188381418a27Smrg             result = se;
188481418a27Smrg             return;
188581418a27Smrg 
188681418a27Smrg         Lcast:
188781418a27Smrg             result = new CastExp(e->loc, se, t);
188881418a27Smrg             result->type = t;        // so semantic() won't be run on e
188981418a27Smrg         }
189081418a27Smrg 
189181418a27Smrg         void visit(AddrExp *e)
189281418a27Smrg         {
189381418a27Smrg             Type *tb;
189481418a27Smrg 
189581418a27Smrg             result = e;
189681418a27Smrg 
189781418a27Smrg             tb = t->toBasetype();
189881418a27Smrg             e->type = e->type->toBasetype();
189981418a27Smrg             if (!tb->equals(e->type))
190081418a27Smrg             {
190181418a27Smrg                 // Look for pointers to functions where the functions are overloaded.
190281418a27Smrg 
190381418a27Smrg                 if (e->e1->op == TOKoverloadset &&
190481418a27Smrg                     (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
190581418a27Smrg                 {
190681418a27Smrg                     OverExp *eo = (OverExp *)e->e1;
190781418a27Smrg                     FuncDeclaration *f = NULL;
190881418a27Smrg                     for (size_t i = 0; i < eo->vars->a.dim; i++)
190981418a27Smrg                     {
191081418a27Smrg                         Dsymbol *s = eo->vars->a[i];
191181418a27Smrg                         FuncDeclaration *f2 = s->isFuncDeclaration();
191281418a27Smrg                         assert(f2);
191381418a27Smrg                         if (f2->overloadExactMatch(t->nextOf()))
191481418a27Smrg                         {
191581418a27Smrg                             if (f)
191681418a27Smrg                             {
191781418a27Smrg                                 /* Error if match in more than one overload set,
191881418a27Smrg                                  * even if one is a 'better' match than the other.
191981418a27Smrg                                  */
192081418a27Smrg                                 ScopeDsymbol::multiplyDefined(e->loc, f, f2);
192181418a27Smrg                             }
192281418a27Smrg                             else
192381418a27Smrg                                 f = f2;
192481418a27Smrg                         }
192581418a27Smrg                     }
192681418a27Smrg                     if (f)
192781418a27Smrg                     {
192881418a27Smrg                         f->tookAddressOf++;
192981418a27Smrg                         SymOffExp *se = new SymOffExp(e->loc, f, 0, false);
193081418a27Smrg                         ::semantic(se, sc);
193181418a27Smrg                         // Let SymOffExp::castTo() do the heavy lifting
193281418a27Smrg                         visit(se);
193381418a27Smrg                         return;
193481418a27Smrg                     }
193581418a27Smrg                 }
193681418a27Smrg 
193781418a27Smrg                 if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tfunction &&
193881418a27Smrg                     tb->ty == Tpointer && tb->nextOf()->ty == Tfunction &&
193981418a27Smrg                     e->e1->op == TOKvar)
194081418a27Smrg                 {
194181418a27Smrg                     VarExp *ve = (VarExp *)e->e1;
194281418a27Smrg                     FuncDeclaration *f = ve->var->isFuncDeclaration();
194381418a27Smrg                     if (f)
194481418a27Smrg                     {
194581418a27Smrg                         assert(f->isImportedSymbol());
194681418a27Smrg                         f = f->overloadExactMatch(tb->nextOf());
194781418a27Smrg                         if (f)
194881418a27Smrg                         {
194981418a27Smrg                             result = new VarExp(e->loc, f, false);
195081418a27Smrg                             result->type = f->type;
195181418a27Smrg                             result = new AddrExp(e->loc, result, t);
195281418a27Smrg                             return;
195381418a27Smrg                         }
195481418a27Smrg                     }
195581418a27Smrg                 }
195681418a27Smrg 
195781418a27Smrg                 if (FuncDeclaration *f = isFuncAddress(e))
195881418a27Smrg                 {
195981418a27Smrg                     if (f->checkForwardRef(e->loc))
196081418a27Smrg                     {
196181418a27Smrg                         result = new ErrorExp();
196281418a27Smrg                         return;
196381418a27Smrg                     }
196481418a27Smrg                 }
196581418a27Smrg 
196681418a27Smrg                 visit((Expression *)e);
196781418a27Smrg             }
196881418a27Smrg             result->type = t;
196981418a27Smrg         }
197081418a27Smrg 
197181418a27Smrg         void visit(TupleExp *e)
197281418a27Smrg         {
197381418a27Smrg             if (e->type->equals(t))
197481418a27Smrg             {
197581418a27Smrg                 result = e;
197681418a27Smrg                 return;
197781418a27Smrg             }
197881418a27Smrg 
197981418a27Smrg             TupleExp *te = (TupleExp *)e->copy();
198081418a27Smrg             te->e0 = e->e0 ? e->e0->copy() : NULL;
198181418a27Smrg             te->exps = (Expressions *)e->exps->copy();
198281418a27Smrg             for (size_t i = 0; i < te->exps->dim; i++)
198381418a27Smrg             {
198481418a27Smrg                 Expression *ex = (*te->exps)[i];
198581418a27Smrg                 ex = ex->castTo(sc, t);
198681418a27Smrg                 (*te->exps)[i] = ex;
198781418a27Smrg             }
198881418a27Smrg             result = te;
198981418a27Smrg 
199081418a27Smrg             /* Questionable behavior: In here, result->type is not set to t.
199181418a27Smrg              * Therefoe:
199281418a27Smrg              *  TypeTuple!(int, int) values;
199381418a27Smrg              *  auto values2 = cast(long)values;
199481418a27Smrg              *  // typeof(values2) == TypeTuple!(int, int) !!
199581418a27Smrg              *
199681418a27Smrg              * Only when the casted tuple is immediately expanded, it would work.
199781418a27Smrg              *  auto arr = [cast(long)values];
199881418a27Smrg              *  // typeof(arr) == long[]
199981418a27Smrg              */
200081418a27Smrg         }
200181418a27Smrg 
200281418a27Smrg         void visit(ArrayLiteralExp *e)
200381418a27Smrg         {
200481418a27Smrg             if (e->type == t)
200581418a27Smrg             {
200681418a27Smrg                 result = e;
200781418a27Smrg                 return;
200881418a27Smrg             }
200981418a27Smrg             ArrayLiteralExp *ae = e;
201081418a27Smrg             Type *typeb = e->type->toBasetype();
201181418a27Smrg             Type *tb = t->toBasetype();
201281418a27Smrg             if ((tb->ty == Tarray || tb->ty == Tsarray) &&
201381418a27Smrg                 (typeb->ty == Tarray || typeb->ty == Tsarray))
201481418a27Smrg             {
201581418a27Smrg                 if (tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid)
201681418a27Smrg                 {
201781418a27Smrg                     // Don't do anything to cast non-void[] to void[]
201881418a27Smrg                 }
201981418a27Smrg                 else if (typeb->ty == Tsarray && typeb->nextOf()->toBasetype()->ty == Tvoid)
202081418a27Smrg                 {
202181418a27Smrg                     // Don't do anything for casting void[n] to others
202281418a27Smrg                 }
202381418a27Smrg                 else
202481418a27Smrg                 {
202581418a27Smrg                     if (tb->ty == Tsarray)
202681418a27Smrg                     {
202781418a27Smrg                         TypeSArray *tsa = (TypeSArray *)tb;
202881418a27Smrg                         if (e->elements->dim != tsa->dim->toInteger())
202981418a27Smrg                             goto L1;
203081418a27Smrg                     }
203181418a27Smrg 
203281418a27Smrg                     ae = (ArrayLiteralExp *)e->copy();
203381418a27Smrg                     if (e->basis)
203481418a27Smrg                         ae->basis = e->basis->castTo(sc, tb->nextOf());
203581418a27Smrg                     ae->elements = e->elements->copy();
203681418a27Smrg                     for (size_t i = 0; i < e->elements->dim; i++)
203781418a27Smrg                     {
203881418a27Smrg                         Expression *ex = (*e->elements)[i];
203981418a27Smrg                         if (!ex)
204081418a27Smrg                             continue;
204181418a27Smrg                         ex = ex->castTo(sc, tb->nextOf());
204281418a27Smrg                         (*ae->elements)[i] = ex;
204381418a27Smrg                     }
204481418a27Smrg                     ae->type = t;
204581418a27Smrg                     result = ae;
204681418a27Smrg                     return;
204781418a27Smrg                 }
204881418a27Smrg             }
204981418a27Smrg             else if (tb->ty == Tpointer && typeb->ty == Tsarray)
205081418a27Smrg             {
205181418a27Smrg                 Type *tp = typeb->nextOf()->pointerTo();
205281418a27Smrg                 if (!tp->equals(ae->type))
205381418a27Smrg                 {
205481418a27Smrg                     ae = (ArrayLiteralExp *)e->copy();
205581418a27Smrg                     ae->type = tp;
205681418a27Smrg                 }
205781418a27Smrg             }
205881418a27Smrg             else if (tb->ty == Tvector &&
205981418a27Smrg                 (typeb->ty == Tarray || typeb->ty == Tsarray))
206081418a27Smrg             {
206181418a27Smrg                 // Convert array literal to vector type
206281418a27Smrg                 TypeVector *tv = (TypeVector *)tb;
206381418a27Smrg                 TypeSArray *tbase = (TypeSArray *)tv->basetype;
206481418a27Smrg                 assert(tbase->ty == Tsarray);
206581418a27Smrg                 const size_t edim = e->elements->dim;
206681418a27Smrg                 const size_t tbasedim = tbase->dim->toInteger();
206781418a27Smrg                 if (edim > tbasedim)
206881418a27Smrg                     goto L1;
206981418a27Smrg 
207081418a27Smrg                 ae = (ArrayLiteralExp *)e->copy();
207181418a27Smrg                 ae->type = tbase;   // Bugzilla 12642
207281418a27Smrg                 ae->elements = e->elements->copy();
207381418a27Smrg                 Type *telement = tv->elementType();
207481418a27Smrg                 for (size_t i = 0; i < edim; i++)
207581418a27Smrg                 {
207681418a27Smrg                     Expression *ex = (*e->elements)[i];
207781418a27Smrg                     ex = ex->castTo(sc, telement);
207881418a27Smrg                     (*ae->elements)[i] = ex;
207981418a27Smrg                 }
208081418a27Smrg                 // Fill in the rest with the default initializer
208181418a27Smrg                 ae->elements->setDim(tbasedim);
208281418a27Smrg                 for (size_t i = edim; i < tbasedim; i++)
208381418a27Smrg                 {
208481418a27Smrg                     Expression *ex = typeb->nextOf()->defaultInitLiteral(e->loc);
208581418a27Smrg                     ex = ex->castTo(sc, telement);
208681418a27Smrg                     (*ae->elements)[i] = ex;
208781418a27Smrg                 }
208881418a27Smrg                 Expression *ev = new VectorExp(e->loc, ae, tb);
208981418a27Smrg                 ev = ::semantic(ev, sc);
209081418a27Smrg                 result = ev;
209181418a27Smrg                 return;
209281418a27Smrg             }
209381418a27Smrg         L1:
209481418a27Smrg             visit((Expression *)ae);
209581418a27Smrg         }
209681418a27Smrg 
209781418a27Smrg         void visit(AssocArrayLiteralExp *e)
209881418a27Smrg         {
209981418a27Smrg             if (e->type == t)
210081418a27Smrg             {
210181418a27Smrg                 result = e;
210281418a27Smrg                 return;
210381418a27Smrg             }
210481418a27Smrg             Type *typeb = e->type->toBasetype();
210581418a27Smrg             Type *tb = t->toBasetype();
210681418a27Smrg             if (tb->ty == Taarray && typeb->ty == Taarray &&
210781418a27Smrg                 tb->nextOf()->toBasetype()->ty != Tvoid)
210881418a27Smrg             {
210981418a27Smrg                 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e->copy();
211081418a27Smrg                 ae->keys = e->keys->copy();
211181418a27Smrg                 ae->values = e->values->copy();
211281418a27Smrg                 assert(e->keys->dim == e->values->dim);
211381418a27Smrg                 for (size_t i = 0; i < e->keys->dim; i++)
211481418a27Smrg                 {
211581418a27Smrg                     Expression *ex = (*e->values)[i];
211681418a27Smrg                     ex = ex->castTo(sc, tb->nextOf());
211781418a27Smrg                     (*ae->values)[i] = ex;
211881418a27Smrg 
211981418a27Smrg                     ex = (*e->keys)[i];
212081418a27Smrg                     ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
212181418a27Smrg                     (*ae->keys)[i] = ex;
212281418a27Smrg                 }
212381418a27Smrg                 ae->type = t;
212481418a27Smrg                 result = ae;
212581418a27Smrg                 return;
212681418a27Smrg             }
212781418a27Smrg             visit((Expression *)e);
212881418a27Smrg         }
212981418a27Smrg 
213081418a27Smrg         void visit(SymOffExp *e)
213181418a27Smrg         {
213281418a27Smrg             if (e->type == t && !e->hasOverloads)
213381418a27Smrg             {
213481418a27Smrg                 result = e;
213581418a27Smrg                 return;
213681418a27Smrg             }
213781418a27Smrg             Type *tb = t->toBasetype();
213881418a27Smrg             Type *typeb = e->type->toBasetype();
213981418a27Smrg 
214081418a27Smrg             if (tb->equals(typeb))
214181418a27Smrg             {
214281418a27Smrg                 result = e->copy();
214381418a27Smrg                 result->type = t;
214481418a27Smrg                 ((SymOffExp *)result)->hasOverloads = false;
214581418a27Smrg                 return;
214681418a27Smrg             }
214781418a27Smrg 
214881418a27Smrg             // Look for pointers to functions where the functions are overloaded.
214981418a27Smrg             if (e->hasOverloads &&
215081418a27Smrg                 typeb->ty == Tpointer && typeb->nextOf()->ty == Tfunction &&
215181418a27Smrg                 (tb->ty == Tpointer || tb->ty == Tdelegate) && tb->nextOf()->ty == Tfunction)
215281418a27Smrg             {
215381418a27Smrg                 FuncDeclaration *f = e->var->isFuncDeclaration();
215481418a27Smrg                 f = f ? f->overloadExactMatch(tb->nextOf()) : NULL;
215581418a27Smrg                 if (f)
215681418a27Smrg                 {
215781418a27Smrg                     if (tb->ty == Tdelegate)
215881418a27Smrg                     {
215981418a27Smrg                         if (f->needThis() && hasThis(sc))
216081418a27Smrg                         {
216181418a27Smrg                             result = new DelegateExp(e->loc, new ThisExp(e->loc), f, false);
216281418a27Smrg                             result = ::semantic(result, sc);
216381418a27Smrg                         }
216481418a27Smrg                         else if (f->isNested())
216581418a27Smrg                         {
216681418a27Smrg                             result = new DelegateExp(e->loc, new IntegerExp(0), f, false);
216781418a27Smrg                             result = ::semantic(result, sc);
216881418a27Smrg                         }
216981418a27Smrg                         else if (f->needThis())
217081418a27Smrg                         {
217181418a27Smrg                             e->error("no 'this' to create delegate for %s", f->toChars());
217281418a27Smrg                             result = new ErrorExp();
217381418a27Smrg                             return;
217481418a27Smrg                         }
217581418a27Smrg                         else
217681418a27Smrg                         {
217781418a27Smrg                             e->error("cannot cast from function pointer to delegate");
217881418a27Smrg                             result = new ErrorExp();
217981418a27Smrg                             return;
218081418a27Smrg                         }
218181418a27Smrg                     }
218281418a27Smrg                     else
218381418a27Smrg                     {
218481418a27Smrg                         result = new SymOffExp(e->loc, f, 0, false);
218581418a27Smrg                         result->type = t;
218681418a27Smrg                     }
218781418a27Smrg                     f->tookAddressOf++;
218881418a27Smrg                     return;
218981418a27Smrg                 }
219081418a27Smrg             }
219181418a27Smrg 
219281418a27Smrg             if (FuncDeclaration *f = isFuncAddress(e))
219381418a27Smrg             {
219481418a27Smrg                 if (f->checkForwardRef(e->loc))
219581418a27Smrg                 {
219681418a27Smrg                     result = new ErrorExp();
219781418a27Smrg                     return;
219881418a27Smrg                 }
219981418a27Smrg             }
220081418a27Smrg 
220181418a27Smrg             visit((Expression *)e);
220281418a27Smrg         }
220381418a27Smrg 
220481418a27Smrg         void visit(DelegateExp *e)
220581418a27Smrg         {
220681418a27Smrg             static const char msg[] = "cannot form delegate due to covariant return type";
220781418a27Smrg 
220881418a27Smrg             Type *tb = t->toBasetype();
220981418a27Smrg             Type *typeb = e->type->toBasetype();
221081418a27Smrg             if (!tb->equals(typeb) || e->hasOverloads)
221181418a27Smrg             {
221281418a27Smrg                 // Look for delegates to functions where the functions are overloaded.
221381418a27Smrg                 if (typeb->ty == Tdelegate &&
221481418a27Smrg                     tb->ty == Tdelegate)
221581418a27Smrg                 {
221681418a27Smrg                     if (e->func)
221781418a27Smrg                     {
221881418a27Smrg                         FuncDeclaration *f = e->func->overloadExactMatch(tb->nextOf());
221981418a27Smrg                         if (f)
222081418a27Smrg                         {
222181418a27Smrg                             int offset;
222281418a27Smrg                             if (f->tintro && f->tintro->nextOf()->isBaseOf(f->type->nextOf(), &offset) && offset)
222381418a27Smrg                                 e->error("%s", msg);
222481418a27Smrg                             if (f != e->func)    // if address not already marked as taken
222581418a27Smrg                                 f->tookAddressOf++;
222681418a27Smrg                             result = new DelegateExp(e->loc, e->e1, f, false);
222781418a27Smrg                             result->type = t;
222881418a27Smrg                             return;
222981418a27Smrg                         }
223081418a27Smrg                         if (e->func->tintro)
223181418a27Smrg                             e->error("%s", msg);
223281418a27Smrg                     }
223381418a27Smrg                 }
223481418a27Smrg 
223581418a27Smrg                 if (FuncDeclaration *f = isFuncAddress(e))
223681418a27Smrg                 {
223781418a27Smrg                     if (f->checkForwardRef(e->loc))
223881418a27Smrg                     {
223981418a27Smrg                         result = new ErrorExp();
224081418a27Smrg                         return;
224181418a27Smrg                     }
224281418a27Smrg                 }
224381418a27Smrg 
224481418a27Smrg                 visit((Expression *)e);
224581418a27Smrg             }
224681418a27Smrg             else
224781418a27Smrg             {
224881418a27Smrg                 int offset;
224981418a27Smrg                 e->func->tookAddressOf++;
225081418a27Smrg                 if (e->func->tintro && e->func->tintro->nextOf()->isBaseOf(e->func->type->nextOf(), &offset) && offset)
225181418a27Smrg                     e->error("%s", msg);
225281418a27Smrg                 result = e->copy();
225381418a27Smrg                 result->type = t;
225481418a27Smrg             }
225581418a27Smrg         }
225681418a27Smrg 
225781418a27Smrg         void visit(FuncExp *e)
225881418a27Smrg         {
225981418a27Smrg             //printf("FuncExp::castTo type = %s, t = %s\n", e->type->toChars(), t->toChars());
226081418a27Smrg             FuncExp *fe;
226181418a27Smrg             if (e->matchType(t, sc, &fe, 1) > MATCHnomatch)
226281418a27Smrg             {
226381418a27Smrg                 result = fe;
226481418a27Smrg                 return;
226581418a27Smrg             }
226681418a27Smrg             visit((Expression *)e);
226781418a27Smrg         }
226881418a27Smrg 
226981418a27Smrg         void visit(CondExp *e)
227081418a27Smrg         {
227181418a27Smrg             if (!e->type->equals(t))
227281418a27Smrg             {
227381418a27Smrg                 result = new CondExp(e->loc, e->econd, e->e1->castTo(sc, t), e->e2->castTo(sc, t));
227481418a27Smrg                 result->type = t;
227581418a27Smrg                 return;
227681418a27Smrg             }
227781418a27Smrg             result = e;
227881418a27Smrg         }
227981418a27Smrg 
228081418a27Smrg         void visit(CommaExp *e)
228181418a27Smrg         {
228281418a27Smrg             Expression *e2c = e->e2->castTo(sc, t);
228381418a27Smrg 
228481418a27Smrg             if (e2c != e->e2)
228581418a27Smrg             {
228681418a27Smrg                 result = new CommaExp(e->loc, e->e1, e2c);
228781418a27Smrg                 result->type = e2c->type;
228881418a27Smrg             }
228981418a27Smrg             else
229081418a27Smrg             {
229181418a27Smrg                 result = e;
229281418a27Smrg                 result->type = e->e2->type;
229381418a27Smrg             }
229481418a27Smrg         }
229581418a27Smrg 
229681418a27Smrg         void visit(SliceExp *e)
229781418a27Smrg         {
229881418a27Smrg             //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e->toChars(), e->type->toChars(), t->toChars());
229981418a27Smrg             Type *typeb = e->type->toBasetype();
230081418a27Smrg             Type *tb = t->toBasetype();
230181418a27Smrg             if (e->type->equals(t) || typeb->ty != Tarray ||
230281418a27Smrg                 (tb->ty != Tarray && tb->ty != Tsarray))
230381418a27Smrg             {
230481418a27Smrg                 visit((Expression *)e);
230581418a27Smrg                 return;
230681418a27Smrg             }
230781418a27Smrg 
230881418a27Smrg             if (tb->ty == Tarray)
230981418a27Smrg             {
231081418a27Smrg                 if (typeb->nextOf()->equivalent(tb->nextOf()))
231181418a27Smrg                 {
231281418a27Smrg                     // T[] to const(T)[]
231381418a27Smrg                     result = e->copy();
231481418a27Smrg                     result->type = t;
231581418a27Smrg                 }
231681418a27Smrg                 else
231781418a27Smrg                 {
231881418a27Smrg                     visit((Expression *)e);
231981418a27Smrg                 }
232081418a27Smrg                 return;
232181418a27Smrg             }
232281418a27Smrg 
232381418a27Smrg             // Handle the cast from Tarray to Tsarray with CT-known slicing
232481418a27Smrg 
232581418a27Smrg             TypeSArray *tsa = (TypeSArray *)toStaticArrayType(e);
232681418a27Smrg             if (tsa && tsa->size(e->loc) == tb->size(e->loc))
232781418a27Smrg             {
232881418a27Smrg                 /* Match if the sarray sizes are equal:
232981418a27Smrg                  *  T[a .. b] to const(T)[b-a]
233081418a27Smrg                  *  T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
233181418a27Smrg                  *
233281418a27Smrg                  * If a SliceExp has Tsarray, it will become lvalue.
233381418a27Smrg                  * That's handled in SliceExp::isLvalue and toLvalue
233481418a27Smrg                  */
233581418a27Smrg                 result = e->copy();
233681418a27Smrg                 result->type = t;
233781418a27Smrg                 return;
233881418a27Smrg             }
233981418a27Smrg             if (tsa && tsa->dim->equals(((TypeSArray *)tb)->dim))
234081418a27Smrg             {
234181418a27Smrg                 /* Match if the dimensions are equal
234281418a27Smrg                  * with the implicit conversion of e->e1:
234381418a27Smrg                  *  cast(float[2]) [2.0, 1.0, 0.0][0..2];
234481418a27Smrg                  */
234581418a27Smrg                 Type *t1b = e->e1->type->toBasetype();
234681418a27Smrg                 if (t1b->ty == Tsarray)
234781418a27Smrg                     t1b = tb->nextOf()->sarrayOf(((TypeSArray *)t1b)->dim->toInteger());
234881418a27Smrg                 else if (t1b->ty == Tarray)
234981418a27Smrg                     t1b = tb->nextOf()->arrayOf();
235081418a27Smrg                 else if (t1b->ty == Tpointer)
235181418a27Smrg                     t1b = tb->nextOf()->pointerTo();
235281418a27Smrg                 else
235381418a27Smrg                     assert(0);
235481418a27Smrg                 if (e->e1->implicitConvTo(t1b) > MATCHnomatch)
235581418a27Smrg                 {
235681418a27Smrg                     Expression *e1x = e->e1->implicitCastTo(sc, t1b);
235781418a27Smrg                     assert(e1x->op != TOKerror);
235881418a27Smrg                     e = (SliceExp *)e->copy();
235981418a27Smrg                     e->e1 = e1x;
236081418a27Smrg                     e->type = t;
236181418a27Smrg                     result = e;
236281418a27Smrg                     return;
236381418a27Smrg                 }
236481418a27Smrg             }
236581418a27Smrg             e->error("cannot cast expression %s of type %s to %s",
236681418a27Smrg                 e->toChars(), tsa ? tsa->toChars() : e->type->toChars(),
236781418a27Smrg                 t->toChars());
236881418a27Smrg             result = new ErrorExp();
236981418a27Smrg         }
237081418a27Smrg     };
237181418a27Smrg 
237281418a27Smrg     CastTo v(sc, t);
237381418a27Smrg     e->accept(&v);
237481418a27Smrg     return v.result;
237581418a27Smrg }
237681418a27Smrg 
237781418a27Smrg /* ==================== inferType ====================== */
237881418a27Smrg 
237981418a27Smrg /****************************************
238081418a27Smrg  * Set type inference target
238181418a27Smrg  *      t       Target type
238281418a27Smrg  *      flag    1: don't put an error when inference fails
238381418a27Smrg  */
238481418a27Smrg 
inferType(Expression * e,Type * t,int flag)238581418a27Smrg Expression *inferType(Expression *e, Type *t, int flag)
238681418a27Smrg {
238781418a27Smrg     class InferType : public Visitor
238881418a27Smrg     {
238981418a27Smrg     public:
239081418a27Smrg         Type *t;
239181418a27Smrg         int flag;
239281418a27Smrg         Expression *result;
239381418a27Smrg 
239481418a27Smrg         InferType(Type *t, int flag)
239581418a27Smrg             : t(t), flag(flag)
239681418a27Smrg         {
239781418a27Smrg             result = NULL;
239881418a27Smrg         }
239981418a27Smrg 
240081418a27Smrg 
240181418a27Smrg         void visit(Expression *e)
240281418a27Smrg         {
240381418a27Smrg             result = e;
240481418a27Smrg         }
240581418a27Smrg 
240681418a27Smrg         void visit(ArrayLiteralExp *ale)
240781418a27Smrg         {
240881418a27Smrg             Type *tb = t->toBasetype();
240981418a27Smrg             if (tb->ty == Tarray || tb->ty == Tsarray)
241081418a27Smrg             {
241181418a27Smrg                 Type *tn = tb->nextOf();
241281418a27Smrg                 if (ale->basis)
241381418a27Smrg                     ale->basis = inferType(ale->basis, tn, flag);
241481418a27Smrg                 for (size_t i = 0; i < ale->elements->dim; i++)
241581418a27Smrg                 {
241681418a27Smrg                     Expression *e = (*ale->elements)[i];
241781418a27Smrg                     if (e)
241881418a27Smrg                     {
241981418a27Smrg                         e = inferType(e, tn, flag);
242081418a27Smrg                         (*ale->elements)[i] = e;
242181418a27Smrg                     }
242281418a27Smrg                 }
242381418a27Smrg             }
242481418a27Smrg             result = ale;
242581418a27Smrg         }
242681418a27Smrg 
242781418a27Smrg         void visit(AssocArrayLiteralExp *aale)
242881418a27Smrg         {
242981418a27Smrg             Type *tb = t->toBasetype();
243081418a27Smrg             if (tb->ty == Taarray)
243181418a27Smrg             {
243281418a27Smrg                 TypeAArray *taa = (TypeAArray *)tb;
243381418a27Smrg                 Type *ti = taa->index;
243481418a27Smrg                 Type *tv = taa->nextOf();
243581418a27Smrg                 for (size_t i = 0; i < aale->keys->dim; i++)
243681418a27Smrg                 {
243781418a27Smrg                     Expression *e = (*aale->keys)[i];
243881418a27Smrg                     if (e)
243981418a27Smrg                     {
244081418a27Smrg                         e = inferType(e, ti, flag);
244181418a27Smrg                         (*aale->keys)[i] = e;
244281418a27Smrg                     }
244381418a27Smrg                 }
244481418a27Smrg                 for (size_t i = 0; i < aale->values->dim; i++)
244581418a27Smrg                 {
244681418a27Smrg                     Expression *e = (*aale->values)[i];
244781418a27Smrg                     if (e)
244881418a27Smrg                     {
244981418a27Smrg                         e = inferType(e, tv, flag);
245081418a27Smrg                         (*aale->values)[i] = e;
245181418a27Smrg                     }
245281418a27Smrg                 }
245381418a27Smrg             }
245481418a27Smrg             result = aale;
245581418a27Smrg         }
245681418a27Smrg 
245781418a27Smrg         void visit(FuncExp *fe)
245881418a27Smrg         {
245981418a27Smrg             //printf("FuncExp::inferType('%s'), to=%s\n", fe->type ? fe->type->toChars() : "null", t->toChars());
246081418a27Smrg             if (t->ty == Tdelegate ||
246181418a27Smrg                 (t->ty == Tpointer && t->nextOf()->ty == Tfunction))
246281418a27Smrg             {
246381418a27Smrg                 fe->fd->treq = t;
246481418a27Smrg             }
246581418a27Smrg             result = fe;
246681418a27Smrg         }
246781418a27Smrg 
246881418a27Smrg         void visit(CondExp *ce)
246981418a27Smrg         {
247081418a27Smrg             Type *tb = t->toBasetype();
247181418a27Smrg             ce->e1 = inferType(ce->e1, tb, flag);
247281418a27Smrg             ce->e2 = inferType(ce->e2, tb, flag);
247381418a27Smrg             result = ce;
247481418a27Smrg         }
247581418a27Smrg     };
247681418a27Smrg 
247781418a27Smrg     if (!t)
247881418a27Smrg         return e;
247981418a27Smrg 
248081418a27Smrg     InferType v(t, flag);
248181418a27Smrg     e->accept(&v);
248281418a27Smrg     return v.result;
248381418a27Smrg }
248481418a27Smrg 
248581418a27Smrg /* ==================== ====================== */
248681418a27Smrg 
248781418a27Smrg /****************************************
248881418a27Smrg  * Scale addition/subtraction to/from pointer.
248981418a27Smrg  */
249081418a27Smrg 
scaleFactor(BinExp * be,Scope * sc)249181418a27Smrg Expression *scaleFactor(BinExp *be, Scope *sc)
249281418a27Smrg {
249381418a27Smrg     Type *t1b = be->e1->type->toBasetype();
249481418a27Smrg     Type *t2b = be->e2->type->toBasetype();
249581418a27Smrg     Expression *eoff;
249681418a27Smrg 
249781418a27Smrg     if (t1b->ty == Tpointer && t2b->isintegral())
249881418a27Smrg     {
249981418a27Smrg         // Need to adjust operator by the stride
250081418a27Smrg         // Replace (ptr + int) with (ptr + (int * stride))
250181418a27Smrg         Type *t = Type::tptrdiff_t;
250281418a27Smrg 
250381418a27Smrg         d_uns64 stride = t1b->nextOf()->size(be->loc);
250481418a27Smrg         if (!t->equals(t2b))
250581418a27Smrg             be->e2 = be->e2->castTo(sc, t);
250681418a27Smrg         eoff = be->e2;
250781418a27Smrg         be->e2 = new MulExp(be->loc, be->e2, new IntegerExp(Loc(), stride, t));
250881418a27Smrg         be->e2->type = t;
250981418a27Smrg         be->type = be->e1->type;
251081418a27Smrg     }
251181418a27Smrg     else if (t2b->ty == Tpointer && t1b->isintegral())
251281418a27Smrg     {
251381418a27Smrg         // Need to adjust operator by the stride
251481418a27Smrg         // Replace (int + ptr) with (ptr + (int * stride))
251581418a27Smrg         Type *t = Type::tptrdiff_t;
251681418a27Smrg         Expression *e;
251781418a27Smrg 
251881418a27Smrg         d_uns64 stride = t2b->nextOf()->size(be->loc);
251981418a27Smrg         if (!t->equals(t1b))
252081418a27Smrg             e = be->e1->castTo(sc, t);
252181418a27Smrg         else
252281418a27Smrg             e = be->e1;
252381418a27Smrg         eoff = e;
252481418a27Smrg         e = new MulExp(be->loc, e, new IntegerExp(Loc(), stride, t));
252581418a27Smrg         e->type = t;
252681418a27Smrg         be->type = be->e2->type;
252781418a27Smrg         be->e1 = be->e2;
252881418a27Smrg         be->e2 = e;
252981418a27Smrg     }
253081418a27Smrg     else
253181418a27Smrg         assert(0);
253281418a27Smrg 
253381418a27Smrg     if (sc->func && !sc->intypeof)
253481418a27Smrg     {
253581418a27Smrg         eoff = eoff->optimize(WANTvalue);
253681418a27Smrg         if (eoff->op == TOKint64 && eoff->toInteger() == 0)
253781418a27Smrg             ;
253881418a27Smrg         else if (sc->func->setUnsafe())
253981418a27Smrg         {
254081418a27Smrg             be->error("pointer arithmetic not allowed in @safe functions");
254181418a27Smrg             return new ErrorExp();
254281418a27Smrg         }
254381418a27Smrg     }
254481418a27Smrg 
254581418a27Smrg     return be;
254681418a27Smrg }
254781418a27Smrg 
254881418a27Smrg /**************************************
254981418a27Smrg  * Return true if e is an empty array literal with dimensionality
255081418a27Smrg  * equal to or less than type of other array.
255181418a27Smrg  * [], [[]], [[[]]], etc.
255281418a27Smrg  * I.e., make sure that [1,2] is compatible with [],
255381418a27Smrg  * [[1,2]] is compatible with [[]], etc.
255481418a27Smrg  */
isVoidArrayLiteral(Expression * e,Type * other)255581418a27Smrg bool isVoidArrayLiteral(Expression *e, Type *other)
255681418a27Smrg {
255781418a27Smrg     while (e->op == TOKarrayliteral && e->type->ty == Tarray
255881418a27Smrg         && (((ArrayLiteralExp *)e)->elements->dim == 1))
255981418a27Smrg     {
256081418a27Smrg         ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
256181418a27Smrg         e = ale->getElement(0);
256281418a27Smrg         if (other->ty == Tsarray || other->ty == Tarray)
256381418a27Smrg             other = other->nextOf();
256481418a27Smrg         else
256581418a27Smrg             return false;
256681418a27Smrg     }
256781418a27Smrg     if (other->ty != Tsarray && other->ty != Tarray)
256881418a27Smrg         return false;
256981418a27Smrg     Type *t = e->type;
257081418a27Smrg     return (e->op == TOKarrayliteral && t->ty == Tarray &&
257181418a27Smrg         t->nextOf()->ty == Tvoid &&
257281418a27Smrg         ((ArrayLiteralExp *)e)->elements->dim == 0);
257381418a27Smrg }
257481418a27Smrg 
257581418a27Smrg // used by deduceType()
rawTypeMerge(Type * t1,Type * t2)257681418a27Smrg Type *rawTypeMerge(Type *t1, Type *t2)
257781418a27Smrg {
257881418a27Smrg     if (t1->equals(t2))
257981418a27Smrg         return t1;
258081418a27Smrg     if (t1->equivalent(t2))
258181418a27Smrg         return t1->castMod(MODmerge(t1->mod, t2->mod));
258281418a27Smrg 
258381418a27Smrg     Type *t1b = t1->toBasetype();
258481418a27Smrg     Type *t2b = t2->toBasetype();
258581418a27Smrg     if (t1b->equals(t2b))
258681418a27Smrg         return t1b;
258781418a27Smrg     if (t1b->equivalent(t2b))
258881418a27Smrg         return t1b->castMod(MODmerge(t1b->mod, t2b->mod));
258981418a27Smrg 
259081418a27Smrg     TY ty = (TY)impcnvResult[t1b->ty][t2b->ty];
259181418a27Smrg     if (ty != Terror)
259281418a27Smrg         return Type::basic[ty];
259381418a27Smrg 
259481418a27Smrg     return NULL;
259581418a27Smrg }
259681418a27Smrg 
259781418a27Smrg /**************************************
259881418a27Smrg  * Combine types.
259981418a27Smrg  * Output:
260081418a27Smrg  *      *pt     merged type, if *pt is not NULL
260181418a27Smrg  *      *pe1    rewritten e1
260281418a27Smrg  *      *pe2    rewritten e2
260381418a27Smrg  * Returns:
260481418a27Smrg  *      true    success
260581418a27Smrg  *      false   failed
260681418a27Smrg  */
260781418a27Smrg 
typeMerge(Scope * sc,TOK op,Type ** pt,Expression ** pe1,Expression ** pe2)260881418a27Smrg bool typeMerge(Scope *sc, TOK op, Type **pt, Expression **pe1, Expression **pe2)
260981418a27Smrg {
261081418a27Smrg     //printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars());
261181418a27Smrg 
261281418a27Smrg     MATCH m;
261381418a27Smrg     Expression *e1 = *pe1;
261481418a27Smrg     Expression *e2 = *pe2;
261581418a27Smrg     Type *t1b = e1->type->toBasetype();
261681418a27Smrg     Type *t2b = e2->type->toBasetype();
261781418a27Smrg 
261881418a27Smrg     if (op != TOKquestion ||
261981418a27Smrg         (t1b->ty != t2b->ty && (t1b->isTypeBasic() && t2b->isTypeBasic())))
262081418a27Smrg     {
262181418a27Smrg         e1 = integralPromotions(e1, sc);
262281418a27Smrg         e2 = integralPromotions(e2, sc);
262381418a27Smrg     }
262481418a27Smrg 
262581418a27Smrg     Type *t1 = e1->type;
262681418a27Smrg     Type *t2 = e2->type;
262781418a27Smrg     assert(t1);
262881418a27Smrg     Type *t = t1;
262981418a27Smrg 
263081418a27Smrg     /* The start type of alias this type recursion.
263181418a27Smrg      * In following case, we should save A, and stop recursion
263281418a27Smrg      * if it appears again.
263381418a27Smrg      *      X -> Y -> [A] -> B -> A -> B -> ...
263481418a27Smrg      */
263581418a27Smrg     Type *att1 = NULL;
263681418a27Smrg     Type *att2 = NULL;
263781418a27Smrg 
263881418a27Smrg     //if (t1) printf("\tt1 = %s\n", t1->toChars());
263981418a27Smrg     //if (t2) printf("\tt2 = %s\n", t2->toChars());
264081418a27Smrg     assert(t2);
264181418a27Smrg 
264281418a27Smrg     if (t1->mod != t2->mod &&
264381418a27Smrg         t1->ty == Tenum && t2->ty == Tenum &&
264481418a27Smrg         ((TypeEnum *)t1)->sym == ((TypeEnum *)t2)->sym)
264581418a27Smrg     {
264681418a27Smrg         unsigned char mod = MODmerge(t1->mod, t2->mod);
264781418a27Smrg         t1 = t1->castMod(mod);
264881418a27Smrg         t2 = t2->castMod(mod);
264981418a27Smrg     }
265081418a27Smrg 
265181418a27Smrg Lagain:
265281418a27Smrg     t1b = t1->toBasetype();
265381418a27Smrg     t2b = t2->toBasetype();
265481418a27Smrg 
265581418a27Smrg     TY ty = (TY)impcnvResult[t1b->ty][t2b->ty];
265681418a27Smrg     if (ty != Terror)
265781418a27Smrg     {
265881418a27Smrg         TY ty1 = (TY)impcnvType1[t1b->ty][t2b->ty];
265981418a27Smrg         TY ty2 = (TY)impcnvType2[t1b->ty][t2b->ty];
266081418a27Smrg 
266181418a27Smrg         if (t1b->ty == ty1)     // if no promotions
266281418a27Smrg         {
266381418a27Smrg             if (t1->equals(t2))
266481418a27Smrg             {
266581418a27Smrg                 t = t1;
266681418a27Smrg                 goto Lret;
266781418a27Smrg             }
266881418a27Smrg 
266981418a27Smrg             if (t1b->equals(t2b))
267081418a27Smrg             {
267181418a27Smrg                 t = t1b;
267281418a27Smrg                 goto Lret;
267381418a27Smrg             }
267481418a27Smrg         }
267581418a27Smrg 
267681418a27Smrg         t = Type::basic[ty];
267781418a27Smrg 
267881418a27Smrg         t1 = Type::basic[ty1];
267981418a27Smrg         t2 = Type::basic[ty2];
268081418a27Smrg         e1 = e1->castTo(sc, t1);
268181418a27Smrg         e2 = e2->castTo(sc, t2);
268281418a27Smrg         //printf("after typeCombine():\n");
268381418a27Smrg         //print();
268481418a27Smrg         //printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2);
268581418a27Smrg         goto Lret;
268681418a27Smrg     }
268781418a27Smrg 
268881418a27Smrg     t1 = t1b;
268981418a27Smrg     t2 = t2b;
269081418a27Smrg 
269181418a27Smrg     if (t1->ty == Ttuple || t2->ty == Ttuple)
269281418a27Smrg         goto Lincompatible;
269381418a27Smrg 
269481418a27Smrg     if (t1->equals(t2))
269581418a27Smrg     {
269681418a27Smrg         // merging can not result in new enum type
269781418a27Smrg         if (t->ty == Tenum)
269881418a27Smrg             t = t1b;
269981418a27Smrg     }
270081418a27Smrg     else if ((t1->ty == Tpointer && t2->ty == Tpointer) ||
270181418a27Smrg              (t1->ty == Tdelegate && t2->ty == Tdelegate))
270281418a27Smrg     {
270381418a27Smrg         // Bring pointers to compatible type
270481418a27Smrg         Type *t1n = t1->nextOf();
270581418a27Smrg         Type *t2n = t2->nextOf();
270681418a27Smrg 
270781418a27Smrg         if (t1n->equals(t2n))
270881418a27Smrg             ;
270981418a27Smrg         else if (t1n->ty == Tvoid)      // pointers to void are always compatible
271081418a27Smrg             t = t2;
271181418a27Smrg         else if (t2n->ty == Tvoid)
271281418a27Smrg             ;
271381418a27Smrg         else if (t1->implicitConvTo(t2))
271481418a27Smrg         {
271581418a27Smrg             goto Lt2;
271681418a27Smrg         }
271781418a27Smrg         else if (t2->implicitConvTo(t1))
271881418a27Smrg         {
271981418a27Smrg             goto Lt1;
272081418a27Smrg         }
272181418a27Smrg         else if (t1n->ty == Tfunction && t2n->ty == Tfunction)
272281418a27Smrg         {
272381418a27Smrg             TypeFunction *tf1 = (TypeFunction *)t1n;
272481418a27Smrg             TypeFunction *tf2 = (TypeFunction *)t2n;
272581418a27Smrg             tf1->purityLevel();
272681418a27Smrg             tf2->purityLevel();
272781418a27Smrg 
272881418a27Smrg             TypeFunction *d = (TypeFunction *)tf1->syntaxCopy();
272981418a27Smrg 
273081418a27Smrg             if (tf1->purity != tf2->purity)
273181418a27Smrg                 d->purity = PUREimpure;
273281418a27Smrg             assert(d->purity != PUREfwdref);
273381418a27Smrg 
273481418a27Smrg             d->isnothrow = (tf1->isnothrow && tf2->isnothrow);
273581418a27Smrg             d->isnogc    = (tf1->isnogc    && tf2->isnogc);
273681418a27Smrg 
273781418a27Smrg             if (tf1->trust == tf2->trust)
273881418a27Smrg                 d->trust = tf1->trust;
273981418a27Smrg             else if (tf1->trust <= TRUSTsystem || tf2->trust <= TRUSTsystem)
274081418a27Smrg                 d->trust = TRUSTsystem;
274181418a27Smrg             else
274281418a27Smrg                 d->trust = TRUSTtrusted;
274381418a27Smrg 
274481418a27Smrg             Type *tx = NULL;
274581418a27Smrg             if (t1->ty == Tdelegate)
274681418a27Smrg             {
274781418a27Smrg                 tx = new TypeDelegate(d);
274881418a27Smrg             }
274981418a27Smrg             else
275081418a27Smrg                 tx = d->pointerTo();
275181418a27Smrg 
275281418a27Smrg             tx = tx->semantic(e1->loc, sc);
275381418a27Smrg 
275481418a27Smrg             if (t1->implicitConvTo(tx) && t2->implicitConvTo(tx))
275581418a27Smrg             {
275681418a27Smrg                 t = tx;
275781418a27Smrg                 e1 = e1->castTo(sc, t);
275881418a27Smrg                 e2 = e2->castTo(sc, t);
275981418a27Smrg                 goto Lret;
276081418a27Smrg             }
276181418a27Smrg             goto Lincompatible;
276281418a27Smrg         }
276381418a27Smrg         else if (t1n->mod != t2n->mod)
276481418a27Smrg         {
276581418a27Smrg             if (!t1n->isImmutable() && !t2n->isImmutable() && t1n->isShared() != t2n->isShared())
276681418a27Smrg                 goto Lincompatible;
276781418a27Smrg             unsigned char mod = MODmerge(t1n->mod, t2n->mod);
276881418a27Smrg             t1 = t1n->castMod(mod)->pointerTo();
276981418a27Smrg             t2 = t2n->castMod(mod)->pointerTo();
277081418a27Smrg             t = t1;
277181418a27Smrg             goto Lagain;
277281418a27Smrg         }
277381418a27Smrg         else if (t1n->ty == Tclass && t2n->ty == Tclass)
277481418a27Smrg         {
277581418a27Smrg             ClassDeclaration *cd1 = t1n->isClassHandle();
277681418a27Smrg             ClassDeclaration *cd2 = t2n->isClassHandle();
277781418a27Smrg             int offset;
277881418a27Smrg 
277981418a27Smrg             if (cd1->isBaseOf(cd2, &offset))
278081418a27Smrg             {
278181418a27Smrg                 if (offset)
278281418a27Smrg                     e2 = e2->castTo(sc, t);
278381418a27Smrg             }
278481418a27Smrg             else if (cd2->isBaseOf(cd1, &offset))
278581418a27Smrg             {
278681418a27Smrg                 t = t2;
278781418a27Smrg                 if (offset)
278881418a27Smrg                     e1 = e1->castTo(sc, t);
278981418a27Smrg             }
279081418a27Smrg             else
279181418a27Smrg                 goto Lincompatible;
279281418a27Smrg         }
279381418a27Smrg         else
279481418a27Smrg         {
279581418a27Smrg             t1 = t1n->constOf()->pointerTo();
279681418a27Smrg             t2 = t2n->constOf()->pointerTo();
279781418a27Smrg             if (t1->implicitConvTo(t2))
279881418a27Smrg             {
279981418a27Smrg                 goto Lt2;
280081418a27Smrg             }
280181418a27Smrg             else if (t2->implicitConvTo(t1))
280281418a27Smrg             {
280381418a27Smrg                 goto Lt1;
280481418a27Smrg             }
280581418a27Smrg             goto Lincompatible;
280681418a27Smrg         }
280781418a27Smrg     }
280881418a27Smrg     else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
280981418a27Smrg              ((e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid) ||
281081418a27Smrg               (e2->op == TOKarrayliteral && t2->ty == Tsarray && t2->nextOf()->ty == Tvoid && ((TypeSArray *)t2)->dim->toInteger() == 0) ||
281181418a27Smrg               (isVoidArrayLiteral(e2, t1)))
281281418a27Smrg             )
281381418a27Smrg     {
281481418a27Smrg         /*  (T[n] op void*)   => T[]
281581418a27Smrg          *  (T[]  op void*)   => T[]
281681418a27Smrg          *  (T[n] op void[0]) => T[]
281781418a27Smrg          *  (T[]  op void[0]) => T[]
281881418a27Smrg          *  (T[n] op void[])  => T[]
281981418a27Smrg          *  (T[]  op void[])  => T[]
282081418a27Smrg          */
282181418a27Smrg         goto Lx1;
282281418a27Smrg     }
282381418a27Smrg     else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
282481418a27Smrg              ((e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid) ||
282581418a27Smrg               (e1->op == TOKarrayliteral && t1->ty == Tsarray && t1->nextOf()->ty == Tvoid && ((TypeSArray *)t1)->dim->toInteger() == 0) ||
282681418a27Smrg               (isVoidArrayLiteral(e1, t2)))
282781418a27Smrg             )
282881418a27Smrg     {
282981418a27Smrg         /*  (void*   op T[n]) => T[]
283081418a27Smrg          *  (void*   op T[])  => T[]
283181418a27Smrg          *  (void[0] op T[n]) => T[]
283281418a27Smrg          *  (void[0] op T[])  => T[]
283381418a27Smrg          *  (void[]  op T[n]) => T[]
283481418a27Smrg          *  (void[]  op T[])  => T[]
283581418a27Smrg          */
283681418a27Smrg         goto Lx2;
283781418a27Smrg     }
283881418a27Smrg     else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
283981418a27Smrg              (m = t1->implicitConvTo(t2)) != MATCHnomatch)
284081418a27Smrg     {
284181418a27Smrg         // Bugzilla 7285: Tsarray op [x, y, ...] should to be Tsarray
284281418a27Smrg         // Bugzilla 14737: Tsarray ~ [x, y, ...] should to be Tarray
284381418a27Smrg         if (t1->ty == Tsarray && e2->op == TOKarrayliteral && op != TOKcat)
284481418a27Smrg             goto Lt1;
284581418a27Smrg         if (m == MATCHconst &&
284681418a27Smrg             (op == TOKaddass || op == TOKminass || op == TOKmulass ||
284781418a27Smrg              op == TOKdivass || op == TOKmodass || op == TOKpowass ||
284881418a27Smrg              op == TOKandass || op == TOKorass  || op == TOKxorass)
284981418a27Smrg            )
285081418a27Smrg         {
285181418a27Smrg             // Don't make the lvalue const
285281418a27Smrg             t = t2;
285381418a27Smrg             goto Lret;
285481418a27Smrg         }
285581418a27Smrg         goto Lt2;
285681418a27Smrg     }
285781418a27Smrg     else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1))
285881418a27Smrg     {
285981418a27Smrg         // Bugzilla 7285 & 14737
286081418a27Smrg         if (t2->ty == Tsarray && e1->op == TOKarrayliteral && op != TOKcat)
286181418a27Smrg             goto Lt2;
286281418a27Smrg         goto Lt1;
286381418a27Smrg     }
286481418a27Smrg     else if ((t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Tpointer) &&
286581418a27Smrg              (t2->ty == Tsarray || t2->ty == Tarray || t2->ty == Tpointer) &&
286681418a27Smrg              t1->nextOf()->mod != t2->nextOf()->mod
286781418a27Smrg             )
286881418a27Smrg     {
286981418a27Smrg         /* If one is mutable and the other invariant, then retry
287081418a27Smrg          * with both of them as const
287181418a27Smrg          */
287281418a27Smrg         Type *t1n = t1->nextOf();
287381418a27Smrg         Type *t2n = t2->nextOf();
287481418a27Smrg         unsigned char mod;
287581418a27Smrg         if (e1->op == TOKnull && e2->op != TOKnull)
287681418a27Smrg             mod = t2n->mod;
287781418a27Smrg         else if (e1->op != TOKnull && e2->op == TOKnull)
287881418a27Smrg             mod = t1n->mod;
287981418a27Smrg         else if (!t1n->isImmutable() && !t2n->isImmutable() && t1n->isShared() != t2n->isShared())
288081418a27Smrg             goto Lincompatible;
288181418a27Smrg         else
288281418a27Smrg             mod = MODmerge(t1n->mod, t2n->mod);
288381418a27Smrg 
288481418a27Smrg         if (t1->ty == Tpointer)
288581418a27Smrg             t1 = t1n->castMod(mod)->pointerTo();
288681418a27Smrg         else
288781418a27Smrg             t1 = t1n->castMod(mod)->arrayOf();
288881418a27Smrg 
288981418a27Smrg         if (t2->ty == Tpointer)
289081418a27Smrg             t2 = t2n->castMod(mod)->pointerTo();
289181418a27Smrg         else
289281418a27Smrg             t2 = t2n->castMod(mod)->arrayOf();
289381418a27Smrg         t = t1;
289481418a27Smrg         goto Lagain;
289581418a27Smrg     }
289681418a27Smrg     else if (t1->ty == Tclass && t2->ty == Tclass)
289781418a27Smrg     {
289881418a27Smrg         if (t1->mod != t2->mod)
289981418a27Smrg         {
290081418a27Smrg             unsigned char mod;
290181418a27Smrg             if (e1->op == TOKnull && e2->op != TOKnull)
290281418a27Smrg                 mod = t2->mod;
290381418a27Smrg             else if (e1->op != TOKnull && e2->op == TOKnull)
290481418a27Smrg                 mod = t1->mod;
290581418a27Smrg             else if (!t1->isImmutable() && !t2->isImmutable() && t1->isShared() != t2->isShared())
290681418a27Smrg                 goto Lincompatible;
290781418a27Smrg             else
290881418a27Smrg                 mod = MODmerge(t1->mod, t2->mod);
290981418a27Smrg             t1 = t1->castMod(mod);
291081418a27Smrg             t2 = t2->castMod(mod);
291181418a27Smrg             t = t1;
291281418a27Smrg             goto Lagain;
291381418a27Smrg         }
291481418a27Smrg         goto Lcc;
291581418a27Smrg     }
291681418a27Smrg     else if (t1->ty == Tclass || t2->ty == Tclass)
291781418a27Smrg     {
291881418a27Smrg Lcc:
291981418a27Smrg         while (1)
292081418a27Smrg         {
292181418a27Smrg             MATCH i1 = e2->implicitConvTo(t1);
292281418a27Smrg             MATCH i2 = e1->implicitConvTo(t2);
292381418a27Smrg 
292481418a27Smrg             if (i1 && i2)
292581418a27Smrg             {
292681418a27Smrg                 // We have the case of class vs. void*, so pick class
292781418a27Smrg                 if (t1->ty == Tpointer)
292881418a27Smrg                     i1 = MATCHnomatch;
292981418a27Smrg                 else if (t2->ty == Tpointer)
293081418a27Smrg                     i2 = MATCHnomatch;
293181418a27Smrg             }
293281418a27Smrg 
293381418a27Smrg             if (i2)
293481418a27Smrg             {
293581418a27Smrg                 e2 = e2->castTo(sc, t2);
293681418a27Smrg                 goto Lt2;
293781418a27Smrg             }
293881418a27Smrg             else if (i1)
293981418a27Smrg             {
294081418a27Smrg                 e1 = e1->castTo(sc, t1);
294181418a27Smrg                 goto Lt1;
294281418a27Smrg             }
294381418a27Smrg             else if (t1->ty == Tclass && t2->ty == Tclass)
294481418a27Smrg             {
294581418a27Smrg                 TypeClass *tc1 = (TypeClass *)t1;
294681418a27Smrg                 TypeClass *tc2 = (TypeClass *)t2;
294781418a27Smrg 
294881418a27Smrg                 /* Pick 'tightest' type
294981418a27Smrg                  */
295081418a27Smrg                 ClassDeclaration *cd1 = tc1->sym->baseClass;
295181418a27Smrg                 ClassDeclaration *cd2 = tc2->sym->baseClass;
295281418a27Smrg 
295381418a27Smrg                 if (cd1 && cd2)
295481418a27Smrg                 {
295581418a27Smrg                     t1 = cd1->type->castMod(t1->mod);
295681418a27Smrg                     t2 = cd2->type->castMod(t2->mod);
295781418a27Smrg                 }
295881418a27Smrg                 else if (cd1)
295981418a27Smrg                     t1 = cd1->type;
296081418a27Smrg                 else if (cd2)
296181418a27Smrg                     t2 = cd2->type;
296281418a27Smrg                 else
296381418a27Smrg                     goto Lincompatible;
296481418a27Smrg             }
296581418a27Smrg             else if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
296681418a27Smrg             {
296781418a27Smrg                 if (att1 && e1->type == att1)
296881418a27Smrg                     goto Lincompatible;
296981418a27Smrg                 if (!att1 && e1->type->checkAliasThisRec())
297081418a27Smrg                     att1 = e1->type;
297181418a27Smrg                 //printf("att tmerge(c || c) e1 = %s\n", e1->type->toChars());
297281418a27Smrg                 e1 = resolveAliasThis(sc, e1);
297381418a27Smrg                 t1 = e1->type;
297481418a27Smrg                 continue;
297581418a27Smrg             }
297681418a27Smrg             else if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
297781418a27Smrg             {
297881418a27Smrg                 if (att2 && e2->type == att2)
297981418a27Smrg                     goto Lincompatible;
298081418a27Smrg                 if (!att2 && e2->type->checkAliasThisRec())
298181418a27Smrg                     att2 = e2->type;
298281418a27Smrg                 //printf("att tmerge(c || c) e2 = %s\n", e2->type->toChars());
298381418a27Smrg                 e2 = resolveAliasThis(sc, e2);
298481418a27Smrg                 t2 = e2->type;
298581418a27Smrg                 continue;
298681418a27Smrg             }
298781418a27Smrg             else
298881418a27Smrg                 goto Lincompatible;
298981418a27Smrg         }
299081418a27Smrg     }
299181418a27Smrg     else if (t1->ty == Tstruct && t2->ty == Tstruct)
299281418a27Smrg     {
299381418a27Smrg         if (t1->mod != t2->mod)
299481418a27Smrg         {
299581418a27Smrg             if (!t1->isImmutable() && !t2->isImmutable() && t1->isShared() != t2->isShared())
299681418a27Smrg                 goto Lincompatible;
299781418a27Smrg             unsigned char mod = MODmerge(t1->mod, t2->mod);
299881418a27Smrg             t1 = t1->castMod(mod);
299981418a27Smrg             t2 = t2->castMod(mod);
300081418a27Smrg             t = t1;
300181418a27Smrg             goto Lagain;
300281418a27Smrg         }
300381418a27Smrg 
300481418a27Smrg         TypeStruct *ts1 = (TypeStruct *)t1;
300581418a27Smrg         TypeStruct *ts2 = (TypeStruct *)t2;
300681418a27Smrg         if (ts1->sym != ts2->sym)
300781418a27Smrg         {
300881418a27Smrg             if (!ts1->sym->aliasthis && !ts2->sym->aliasthis)
300981418a27Smrg                 goto Lincompatible;
301081418a27Smrg 
301181418a27Smrg             MATCH i1 = MATCHnomatch;
301281418a27Smrg             MATCH i2 = MATCHnomatch;
301381418a27Smrg 
301481418a27Smrg             Expression *e1b = NULL;
301581418a27Smrg             Expression *e2b = NULL;
301681418a27Smrg             if (ts2->sym->aliasthis)
301781418a27Smrg             {
301881418a27Smrg                 if (att2 && e2->type == att2)
301981418a27Smrg                     goto Lincompatible;
302081418a27Smrg                 if (!att2 && e2->type->checkAliasThisRec())
302181418a27Smrg                     att2 = e2->type;
302281418a27Smrg                 //printf("att tmerge(s && s) e2 = %s\n", e2->type->toChars());
302381418a27Smrg                 e2b = resolveAliasThis(sc, e2);
302481418a27Smrg                 i1 = e2b->implicitConvTo(t1);
302581418a27Smrg             }
302681418a27Smrg             if (ts1->sym->aliasthis)
302781418a27Smrg             {
302881418a27Smrg                 if (att1 && e1->type == att1)
302981418a27Smrg                     goto Lincompatible;
303081418a27Smrg                 if (!att1 && e1->type->checkAliasThisRec())
303181418a27Smrg                     att1 = e1->type;
303281418a27Smrg                 //printf("att tmerge(s && s) e1 = %s\n", e1->type->toChars());
303381418a27Smrg                 e1b = resolveAliasThis(sc, e1);
303481418a27Smrg                 i2 = e1b->implicitConvTo(t2);
303581418a27Smrg             }
303681418a27Smrg             if (i1 && i2)
303781418a27Smrg                 goto Lincompatible;
303881418a27Smrg 
303981418a27Smrg             if (i1)
304081418a27Smrg                 goto Lt1;
304181418a27Smrg             else if (i2)
304281418a27Smrg                 goto Lt2;
304381418a27Smrg 
304481418a27Smrg             if (e1b)
304581418a27Smrg             {
304681418a27Smrg                 e1 = e1b;
304781418a27Smrg                 t1 = e1b->type->toBasetype();
304881418a27Smrg             }
304981418a27Smrg             if (e2b)
305081418a27Smrg             {
305181418a27Smrg                 e2 = e2b;
305281418a27Smrg                 t2 = e2b->type->toBasetype();
305381418a27Smrg             }
305481418a27Smrg             t = t1;
305581418a27Smrg             goto Lagain;
305681418a27Smrg         }
305781418a27Smrg     }
305881418a27Smrg     else if (t1->ty == Tstruct || t2->ty == Tstruct)
305981418a27Smrg     {
306081418a27Smrg         if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
306181418a27Smrg         {
306281418a27Smrg             if (att1 && e1->type == att1)
306381418a27Smrg                 goto Lincompatible;
306481418a27Smrg             if (!att1 && e1->type->checkAliasThisRec())
306581418a27Smrg                 att1 = e1->type;
306681418a27Smrg             //printf("att tmerge(s || s) e1 = %s\n", e1->type->toChars());
306781418a27Smrg             e1 = resolveAliasThis(sc, e1);
306881418a27Smrg             t1 = e1->type;
306981418a27Smrg             t = t1;
307081418a27Smrg             goto Lagain;
307181418a27Smrg         }
307281418a27Smrg         if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
307381418a27Smrg         {
307481418a27Smrg             if (att2 && e2->type == att2)
307581418a27Smrg                 goto Lincompatible;
307681418a27Smrg             if (!att2 && e2->type->checkAliasThisRec())
307781418a27Smrg                 att2 = e2->type;
307881418a27Smrg             //printf("att tmerge(s || s) e2 = %s\n", e2->type->toChars());
307981418a27Smrg             e2 = resolveAliasThis(sc, e2);
308081418a27Smrg             t2 = e2->type;
308181418a27Smrg             t = t2;
308281418a27Smrg             goto Lagain;
308381418a27Smrg         }
308481418a27Smrg         goto Lincompatible;
308581418a27Smrg     }
308681418a27Smrg     else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2))
308781418a27Smrg     {
308881418a27Smrg         goto Lt2;
308981418a27Smrg     }
309081418a27Smrg     else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1))
309181418a27Smrg     {
309281418a27Smrg         goto Lt1;
309381418a27Smrg     }
309481418a27Smrg     else if (t1->ty == Tsarray && t2->ty == Tsarray &&
309581418a27Smrg              e2->implicitConvTo(t1->nextOf()->arrayOf()))
309681418a27Smrg     {
309781418a27Smrg      Lx1:
309881418a27Smrg         t = t1->nextOf()->arrayOf();    // T[]
309981418a27Smrg         e1 = e1->castTo(sc, t);
310081418a27Smrg         e2 = e2->castTo(sc, t);
310181418a27Smrg     }
310281418a27Smrg     else if (t1->ty == Tsarray && t2->ty == Tsarray &&
310381418a27Smrg              e1->implicitConvTo(t2->nextOf()->arrayOf()))
310481418a27Smrg     {
310581418a27Smrg      Lx2:
310681418a27Smrg         t = t2->nextOf()->arrayOf();
310781418a27Smrg         e1 = e1->castTo(sc, t);
310881418a27Smrg         e2 = e2->castTo(sc, t);
310981418a27Smrg     }
311081418a27Smrg     else if (t1->ty == Tvector && t2->ty == Tvector)
311181418a27Smrg     {
311281418a27Smrg         // Bugzilla 13841, all vector types should have no common types between
311381418a27Smrg         // different vectors, even though their sizes are same.
311481418a27Smrg         TypeVector *tv1 = (TypeVector *)t1;
311581418a27Smrg         TypeVector *tv2 = (TypeVector *)t2;
311681418a27Smrg         if (!tv1->basetype->equals(tv2->basetype))
311781418a27Smrg             goto Lincompatible;
311881418a27Smrg 
311981418a27Smrg         goto LmodCompare;
312081418a27Smrg     }
312181418a27Smrg     else if (t1->ty == Tvector && t2->ty != Tvector &&
312281418a27Smrg              e2->implicitConvTo(t1))
312381418a27Smrg     {
312481418a27Smrg         e2 = e2->castTo(sc, t1);
312581418a27Smrg         t2 = t1;
312681418a27Smrg         t = t1;
312781418a27Smrg         goto Lagain;
312881418a27Smrg     }
312981418a27Smrg     else if (t2->ty == Tvector && t1->ty != Tvector &&
313081418a27Smrg              e1->implicitConvTo(t2))
313181418a27Smrg     {
313281418a27Smrg         e1 = e1->castTo(sc, t2);
313381418a27Smrg         t1 = t2;
313481418a27Smrg         t = t1;
313581418a27Smrg         goto Lagain;
313681418a27Smrg     }
313781418a27Smrg     else if (t1->isintegral() && t2->isintegral())
313881418a27Smrg     {
313981418a27Smrg         if (t1->ty != t2->ty)
314081418a27Smrg         {
314181418a27Smrg             if (t1->ty == Tvector || t2->ty == Tvector)
314281418a27Smrg                 goto Lincompatible;
314381418a27Smrg             e1 = integralPromotions(e1, sc);
314481418a27Smrg             e2 = integralPromotions(e2, sc);
314581418a27Smrg             t1 = e1->type;
314681418a27Smrg             t2 = e2->type;
314781418a27Smrg             goto Lagain;
314881418a27Smrg         }
314981418a27Smrg         assert(t1->ty == t2->ty);
315081418a27Smrg LmodCompare:
315181418a27Smrg         if (!t1->isImmutable() && !t2->isImmutable() && t1->isShared() != t2->isShared())
315281418a27Smrg             goto Lincompatible;
315381418a27Smrg         unsigned char mod = MODmerge(t1->mod, t2->mod);
315481418a27Smrg 
315581418a27Smrg         t1 = t1->castMod(mod);
315681418a27Smrg         t2 = t2->castMod(mod);
315781418a27Smrg         t = t1;
315881418a27Smrg         e1 = e1->castTo(sc, t);
315981418a27Smrg         e2 = e2->castTo(sc, t);
316081418a27Smrg         goto Lagain;
316181418a27Smrg     }
316281418a27Smrg     else if (t1->ty == Tnull && t2->ty == Tnull)
316381418a27Smrg     {
316481418a27Smrg         unsigned char mod = MODmerge(t1->mod, t2->mod);
316581418a27Smrg 
316681418a27Smrg         t = t1->castMod(mod);
316781418a27Smrg         e1 = e1->castTo(sc, t);
316881418a27Smrg         e2 = e2->castTo(sc, t);
316981418a27Smrg         goto Lret;
317081418a27Smrg     }
317181418a27Smrg     else if (t2->ty == Tnull &&
317281418a27Smrg         (t1->ty == Tpointer || t1->ty == Taarray || t1->ty == Tarray))
317381418a27Smrg     {
317481418a27Smrg         goto Lt1;
317581418a27Smrg     }
317681418a27Smrg     else if (t1->ty == Tnull &&
317781418a27Smrg         (t2->ty == Tpointer || t2->ty == Taarray || t2->ty == Tarray))
317881418a27Smrg     {
317981418a27Smrg         goto Lt2;
318081418a27Smrg     }
318181418a27Smrg     else if (t1->ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
318281418a27Smrg     {
318381418a27Smrg         if (e2->implicitConvTo(t1->nextOf()))
318481418a27Smrg         {
318581418a27Smrg             // T[] op T
318681418a27Smrg             // T[] op cast(T)U
318781418a27Smrg             e2 = e2->castTo(sc, t1->nextOf());
318881418a27Smrg             t = t1->nextOf()->arrayOf();
318981418a27Smrg         }
319081418a27Smrg         else if (t1->nextOf()->implicitConvTo(e2->type))
319181418a27Smrg         {
319281418a27Smrg             // (cast(T)U)[] op T    (Bugzilla 12780)
319381418a27Smrg             // e1 is left as U[], it will be handled in arrayOp() later.
319481418a27Smrg             t = e2->type->arrayOf();
319581418a27Smrg         }
319681418a27Smrg         else if (t2->ty == Tarray && isArrayOpOperand(e2))
319781418a27Smrg         {
319881418a27Smrg             if (t1->nextOf()->implicitConvTo(t2->nextOf()))
319981418a27Smrg             {
320081418a27Smrg                 // (cast(T)U)[] op T[]  (Bugzilla 12780)
320181418a27Smrg                 // e1 is left as U[], it will be handled in arrayOp() later.
320281418a27Smrg                 t = t2->nextOf()->arrayOf();
320381418a27Smrg             }
320481418a27Smrg             else if (t2->nextOf()->implicitConvTo(t1->nextOf()))
320581418a27Smrg             {
320681418a27Smrg                 // T[] op (cast(T)U)[]  (Bugzilla 12780)
320781418a27Smrg                 // e2 is left as U[], it will be handled in arrayOp() later.
320881418a27Smrg                 t = t1->nextOf()->arrayOf();
320981418a27Smrg             }
321081418a27Smrg             else
321181418a27Smrg                 goto Lincompatible;
321281418a27Smrg         }
321381418a27Smrg         else
321481418a27Smrg             goto Lincompatible;
321581418a27Smrg     }
321681418a27Smrg     else if (t2->ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2))
321781418a27Smrg     {
321881418a27Smrg         if (e1->implicitConvTo(t2->nextOf()))
321981418a27Smrg         {
322081418a27Smrg             // T op T[]
322181418a27Smrg             // cast(T)U op T[]
322281418a27Smrg             e1 = e1->castTo(sc, t2->nextOf());
322381418a27Smrg             t = t2->nextOf()->arrayOf();
322481418a27Smrg         }
322581418a27Smrg         else if (t2->nextOf()->implicitConvTo(e1->type))
322681418a27Smrg         {
322781418a27Smrg             // T op (cast(T)U)[]    (Bugzilla 12780)
322881418a27Smrg             // e2 is left as U[], it will be handled in arrayOp() later.
322981418a27Smrg             t = e1->type->arrayOf();
323081418a27Smrg         }
323181418a27Smrg         else
323281418a27Smrg             goto Lincompatible;
323381418a27Smrg 
323481418a27Smrg         //printf("test %s\n", Token::toChars(op));
323581418a27Smrg         e1 = e1->optimize(WANTvalue);
323681418a27Smrg         if (isCommutative(op) && e1->isConst())
323781418a27Smrg         {
323881418a27Smrg             /* Swap operands to minimize number of functions generated
323981418a27Smrg              */
324081418a27Smrg             //printf("swap %s\n", Token::toChars(op));
324181418a27Smrg             Expression *tmp = e1;
324281418a27Smrg             e1 = e2;
324381418a27Smrg             e2 = tmp;
324481418a27Smrg         }
324581418a27Smrg     }
324681418a27Smrg     else
324781418a27Smrg     {
324881418a27Smrg     Lincompatible:
324981418a27Smrg         return false;
325081418a27Smrg     }
325181418a27Smrg Lret:
325281418a27Smrg     if (!*pt)
325381418a27Smrg         *pt = t;
325481418a27Smrg     *pe1 = e1;
325581418a27Smrg     *pe2 = e2;
325681418a27Smrg     //print();
325781418a27Smrg     return true;
325881418a27Smrg 
325981418a27Smrg 
326081418a27Smrg Lt1:
326181418a27Smrg     e2 = e2->castTo(sc, t1);
326281418a27Smrg     t = t1;
326381418a27Smrg     goto Lret;
326481418a27Smrg 
326581418a27Smrg Lt2:
326681418a27Smrg     e1 = e1->castTo(sc, t2);
326781418a27Smrg     t = t2;
326881418a27Smrg     goto Lret;
326981418a27Smrg }
327081418a27Smrg 
327181418a27Smrg /************************************
327281418a27Smrg  * Bring leaves to common type.
327381418a27Smrg  * Returns ErrorExp if error occurs. otherwise returns NULL.
327481418a27Smrg  */
327581418a27Smrg 
typeCombine(BinExp * be,Scope * sc)327681418a27Smrg Expression *typeCombine(BinExp *be, Scope *sc)
327781418a27Smrg {
327881418a27Smrg     Type *t1 = be->e1->type->toBasetype();
327981418a27Smrg     Type *t2 = be->e2->type->toBasetype();
328081418a27Smrg 
328181418a27Smrg     if (be->op == TOKmin || be->op == TOKadd)
328281418a27Smrg     {
328381418a27Smrg         // struct+struct, and class+class are errors
328481418a27Smrg         if (t1->ty == Tstruct && t2->ty == Tstruct)
328581418a27Smrg             goto Lerror;
328681418a27Smrg         else if (t1->ty == Tclass && t2->ty == Tclass)
328781418a27Smrg             goto Lerror;
328881418a27Smrg         else if (t1->ty == Taarray && t2->ty == Taarray)
328981418a27Smrg             goto Lerror;
329081418a27Smrg     }
329181418a27Smrg 
329281418a27Smrg     if (!typeMerge(sc, be->op, &be->type, &be->e1, &be->e2))
329381418a27Smrg         goto Lerror;
329481418a27Smrg     // If the types have no value, return an error
329581418a27Smrg     if (be->e1->op == TOKerror)
329681418a27Smrg         return be->e1;
329781418a27Smrg     if (be->e2->op == TOKerror)
329881418a27Smrg         return be->e2;
329981418a27Smrg     return NULL;
330081418a27Smrg 
330181418a27Smrg Lerror:
330281418a27Smrg     Expression *ex = be->incompatibleTypes();
330381418a27Smrg     if (ex->op == TOKerror)
330481418a27Smrg         return ex;
330581418a27Smrg     return new ErrorExp();
330681418a27Smrg }
330781418a27Smrg 
330881418a27Smrg /***********************************
330981418a27Smrg  * Do integral promotions (convertchk).
331081418a27Smrg  * Don't convert <array of> to <pointer to>
331181418a27Smrg  */
331281418a27Smrg 
integralPromotions(Expression * e,Scope * sc)331381418a27Smrg Expression *integralPromotions(Expression *e, Scope *sc)
331481418a27Smrg {
331581418a27Smrg     //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
331681418a27Smrg     switch (e->type->toBasetype()->ty)
331781418a27Smrg     {
331881418a27Smrg         case Tvoid:
331981418a27Smrg             e->error("void has no value");
332081418a27Smrg             return new ErrorExp();
332181418a27Smrg 
332281418a27Smrg         case Tint8:
332381418a27Smrg         case Tuns8:
332481418a27Smrg         case Tint16:
332581418a27Smrg         case Tuns16:
332681418a27Smrg         case Tbool:
332781418a27Smrg         case Tchar:
332881418a27Smrg         case Twchar:
332981418a27Smrg             e = e->castTo(sc, Type::tint32);
333081418a27Smrg             break;
333181418a27Smrg 
333281418a27Smrg         case Tdchar:
333381418a27Smrg             e = e->castTo(sc, Type::tuns32);
333481418a27Smrg             break;
333581418a27Smrg         default:
333681418a27Smrg             break;
333781418a27Smrg     }
333881418a27Smrg     return e;
333981418a27Smrg }
334081418a27Smrg 
334181418a27Smrg /***********************************
334281418a27Smrg  * See if both types are arrays that can be compared
334381418a27Smrg  * for equality. Return true if so.
334481418a27Smrg  * If they are arrays, but incompatible, issue error.
334581418a27Smrg  * This is to enable comparing things like an immutable
334681418a27Smrg  * array with a mutable one.
334781418a27Smrg  */
334881418a27Smrg 
arrayTypeCompatible(Loc loc,Type * t1,Type * t2)334981418a27Smrg bool arrayTypeCompatible(Loc loc, Type *t1, Type *t2)
335081418a27Smrg {
335181418a27Smrg     t1 = t1->toBasetype()->merge2();
335281418a27Smrg     t2 = t2->toBasetype()->merge2();
335381418a27Smrg 
335481418a27Smrg     if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
335581418a27Smrg         (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
335681418a27Smrg     {
335781418a27Smrg         if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
335881418a27Smrg             t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
335981418a27Smrg             (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
336081418a27Smrg         {
336181418a27Smrg             error(loc, "array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
336281418a27Smrg         }
336381418a27Smrg         return true;
336481418a27Smrg     }
336581418a27Smrg     return false;
336681418a27Smrg }
336781418a27Smrg 
336881418a27Smrg /***********************************
336981418a27Smrg  * See if both types are arrays that can be compared
337081418a27Smrg  * for equality without any casting. Return true if so.
337181418a27Smrg  * This is to enable comparing things like an immutable
337281418a27Smrg  * array with a mutable one.
337381418a27Smrg  */
arrayTypeCompatibleWithoutCasting(Type * t1,Type * t2)337481418a27Smrg bool arrayTypeCompatibleWithoutCasting(Type *t1, Type *t2)
337581418a27Smrg {
337681418a27Smrg     t1 = t1->toBasetype();
337781418a27Smrg     t2 = t2->toBasetype();
337881418a27Smrg 
337981418a27Smrg     if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
338081418a27Smrg         t2->ty == t1->ty)
338181418a27Smrg     {
338281418a27Smrg         if (t1->nextOf()->implicitConvTo(t2->nextOf()) >= MATCHconst ||
338381418a27Smrg             t2->nextOf()->implicitConvTo(t1->nextOf()) >= MATCHconst)
338481418a27Smrg             return true;
338581418a27Smrg     }
338681418a27Smrg     return false;
338781418a27Smrg }
338881418a27Smrg 
338981418a27Smrg /******************************************************************/
339081418a27Smrg 
339181418a27Smrg /* Determine the integral ranges of an expression.
339281418a27Smrg  * This is used to determine if implicit narrowing conversions will
339381418a27Smrg  * be allowed.
339481418a27Smrg  */
339581418a27Smrg 
getIntRange(Expression * e)339681418a27Smrg IntRange getIntRange(Expression *e)
339781418a27Smrg {
339881418a27Smrg     class IntRangeVisitor : public Visitor
339981418a27Smrg     {
340081418a27Smrg     public:
340181418a27Smrg         IntRange range;
340281418a27Smrg 
340381418a27Smrg         void visit(Expression *e)
340481418a27Smrg         {
340581418a27Smrg             range = IntRange::fromType(e->type);
340681418a27Smrg         }
340781418a27Smrg 
340881418a27Smrg         void visit(IntegerExp *e)
340981418a27Smrg         {
341081418a27Smrg             range = IntRange(SignExtendedNumber(e->getInteger())).cast(e->type);
341181418a27Smrg         }
341281418a27Smrg 
341381418a27Smrg         void visit(CastExp *e)
341481418a27Smrg         {
341581418a27Smrg             range = getIntRange(e->e1).cast(e->type);
341681418a27Smrg         }
341781418a27Smrg 
341881418a27Smrg         void visit(AddExp *e)
341981418a27Smrg         {
342081418a27Smrg             IntRange ir1 = getIntRange(e->e1);
342181418a27Smrg             IntRange ir2 = getIntRange(e->e2);
342281418a27Smrg             range = (ir1 + ir2).cast(e->type);
342381418a27Smrg         }
342481418a27Smrg 
342581418a27Smrg         void visit(MinExp *e)
342681418a27Smrg         {
342781418a27Smrg             IntRange ir1 = getIntRange(e->e1);
342881418a27Smrg             IntRange ir2 = getIntRange(e->e2);
342981418a27Smrg             range = (ir1 - ir2).cast(e->type);
343081418a27Smrg         }
343181418a27Smrg 
343281418a27Smrg         void visit(DivExp *e)
343381418a27Smrg         {
343481418a27Smrg             IntRange ir1 = getIntRange(e->e1);
343581418a27Smrg             IntRange ir2 = getIntRange(e->e2);
343681418a27Smrg 
343781418a27Smrg             range = (ir1 / ir2).cast(e->type);
343881418a27Smrg         }
343981418a27Smrg 
344081418a27Smrg         void visit(MulExp *e)
344181418a27Smrg         {
344281418a27Smrg             IntRange ir1 = getIntRange(e->e1);
344381418a27Smrg             IntRange ir2 = getIntRange(e->e2);
344481418a27Smrg 
344581418a27Smrg             range = (ir1 * ir2).cast(e->type);
344681418a27Smrg         }
344781418a27Smrg 
344881418a27Smrg         void visit(ModExp *e)
344981418a27Smrg         {
345081418a27Smrg             IntRange ir1 = getIntRange(e->e1);
345181418a27Smrg             IntRange ir2 = getIntRange(e->e2);
345281418a27Smrg 
345381418a27Smrg             // Modding on 0 is invalid anyway.
345481418a27Smrg             if (!ir2.absNeg().imin.negative)
345581418a27Smrg             {
345681418a27Smrg                 visit((Expression *)e);
345781418a27Smrg                 return;
345881418a27Smrg             }
345981418a27Smrg             range = (ir1 % ir2).cast(e->type);
346081418a27Smrg         }
346181418a27Smrg 
346281418a27Smrg         void visit(AndExp *e)
346381418a27Smrg         {
346481418a27Smrg             IntRange result;
346581418a27Smrg             bool hasResult = false;
346681418a27Smrg             result.unionOrAssign(getIntRange(e->e1) & getIntRange(e->e2), hasResult);
346781418a27Smrg 
346881418a27Smrg             assert(hasResult);
346981418a27Smrg             range = result.cast(e->type);
347081418a27Smrg         }
347181418a27Smrg 
347281418a27Smrg         void visit(OrExp *e)
347381418a27Smrg         {
347481418a27Smrg             IntRange result;
347581418a27Smrg             bool hasResult = false;
347681418a27Smrg             result.unionOrAssign(getIntRange(e->e1) | getIntRange(e->e2), hasResult);
347781418a27Smrg 
347881418a27Smrg             assert(hasResult);
347981418a27Smrg             range = result.cast(e->type);
348081418a27Smrg         }
348181418a27Smrg 
348281418a27Smrg         void visit(XorExp *e)
348381418a27Smrg         {
348481418a27Smrg             IntRange result;
348581418a27Smrg             bool hasResult = false;
348681418a27Smrg             result.unionOrAssign(getIntRange(e->e1) ^ getIntRange(e->e2), hasResult);
348781418a27Smrg 
348881418a27Smrg             assert(hasResult);
348981418a27Smrg             range = result.cast(e->type);
349081418a27Smrg         }
349181418a27Smrg 
349281418a27Smrg         void visit(ShlExp *e)
349381418a27Smrg         {
349481418a27Smrg             IntRange ir1 = getIntRange(e->e1);
349581418a27Smrg             IntRange ir2 = getIntRange(e->e2);
349681418a27Smrg 
349781418a27Smrg             range = (ir1 << ir2).cast(e->type);
349881418a27Smrg         }
349981418a27Smrg 
350081418a27Smrg         void visit(ShrExp *e)
350181418a27Smrg         {
350281418a27Smrg             IntRange ir1 = getIntRange(e->e1);
350381418a27Smrg             IntRange ir2 = getIntRange(e->e2);
350481418a27Smrg 
350581418a27Smrg             range = (ir1 >> ir2).cast(e->type);
350681418a27Smrg         }
350781418a27Smrg 
350881418a27Smrg         void visit(UshrExp *e)
350981418a27Smrg         {
351081418a27Smrg             IntRange ir1 = getIntRange(e->e1).castUnsigned(e->e1->type);
351181418a27Smrg             IntRange ir2 = getIntRange(e->e2);
351281418a27Smrg 
351381418a27Smrg             range = (ir1 >> ir2).cast(e->type);
351481418a27Smrg         }
351581418a27Smrg 
351681418a27Smrg         void visit(AssignExp *e)
351781418a27Smrg         {
351881418a27Smrg             range = getIntRange(e->e2).cast(e->type);
351981418a27Smrg         }
352081418a27Smrg 
352181418a27Smrg         void visit(CondExp *e)
352281418a27Smrg         {
352381418a27Smrg             // No need to check e->econd; assume caller has called optimize()
352481418a27Smrg             IntRange ir1 = getIntRange(e->e1);
352581418a27Smrg             IntRange ir2 = getIntRange(e->e2);
352681418a27Smrg             range = ir1.unionWith(ir2).cast(e->type);
352781418a27Smrg         }
352881418a27Smrg 
352981418a27Smrg         void visit(VarExp *e)
353081418a27Smrg         {
353181418a27Smrg             Expression *ie;
353281418a27Smrg             VarDeclaration* vd = e->var->isVarDeclaration();
353381418a27Smrg             if (vd && vd->range)
353481418a27Smrg                 range = vd->range->cast(e->type);
353581418a27Smrg             else if (vd && vd->_init && !vd->type->isMutable() &&
353681418a27Smrg                 (ie = vd->getConstInitializer()) != NULL)
353781418a27Smrg                 ie->accept(this);
353881418a27Smrg             else
353981418a27Smrg                 visit((Expression *)e);
354081418a27Smrg         }
354181418a27Smrg 
354281418a27Smrg         void visit(CommaExp *e)
354381418a27Smrg         {
354481418a27Smrg             e->e2->accept(this);
354581418a27Smrg         }
354681418a27Smrg 
354781418a27Smrg         void visit(ComExp *e)
354881418a27Smrg         {
354981418a27Smrg             IntRange ir = getIntRange(e->e1);
355081418a27Smrg             range = IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative),
355181418a27Smrg                             SignExtendedNumber(~ir.imin.value, !ir.imin.negative)).cast(e->type);
355281418a27Smrg         }
355381418a27Smrg 
355481418a27Smrg         void visit(NegExp *e)
355581418a27Smrg         {
355681418a27Smrg             IntRange ir = getIntRange(e->e1);
355781418a27Smrg             range = (-ir).cast(e->type);
355881418a27Smrg         }
355981418a27Smrg     };
356081418a27Smrg 
356181418a27Smrg     IntRangeVisitor v;
356281418a27Smrg     e->accept(&v);
356381418a27Smrg     return v.range;
356481418a27Smrg }
3565