Mercurial > projects > ldc
diff dmd2/cast.c @ 1526:54b3c1394d62
Merged dmdfe 2.031.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Tue, 07 Jul 2009 02:26:11 +0100 |
parents | 638d16625da2 |
children | e4f7b5d9c68a |
line wrap: on
line diff
--- a/dmd2/cast.c Mon Jul 06 23:57:27 2009 +0100 +++ b/dmd2/cast.c Tue Jul 07 02:26:11 2009 +0100 @@ -33,6 +33,7 @@ if (match) { TY tyfrom = type->toBasetype()->ty; TY tyto = t->toBasetype()->ty; +#if DMDV1 if (global.params.warnings && Type::impcnvWarn[tyfrom][tyto] && op != TOKint64) @@ -41,7 +42,6 @@ if (e->op == TOKint64) return e->implicitCastTo(sc, t); - if (tyfrom == Tint32 && (op == TOKadd || op == TOKmin || op == TOKand || op == TOKor || op == TOKxor) @@ -61,6 +61,7 @@ toChars(), type->toChars(), t->toChars()); } } +#endif #if DMDV2 if (match == MATCHconst && t == type->constOf()) { @@ -144,6 +145,16 @@ 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) @@ -676,18 +687,72 @@ 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; - MATCH m2; - - m1 = e1->implicitConvTo(t); - m2 = e2->implicitConvTo(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 ====================== */ @@ -1258,22 +1323,35 @@ f = f->overloadExactMatch(tb->nextOf(), m); if (f) { - if (tb->ty == Tdelegate && f->needThis() && hasThis(sc)) + if (tb->ty == Tdelegate) { - e = new DelegateExp(loc, new ThisExp(loc), f); - e = e->semantic(sc); - } - else if (tb->ty == Tdelegate && f->isNested()) - { - e = new DelegateExp(loc, new IntegerExp(0), f); - e = e->semantic(sc); + 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; } } @@ -1353,6 +1431,23 @@ 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; +} + /* ==================== ====================== */ /**************************************** @@ -1777,3 +1872,226 @@ } 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(); + + 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(); +} + +