
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.

#include <stdio.h>
#include <assert.h>

#include "rmem.h"

#include "expression.h"
#include "mtype.h"
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"

/* ==================== implicitCast ====================== */

/**************************************
 * Do an implicit cast.
 * Issue error if it can't be done.
 */

Expression *Expression::implicitCastTo(Scope *sc, Type *t)
{
    //printf("Expression::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars());

    MATCH match = implicitConvTo(t);
    if (match)
    {	TY tyfrom = type->toBasetype()->ty;
	TY tyto = t->toBasetype()->ty;
#if DMDV1
	if (global.params.warnings &&
	    Type::impcnvWarn[tyfrom][tyto] &&
	    op != TOKint64)
	{
	    Expression *e = optimize(WANTflags | WANTvalue);

	    if (e->op == TOKint64)
		return e->implicitCastTo(sc, t);
	    if (tyfrom == Tint32 &&
		(op == TOKadd || op == TOKmin ||
		 op == TOKand || op == TOKor || op == TOKxor)
	       )
	    {
		/* This is really only a semi-kludge fix,
		 * we really should look at the operands of op
		 * and see if they are narrower types.
		 * For example, b=b|b and b=b|7 and s=b+b should be allowed,
		 * but b=b|i should be an error.
		 */
		;
	    }
	    else
	    {
		warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data",
		    toChars(), type->toChars(), t->toChars());
	    }
	}
#endif
#if DMDV2
	if (match == MATCHconst && t == type->constOf())
	{
	    Expression *e = copy();
	    e->type = t;
	    return e;
	}
#endif
	return castTo(sc, t);
    }

    Expression *e = optimize(WANTflags | WANTvalue);
    if (e != this)
	return e->implicitCastTo(sc, t);

#if 0
printf("ty = %d\n", type->ty);
print();
type->print();
printf("to:\n");
t->print();
printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco);
//printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t);
fflush(stdout);
#endif
    if (!t->deco)
    {	/* Can happen with:
	 *    enum E { One }
	 *    class A
	 *    { static void fork(EDG dg) { dg(E.One); }
	 *	alias void delegate(E) EDG;
	 *    }
	 * Should eventually make it work.
	 */
	error("forward reference to type %s", t->toChars());
    }
    else if (t->reliesOnTident())
	error("forward reference to type %s", t->reliesOnTident()->toChars());

    error("cannot implicitly convert expression (%s) of type %s to %s",
	toChars(), type->toChars(), t->toChars());
    return castTo(sc, t);
}

Expression *StringExp::implicitCastTo(Scope *sc, Type *t)
{
    //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars());
    unsigned char committed = this->committed;
    Expression *e = Expression::implicitCastTo(sc, t);
    if (e->op == TOKstring)
    {
	// Retain polysemous nature if it started out that way
	((StringExp *)e)->committed = committed;
    }
    return e;
}

/*******************************************
 * Return !=0 if we can implicitly convert this to type t.
 * Don't do the actual cast.
 */

MATCH Expression::implicitConvTo(Type *t)
{
#if 0
    printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    //static int nest; if (++nest == 10) halt();
    if (!type)
    {	error("%s is not an expression", toChars());
	type = Type::terror;
    }
    Expression *e = optimize(WANTvalue | WANTflags);
    if (e->type == t)
	return MATCHexact;
    if (e != this)
    {	//printf("\toptimized to %s of type %s\n", e->toChars(), e->type->toChars());
	return e->implicitConvTo(t);
    }
    MATCH match = type->implicitConvTo(t);
    if (match != MATCHnomatch)
	return match;

    /* See if we can do integral narrowing conversions
     */
    if (type->isintegral() && t->isintegral() &&
	type->isTypeBasic() && t->isTypeBasic())
    {	IntRange ir = getIntRange();
	if (ir.imax <= t->sizemask())
	    return MATCHconvert;
    }

#if 0
    Type *tb = t->toBasetype();
    if (tb->ty == Tdelegate)
    {	TypeDelegate *td = (TypeDelegate *)tb;
	TypeFunction *tf = (TypeFunction *)td->nextOf();

	if (!tf->varargs &&
	    !(tf->arguments && tf->arguments->dim)
	   )
	{
	    match = type->implicitConvTo(tf->nextOf());
	    if (match)
		return match;
	    if (tf->nextOf()->toBasetype()->ty == Tvoid)
		return MATCHconvert;
	}
    }
#endif
    return MATCHnomatch;
}


MATCH IntegerExp::implicitConvTo(Type *t)
{
#if 0
    printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    MATCH m = type->implicitConvTo(t);
    if (m >= MATCHconst)
	return m;

    TY ty = type->toBasetype()->ty;
    TY toty = t->toBasetype()->ty;

    if (m == MATCHnomatch && t->ty == Tenum)
	goto Lno;

    switch (ty)
    {
	case Tbit:
	case Tbool:
	    value &= 1;
	    ty = Tint32;
	    break;

	case Tint8:
	    value = (signed char)value;
	    ty = Tint32;
	    break;

	case Tchar:
	case Tuns8:
	    value &= 0xFF;
	    ty = Tint32;
	    break;

	case Tint16:
	    value = (short)value;
	    ty = Tint32;
	    break;

	case Tuns16:
	case Twchar:
	    value &= 0xFFFF;
	    ty = Tint32;
	    break;

	case Tint32:
	    value = (int)value;
	    break;

	case Tuns32:
	case Tdchar:
	    value &= 0xFFFFFFFF;
	    ty = Tuns32;
	    break;

	default:
	    break;
    }

    // Only allow conversion if no change in value
    switch (toty)
    {
	case Tbit:
	case Tbool:
	    if ((value & 1) != value)
		goto Lno;
	    goto Lyes;

	case Tint8:
	    if ((signed char)value != value)
		goto Lno;
	    goto Lyes;

	case Tchar:
	case Tuns8:
	    //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
	    if ((unsigned char)value != value)
		goto Lno;
	    goto Lyes;

	case Tint16:
	    if ((short)value != value)
		goto Lno;
	    goto Lyes;

	case Tuns16:
	    if ((unsigned short)value != value)
		goto Lno;
	    goto Lyes;

	case Tint32:
	    if (ty == Tuns32)
	    {
	    }
	    else if ((int)value != value)
		goto Lno;
	    goto Lyes;

	case Tuns32:
	    if (ty == Tint32)
	    {
	    }
	    else if ((unsigned)value != value)
		goto Lno;
	    goto Lyes;

	case Tdchar:
	    if (value > 0x10FFFFUL)
		goto Lno;
	    goto Lyes;

	case Twchar:
	    if ((unsigned short)value != value)
		goto Lno;
	    goto Lyes;

	case Tfloat32:
	{
	    volatile float f;
	    if (type->isunsigned())
	    {
		f = (float)value;
		if (f != value)
		    goto Lno;
	    }
	    else
	    {
		f = (float)(long long)value;
		if (f != (long long)value)
		    goto Lno;
	    }
	    goto Lyes;
	}

	case Tfloat64:
	{
	    volatile double f;
	    if (type->isunsigned())
	    {
		f = (double)value;
		if (f != value)
		    goto Lno;
	    }
	    else
	    {
		f = (double)(long long)value;
		if (f != (long long)value)
		    goto Lno;
	    }
	    goto Lyes;
	}

	case Tfloat80:
	{
	    volatile long double f;
	    if (type->isunsigned())
	    {
		f = (long double)value;
		if (f != value)
		    goto Lno;
	    }
	    else
	    {
		f = (long double)(long long)value;
		if (f != (long long)value)
		    goto Lno;
	    }
	    goto Lyes;
	}

	case Tpointer:
//printf("type = %s\n", type->toBasetype()->toChars());
//printf("t = %s\n", t->toBasetype()->toChars());
	    if (ty == Tpointer &&
	        type->toBasetype()->nextOf()->ty == t->toBasetype()->nextOf()->ty)
	    {	/* Allow things like:
		 *	const char* P = cast(char *)3;
		 *	char* q = P;
		 */
		goto Lyes;
	    }
	    break;
    }
    return Expression::implicitConvTo(t);

Lyes:
    //printf("MATCHconvert\n");
    return MATCHconvert;

Lno:
    //printf("MATCHnomatch\n");
    return MATCHnomatch;
}

