diff dmd/cast.c @ 159:5acec6b2eef8 trunk

[svn r175] merged dmd 1.029
author ChristianK
date Thu, 01 May 2008 15:15:28 +0200
parents 5825d48b27d1
children a58d8f4b84df
line wrap: on
line diff
--- a/dmd/cast.c	Thu May 01 13:33:02 2008 +0200
+++ b/dmd/cast.c	Thu May 01 15:15:28 2008 +0200
@@ -1,1454 +1,1455 @@
-
-// Copyright (c) 1999-2006 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>
-
-#if _WIN32 || IN_GCC || IN_LLVM
-#include "mem.h"
-#else
-#include "../root/mem.h"
-#endif
-
-#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("implicitCastTo(%s) => %s\n", type->toChars(), t->toChars());
-    if (implicitConvTo(t))
-    {
-	if (global.params.warnings &&
-	    Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] &&
-	    op != TOKint64)
-	{
-	    Expression *e = optimize(WANTflags | WANTvalue);
-
-	    if (e->op == TOKint64)
-		return e->implicitCastTo(sc, t);
-
-	    fprintf(stdmsg, "warning - ");
-	    error("implicit conversion of expression (%s) of type %s to %s can cause loss of data",
-		toChars(), type->toChars(), t->toChars());
-	}
-	return castTo(sc, t);
-    }
-
-    Expression *e = optimize(WANTflags | WANTvalue);
-    if (e != this)
-	return e->implicitCastTo(sc, t);
-
-#if 0
-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->next->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);
-}
-
-/*******************************************
- * 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
-    if (!type)
-    {	error("%s is not an expression", toChars());
-	type = Type::terror;
-    }
-    if (t->ty == Tbit && isBit())
-	return MATCHconvert;
-    Expression *e = optimize(WANTvalue | WANTflags);
-    if (e != this)
-    {	//printf("optimzed to %s\n", e->toChars());
-	return e->implicitConvTo(t);
-    }
-    MATCH match = type->implicitConvTo(t);
-    if (match)
-	return match;
-#if 0
-    Type *tb = t->toBasetype();
-    if (tb->ty == Tdelegate)
-    {	TypeDelegate *td = (TypeDelegate *)tb;
-	TypeFunction *tf = (TypeFunction *)td->next;
-
-	if (!tf->varargs &&
-	    !(tf->arguments && tf->arguments->dim)
-	   )
-	{
-	    match = type->implicitConvTo(tf->next);
-	    if (match)
-		return match;
-	    if (tf->next->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
-    if (type->equals(t))
-	return MATCHexact;
-
-    enum TY ty = type->toBasetype()->ty;
-    enum TY toty = t->toBasetype()->ty;
-
-    if (type->implicitConvTo(t) == MATCHnomatch && t->ty == Tenum)
-    {
-	return MATCHnomatch;
-    }
-
-    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", (integer_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;
-	}
-    }
-    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)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    if (this->type->equals(t))
-	return MATCHexact;
-    // NULL implicitly converts to any pointer type or dynamic array
-    if (type->ty == Tpointer && type->next->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);
-}
-
-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->next->ty == Tvoid)
-    {
-	return MATCHnomatch;
-    }
-    if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer)
-    {
-	if (type->next->ty == Tchar)
-	{
-	    switch (t->ty)
-	    {
-		case Tsarray:
-		    if (type->ty == Tsarray &&
-			((TypeSArray *)type)->dim->toInteger() !=
-			((TypeSArray *)t)->dim->toInteger())
-			return MATCHnomatch;
-		    goto L1;
-		case Tarray:
-		    goto L1;
-		case Tpointer:
-		L1:
-		    if (t->next->ty == Tchar)
-			return MATCHexact;
-		    else if (t->next->ty == Twchar)
-			return MATCHexact;
-		    else if (t->next->ty == Tdchar)
-			return MATCHexact;
-		    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;
-
-    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->next);
-	    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)->key);
-	    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->next);
-	    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.
-	VarExp *ve;
-	FuncDeclaration *f;
-
-	t = t->toBasetype();
-	if (type->ty == Tpointer && type->next->ty == Tfunction &&
-	    t->ty == Tpointer && t->next->ty == Tfunction &&
-	    e1->op == TOKvar)
-	{
-	    ve = (VarExp *)e1;
-	    f = ve->var->isFuncDeclaration();
-	    if (f && f->overloadExactMatch(t->next))
-		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->next->ty == Tfunction &&
-	    t->ty == Tpointer && t->next->ty == Tfunction)
-	{
-	    f = var->isFuncDeclaration();
-	    if (f && f->overloadExactMatch(t->next))
-		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 == 0)
-    {
-	// Look for pointers to functions where the functions are overloaded.
-	FuncDeclaration *f;
-
-	t = t->toBasetype();
-	if (type->ty == Tdelegate && type->next->ty == Tfunction &&
-	    t->ty == Tdelegate && t->next->ty == Tfunction)
-	{
-	    if (func && func->overloadExactMatch(t->next))
-		result = MATCHexact;
-	}
-    }
-    return result;
-}
-
-MATCH CondExp::implicitConvTo(Type *t)
-{
-    MATCH m1;
-    MATCH m2;
-
-    m1 = e1->implicitConvTo(t);
-    m2 = e2->implicitConvTo(t);
-
-    // Pick the worst match
-    return (m1 < m2) ? m1 : m2;
-}
-
-
-/* ==================== 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
-	{
-	    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 (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;
-		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;
-		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;
-		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;
-		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.
-	VarExp *ve;
-	FuncDeclaration *f;
-
-	if (type->ty == Tpointer && type->next->ty == Tfunction &&
-	    tb->ty == Tpointer && tb->next->ty == Tfunction &&
-	    e1->op == TOKvar)
-	{
-	    ve = (VarExp *)e1;
-	    f = ve->var->isFuncDeclaration();
-	    if (f)
-	    {
-		f = f->overloadExactMatch(tb->next);
-		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, t=%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) &&
-	tb->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)
-    {
-	e = (ArrayLiteralExp *)copy();
-	e->type = typeb->nextOf()->pointerTo();
-    }
-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)
-{
-    Type *tb;
-
-#if 0
-    printf("SymOffExp::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.
-	FuncDeclaration *f;
-
-	if (type->ty == Tpointer && type->next->ty == Tfunction &&
-	    tb->ty == Tpointer && tb->next->ty == Tfunction)
-	{
-	    f = var->isFuncDeclaration();
-	    if (f)
-	    {
-		f = f->overloadExactMatch(tb->next);
-		if (f)
-		{
-		    e = new SymOffExp(loc, f, 0);
-		    e->type = t;
-		    return e;
-		}
-	    }
-	}
-	e = Expression::castTo(sc, t);
-    }
-    e->type = t;
-    return e;
-}
-
-Expression *DelegateExp::castTo(Scope *sc, Type *t)
-{
-    Type *tb;
-#if 0
-    printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
-	toChars(), type->toChars(), t->toChars());
-#endif
-    Expression *e = this;
-    static char msg[] = "cannot form delegate due to covariant return type";
-
-    tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
-    {
-	// Look for delegates to functions where the functions are overloaded.
-	FuncDeclaration *f;
-
-	if (type->ty == Tdelegate && type->next->ty == Tfunction &&
-	    tb->ty == Tdelegate && tb->next->ty == Tfunction)
-	{
-	    if (func)
-	    {
-		f = func->overloadExactMatch(tb->next);
-		if (f)
-		{   int offset;
-		    if (f->tintro && f->tintro->next->isBaseOf(f->type->next, &offset) && offset)
-			error("%s", msg);
-		    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;
-
-	if (func->tintro && func->tintro->next->isBaseOf(func->type->next, &offset) && offset)
-	    error("%s", msg);
-    }
-    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;
-}
-
-/* ==================== ====================== */
-
-/****************************************
- * 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->next->size();
-	if (!t->equals(t2b))
-	    e2 = e2->castTo(sc, t);
-    // LLVMDC: llvm uses typesafe pointer arithmetic
-    #if !IN_LLVM
-	if (t1b->next->isbit())
-	    // BUG: should add runtime check for misaligned offsets
-	    // This perhaps should be done by rewriting as &p[i]
-	    // and letting back end do it.
-	    e2 = new UshrExp(loc, e2, new IntegerExp(0, 3, t));
-	else
-	    e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
-    #endif
-	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->next->size();
-	if (!t->equals(t1b))
-	    e = e1->castTo(sc, t);
-	else
-	    e = e1;
-    #if !IN_LLVM
-	if (t2b->next->isbit())
-	    // BUG: should add runtime check for misaligned offsets
-	    e = new UshrExp(loc, e, new IntegerExp(0, 3, t));
-	else
-	    e = new MulExp(loc, e, new IntegerExp(0, stride, t));
-    #endif
-	e->type = t;
-	type = e2->type;
-	e1 = e2;
-	e2 = e;
-    }
-    return this;
-}
-
-/************************************
- * Bring leaves to common type.
- */
-
-Expression *BinExp::typeCombine(Scope *sc)
-{
-    Type *t1;
-    Type *t2;
-    Type *t;
-    TY ty;
-
-    //printf("BinExp::typeCombine()\n");
-    //dump(0);
-
-    e1 = e1->integralPromotions(sc);
-    e2 = e2->integralPromotions(sc);
-
-    // BUG: do toBasetype()
-    t1 = e1->type;
-    t2 = e2->type;
-    assert(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)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)
-	    {
-		if (!type)
-		    type = t1;
-		return this;
-	    }
-
-	    if (t1b == t2b)
-	    {
-		if (!type)
-		    type = t1b;
-		return this;
-	    }
-	}
-
-	if (!type)
-	    type = Type::basic[ty];
-
-	t1 = Type::basic[ty1];
-	t2 = Type::basic[ty2];
-	e1 = e1->castTo(sc, t1);
-	e2 = e2->castTo(sc, t2);
-#if 0
-	if (type != Type::basic[ty])
-	{   t = type;
-	    type = Type::basic[ty];
-	    return castTo(sc, t);
-	}
-#endif
-	//printf("after typeCombine():\n");
-	//dump(0);
-	//printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2);
-	return this;
-    }
-
-    t = t1;
-    if (t1 == t2)
-    {
-	if ((t1->ty == Tstruct || t1->ty == Tclass) &&
-	    (op == TOKmin || op == TOKadd))
-	    goto Lincompatible;
-    }
-    else if (t1->isintegral() && t2->isintegral())
-    {
-	printf("t1 = %s, t2 = %s\n", t1->toChars(), t2->toChars());
-	int sz1 = t1->size();
-	int sz2 = t2->size();
-	int sign1 = t1->isunsigned() == 0;
-	int sign2 = t2->isunsigned() == 0;
-
-	if (sign1 == sign2)
-	{
-	    if (sz1 < sz2)
-		goto Lt2;
-	    else
-		goto Lt1;
-	}
-	if (!sign1)
-	{
-	    if (sz1 >= sz2)
-		goto Lt1;
-	    else
-		goto Lt2;
-	}
-	else
-	{
-	    if (sz2 >= sz1)
-		goto Lt2;
-	    else
-		goto Lt1;
-	}
-    }
-    else if (t1->ty == Tpointer && t2->ty == Tpointer)
-    {
-	// Bring pointers to compatible type
-	Type *t1n = t1->next;
-	Type *t2n = t2->next;
-
-//t1->print();
-//t2->print();
-//if (t1n == t2n) *(char *)0 = 0;
-	assert(t1n != t2n);
-	if (t1n->ty == Tvoid)		// pointers to void are always compatible
-	    t = t2;
-	else if (t2n->ty == Tvoid)
-	    ;
-	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->next->ty == Tvoid)
-    {
-	goto Lx1;
-    }
-    else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
-	     e1->op == TOKnull && t1->ty == Tpointer && t1->next->ty == Tvoid)
-    {
-	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;
-    }
-    else if (t1->ty == Tclass || t2->ty == Tclass)
-    {	int i1;
-	int i2;
-
-	i1 = e2->implicitConvTo(t1);
-	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
-	    goto Lincompatible;
-    }
-    else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2))
-    {
-	goto Lt2;
-    }
-//else if (e2->op == TOKstring) { printf("test2\n"); }
-    else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1))
-    {
-	goto Lt1;
-    }
-    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
-	     e2->implicitConvTo(t1->next->arrayOf()))
-    {
-     Lx1:
-	t = t1->next->arrayOf();
-	e1 = e1->castTo(sc, t);
-	e2 = e2->castTo(sc, t);
-    }
-    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
-	     e1->implicitConvTo(t2->next->arrayOf()))
-    {
-     Lx2:
-	t = t2->next->arrayOf();
-	e1 = e1->castTo(sc, t);
-	e2 = e2->castTo(sc, t);
-    }
-    else
-    {
-     Lincompatible:
-	incompatibleTypes();
-    }
-Lret:
-    if (!type)
-	type = t;
-    //dump(0);
-    return this;
-
-
-Lt1:
-    e2 = e2->castTo(sc, t1);
-    t = t1;
-    goto Lret;
-
-Lt2:
-    e1 = e1->castTo(sc, t2);
-    t = t2;
-    goto Lret;
-}
-
-/***********************************
- * Do integral promotions (convertchk).
- * Don't convert <array of> to <pointer to>
- */
-
-Expression *Expression::integralPromotions(Scope *sc)
-{   Expression *e;
-
-    e = this;
-    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;
-}
-
+
+// Copyright (c) 1999-2006 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>
+
+#if _WIN32 || IN_GCC || IN_LLVM
+#include "mem.h"
+#else
+#include "../root/mem.h"
+#endif
+
+#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("implicitCastTo(%s) => %s\n", type->toChars(), t->toChars());
+    if (implicitConvTo(t))
+    {
+	if (global.params.warnings &&
+	    Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] &&
+	    op != TOKint64)
+	{
+	    Expression *e = optimize(WANTflags | WANTvalue);
+
+	    if (e->op == TOKint64)
+		return e->implicitCastTo(sc, t);
+
+	    fprintf(stdmsg, "warning - ");
+	    error("implicit conversion of expression (%s) of type %s to %s can cause loss of data",
+		toChars(), type->toChars(), t->toChars());
+	}
+	return castTo(sc, t);
+    }
+
+    Expression *e = optimize(WANTflags | WANTvalue);
+    if (e != this)
+	return e->implicitCastTo(sc, t);
+
+#if 0
+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->next->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);
+}
+
+/*******************************************
+ * 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
+    if (!type)
+    {	error("%s is not an expression", toChars());
+	type = Type::terror;
+    }
+    if (t->ty == Tbit && isBit())
+	return MATCHconvert;
+    Expression *e = optimize(WANTvalue | WANTflags);
+    if (e != this)
+    {	//printf("optimzed to %s\n", e->toChars());
+	return e->implicitConvTo(t);
+    }
+    MATCH match = type->implicitConvTo(t);
+    if (match)
+	return match;
+#if 0
+    Type *tb = t->toBasetype();
+    if (tb->ty == Tdelegate)
+    {	TypeDelegate *td = (TypeDelegate *)tb;
+	TypeFunction *tf = (TypeFunction *)td->next;
+
+	if (!tf->varargs &&
+	    !(tf->arguments && tf->arguments->dim)
+	   )
+	{
+	    match = type->implicitConvTo(tf->next);
+	    if (match)
+		return match;
+	    if (tf->next->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
+    if (type->equals(t))
+	return MATCHexact;
+
+    enum TY ty = type->toBasetype()->ty;
+    enum TY toty = t->toBasetype()->ty;
+
+    if (type->implicitConvTo(t) == MATCHnomatch && t->ty == Tenum)
+    {
+	return MATCHnomatch;
+    }
+
+    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", (integer_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;
+	}
+    }
+    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)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    if (this->type->equals(t))
+	return MATCHexact;
+    // NULL implicitly converts to any pointer type or dynamic array
+    if (type->ty == Tpointer && type->next->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);
+}
+
+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->next->ty == Tvoid)
+    {
+	return MATCHnomatch;
+    }
+    if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer)
+    {
+	if (type->next->ty == Tchar)
+	{
+	    switch (t->ty)
+	    {
+		case Tsarray:
+		    if (type->ty == Tsarray &&
+			((TypeSArray *)type)->dim->toInteger() !=
+			((TypeSArray *)t)->dim->toInteger())
+			return MATCHnomatch;
+		    goto L1;
+		case Tarray:
+		    goto L1;
+		case Tpointer:
+		L1:
+		    if (t->next->ty == Tchar)
+			return MATCHexact;
+		    else if (t->next->ty == Twchar)
+			return MATCHexact;
+		    else if (t->next->ty == Tdchar)
+			return MATCHexact;
+		    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;
+
+    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->next);
+	    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)->key);
+	    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->next);
+	    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.
+	VarExp *ve;
+	FuncDeclaration *f;
+
+	t = t->toBasetype();
+	if (type->ty == Tpointer && type->next->ty == Tfunction &&
+	    t->ty == Tpointer && t->next->ty == Tfunction &&
+	    e1->op == TOKvar)
+	{
+	    ve = (VarExp *)e1;
+	    f = ve->var->isFuncDeclaration();
+	    if (f && f->overloadExactMatch(t->next))
+		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->next->ty == Tfunction &&
+	    t->ty == Tpointer && t->next->ty == Tfunction)
+	{
+	    f = var->isFuncDeclaration();
+	    if (f && f->overloadExactMatch(t->next))
+		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 == 0)
+    {
+	// Look for pointers to functions where the functions are overloaded.
+	FuncDeclaration *f;
+
+	t = t->toBasetype();
+	if (type->ty == Tdelegate && type->next->ty == Tfunction &&
+	    t->ty == Tdelegate && t->next->ty == Tfunction)
+	{
+	    if (func && func->overloadExactMatch(t->next))
+		result = MATCHexact;
+	}
+    }
+    return result;
+}
+
+MATCH CondExp::implicitConvTo(Type *t)
+{
+    MATCH m1;
+    MATCH m2;
+
+    m1 = e1->implicitConvTo(t);
+    m2 = e2->implicitConvTo(t);
+
+    // Pick the worst match
+    return (m1 < m2) ? m1 : m2;
+}
+
+
+/* ==================== 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
+	{
+	    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 (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;
+		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;
+		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;
+		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;
+		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.
+	VarExp *ve;
+	FuncDeclaration *f;
+
+	if (type->ty == Tpointer && type->next->ty == Tfunction &&
+	    tb->ty == Tpointer && tb->next->ty == Tfunction &&
+	    e1->op == TOKvar)
+	{
+	    ve = (VarExp *)e1;
+	    f = ve->var->isFuncDeclaration();
+	    if (f)
+	    {
+		f = f->overloadExactMatch(tb->next);
+		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, t=%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)
+    {
+	e = (ArrayLiteralExp *)copy();
+	e->type = typeb->nextOf()->pointerTo();
+    }
+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)
+{
+    Type *tb;
+
+#if 0
+    printf("SymOffExp::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.
+	FuncDeclaration *f;
+
+	if (type->ty == Tpointer && type->next->ty == Tfunction &&
+	    tb->ty == Tpointer && tb->next->ty == Tfunction)
+	{
+	    f = var->isFuncDeclaration();
+	    if (f)
+	    {
+		f = f->overloadExactMatch(tb->next);
+		if (f)
+		{
+		    e = new SymOffExp(loc, f, 0);
+		    e->type = t;
+		    return e;
+		}
+	    }
+	}
+	e = Expression::castTo(sc, t);
+    }
+    e->type = t;
+    return e;
+}
+
+Expression *DelegateExp::castTo(Scope *sc, Type *t)
+{
+    Type *tb;
+#if 0
+    printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    Expression *e = this;
+    static char msg[] = "cannot form delegate due to covariant return type";
+
+    tb = t->toBasetype();
+    type = type->toBasetype();
+    if (tb != type)
+    {
+	// Look for delegates to functions where the functions are overloaded.
+	FuncDeclaration *f;
+
+	if (type->ty == Tdelegate && type->next->ty == Tfunction &&
+	    tb->ty == Tdelegate && tb->next->ty == Tfunction)
+	{
+	    if (func)
+	    {
+		f = func->overloadExactMatch(tb->next);
+		if (f)
+		{   int offset;
+		    if (f->tintro && f->tintro->next->isBaseOf(f->type->next, &offset) && offset)
+			error("%s", msg);
+		    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;
+
+	if (func->tintro && func->tintro->next->isBaseOf(func->type->next, &offset) && offset)
+	    error("%s", msg);
+    }
+    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;
+}
+
+/* ==================== ====================== */
+
+/****************************************
+ * 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->next->size();
+	if (!t->equals(t2b))
+	    e2 = e2->castTo(sc, t);
+    // LLVMDC: llvm uses typesafe pointer arithmetic
+    #if !IN_LLVM
+	if (t1b->next->isbit())
+	    // BUG: should add runtime check for misaligned offsets
+	    // This perhaps should be done by rewriting as &p[i]
+	    // and letting back end do it.
+	    e2 = new UshrExp(loc, e2, new IntegerExp(0, 3, t));
+	else
+	    e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
+    #endif
+	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->next->size();
+	if (!t->equals(t1b))
+	    e = e1->castTo(sc, t);
+	else
+	    e = e1;
+    #if !IN_LLVM
+	if (t2b->next->isbit())
+	    // BUG: should add runtime check for misaligned offsets
+	    e = new UshrExp(loc, e, new IntegerExp(0, 3, t));
+	else
+	    e = new MulExp(loc, e, new IntegerExp(0, stride, t));
+    #endif
+	e->type = t;
+	type = e2->type;
+	e1 = e2;
+	e2 = e;
+    }
+    return this;
+}
+
+/************************************
+ * Bring leaves to common type.
+ */
+
+Expression *BinExp::typeCombine(Scope *sc)
+{
+    Type *t1;
+    Type *t2;
+    Type *t;
+    TY ty;
+
+    //printf("BinExp::typeCombine()\n");
+    //dump(0);
+
+    e1 = e1->integralPromotions(sc);
+    e2 = e2->integralPromotions(sc);
+
+    // BUG: do toBasetype()
+    t1 = e1->type;
+    t2 = e2->type;
+    assert(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)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)
+	    {
+		if (!type)
+		    type = t1;
+		return this;
+	    }
+
+	    if (t1b == t2b)
+	    {
+		if (!type)
+		    type = t1b;
+		return this;
+	    }
+	}
+
+	if (!type)
+	    type = Type::basic[ty];
+
+	t1 = Type::basic[ty1];
+	t2 = Type::basic[ty2];
+	e1 = e1->castTo(sc, t1);
+	e2 = e2->castTo(sc, t2);
+#if 0
+	if (type != Type::basic[ty])
+	{   t = type;
+	    type = Type::basic[ty];
+	    return castTo(sc, t);
+	}
+#endif
+	//printf("after typeCombine():\n");
+	//dump(0);
+	//printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2);
+	return this;
+    }
+
+    t = t1;
+    if (t1 == t2)
+    {
+	if ((t1->ty == Tstruct || t1->ty == Tclass) &&
+	    (op == TOKmin || op == TOKadd))
+	    goto Lincompatible;
+    }
+    else if (t1->isintegral() && t2->isintegral())
+    {
+	printf("t1 = %s, t2 = %s\n", t1->toChars(), t2->toChars());
+	int sz1 = t1->size();
+	int sz2 = t2->size();
+	int sign1 = t1->isunsigned() == 0;
+	int sign2 = t2->isunsigned() == 0;
+
+	if (sign1 == sign2)
+	{
+	    if (sz1 < sz2)
+		goto Lt2;
+	    else
+		goto Lt1;
+	}
+	if (!sign1)
+	{
+	    if (sz1 >= sz2)
+		goto Lt1;
+	    else
+		goto Lt2;
+	}
+	else
+	{
+	    if (sz2 >= sz1)
+		goto Lt2;
+	    else
+		goto Lt1;
+	}
+    }
+    else if (t1->ty == Tpointer && t2->ty == Tpointer)
+    {
+	// Bring pointers to compatible type
+	Type *t1n = t1->next;
+	Type *t2n = t2->next;
+
+//t1->print();
+//t2->print();
+//if (t1n == t2n) *(char *)0 = 0;
+	assert(t1n != t2n);
+	if (t1n->ty == Tvoid)		// pointers to void are always compatible
+	    t = t2;
+	else if (t2n->ty == Tvoid)
+	    ;
+	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->next->ty == Tvoid)
+    {
+	goto Lx1;
+    }
+    else if ((t2->ty == Tsarray || t2->ty == Tarray) &&
+	     e1->op == TOKnull && t1->ty == Tpointer && t1->next->ty == Tvoid)
+    {
+	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;
+    }
+    else if (t1->ty == Tclass || t2->ty == Tclass)
+    {	int i1;
+	int i2;
+
+	i1 = e2->implicitConvTo(t1);
+	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
+	    goto Lincompatible;
+    }
+    else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2))
+    {
+	goto Lt2;
+    }
+//else if (e2->op == TOKstring) { printf("test2\n"); }
+    else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1))
+    {
+	goto Lt1;
+    }
+    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
+	     e2->implicitConvTo(t1->next->arrayOf()))
+    {
+     Lx1:
+	t = t1->next->arrayOf();
+	e1 = e1->castTo(sc, t);
+	e2 = e2->castTo(sc, t);
+    }
+    else if (t1->ty == Tsarray && t2->ty == Tsarray &&
+	     e1->implicitConvTo(t2->next->arrayOf()))
+    {
+     Lx2:
+	t = t2->next->arrayOf();
+	e1 = e1->castTo(sc, t);
+	e2 = e2->castTo(sc, t);
+    }
+    else
+    {
+     Lincompatible:
+	incompatibleTypes();
+    }
+Lret:
+    if (!type)
+	type = t;
+    //dump(0);
+    return this;
+
+
+Lt1:
+    e2 = e2->castTo(sc, t1);
+    t = t1;
+    goto Lret;
+
+Lt2:
+    e1 = e1->castTo(sc, t2);
+    t = t2;
+    goto Lret;
+}
+
+/***********************************
+ * Do integral promotions (convertchk).
+ * Don't convert <array of> to <pointer to>
+ */
+
+Expression *Expression::integralPromotions(Scope *sc)
+{   Expression *e;
+
+    e = this;
+    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;
+}
+