MATCH NullExp::implicitConvTo(Type *t)
{
#if 0
    printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n",
	toChars(), type->toChars(), t->toChars(), committed);
#endif
    if (this->type->equals(t))
	return MATCHexact;

    /* Allow implicit conversions from invariant to mutable|const,
     * and mutable to invariant. It works because, after all, a null
     * doesn't actually point to anything.
     */
    if (t->invariantOf()->equals(type->invariantOf()))
	return MATCHconst;

    // NULL implicitly converts to any pointer type or dynamic array
    if (type->ty == Tpointer && type->nextOf()->ty == Tvoid)
    {
	if (t->ty == Ttypedef)
	    t = ((TypeTypedef *)t)->sym->basetype;
	if (t->ty == Tpointer || t->ty == Tarray ||
	    t->ty == Taarray  || t->ty == Tclass ||
	    t->ty == Tdelegate)
	    return committed ? MATCHconvert : MATCHexact;
    }
    return Expression::implicitConvTo(t);
}

#if DMDV2
MATCH StructLiteralExp::implicitConvTo(Type *t)
{
#if 0
    printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    MATCH m = Expression::implicitConvTo(t);
    if (m != MATCHnomatch)
	return m;
    if (type->ty == t->ty && type->ty == Tstruct &&
	((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym)
    {
	m = MATCHconst;
	for (int i = 0; i < elements->dim; i++)
	{   Expression *e = (Expression *)elements->data[i];
	    Type *te = e->type;
	    if (t->mod == 0)
		te = te->mutableOf();
	    else
	    {	assert(t->mod == MODinvariant);
		te = te->invariantOf();
	    }
	    MATCH m2 = e->implicitConvTo(te);
	    //printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2);
	    if (m2 < m)
		m = m2;
	}
    }
    return m;
}
#endif

MATCH StringExp::implicitConvTo(Type *t)
{   MATCH m;

#if 0
    printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n",
	toChars(), committed, type->toChars(), t->toChars());
#endif
    if (!committed)
    {
    if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
    {
	return MATCHnomatch;
    }
    if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer)
    {
	TY tyn = type->nextOf()->ty;
	if (tyn == Tchar || tyn == Twchar || tyn == Tdchar)
	{   Type *tn;
	    MATCH m;

	    switch (t->ty)
	    {
		case Tsarray:
		    if (type->ty == Tsarray)
		    {
			if (((TypeSArray *)type)->dim->toInteger() !=
			    ((TypeSArray *)t)->dim->toInteger())
			    return MATCHnomatch;
			TY tynto = t->nextOf()->ty;
			if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
			    return MATCHexact;
		    }
		    else if (type->ty == Tarray)
		    {
			if (length() >
			    ((TypeSArray *)t)->dim->toInteger())
			    return MATCHnomatch;
			TY tynto = t->nextOf()->ty;
			if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
			    return MATCHexact;
		    }
		case Tarray:
		case Tpointer:
		    tn = t->nextOf();
		    m = MATCHexact;
		    if (type->nextOf()->mod != tn->mod)
		    {	if (!tn->isConst())
			    return MATCHnomatch;
			m = MATCHconst;
		    }
		    switch (tn->ty)
		    {
			case Tchar:
			case Twchar:
			case Tdchar:
			    return m;
		    }
		    break;
	    }
	}
    }
    }
    return Expression::implicitConvTo(t);
#if 0
    m = (MATCH)type->implicitConvTo(t);
    if (m)
    {
	return m;
    }

    return MATCHnomatch;
#endif
}

MATCH ArrayLiteralExp::implicitConvTo(Type *t)
{   MATCH result = MATCHexact;

#if 0
    printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    Type *typeb = type->toBasetype();
    Type *tb = t->toBasetype();
    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
	(typeb->ty == Tarray || typeb->ty == Tsarray))
    {
	if (tb->ty == Tsarray)
	{   TypeSArray *tsa = (TypeSArray *)tb;
	    if (elements->dim != tsa->dim->toInteger())
		result = MATCHnomatch;
	}

	for (int i = 0; i < elements->dim; i++)
	{   Expression *e = (Expression *)elements->data[i];
	    MATCH m = (MATCH)e->implicitConvTo(tb->nextOf());
	    if (m < result)
		result = m;			// remember worst match
	    if (result == MATCHnomatch)
		break;				// no need to check for worse
	}
	return result;
    }
    else
	return Expression::implicitConvTo(t);
}

MATCH AssocArrayLiteralExp::implicitConvTo(Type *t)
{   MATCH result = MATCHexact;

    Type *typeb = type->toBasetype();
    Type *tb = t->toBasetype();
    if (tb->ty == Taarray && typeb->ty == Taarray)
    {
	for (size_t i = 0; i < keys->dim; i++)
	{   Expression *e = (Expression *)keys->data[i];
	    MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->index);
	    if (m < result)
		result = m;			// remember worst match
	    if (result == MATCHnomatch)
		break;				// no need to check for worse
	    e = (Expression *)values->data[i];
	    m = (MATCH)e->implicitConvTo(tb->nextOf());
	    if (m < result)
		result = m;			// remember worst match
	    if (result == MATCHnomatch)
		break;				// no need to check for worse
	}
	return result;
    }
    else
	return Expression::implicitConvTo(t);
}

MATCH AddrExp::implicitConvTo(Type *t)
{
#if 0
    printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    MATCH result;

    result = type->implicitConvTo(t);
    //printf("\tresult = %d\n", result);

    if (result == MATCHnomatch)
    {
	// Look for pointers to functions where the functions are overloaded.

	t = t->toBasetype();

	if (e1->op == TOKoverloadset &&
	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
	{   OverExp *eo = (OverExp *)e1;
	    FuncDeclaration *f = NULL;
	    for (int i = 0; i < eo->vars->a.dim; i++)
	    {   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
		FuncDeclaration *f2 = s->isFuncDeclaration();
		assert(f2);
		if (f2->overloadExactMatch(t->nextOf(), m))
		{   if (f)
			/* Error if match in more than one overload set,
			 * even if one is a 'better' match than the other.
			 */
			ScopeDsymbol::multiplyDefined(loc, f, f2);
		    else
			f = f2;
		    result = MATCHexact;
		}
	    }
	}

	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
	    t->ty == Tpointer && t->nextOf()->ty == Tfunction &&
	    e1->op == TOKvar)
	{
	    /* I don't think this can ever happen -
	     * it should have been
	     * converted to a SymOffExp.
	     */
	    assert(0);
	    VarExp *ve = (VarExp *)e1;
	    FuncDeclaration *f = ve->var->isFuncDeclaration();
	    if (f && f->overloadExactMatch(t->nextOf(), m))
		result = MATCHexact;
	}
    }
    //printf("\tresult = %d\n", result);
    return result;
}

MATCH SymOffExp::implicitConvTo(Type *t)
{
#if 0
    printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    MATCH result;

    result = type->implicitConvTo(t);
    //printf("\tresult = %d\n", result);

    if (result == MATCHnomatch)
    {
	// Look for pointers to functions where the functions are overloaded.
	FuncDeclaration *f;

	t = t->toBasetype();
	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
	{
	    f = var->isFuncDeclaration();
	    if (f)
	    {	f = f->overloadExactMatch(t->nextOf(), m);
		if (f)
		{   if ((t->ty == Tdelegate && (f->needThis() || f->isNested())) ||
			(t->ty == Tpointer && !(f->needThis() || f->isNested())))
		    {
			result = MATCHexact;
		    }
		}
	    }
	}
    }
    //printf("\tresult = %d\n", result);
    return result;
}

MATCH DelegateExp::implicitConvTo(Type *t)
{
#if 0
    printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    MATCH result;

    result = type->implicitConvTo(t);

    if (result == MATCHnomatch)
    {
	// Look for pointers to functions where the functions are overloaded.
	FuncDeclaration *f;

	t = t->toBasetype();
	if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction &&
	    t->ty == Tdelegate && t->nextOf()->ty == Tfunction)
	{
	    if (func && func->overloadExactMatch(t->nextOf(), m))
		result = MATCHexact;
	}
    }
    return result;
}

MATCH OrExp::implicitConvTo(Type *t)
{
    MATCH result = Expression::implicitConvTo(t);

    if (result == MATCHnomatch)
    {
	MATCH m1 = e1->implicitConvTo(t);
	MATCH m2 = e2->implicitConvTo(t);

	// Pick the worst match
	result = (m1 < m2) ? m1 : m2;
    }
    return result;
}

MATCH XorExp::implicitConvTo(Type *t)
{
    MATCH result = Expression::implicitConvTo(t);

    if (result == MATCHnomatch)
    {
	MATCH m1 = e1->implicitConvTo(t);
	MATCH m2 = e2->implicitConvTo(t);

	// Pick the worst match
	result = (m1 < m2) ? m1 : m2;
    }
    return result;
}

MATCH CondExp::implicitConvTo(Type *t)
{
    MATCH m1 = e1->implicitConvTo(t);
    MATCH m2 = e2->implicitConvTo(t);
    //printf("CondExp: m1 %d m2 %d\n", m1, m2);

    // Pick the worst match
    return (m1 < m2) ? m1 : m2;
}

MATCH CommaExp::implicitConvTo(Type *t)
{
    return e2->implicitConvTo(t);
}

MATCH CastExp::implicitConvTo(Type *t)
{
#if 0
    printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    MATCH result;

    result = type->implicitConvTo(t);

    if (result == MATCHnomatch)
    {
	if (t->isintegral() &&
	    e1->type->isintegral() &&
	    e1->implicitConvTo(t) != MATCHnomatch)
	    result = MATCHconvert;
	else
	    result = Expression::implicitConvTo(t);
    }
    return result;
}

/* ==================== castTo ====================== */

/**************************************
 * Do an explicit cast.
 */

Expression *Expression::castTo(Scope *sc, Type *t)
{
    //printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars());
#if 0
    printf("Expression::castTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    if (type == t)
	return this;
    Expression *e = this;
    Type *tb = t->toBasetype();
    Type *typeb = type->toBasetype();
    if (tb != typeb)
    {
	// Do (type *) cast of (type [dim])
	if (tb->ty == Tpointer &&
	    typeb->ty == Tsarray
	   )
	{
	    //printf("Converting [dim] to *\n");

	    if (typeb->size(loc) == 0)
		e = new NullExp(loc);
	    else
		e = new AddrExp(loc, e);
	}
#if 0
	else if (tb->ty == Tdelegate && type->ty != Tdelegate)
	{
	    TypeDelegate *td = (TypeDelegate *)tb;
	    TypeFunction *tf = (TypeFunction *)td->nextOf();
	    return toDelegate(sc, tf->nextOf());
	}
#endif
	else
	{
	    if (typeb->ty == Tstruct)
	    {   TypeStruct *ts = (TypeStruct *)typeb;
		if (!(tb->ty == Tstruct && ts->sym == ((TypeStruct *)tb)->sym) &&
		    ts->sym->aliasthis)
		{   /* Forward the cast to our alias this member, rewrite to:
		     *   cast(to)e1.aliasthis
		     */
		    Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident);
		    Expression *e = new CastExp(loc, e1, tb);
		    e = e->semantic(sc);
		    return e;
		}
	    }
	    else if (typeb->ty == Tclass)
	    {   TypeClass *ts = (TypeClass *)typeb;
		if (tb->ty != Tclass &&
		    ts->sym->aliasthis)
		{   /* Forward the cast to our alias this member, rewrite to:
		     *   cast(to)e1.aliasthis
		     */
		    Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident);
		    Expression *e = new CastExp(loc, e1, tb);
		    e = e->semantic(sc);
		    return e;
		}
	    }
	    e = new CastExp(loc, e, tb);
	}
    }
    else
    {
	e = e->copy();	// because of COW for assignment to e->type
    }
    assert(e != this);
    e->type = t;
    //printf("Returning: %s\n", e->toChars());
    return e;
}


Expression *RealExp::castTo(Scope *sc, Type *t)
{   Expression *e = this;
    if (type != t)
    {
	if ((type->isreal() && t->isreal()) ||
	    (type->isimaginary() && t->isimaginary())
	   )
	{   e = copy();
	    e->type = t;
	}
	else
	    e = Expression::castTo(sc, t);
    }
    return e;
}


Expression *ComplexExp::castTo(Scope *sc, Type *t)
{   Expression *e = this;
    if (type != t)
    {
	if (type->iscomplex() && t->iscomplex())
	{   e = copy();
	    e->type = t;
	}
	else
	    e = Expression::castTo(sc, t);
    }
    return e;
}


Expression *NullExp::castTo(Scope *sc, Type *t)
{   NullExp *e;
    Type *tb;

    //printf("NullExp::castTo(t = %p)\n", t);
    if (type == t)
    {
	committed = 1;
	return this;
    }
    e = (NullExp *)copy();
    e->committed = 1;
    tb = t->toBasetype();
    e->type = type->toBasetype();
    if (tb != e->type)
    {
	// NULL implicitly converts to any pointer type or dynamic array
	if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
	    (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray ||
	     tb->ty == Tdelegate))
	{
#if 0
	    if (tb->ty == Tdelegate)
	    {   TypeDelegate *td = (TypeDelegate *)tb;
		TypeFunction *tf = (TypeFunction *)td->nextOf();

		if (!tf->varargs &&
		    !(tf->arguments && tf->arguments->dim)
		   )
		{
		    return Expression::castTo(sc, t);
		}
	    }
#endif
	}
	else
	{
	    return e->Expression::castTo(sc, t);
	}
    }
    e->type = t;
    return e;
}

Expression *StringExp::castTo(Scope *sc, Type *t)
{
    /* This follows copy-on-write; any changes to 'this'
     * will result in a copy.
     * The this->string member is considered immutable.
     */
    StringExp *se;
    Type *tb;
    int copied = 0;

    //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed);

    if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
    {
	error("cannot convert string literal to void*");
    }

    se = this;
    if (!committed)
    {   se = (StringExp *)copy();
	se->committed = 1;
	copied = 1;
    }

    if (type == t)
    {
	return se;
    }

    tb = t->toBasetype();
    //printf("\ttype = %s\n", type->toChars());
    if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate)
	return Expression::castTo(sc, t);

    Type *typeb = type->toBasetype();
    if (typeb == tb)
    {
	if (!copied)
	{   se = (StringExp *)copy();
	    copied = 1;
	}
	se->type = t;
	return se;
    }

    if (committed && tb->ty == Tsarray && typeb->ty == Tarray)
    {
	se = (StringExp *)copy();
	se->sz = tb->nextOf()->size();
	se->len = (len * sz) / se->sz;
	se->committed = 1;
	se->type = t;
	return se;
    }

    if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
    {	if (!copied)
	{   se = (StringExp *)copy();
	    copied = 1;
	}
	goto Lcast;
    }
    if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer)
    {	if (!copied)
	{   se = (StringExp *)copy();
	    copied = 1;
	}
	goto Lcast;
    }

    if (typeb->nextOf()->size() == tb->nextOf()->size())
    {
	if (!copied)
	{   se = (StringExp *)copy();
	    copied = 1;
	}
	if (tb->ty == Tsarray)
	    goto L2;	// handle possible change in static array dimension
	se->type = t;
	return se;
    }

    if (committed)
	goto Lcast;

#define X(tf,tt)	((tf) * 256 + (tt))
    {
    OutBuffer buffer;
    size_t newlen = 0;
    int tfty = typeb->nextOf()->toBasetype()->ty;
    int ttty = tb->nextOf()->toBasetype()->ty;
    switch (X(tfty, ttty))
    {
	case X(Tchar, Tchar):
	case X(Twchar,Twchar):
	case X(Tdchar,Tdchar):
	    break;

	case X(Tchar, Twchar):
	    for (size_t u = 0; u < len;)
	    {	unsigned c;
		const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
		if (p)
		    error("%s", p);
		else
		    buffer.writeUTF16(c);
	    }
	    newlen = buffer.offset / 2;
	    buffer.writeUTF16(0);
	    goto L1;

	case X(Tchar, Tdchar):
	    for (size_t u = 0; u < len;)
	    {	unsigned c;
		const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
		if (p)
		    error("%s", p);
		buffer.write4(c);
		newlen++;
	    }
	    buffer.write4(0);
	    goto L1;

	case X(Twchar,Tchar):
	    for (size_t u = 0; u < len;)
	    {	unsigned c;
		const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
		if (p)
		    error("%s", p);
		else
		    buffer.writeUTF8(c);
	    }
	    newlen = buffer.offset;
	    buffer.writeUTF8(0);
	    goto L1;

	case X(Twchar,Tdchar):
	    for (size_t u = 0; u < len;)
	    {	unsigned c;
		const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
		if (p)
		    error("%s", p);
		buffer.write4(c);
		newlen++;
	    }
	    buffer.write4(0);
	    goto L1;

	case X(Tdchar,Tchar):
	    for (size_t u = 0; u < len; u++)
	    {
		unsigned c = ((unsigned *)se->string)[u];
		if (!utf_isValidDchar(c))
		    error("invalid UCS-32 char \\U%08x", c);
		else
		    buffer.writeUTF8(c);
		newlen++;
	    }
	    newlen = buffer.offset;
	    buffer.writeUTF8(0);
	    goto L1;

	case X(Tdchar,Twchar):
	    for (size_t u = 0; u < len; u++)
	    {
		unsigned c = ((unsigned *)se->string)[u];
		if (!utf_isValidDchar(c))
		    error("invalid UCS-32 char \\U%08x", c);
		else
		    buffer.writeUTF16(c);
		newlen++;
	    }
	    newlen = buffer.offset / 2;
	    buffer.writeUTF16(0);
	    goto L1;

	L1:
	    if (!copied)
	    {   se = (StringExp *)copy();
		copied = 1;
	    }
	    se->string = buffer.extractData();
	    se->len = newlen;
	    se->sz = tb->nextOf()->size();
	    break;

	default:
	    assert(typeb->nextOf()->size() != tb->nextOf()->size());
	    goto Lcast;
    }
    }
#undef X
L2:
    assert(copied);

    // See if need to truncate or extend the literal
    if (tb->ty == Tsarray)
    {
	int dim2 = ((TypeSArray *)tb)->dim->toInteger();

	//printf("dim from = %d, to = %d\n", se->len, dim2);

	// Changing dimensions
	if (dim2 != se->len)
	{
	    // Copy when changing the string literal
	    unsigned newsz = se->sz;
	    void *s;
	    int d;

	    d = (dim2 < se->len) ? dim2 : se->len;
	    s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
	    memcpy(s, se->string, d * newsz);
	    // Extend with 0, add terminating 0
	    memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
	    se->string = s;
	    se->len = dim2;
	}
    }
    se->type = t;
    return se;

Lcast:
    Expression *e = new CastExp(loc, se, t);
    e->type = t;	// so semantic() won't be run on e
    return e;
}

Expression *AddrExp::castTo(Scope *sc, Type *t)
{
    Type *tb;

#if 0
    printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    Expression *e = this;

    tb = t->toBasetype();
    type = type->toBasetype();
    if (tb != type)
    {
	// Look for pointers to functions where the functions are overloaded.

	if (e1->op == TOKoverloadset &&
	    (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction)
	{   OverExp *eo = (OverExp *)e1;
	    FuncDeclaration *f = NULL;
	    for (int i = 0; i < eo->vars->a.dim; i++)
	    {   Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
		FuncDeclaration *f2 = s->isFuncDeclaration();
		assert(f2);
		if (f2->overloadExactMatch(t->nextOf(), m))
		{   if (f)
			/* Error if match in more than one overload set,
			 * even if one is a 'better' match than the other.
			 */
			ScopeDsymbol::multiplyDefined(loc, f, f2);
		    else
			f = f2;
		}
	    }
	    if (f)
	    {	f->tookAddressOf++;
		SymOffExp *se = new SymOffExp(loc, f, 0, 0);
		se->semantic(sc);
		// Let SymOffExp::castTo() do the heavy lifting
		return se->castTo(sc, t);
	    }
	}


	if (type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
	    tb->ty == Tpointer && tb->nextOf()->ty == Tfunction &&
	    e1->op == TOKvar)
	{
	    VarExp *ve = (VarExp *)e1;
	    FuncDeclaration *f = ve->var->isFuncDeclaration();
	    if (f)
	    {
		assert(0);	// should be SymOffExp instead
		f = f->overloadExactMatch(tb->nextOf(), m);
		if (f)
		{
		    e = new VarExp(loc, f);
		    e->type = f->type;
		    e = new AddrExp(loc, e);
		    e->type = t;
		    return e;
		}
	    }
	}
	e = Expression::castTo(sc, t);
    }
    e->type = t;
    return e;
}


Expression *TupleExp::castTo(Scope *sc, Type *t)
{   TupleExp *e = (TupleExp *)copy();
    e->exps = (Expressions *)exps->copy();
    for (size_t i = 0; i < e->exps->dim; i++)
    {   Expression *ex = (Expression *)e->exps->data[i];
	ex = ex->castTo(sc, t);
	e->exps->data[i] = (void *)ex;
    }
    return e;
}


Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
{
#if 0
    printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    if (type == t)
	return this;
    ArrayLiteralExp *e = this;
    Type *typeb = type->toBasetype();
    Type *tb = t->toBasetype();
    if ((tb->ty == Tarray || tb->ty == Tsarray) &&
	(typeb->ty == Tarray || typeb->ty == Tsarray) &&
	// Not trying to convert non-void[] to void[]
	!(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid))
    {
	if (tb->ty == Tsarray)
	{   TypeSArray *tsa = (TypeSArray *)tb;
	    if (elements->dim != tsa->dim->toInteger())
		goto L1;
	}

	e = (ArrayLiteralExp *)copy();
	e->elements = (Expressions *)elements->copy();
	for (int i = 0; i < elements->dim; i++)
	{   Expression *ex = (Expression *)elements->data[i];
	    ex = ex->castTo(sc, tb->nextOf());
	    e->elements->data[i] = (void *)ex;
	}
	e->type = t;
	return e;
    }
    if (tb->ty == Tpointer && typeb->ty == Tsarray)
    {
	Type *tp = typeb->nextOf()->pointerTo();
	if (!tp->equals(e->type))
	{   e = (ArrayLiteralExp *)copy();
	    e->type = tp;
	}
    }
L1:
    return e->Expression::castTo(sc, t);
}

Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
{
    if (type == t)
	return this;
    AssocArrayLiteralExp *e = this;
    Type *typeb = type->toBasetype();
    Type *tb = t->toBasetype();
    if (tb->ty == Taarray && typeb->ty == Taarray &&
	tb->nextOf()->toBasetype()->ty != Tvoid)
    {
	e = (AssocArrayLiteralExp *)copy();
	e->keys = (Expressions *)keys->copy();
	e->values = (Expressions *)values->copy();
	assert(keys->dim == values->dim);
	for (size_t i = 0; i < keys->dim; i++)
	{   Expression *ex = (Expression *)values->data[i];
	    ex = ex->castTo(sc, tb->nextOf());
	    e->values->data[i] = (void *)ex;

	    ex = (Expression *)keys->data[i];
	    ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
	    e->keys->data[i] = (void *)ex;
	}
	e->type = t;
	return e;
    }
L1:
    return e->Expression::castTo(sc, t);
}

Expression *SymOffExp::castTo(Scope *sc, Type *t)
{
#if 0
    printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    if (type == t && hasOverloads == 0)
	return this;
    Expression *e;
    Type *tb = t->toBasetype();
    Type *typeb = type->toBasetype();
    if (tb != typeb)
    {
	// Look for pointers to functions where the functions are overloaded.
	FuncDeclaration *f;

	if (hasOverloads &&
	    typeb->ty == Tpointer && typeb->nextOf()->ty == Tfunction &&
	    (tb->ty == Tpointer || tb->ty == Tdelegate) && tb->nextOf()->ty == Tfunction)
	{
	    f = var->isFuncDeclaration();
	    if (f)
	    {
		f = f->overloadExactMatch(tb->nextOf(), m);
		if (f)
		{
		    if (tb->ty == Tdelegate)
		    {
			if (f->needThis() && hasThis(sc))
			{
			    e = new DelegateExp(loc, new ThisExp(loc), f);
			    e = e->semantic(sc);
			}
			else if (f->isNested())
			{
			    e = new DelegateExp(loc, new IntegerExp(0), f);
			    e = e->semantic(sc);
			}
			else if (f->needThis())
			{   error("no 'this' to create delegate for %s", f->toChars());
			    e = new ErrorExp();
			}
			else
			{   error("cannot cast from function pointer to delegate");
			    e = new ErrorExp();
			}
		    }
		    else
		    {
			e = new SymOffExp(loc, f, 0);
			e->type = t;
		    }
#if DMDV2
		    f->tookAddressOf++;
#endif
		    return e;
		}
	    }
	}
	e = Expression::castTo(sc, t);
    }
    else
    {	e = copy();
	e->type = t;
	((SymOffExp *)e)->hasOverloads = 0;
    }
    return e;
}

Expression *DelegateExp::castTo(Scope *sc, Type *t)
{
#if 0
    printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
	toChars(), type->toChars(), t->toChars());
#endif
    static char msg[] = "cannot form delegate due to covariant return type";

    Expression *e = this;
    Type *tb = t->toBasetype();
    Type *typeb = type->toBasetype();
    if (tb != typeb)
    {
	// Look for delegates to functions where the functions are overloaded.
	FuncDeclaration *f;

	if (typeb->ty == Tdelegate && typeb->nextOf()->ty == Tfunction &&
	    tb->ty == Tdelegate && tb->nextOf()->ty == Tfunction)
	{
	    if (func)
	    {
		f = func->overloadExactMatch(tb->nextOf(), m);
		if (f)
		{   int offset;
		    if (f->tintro && f->tintro->nextOf()->isBaseOf(f->type->nextOf(), &offset) && offset)
			error("%s", msg);
		    f->tookAddressOf++;
		    e = new DelegateExp(loc, e1, f);
		    e->type = t;
		    return e;
		}
		if (func->tintro)
		    error("%s", msg);
	    }
	}
	e = Expression::castTo(sc, t);
    }
    else
    {	int offset;

	func->tookAddressOf++;
	if (func->tintro && func->tintro->nextOf()->isBaseOf(func->type->nextOf(), &offset) && offset)
	    error("%s", msg);
	e = copy();
	e->type = t;
    }
    return e;
}

Expression *CondExp::castTo(Scope *sc, Type *t)
{
    Expression *e = this;

    if (type != t)
    {
	if (1 || e1->op == TOKstring || e2->op == TOKstring)
	{   e = new CondExp(loc, econd, e1->castTo(sc, t), e2->castTo(sc, t));
	    e->type = t;
	}
	else
	    e = Expression::castTo(sc, t);
    }
    return e;
}

Expression *CommaExp::castTo(Scope *sc, Type *t)
{
    Expression *e2c = e2->castTo(sc, t);
    Expression *e;

    if (e2c != e2)
    {
	e = new CommaExp(loc, e1, e2c);
	e->type = e2c->type;
    }
    else
    {	e = this;
	e->type = e2->type;
    }
    return e;
}

/* ==================== ====================== */

/****************************************
 * Scale addition/subtraction to/from pointer.
 */

Expression *BinExp::scaleFactor(Scope *sc)
{   d_uns64 stride;
    Type *t1b = e1->type->toBasetype();
    Type *t2b = e2->type->toBasetype();

    if (t1b->ty == Tpointer && t2b->isintegral())
    {   // Need to adjust operator by the stride
	// Replace (ptr + int) with (ptr + (int * stride))
	Type *t = Type::tptrdiff_t;

	stride = t1b->nextOf()->size(loc);
	if (!t->equals(t2b))
	    e2 = e2->castTo(sc, t);
	e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
	e2->type = t;
	type = e1->type;
    }
    else if (t2b->ty == Tpointer && t1b->isintegral())
    {   // Need to adjust operator by the stride
	// Replace (int + ptr) with (ptr + (int * stride))
	Type *t = Type::tptrdiff_t;
	Expression *e;

	stride = t2b->nextOf()->size(loc);
	if (!t->equals(t1b))
	    e = e1->castTo(sc, t);
	else
	    e = e1;
	e = new MulExp(loc, e, new IntegerExp(0, stride, t));
	e->type = t;
	type = e2->type;
	e1 = e2;
	e2 = e;
    }
    return this;
}

/**************************************
 * Combine types.
 * Output:
 *	*pt	merged type, if *pt is not NULL
 *	*pe1	rewritten e1
 *	*pe2	rewritten e2
 * Returns:
 *	!=0	success
 *	0	failed
 */

int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression **pe2)
{
    //printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars());
    //dump(0);

    Expression *e1 = (*pe1)->integralPromotions(sc);
    Expression *e2 = (*pe2)->integralPromotions(sc);

    Type *t1 = e1->type;
    Type *t2 = e2->type;
    assert(t1);
    Type *t = t1;

    //if (t1) printf("\tt1 = %s\n", t1->toChars());
    //if (t2) printf("\tt2 = %s\n", t2->toChars());
#ifdef DEBUG
    if (!t2) printf("\te2 = '%s'\n", e2->toChars());
#endif
    assert(t2);

    Type *t1b = t1->toBasetype();
    Type *t2b = t2->toBasetype();

    TY ty = (TY)Type::impcnvResult[t1b->ty][t2b->ty];
    if (ty != Terror)
    {	TY ty1;
	TY ty2;

	ty1 = (TY)Type::impcnvType1[t1b->ty][t2b->ty];
	ty2 = (TY)Type::impcnvType2[t1b->ty][t2b->ty];

	if (t1b->ty == ty1)	// if no promotions
	{
	    if (t1 == t2)
	    {
		t = t1;
		goto Lret;
	    }

	    if (t1b == t2b)
	    {
		t = t1b;
		goto Lret;
	    }
	}

	t = Type::basic[ty];

	t1 = Type::basic[ty1];
	t2 = Type::basic[ty2];
	e1 = e1->castTo(sc, t1);
	e2 = e2->castTo(sc, t2);
	//printf("after typeCombine():\n");
	//dump(0);
	//printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2);
	goto Lret;
    }

    t1 = t1b;
    t2 = t2b;

Lagain:
    if (t1 == t2)
    {
    }
    else if (t1->ty == Tpointer && t2->ty == Tpointer)
    {
	// Bring pointers to compatible type
	Type *t1n = t1->nextOf();
	Type *t2n = t2->nextOf();

	if (t1n == t2n)
	    ;
	else if (t1n->ty == Tvoid)	// pointers to void are always compatible
	    t = t2;
	else if (t2n->ty == Tvoid)
	    ;
	else if (t1n->mod != t2n->mod)
	{
	    t1 = t1n->mutableOf()->constOf()->pointerTo();
	    t2 = t2n->mutableOf()->constOf()->pointerTo();
	    t = t1;
	    goto Lagain;
	}
	else if (t1n->ty == Tclass && t2n->ty == Tclass)
	{   ClassDeclaration *cd1 = t1n->isClassHandle();
	    ClassDeclaration *cd2 = t2n->isClassHandle();
	    int offset;

	    if (cd1->isBaseOf(cd2, &offset))
	    {
		if (offset)
		    e2 = e2->castTo(sc, t);
	    }
	    else if (cd2->isBaseOf(cd1, &offset))
	    {
		t = t2;
		if (offset)
		    e1 = e1->castTo(sc, t);
	    }
	    else
		goto Lincompatible;
	}
	else
	    goto Lincompatible;
    }
    else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
	     e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid)
    {	/*  (T[n] op void*)
	 *  (T[] op void*)
	 */
	goto Lx1;
    }
    else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
	     e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid)
    {	/*  (void* op T[n])
	 *  (void* op T[])
	 */
	goto Lx2;
    }
    else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2))
    {
	goto Lt2;
    }
    else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1))
    {
	goto Lt1;
    }
    /* If one is mutable and the other invariant, then retry
     * with both of them as const
     */
    else if ((t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Tpointer) &&
	     (t2->ty == Tsarray || t2->ty == Tarray || t2->ty == Tpointer) &&
	     t1->nextOf()->mod != t2->nextOf()->mod
	    )
    {
	if (t1->ty == Tpointer)
	    t1 = t1->nextOf()->mutableOf()->constOf()->pointerTo();
	else
	    t1 = t1->nextOf()->mutableOf()->constOf()->arrayOf();

	if (t2->ty == Tpointer)
	    t2 = t2->nextOf()->mutableOf()->constOf()->pointerTo();
	else
	    t2 = t2->nextOf()->mutableOf()->constOf()->arrayOf();
	t = t1;
	goto Lagain;
    }
    else if (t1->ty == Tclass || t2->ty == Tclass)
    {
	while (1)
	{
	    int i1 = e2->implicitConvTo(t1);
	    int i2 = e1->implicitConvTo(t2);

	    if (i1 && i2)
	    {
		// We have the case of class vs. void*, so pick class
		if (t1->ty == Tpointer)
		    i1 = 0;
		else if (t2->ty == Tpointer)
		    i2 = 0;
	    }

	    if (i2)
	    {
		goto Lt2;
	    }
	    else if (i1)
	    {
		goto Lt1;
	    }
	    else if (t1->ty == Tclass && t2->ty == Tclass)
	    {	TypeClass *tc1 = (TypeClass *)t1;
		TypeClass *tc2 = (TypeClass *)t2;

		/* Pick 'tightest' type
		 */
		ClassDeclaration *cd1 = tc1->sym->baseClass;
		ClassDeclaration *cd2 = tc2->sym->baseClass;

		if (cd1 && cd2)
		{   t1 = cd1->type;
		    t2 = cd2->type;
		}
		else if (cd1)
		    t1 = cd1->type;
		else if (cd2)
		    t2 = cd2->type;
		else
		    goto Lincompatible;
	    }
	    else
		goto Lincompatible;
	}
    }
    else if (t1->ty == Tstruct && t2->ty == Tstruct)
    {
	if (((TypeStruct *)t1)->sym != ((TypeStruct *)t2)->sym)
	    goto Lincompatible;
    }
    else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2))
    {
	goto Lt2;
    }
    else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1))
    {
	goto Lt1;
    }
    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
	     e2->implicitConvTo(t1->nextOf()->arrayOf()))
    {
     Lx1:
	t = t1->nextOf()->arrayOf();
	e1 = e1->castTo(sc, t);
	e2 = e2->castTo(sc, t);
    }
    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
	     e1->implicitConvTo(t2->nextOf()->arrayOf()))
    {
     Lx2:
	t = t2->nextOf()->arrayOf();
	e1 = e1->castTo(sc, t);
	e2 = e2->castTo(sc, t);
    }
    else if (t1->isintegral() && t2->isintegral())
    {
	assert(0);
    }
    else if (e1->op == TOKslice && t1->ty == Tarray &&
	     e2->implicitConvTo(t1->nextOf()))
    {	// T[] op T
	e2 = e2->castTo(sc, t1->nextOf());
	t = t1->nextOf()->arrayOf();
    }
    else if (e2->op == TOKslice && t2->ty == Tarray &&
	     e1->implicitConvTo(t2->nextOf()))
    {	// T op T[]
	e1 = e1->castTo(sc, t2->nextOf());
	t = t2->nextOf()->arrayOf();

	//printf("test %s\n", e->toChars());
	e1 = e1->optimize(WANTvalue);
	if (e && e->isCommutative() && e1->isConst())
	{   /* Swap operands to minimize number of functions generated
	     */
	    //printf("swap %s\n", e->toChars());
	    Expression *tmp = e1;
	    e1 = e2;
	    e2 = tmp;
	}
    }
    else
    {
     Lincompatible:
	return 0;
    }
Lret:
    if (!*pt)
	*pt = t;
    *pe1 = e1;
    *pe2 = e2;
#if 0
    printf("-typeMerge() %s op %s\n", e1->toChars(), e2->toChars());
    if (e1->type) printf("\tt1 = %s\n", e1->type->toChars());
    if (e2->type) printf("\tt2 = %s\n", e2->type->toChars());
    printf("\ttype = %s\n", t->toChars());
#endif
    //dump(0);
    return 1;


Lt1:
    e2 = e2->castTo(sc, t1);
    t = t1;
    goto Lret;

Lt2:
    e1 = e1->castTo(sc, t2);
    t = t2;
    goto Lret;
}

/************************************
 * Bring leaves to common type.
 */

Expression *BinExp::typeCombine(Scope *sc)
{
    Type *t1 = e1->type->toBasetype();
    Type *t2 = e2->type->toBasetype();

    if (op == TOKmin || op == TOKadd)
    {
	if (t1->ty == Tstruct)
	{
	    if (t2->ty == Tstruct &&
		((TypeStruct *)t1)->sym == ((TypeStruct *)t2)->sym)
		goto Lerror;
	}
	else if (t1->ty == Tclass)
	{
	    if (t2->ty == Tclass)
		goto Lerror;
	}
    }

    if (!typeMerge(sc, this, &type, &e1, &e2))
	goto Lerror;
    return this;

Lerror:
    incompatibleTypes();
    type = Type::terror;
    e1 = new ErrorExp();
    e2 = new ErrorExp();
    return this;
}

/***********************************
 * Do integral promotions (convertchk).
 * Don't convert <array of> to <pointer to>
 */

Expression *Expression::integralPromotions(Scope *sc)
{
    Expression *e = this;

    //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
    switch (type->toBasetype()->ty)
    {
	case Tvoid:
	    error("void has no value");
	    break;

	case Tint8:
	case Tuns8:
	case Tint16:
	case Tuns16:
	case Tbit:
	case Tbool:
	case Tchar:
	case Twchar:
	    e = e->castTo(sc, Type::tint32);
	    break;

	case Tdchar:
	    e = e->castTo(sc, Type::tuns32);
	    break;
    }
    return e;
}

/***********************************
 * See if both types are arrays that can be compared
 * for equality. Return !=0 if so.
 * If they are arrays, but incompatible, issue error.
 * This is to enable comparing things like an immutable
 * array with a mutable one.
 */

int arrayTypeCompatible(Loc loc, Type *t1, Type *t2)
{
    t1 = t1->toBasetype();
    t2 = t2->toBasetype();

    if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
	(t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
    {
	if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
	    t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
	    (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
	{
	    error(loc, "array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
	}
	return 1;
    }
    return 0;
}

/******************************************************************/

/* Determine the integral ranges of an expression.
 * This is used to determine if implicit narrowing conversions will
 * be allowed.
 */

uinteger_t getMask(uinteger_t v)
{
    uinteger_t u = 0;
    if (v >= 0x80)
	u = 0xFF;
    while (u < v)
	u = (u << 1) | 1;
    return u;
}

IntRange Expression::getIntRange()
{
    IntRange ir;
    ir.imin = 0;
    ir.imax = type->sizemask();
    return ir;
}

IntRange IntegerExp::getIntRange()
{
    IntRange ir;
    ir.imin = value & type->sizemask();
    ir.imax = ir.imin;
    return ir;
}

IntRange CastExp::getIntRange()
{
    IntRange ir;
    ir = e1->getIntRange();
    // Do sign extension
    switch (e1->type->toBasetype()->ty)
    {
	case Tint8:
	    if (ir.imax & 0x80)
		ir.imax |= 0xFFFFFFFFFFFFFF00ULL;
	    break;
	case Tint16:
	    if (ir.imax & 0x8000)
		ir.imax |= 0xFFFFFFFFFFFF0000ULL;
	    break;
	case Tint32:
	    if (ir.imax & 0x80000000)
		ir.imax |= 0xFFFFFFFF00000000ULL;
	    break;
    }
    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();
//printf("CastExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
    return ir;
}

IntRange DivExp::getIntRange()
{
    if (!e1->type->isunsigned() && !e2->type->isunsigned())
	return Expression::getIntRange();

    IntRange ir;
    IntRange ir1 = e1->getIntRange();
    IntRange ir2 = e2->getIntRange();

    if (ir2.imax == 0 || ir2.imin == 0)
	return Expression::getIntRange();

    ir.imin = ir1.imin / ir2.imax;
    ir.imax = ir1.imax / ir2.imin;

    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();

//printf("DivExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);

    return ir;
}

IntRange AndExp::getIntRange()
{
    IntRange ir;
    IntRange ir1 = e1->getIntRange();
    IntRange ir2 = e2->getIntRange();

    ir.imin = ir1.imin;
    if (ir2.imin < ir.imin)
	ir.imin = ir2.imin;

    ir.imax = ir1.imax;
    if (ir2.imax > ir.imax)
	ir.imax = ir2.imax;

    uinteger_t u;

    u = getMask(ir1.imax);
    ir.imin &= u;
    ir.imax &= u;

    u = getMask(ir2.imax);
    ir.imin &= u;
    ir.imax &= u;

    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();

//printf("AndExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);

    return ir;
}

IntRange OrExp::getIntRange()
{
    IntRange ir;
    IntRange ir1 = e1->getIntRange();
    IntRange ir2 = e2->getIntRange();

    ir.imin = ir1.imin;
    if (ir2.imin < ir.imin)
	ir.imin = ir2.imin;

    ir.imax = ir1.imax;
    if (ir2.imax > ir.imax)
	ir.imax = ir2.imax;

    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();

//printf("OrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);

    return ir;
}

IntRange XorExp::getIntRange()
{
    IntRange ir;
    IntRange ir1 = e1->getIntRange();
    IntRange ir2 = e2->getIntRange();

    ir.imin = ir1.imin;
    if (ir2.imin < ir.imin)
	ir.imin = ir2.imin;

    ir.imax = ir1.imax;
    if (ir2.imax > ir.imax)
	ir.imax = ir2.imax;

    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();

//printf("XorExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);

    return ir;
}

IntRange ShlExp::getIntRange()
{
    IntRange ir;
    IntRange ir1 = e1->getIntRange();
    IntRange ir2 = e2->getIntRange();

    ir.imin = getMask(ir1.imin) << ir2.imin;
    ir.imax = getMask(ir1.imax) << ir2.imax;

    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();

//printf("ShlExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);

    return ir;
}

IntRange ShrExp::getIntRange()
{
    if (!e1->type->isunsigned())
	return Expression::getIntRange();

    IntRange ir;
    IntRange ir1 = e1->getIntRange();
    IntRange ir2 = e2->getIntRange();

    ir.imin = ir1.imin >> ir2.imax;
    ir.imax = ir1.imax >> ir2.imin;

    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();

//printf("ShrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);

    return ir;
}

IntRange UshrExp::getIntRange()
{
    IntRange ir;
    IntRange ir1 = e1->getIntRange();
    IntRange ir2 = e2->getIntRange();

    ir.imin = ir1.imin >> ir2.imax;
    ir.imax = ir1.imax >> ir2.imin;

    ir.imin &= type->sizemask();
    ir.imax &= type->sizemask();

//printf("UshrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);

    return ir;
}

IntRange CommaExp::getIntRange()
{
    return e2->getIntRange();
}


