Updated to dmdfe 2.054

This commit is contained in:
Alexey Prokhin
2011-07-19 19:20:38 +04:00
parent 99f5a73125
commit 7a31b599cc
54 changed files with 4600 additions and 1644 deletions

View File

@@ -1743,12 +1743,12 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
if (dup)
arguments->push(getTypeInfo(sc));
// LDC repaint array type to void[]
if (n->ty != Tvoid) {
e = new CastExp(e->loc, e, e->type);
e->type = Type::tvoid->arrayOf();
}
arguments->push(e);
// LDC repaint array type to void[]
if (n->ty != Tvoid) {
e = new CastExp(e->loc, e, e->type);
e->type = Type::tvoid->arrayOf();
}
arguments->push(e);
if (!dup)
arguments->push(new IntegerExp(0, size, Type::tsize_t));
@@ -1759,7 +1759,6 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
{
Expression *ec;
Expressions *arguments;
bool isBit = (n->ty == Tbit);
//LDC: Build arguments.
static FuncDeclaration *adSort_fd = NULL;
@@ -1769,31 +1768,20 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSort_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSort");
}
static FuncDeclaration *adSortBit_fd = NULL;
if(!adSortBit_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSortBit_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSortBit");
}
if(isBit)
ec = new VarExp(0, adSortBit_fd);
else
ec = new VarExp(0, adSort_fd);
ec = new VarExp(0, adSort_fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions();
// LDC repaint array type to void[]
if (n->ty != Tvoid) {
e = new CastExp(e->loc, e, e->type);
e->type = Type::tvoid->arrayOf();
}
arguments->push(e);
if (next->ty != Tbit)
arguments->push(n->getTypeInfo(sc)); // LDC, we don't support the getInternalTypeInfo
// optimization arbitrarily, not yet at least...
// LDC repaint array type to void[]
if (n->ty != Tvoid) {
e = new CastExp(e->loc, e, e->type);
e->type = Type::tvoid->arrayOf();
}
arguments->push(e);
// LDC, we don't support the getInternalTypeInfo
// optimization arbitrarily, not yet at least...
arguments->push(n->getTypeInfo(sc));
e = new CallExp(e->loc, ec, arguments);
e->type = next->arrayOf();
}

View File

@@ -67,6 +67,7 @@ struct AggregateDeclaration : ScopeDsymbol
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
int isdeprecated; // !=0 if deprecated
#if DMDV2
@@ -234,6 +235,7 @@ struct ClassDeclaration : AggregateDeclaration
static ClassDeclaration *object;
static ClassDeclaration *classinfo;
static ClassDeclaration *throwable;
static ClassDeclaration *exception;
ClassDeclaration *baseClass; // NULL only if this is Object
#if DMDV1

View File

@@ -23,9 +23,7 @@ struct LabelDsymbol;
struct Initializer;
struct Module;
struct Condition;
#ifdef _DH
struct HdrGenState;
#endif
/**************************************************************/

View File

@@ -17,6 +17,10 @@
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
//#define DUMP .dump(__PRETTY_FUNCTION__, this)
#define DUMP
/* ==================== implicitCast ====================== */
@@ -158,8 +162,10 @@ MATCH Expression::implicitConvTo(Type *t)
*/
if (type->isintegral() && t->isintegral() &&
type->isTypeBasic() && t->isTypeBasic())
{ IntRange ir = getIntRange();
if (ir.imax <= t->sizemask())
{ IntRange src = this->getIntRange() DUMP;
IntRange targetUnsigned = IntRange::fromType(t, /*isUnsigned*/true) DUMP;
IntRange targetSigned = IntRange::fromType(t, /*isUnsigned*/false) DUMP;
if (targetUnsigned.contains(src) || targetSigned.contains(src))
return MATCHconvert;
}
@@ -203,7 +209,6 @@ MATCH IntegerExp::implicitConvTo(Type *t)
switch (ty)
{
case Tbit:
case Tbool:
value &= 1;
ty = Tint32;
@@ -248,7 +253,6 @@ MATCH IntegerExp::implicitConvTo(Type *t)
// Only allow conversion if no change in value
switch (toty)
{
case Tbit:
case Tbool:
if ((value & 1) != value)
goto Lno;
@@ -1533,7 +1537,17 @@ Expression *CommaExp::castTo(Scope *sc, Type *t)
*/
Expression *BinExp::scaleFactor(Scope *sc)
{ d_uns64 stride;
{
if (sc->func && !sc->intypeof)
{
if (sc->func->setUnsafe())
{
error("pointer arithmetic not allowed in @safe functions");
return new ErrorExp();
}
}
d_uns64 stride;
Type *t1b = e1->type->toBasetype();
Type *t2b = e2->type->toBasetype();
@@ -1615,10 +1629,17 @@ bool isVoidArrayLiteral(Expression *e, Type *other)
int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression **pe2)
{
//printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars());
//dump(0);
//e->dump(0);
Expression *e1 = (*pe1)->integralPromotions(sc);
Expression *e2 = (*pe2)->integralPromotions(sc);
Expression *e1 = *pe1;
Expression *e2 = *pe2;
if (e->op != TOKquestion ||
e1->type->toBasetype()->ty != e2->type->toBasetype()->ty)
{
e1 = e1->integralPromotions(sc);
e2 = e2->integralPromotions(sc);
}
Type *t1 = e1->type;
Type *t2 = e2->type;
@@ -1861,7 +1882,15 @@ Lagain:
}
else if (t1->isintegral() && t2->isintegral())
{
assert(0);
assert(t1->ty == t2->ty);
unsigned char mod = MODmerge(t1->mod, t2->mod);
t1 = t1->castMod(mod);
t2 = t2->castMod(mod);
t = t1;
e1 = e1->castTo(sc, t);
e2 = e2->castTo(sc, t);
goto Lagain;
}
else if (e1->isArrayOperand() && t1->ty == Tarray &&
e2->implicitConvTo(t1->nextOf()))
@@ -1974,7 +2003,6 @@ Expression *Expression::integralPromotions(Scope *sc)
case Tuns8:
case Tint16:
case Tuns16:
case Tbit:
case Tbool:
case Tchar:
case Twchar:
@@ -2046,233 +2074,309 @@ int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2)
uinteger_t getMask(uinteger_t v)
{
uinteger_t u = 0;
if (v >= 0x80)
u = 0xFF;
while (u < v)
u = (u << 1) | 1;
return u;
// Ref: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
return v /* | 0xff*/;
}
IntRange Expression::getIntRange()
{
IntRange ir;
ir.imin = 0;
if (type->isintegral())
ir.imax = type->sizemask();
else
ir.imax = 0xFFFFFFFFFFFFFFFFULL; // assume the worst
return ir;
return IntRange::fromType(type) DUMP;
}
IntRange IntegerExp::getIntRange()
{
IntRange ir;
ir.imin = value & type->sizemask();
ir.imax = ir.imin;
return ir;
return IntRange(value).cast(type) DUMP;
}
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;
}
if (type->isintegral())
{
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
}
//printf("CastExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
return ir;
return e1->getIntRange().cast(type) DUMP;
}
IntRange AddExp::getIntRange()
{
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
return IntRange(ir1.imin + ir2.imin, ir1.imax + ir2.imax).cast(type) DUMP;
}
IntRange MinExp::getIntRange()
{
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
return IntRange(ir1.imin - ir2.imax, ir1.imax - ir2.imin).cast(type) DUMP;
}
IntRange DivExp::getIntRange()
{
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
if (!(e1->type->isunsigned() || ir1.imax < 0x8000000000000000ULL) &&
!(e2->type->isunsigned() || ir2.imax < 0x8000000000000000ULL))
{
return Expression::getIntRange();
}
// Should we ignore the possibility of div-by-0???
if (ir2.containsZero())
return Expression::getIntRange() DUMP;
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;
// [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)]
SignExtendedNumber bdy[4] = {
ir1.imin / ir2.imin,
ir1.imin / ir2.imax,
ir1.imax / ir2.imin,
ir1.imax / ir2.imax
};
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
}
IntRange MulExp::getIntRange()
{
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
// [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)]
SignExtendedNumber bdy[4] = {
ir1.imin * ir2.imin,
ir1.imin * ir2.imax,
ir1.imax * ir2.imin,
ir1.imax * ir2.imax
};
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
}
IntRange ModExp::getIntRange()
{
IntRange irNum = e1->getIntRange();
IntRange irDen = e2->getIntRange().absNeg();
/*
due to the rules of D (C)'s % operator, we need to consider the cases
separately in different range of signs.
case 1. [500, 1700] % [7, 23] (numerator is always positive)
= [0, 22]
case 2. [-500, 1700] % [7, 23] (numerator can be negative)
= [-22, 22]
case 3. [-1700, -500] % [7, 23] (numerator is always negative)
= [-22, 0]
the number 22 is the maximum absolute value in the denomator's range. We
don't care about divide by zero.
*/
// Modding on 0 is invalid anyway.
if (!irDen.imin.negative)
return Expression::getIntRange() DUMP;
++ irDen.imin;
irDen.imax = -irDen.imin;
if (!irNum.imin.negative)
irNum.imin.value = 0;
else if (irNum.imin < irDen.imin)
irNum.imin = irDen.imin;
if (irNum.imax.negative)
{
irNum.imax.negative = false;
irNum.imax.value = 0;
}
else if (irNum.imax > irDen.imax)
irNum.imax = irDen.imax;
return irNum.cast(type) DUMP;
}
// The algorithms for &, |, ^ are not yet the best! Sometimes they will produce
// not the tightest bound. See
// https://github.com/D-Programming-Language/dmd/pull/116
// for detail.
static IntRange unsignedBitwiseAnd(const IntRange& a, const IntRange& b)
{
// the DiffMasks stores the mask of bits which are variable in the range.
uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value);
uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value);
// Since '&' computes the digitwise-minimum, the we could set all varying
// digits to 0 to get a lower bound, and set all varying digits to 1 to get
// an upper bound.
IntRange result;
result.imin.value = (a.imin.value & ~aDiffMask) & (b.imin.value & ~bDiffMask);
result.imax.value = (a.imax.value | aDiffMask) & (b.imax.value | bDiffMask);
// Sometimes the upper bound is overestimated. The upper bound will never
// exceed the input.
if (result.imax.value > a.imax.value)
result.imax.value = a.imax.value;
if (result.imax.value > b.imax.value)
result.imax.value = b.imax.value;
result.imin.negative = result.imax.negative = a.imin.negative && b.imin.negative;
return result;
}
static IntRange unsignedBitwiseOr(const IntRange& a, const IntRange& b)
{
// the DiffMasks stores the mask of bits which are variable in the range.
uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value);
uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value);
// The imax algorithm by Adam D. Ruppe.
// http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=108796
IntRange result;
result.imin.value = (a.imin.value & ~aDiffMask) | (b.imin.value & ~bDiffMask);
result.imax.value = a.imax.value | b.imax.value | getMask(a.imax.value & b.imax.value);
// Sometimes the lower bound is underestimated. The lower bound will never
// less than the input.
if (result.imin.value < a.imin.value)
result.imin.value = a.imin.value;
if (result.imin.value < b.imin.value)
result.imin.value = b.imin.value;
result.imin.negative = result.imax.negative = a.imin.negative || b.imin.negative;
return result;
}
static IntRange unsignedBitwiseXor(const IntRange& a, const IntRange& b)
{
// the DiffMasks stores the mask of bits which are variable in the range.
uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value);
uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value);
IntRange result;
result.imin.value = (a.imin.value ^ b.imin.value) & ~(aDiffMask | bDiffMask);
result.imax.value = (a.imax.value ^ b.imax.value) | (aDiffMask | bDiffMask);
result.imin.negative = result.imax.negative = a.imin.negative != b.imin.negative;
return result;
}
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;
IntRange ir1neg, ir1pos, ir2neg, ir2pos;
bool has1neg, has1pos, has2neg, has2pos;
ir.imax = ir1.imax;
if (ir2.imax > ir.imax)
ir.imax = ir2.imax;
ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos);
ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos);
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 result;
bool hasResult = false;
if (has1pos && has2pos)
result.unionOrAssign(unsignedBitwiseAnd(ir1pos, ir2pos), /*ref*/hasResult);
if (has1pos && has2neg)
result.unionOrAssign(unsignedBitwiseAnd(ir1pos, ir2neg), /*ref*/hasResult);
if (has1neg && has2pos)
result.unionOrAssign(unsignedBitwiseAnd(ir1neg, ir2pos), /*ref*/hasResult);
if (has1neg && has2neg)
result.unionOrAssign(unsignedBitwiseAnd(ir1neg, ir2neg), /*ref*/hasResult);
assert(hasResult);
return result.cast(type) DUMP;
}
/*
* Adam D. Ruppe's algo for bitwise OR:
* http://www.digitalmars.com/d/archives/digitalmars/D/value_range_propagation_for_logical_OR_108765.html#N108793
*/
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;
IntRange ir1neg, ir1pos, ir2neg, ir2pos;
bool has1neg, has1pos, has2neg, has2pos;
ir.imax = ir1.imax;
if (ir2.imax > ir.imax)
ir.imax = ir2.imax;
ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos);
ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos);
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
IntRange result;
bool hasResult = false;
if (has1pos && has2pos)
result.unionOrAssign(unsignedBitwiseOr(ir1pos, ir2pos), /*ref*/hasResult);
if (has1pos && has2neg)
result.unionOrAssign(unsignedBitwiseOr(ir1pos, ir2neg), /*ref*/hasResult);
if (has1neg && has2pos)
result.unionOrAssign(unsignedBitwiseOr(ir1neg, ir2pos), /*ref*/hasResult);
if (has1neg && has2neg)
result.unionOrAssign(unsignedBitwiseOr(ir1neg, ir2neg), /*ref*/hasResult);
//printf("OrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
assert(hasResult);
return result.cast(type) DUMP;
}
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;
IntRange ir1neg, ir1pos, ir2neg, ir2pos;
bool has1neg, has1pos, has2neg, has2pos;
ir.imax = ir1.imax;
if (ir2.imax > ir.imax)
ir.imax = ir2.imax;
ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos);
ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos);
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
IntRange result;
bool hasResult = false;
if (has1pos && has2pos)
result.unionOrAssign(unsignedBitwiseXor(ir1pos, ir2pos), /*ref*/hasResult);
if (has1pos && has2neg)
result.unionOrAssign(unsignedBitwiseXor(ir1pos, ir2neg), /*ref*/hasResult);
if (has1neg && has2pos)
result.unionOrAssign(unsignedBitwiseXor(ir1neg, ir2pos), /*ref*/hasResult);
if (has1neg && has2neg)
result.unionOrAssign(unsignedBitwiseXor(ir1neg, ir2neg), /*ref*/hasResult);
//printf("XorExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
assert(hasResult);
return result.cast(type) DUMP;
}
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;
if (ir2.imin.negative)
ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
SignExtendedNumber lower = ir1.imin << (ir1.imin.negative ? ir2.imax : ir2.imin);
SignExtendedNumber upper = ir1.imax << (ir1.imax.negative ? ir2.imin : ir2.imax);
//printf("ShlExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
return IntRange(lower, upper).cast(type) DUMP;
}
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;
if (ir2.imin.negative)
ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
SignExtendedNumber lower = ir1.imin >> (ir1.imin.negative ? ir2.imin : ir2.imax);
SignExtendedNumber upper = ir1.imax >> (ir1.imax.negative ? ir2.imax : ir2.imin);
//printf("ShrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
return IntRange(lower, upper).cast(type) DUMP;
}
IntRange UshrExp::getIntRange()
{
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir1 = e1->getIntRange().castUnsigned(e1->type);
IntRange ir2 = e2->getIntRange();
ir.imin = ir1.imin >> ir2.imax;
ir.imax = ir1.imax >> ir2.imin;
if (ir2.imin.negative)
ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
return IntRange(ir1.imin >> ir2.imax, ir1.imax >> ir2.imin).cast(type) DUMP;
//printf("UshrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange CommaExp::getIntRange()
{
return e2->getIntRange();
return e2->getIntRange() DUMP;
}
IntRange ComExp::getIntRange()
{
IntRange ir = e1->getIntRange();
return IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative),
SignExtendedNumber(~ir.imin.value, !ir.imin.negative)).cast(type) DUMP;
}
IntRange NegExp::getIntRange()
{
IntRange ir = e1->getIntRange();
return IntRange(-ir.imax, -ir.imin).cast(type) DUMP;
}

View File

@@ -32,6 +32,7 @@
ClassDeclaration *ClassDeclaration::classinfo;
ClassDeclaration *ClassDeclaration::object;
ClassDeclaration *ClassDeclaration::throwable;
ClassDeclaration *ClassDeclaration::exception;
ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
: AggregateDeclaration(loc, id)
@@ -190,6 +191,12 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
throwable = this;
}
if (id == Id::Exception)
{ if (exception)
exception->error("%s", msg);
exception = this;
}
//if (id == Id::ClassInfo)
if (id == Id::TypeInfo_Class)
{ if (classinfo)
@@ -695,7 +702,8 @@ void ClassDeclaration::semantic(Scope *sc)
if (!ctor && baseClass && baseClass->ctor)
{
//printf("Creating default this(){} for class %s\n", toChars());
CtorDeclaration *ctor = new CtorDeclaration(loc, 0, NULL, 0, 0);
Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0);
CtorDeclaration *ctor = new CtorDeclaration(loc, 0, 0, tf);
ctor->fbody = new CompoundStatement(0, new Statements());
members->push(ctor);
ctor->addMember(sc, this, 1);
@@ -758,6 +766,12 @@ void ClassDeclaration::semantic(Scope *sc)
}
#endif
//printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
if (deferred)
{
deferred->semantic2(sc);
deferred->semantic3(sc);
}
}
void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)

View File

@@ -338,21 +338,26 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
fcp = new FuncDeclaration(loc, 0, Id::cpctor, STCundefined, ftype);
fcp->storage_class |= postblit->storage_class & STCdisable;
// Build *this = p;
Expression *e = new ThisExp(0);
if (!(fcp->storage_class & STCdisable))
{
// Build *this = p;
Expression *e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
e = new PtrExp(0, e);
#endif
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
ea->op = TOKblit;
Statement *s = new ExpStatement(0, ea);
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
ea->op = TOKblit;
Statement *s = new ExpStatement(0, ea);
// Build postBlit();
e = new VarExp(0, postblit, 0);
e = new CallExp(0, e);
// Build postBlit();
e = new VarExp(0, postblit, 0);
e = new CallExp(0, e);
s = new CompoundStatement(0, s, new ExpStatement(0, e));
fcp->fbody = s;
s = new CompoundStatement(0, s, new ExpStatement(0, e));
fcp->fbody = s;
}
else
fcp->fbody = new ExpStatement(0, (Expression *)NULL);
members->push(fcp);
@@ -391,7 +396,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
size_t dim = 1;
size_t dim = (tv->ty == Tsarray ? 1 : 0);
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
@@ -401,15 +406,20 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->postblit)
{ Expression *ex;
{
stc |= sd->postblit->storage_class & STCdisable;
if (stc & STCdisable)
{
e = NULL;
break;
}
// this.v
ex = new ThisExp(0);
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
if (dim == 0)
{ // this.v.postblit()
ex = new DotVarExp(0, ex, sd->postblit, 0);
ex = new CallExp(0, ex);
@@ -432,7 +442,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
/* Build our own "postblit" which executes e
*/
if (e)
if (e || (stc & STCdisable))
{ //printf("Building __fieldPostBlit()\n");
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__fieldPostBlit"));
dd->storage_class |= stc;
@@ -455,6 +465,11 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
for (size_t i = 0; i < postblits.dim; i++)
{ FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i];
stc |= fd->storage_class & STCdisable;
if (stc & STCdisable)
{
e = NULL;
break;
}
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd, 0);
ex = new CallExp(0, ex);
@@ -493,7 +508,7 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
size_t dim = 1;
size_t dim = (tv->ty == Tsarray ? 1 : 0);
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
@@ -509,7 +524,7 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
if (dim == 0)
{ // this.v.dtor()
ex = new DotVarExp(0, ex, sd->dtor, 0);
ex = new CallExp(0, ex);

View File

@@ -20,10 +20,8 @@
#include "module.h"
#include "template.h"
#include "lexer.h"
#ifdef _DH
#include "mtype.h"
#include "scope.h"
#endif
int findCondition(Array *ids, Identifier *ident)
{
@@ -138,6 +136,7 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
"D_NET",
#endif
"OSX", "FreeBSD",
"OpenBSD",
"Solaris",
"LittleEndian", "BigEndian",
"all",

View File

@@ -18,13 +18,9 @@ struct Module;
struct Scope;
struct ScopeDsymbol;
struct DebugCondition;
#ifdef _DH
#include "lexer.h" // dmdhg
#endif
enum TOK;
#ifdef _DH
struct HdrGenState;
#endif
int findCondition(Array *ids, Identifier *ident);

View File

@@ -27,12 +27,10 @@
#include "declaration.h"
#include "utf.h"
#if __FreeBSD__
#define fmodl fmod // hack for now, fix later
#endif
#define LOG 0
int RealEquals(real_t x1, real_t x2);
Expression *expType(Type *type, Expression *e)
{
if (type != e->type)
@@ -486,7 +484,7 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
{ real_t r2 = e2->toReal();
#ifdef __DMC__
c = fmodl(e1->toReal(), r2) + fmodl(e1->toImaginary(), r2) * I;
c = Port::fmodl(e1->toReal(), r2) + Port::fmodl(e1->toImaginary(), r2) * I;
#elif defined(IN_GCC)
c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
#elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__)
@@ -494,14 +492,14 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
// arm also doesn't like fmodl
c = complex_t(fmod(e1->toReal(), r2), fmod(e1->toImaginary(), r2));
#else
c = complex_t(fmodl(e1->toReal(), r2), fmodl(e1->toImaginary(), r2));
c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2));
#endif
}
else if (e2->type->isimaginary())
{ real_t i2 = e2->toImaginary();
#ifdef __DMC__
c = fmodl(e1->toReal(), i2) + fmodl(e1->toImaginary(), i2) * I;
c = Port::fmodl(e1->toReal(), i2) + Port::fmodl(e1->toImaginary(), i2) * I;
#elif defined(IN_GCC)
c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
#elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__)
@@ -509,7 +507,7 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
// arm also doesn't like fmodl
c = complex_t(fmod(e1->toReal(), i2), fmod(e1->toImaginary(), i2));
#else
c = complex_t(fmodl(e1->toReal(), i2), fmodl(e1->toImaginary(), i2));
c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2));
#endif
}
else
@@ -876,11 +874,27 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
cmp = (es1->var == es2->var && es1->offset == es2->offset);
}
else if (e1->isConst() == 1 && e2->isConst() == 1)
return Equal((op == TOKidentity) ? TOKequal : TOKnotequal,
type, e1, e2);
else
assert(0);
{
if (e1->type->isreal())
{
cmp = RealEquals(e1->toReal(), e2->toReal());
}
else if (e1->type->isimaginary())
{
cmp = RealEquals(e1->toImaginary(), e2->toImaginary());
}
else if (e1->type->iscomplex())
{
complex_t v1 = e1->toComplex();
complex_t v2 = e2->toComplex();
cmp = RealEquals(creall(v1), creall(v2)) &&
RealEquals(cimagl(v1), cimagl(v1));
}
else
return Equal((op == TOKidentity) ? TOKequal : TOKnotequal,
type, e1, e2);
}
if (op == TOKnotidentity)
cmp ^= 1;
return new IntegerExp(loc, cmp, type);
@@ -1089,6 +1103,13 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
to->implicitConvTo(e1->type) >= MATCHconst)
return expType(to, e1);
// Allow covariant converions of delegates
// (Perhaps implicit conversion from pure to impure should be a MATCHconst,
// then we wouldn't need this extra check.)
if (e1->type->toBasetype()->ty == Tdelegate &&
e1->type->implicitConvTo(to) == MATCHconvert)
return expType(to, e1);
Type *tb = to->toBasetype();
Type *typeb = type->toBasetype();
@@ -1241,30 +1262,34 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
uinteger_t i = e2->toInteger();
if (i >= length)
{ e2->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
{ e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
}
else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
else if (e1->op == TOKarrayliteral)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
e = (Expression *)ale->elements->data[i];
e->type = type;
if (e->checkSideEffect(2))
e = EXP_CANT_INTERPRET;
}
}
else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64)
{
uinteger_t i = e2->toInteger();
if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
if (e1->op == TOKarrayliteral)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
if (i >= ale->elements->dim)
{ e2->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
{ e1->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
}
else
{ e = (Expression *)ale->elements->data[i];
e->type = type;
if (e->checkSideEffect(2))
e = EXP_CANT_INTERPRET;
}
}
}
else if (e1->op == TOKassocarrayliteral && !e1->checkSideEffect(2))
else if (e1->op == TOKassocarrayliteral)
{
AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1;
/* Search the keys backwards, in case there are duplicate keys
@@ -1279,6 +1304,8 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (ex->isBool(TRUE))
{ e = (Expression *)ae->values->data[i];
e->type = type;
if (e->checkSideEffect(2))
e = EXP_CANT_INTERPRET;
break;
}
}
@@ -1405,6 +1432,14 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
e->type = type;
return e;
}
else if (e1->op == TOKnull && e2->op == TOKnull)
{
if (type == e1->type)
return e1;
if (type == e2->type)
return e2;
return new NullExp(e1->loc, type);
}
else if (e1->op == TOKstring && e2->op == TOKstring)
{
// Concatenate the strings

View File

@@ -273,10 +273,8 @@ TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype,
this->type = new TypeTypedef(this);
this->basetype = basetype->toBasetype();
this->init = init;
#ifdef _DH
this->htype = NULL;
this->hbasetype = NULL;
#endif
this->loc = loc;
#if IN_DMD
this->sinit = NULL;
@@ -294,7 +292,7 @@ Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
assert(!s);
TypedefDeclaration *st;
st = new TypedefDeclaration(loc, ident, basetype, init);
#ifdef _DH
// Syntax copy for header file
if (!htype) // Don't overwrite original
{ if (type) // Make copy for both old and new instances
@@ -312,7 +310,7 @@ Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
}
else
st->hbasetype = hbasetype->syntaxCopy();
#endif
return st;
}
@@ -389,10 +387,8 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
this->loc = loc;
this->type = type;
this->aliassym = NULL;
#ifdef _DH
this->htype = NULL;
this->haliassym = NULL;
#endif
this->overnext = NULL;
this->inSemantic = 0;
this->importprot = PROTundefined;
@@ -407,10 +403,8 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
this->loc = loc;
this->type = NULL;
this->aliassym = s;
#ifdef _DH
this->htype = NULL;
this->haliassym = NULL;
#endif
this->overnext = NULL;
this->inSemantic = 0;
assert(s);
@@ -425,7 +419,7 @@ Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
else
sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
#ifdef _DH
// Syntax copy for header file
if (!htype) // Don't overwrite original
{ if (type) // Make copy for both old and new instances
@@ -443,7 +437,7 @@ Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
}
else
sa->haliassym = haliassym->syntaxCopy(s);
#endif
return sa;
}
@@ -631,7 +625,7 @@ Dsymbol *AliasDeclaration::toAlias()
void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("alias ");
#if 0 && _DH
#if 0
if (hgs->hdrgen)
{
if (haliassym)
@@ -678,10 +672,8 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
assert(type || init);
this->type = type;
this->init = init;
#ifdef _DH
this->htype = NULL;
this->hinit = NULL;
#endif
this->loc = loc;
offset = 0;
noscope = 0;
@@ -733,7 +725,7 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
sv->storage_class = storage_class;
}
#ifdef _DH
// Syntax copy for header file
if (!htype) // Don't overwrite original
{ if (type) // Make copy for both old and new instances
@@ -751,7 +743,7 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
}
else
sv->hinit = hinit->syntaxCopy();
#endif
return sv;
}
@@ -844,17 +836,33 @@ void VarDeclaration::semantic(Scope *sc)
//printf("storage_class = x%x\n", storage_class);
#if DMDV2
#if 1
if (storage_class & STCgshared && sc->func && sc->func->isSafe())
// Safety checks
if (sc->func && !sc->intypeof)
{
error("__gshared not allowed in safe functions; use shared");
if (storage_class & STCgshared)
{
if (sc->func->setUnsafe())
error("__gshared not allowed in safe functions; use shared");
}
if (init && init->isVoidInitializer() && type->hasPointers())
{
if (sc->func->setUnsafe())
error("void initializers for pointers not allowed in safe functions");
}
if (type->hasPointers() && type->toDsymbol(sc))
{
Dsymbol *s = type->toDsymbol(sc);
if (s)
{
AggregateDeclaration *ad = s->isAggregateDeclaration();
if (ad && ad->hasUnions)
{
if (sc->func->setUnsafe())
error("unions containing pointers are not allowed in @safe functions");
}
}
}
}
#else
if (storage_class & STCgshared && global.params.safe && !sc->module->safe)
{
error("__gshared not allowed in safe mode; use shared");
}
#endif
#endif
Dsymbol *parent = toParent();
@@ -1184,18 +1192,24 @@ Lagain:
ei->exp = resolveProperties(sc, ei->exp);
StructDeclaration *sd = ((TypeStruct *)t)->sym;
#if DMDV2
Expression** pinit = &ei->exp;
while ((*pinit)->op == TOKcomma)
{
pinit = &((CommaExp *)*pinit)->e2;
}
/* Look to see if initializer is a call to the constructor
*/
if (sd->ctor && // there are constructors
ei->exp->type->ty == Tstruct && // rvalue is the same struct
((TypeStruct *)ei->exp->type)->sym == sd &&
ei->exp->op == TOKcall)
(*pinit)->type->ty == Tstruct && // rvalue is the same struct
((TypeStruct *)(*pinit)->type)->sym == sd &&
(*pinit)->op == TOKcall)
{
/* Look for form of constructor call which is:
* *__ctmp.ctor(arguments...)
*/
if (1)
{ CallExp *ce = (CallExp *)ei->exp;
{ CallExp *ce = (CallExp *)(*pinit);
if (ce->e1->op == TOKdotvar)
{ DotVarExp *dve = (DotVarExp *)ce->e1;
if (dve->var->isCtorDeclaration())
@@ -1216,12 +1230,12 @@ Lagain:
e->op = TOKblit;
}
e->type = t;
ei->exp = new CommaExp(loc, e, ei->exp);
(*pinit) = new CommaExp(loc, e, (*pinit));
/* Replace __ctmp being constructed with e1
*/
dve->e1 = e1;
ei->exp = ei->exp->semantic(sc);
(*pinit) = (*pinit)->semantic(sc);
goto Ldtor;
}
}
@@ -1650,6 +1664,7 @@ int VarDeclaration::canTakeAddressOf()
return 1;
}
/*******************************
* Does symbol go into data segment?
* Includes extern variables.

View File

@@ -214,10 +214,8 @@ struct TypedefDeclaration : Declaration
const char *kind();
Type *getType();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#ifdef _DH
Type *htype;
Type *hbasetype;
#endif
void toDocBuffer(OutBuffer *buf);
@@ -258,10 +256,8 @@ struct AliasDeclaration : Declaration
Type *getType();
Dsymbol *toAlias();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#ifdef _DH
Type *htype;
Dsymbol *haliassym;
#endif
void toDocBuffer(OutBuffer *buf);
@@ -311,10 +307,8 @@ struct VarDeclaration : Declaration
void semantic2(Scope *sc);
const char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#ifdef _DH
Type *htype;
Initializer *hinit;
#endif
AggregateDeclaration *isThis();
int needThis();
int isImportedSymbol();
@@ -722,7 +716,6 @@ struct FuncDeclaration : Declaration
Loc endloc; // location of closing curly bracket
int vtblIndex; // for member functions, index into vtbl[]
int naked; // !=0 if naked
int inlineAsm; // !=0 if has inline assembler
ILS inlineStatus;
int inlineNest; // !=0 if nested inline
int cantInterpret; // !=0 if cannot interpret function
@@ -759,6 +752,11 @@ struct FuncDeclaration : Declaration
Dsymbols closureVars; // local variables in this function
// which are referenced by nested
// functions
unsigned flags;
#define FUNCFLAGpurityInprocess 1 // working on determining purity
#define FUNCFLAGsafetyInprocess 2 // working on determining safety
#define FUNCFLAGnothrowInprocess 4 // working on determining nothrow
#else
int nestedFrameRef; // !=0 if nested variables referenced
#endif
@@ -798,8 +796,10 @@ struct FuncDeclaration : Declaration
int isCodeseg();
int isOverloadable();
enum PURE isPure();
bool setImpure();
int isSafe();
int isTrusted();
bool setUnsafe();
virtual int isNested();
int needThis();
virtual int isVirtual();
@@ -857,6 +857,9 @@ struct FuncDeclaration : Declaration
// true if overridden with the pragma(allow_inline); stmt
bool allowInlining;
// true if has inline assembler
bool inlineAsm;
#endif
};
@@ -898,10 +901,8 @@ struct FuncLiteralDeclaration : FuncDeclaration
};
struct CtorDeclaration : FuncDeclaration
{ Parameters *arguments;
int varargs;
CtorDeclaration(Loc loc, Loc endloc, Parameters *arguments, int varargs, StorageClass stc);
{
CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -1068,9 +1069,7 @@ struct DeleteDeclaration : FuncDeclaration
int isVirtual();
int addPreInvariant();
int addPostInvariant();
#ifdef _DH
DeleteDeclaration *isDeleteDeclaration() { return this; }
#endif
};
#endif /* DMD_DECLARATION_H */

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -133,6 +133,7 @@ LINK = <a href=\"$0\">$0</a>\n\
LINK2 = <a href=\"$1\">$+</a>\n\
LPAREN= (\n\
RPAREN= )\n\
DOLLAR= $\n\
\n\
RED = <font color=red>$0</font>\n\
BLUE = <font color=blue>$0</font>\n\
@@ -374,6 +375,12 @@ void escapeDdocString(OutBuffer *buf, unsigned start)
unsigned char c = buf->data[u];
switch(c)
{
case '$':
buf->remove(u, 1);
buf->insert(u, "$(DOLLAR)", 9);
u += 8;
break;
case '(':
buf->remove(u, 1); //remove the (
buf->insert(u, "$(LPAREN)", 9); //insert this instead
@@ -792,29 +799,35 @@ void prefix(OutBuffer *buf, Dsymbol *s)
}
}
void Declaration::toDocBuffer(OutBuffer *buf)
void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclaration *td)
{
//printf("Declaration::toDocbuffer() %s, originalType = %p\n", toChars(), originalType);
if (ident)
//printf("declarationToDocBuffer() %s, originalType = %s, td = %s\n", decl->toChars(), decl->originalType ? decl->originalType->toChars() : "--", td ? td->toChars() : "--");
if (decl->ident)
{
prefix(buf, this);
prefix(buf, decl);
if (type)
if (decl->type)
{ HdrGenState hgs;
hgs.ddoc = 1;
if (originalType)
{ //originalType->print();
originalType->toCBuffer(buf, ident, &hgs);
Type *origType = decl->originalType ? decl->originalType : decl->type;
if (origType->ty == Tfunction)
{
TypeFunction *attrType = (TypeFunction*)(decl->ident == Id::ctor ? origType : decl->type);
((TypeFunction*)origType)->toCBufferWithAttributes(buf, decl->ident, &hgs, attrType, td);
}
else
type->toCBuffer(buf, ident, &hgs);
origType->toCBuffer(buf, decl->ident, &hgs);
}
else
buf->writestring(ident->toChars());
buf->writestring(decl->ident->toChars());
buf->writestring(";\n");
}
}
void Declaration::toDocBuffer(OutBuffer *buf)
{
declarationToDocBuffer(this, buf, NULL);
}
void AliasDeclaration::toDocBuffer(OutBuffer *buf)
{
@@ -859,31 +872,9 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
td->onemember == this)
{ /* It's a function template
*/
HdrGenState hgs;
unsigned o = buf->offset;
TypeFunction *tf = (TypeFunction *)type;
hgs.ddoc = 1;
prefix(buf, td);
if (tf)
{ if (tf->nextOf())
tf->nextOf()->toCBuffer(buf, NULL, &hgs);
else
buf->writestring("auto");
}
buf->writeByte(' ');
buf->writestring(ident->toChars());
buf->writeByte('(');
for (int i = 0; i < td->origParameters->dim; i++)
{
TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
if (i)
buf->writestring(", ");
tp->toCBuffer(buf, &hgs);
}
buf->writeByte(')');
Parameter::argsToCBuffer(buf, &hgs, tf ? tf->parameters : NULL, tf ? tf->varargs : 0);
buf->writestring(";\n");
declarationToDocBuffer(this, buf, td);
highlightCode(NULL, this, buf, o);
}
@@ -894,6 +885,17 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
}
}
#if DMDV1
void CtorDeclaration::toDocBuffer(OutBuffer *buf)
{
HdrGenState hgs;
buf->writestring("this");
Parameter::argsToCBuffer(buf, &hgs, arguments, varargs);
buf->writestring(";\n");
}
#endif
void AggregateDeclaration::toDocBuffer(OutBuffer *buf)
{
if (ident)

View File

@@ -218,10 +218,13 @@ char *Dsymbol::locToChars()
OutBuffer buf;
char *p;
Module *m = getModule();
if (!loc.filename) // avoid bug 5861.
{
Module *m = getModule();
if (m && m->srcfile)
loc.filename = m->srcfile->toChars();
if (m && m->srcfile)
loc.filename = m->srcfile->toChars();
}
return loc.toChars();
}

View File

@@ -178,10 +178,8 @@ struct Dsymbol : Object
Dsymbol *search_correct(Identifier *id);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
virtual int overloadInsert(Dsymbol *s);
#ifdef _DH
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
#endif
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual void toJsonBuffer(OutBuffer *buf);
@@ -262,9 +260,7 @@ struct Dsymbol : Object
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
virtual Import *isImport() { return NULL; }
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
#ifdef _DH
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
#endif
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }

View File

@@ -21,9 +21,7 @@
struct Identifier;
struct Type;
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct EnumDeclaration : ScopeDsymbol

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@
#include "identifier.h"
#include "lexer.h"
#include "arraytypes.h"
#include "intrange.h"
struct Type;
struct Scope;
@@ -79,7 +80,7 @@ void initPrecedence();
Expression *resolveProperties(Scope *sc, Expression *e);
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d);
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id, Objects *targsi = NULL);
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d);
Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid);
void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr, Module *from);
void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
@@ -88,6 +89,7 @@ void expandTuples(Expressions *exps);
FuncDeclaration *hasThis(Scope *sc);
Expression *fromConstInitializer(int result, Expression *e);
int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
void valueNoDtor(Expression *e);
/* Interpreter: what form of return value expression is required?
*/
@@ -95,14 +97,10 @@ enum CtfeGoal
{ ctfeNeedRvalue, // Must return an Rvalue
ctfeNeedLvalue, // Must return an Lvalue
ctfeNeedAnyValue, // Can return either an Rvalue or an Lvalue
ctfeNeedLvalueRef,// Must return a reference to an Lvalue (for ref types)
ctfeNeedNothing // The return value is not required
};
struct IntRange
{ uinteger_t imin;
uinteger_t imax;
};
struct Expression : Object
{
Loc loc; // file location
@@ -152,6 +150,7 @@ struct Expression : Object
Expression *checkArithmetic();
void checkDeprecated(Scope *sc, Dsymbol *s);
void checkPurity(Scope *sc, FuncDeclaration *f);
void checkPurity(Scope *sc, VarDeclaration *v, Expression *e1);
void checkSafety(Scope *sc, FuncDeclaration *f);
virtual Expression *checkToBoolean(Scope *sc);
virtual Expression *addDtorHook(Scope *sc);
@@ -301,9 +300,7 @@ struct ComplexExp : Expression
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
#ifdef _DH
OutBuffer hexp;
#endif
#if IN_DMD
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
@@ -1161,11 +1158,10 @@ struct AddrExp : UnaExp
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
Expression *interpret(InterState *istate, CtfeGoal goal);
#endif
};
@@ -1202,6 +1198,7 @@ struct NegExp : UnaExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1232,6 +1229,7 @@ struct ComExp : UnaExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1352,6 +1350,7 @@ struct SliceExp : UnaExp
void scanForNestedRef(Scope *sc);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
int canThrow(bool mustNotThrow);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
@@ -1579,6 +1578,7 @@ struct AddExp : BinExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
int isCommutative();
@@ -1603,6 +1603,7 @@ struct MinExp : BinExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1646,6 +1647,7 @@ struct MulExp : BinExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
int isCommutative();
@@ -1692,6 +1694,7 @@ struct ModExp : BinExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1917,6 +1920,7 @@ struct InExp : BinExp
{
InExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
// For operator overloading

View File

@@ -64,7 +64,6 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
naked = 0;
inlineStatus = ILSuninitialized;
inlineNest = 0;
inlineAsm = 0;
cantInterpret = 0;
isArrayOp = 0;
semanticRun = PASSinit;
@@ -87,13 +86,14 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
#if DMDV2
builtin = BUILTINunknown;
tookAddressOf = 0;
flags = 0;
#endif
#if IN_LLVM
// LDC
isArrayOp = false;
allowInlining = false;
availableExternally = true; // assume this unless proven otherwise
inlineAsm = true;
// function types in ldc don't merge if the context parameter differs
// so we actually don't care about the function declaration, but only
@@ -201,7 +201,7 @@ void FuncDeclaration::semantic(Scope *sc)
{
sc = sc->push();
sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCdisable
| STCsafe | STCtrusted | STCsystem); // forward to function type
| STCsafe | STCtrusted | STCsystem | STCproperty); // forward to function type
if (isCtorDeclaration())
sc->flags |= SCOPEctor;
@@ -282,16 +282,31 @@ void FuncDeclaration::semantic(Scope *sc)
linkage = sc->linkage;
protection = sc->protection;
/* Purity and safety can be inferred for some functions by examining
* the function body.
*/
if (fbody &&
(isFuncLiteralDeclaration() || parent->isTemplateInstance()))
{
if (f->purity == PUREimpure && // purity not specified
!f->hasLazyParameters()
)
{
flags |= FUNCFLAGpurityInprocess;
}
if (f->trust == TRUSTdefault)
flags |= FUNCFLAGsafetyInprocess;
if (!f->isnothrow)
flags |= FUNCFLAGnothrowInprocess;
}
if (storage_class & STCscope)
error("functions cannot be scope");
if (isAbstract() && !isVirtual())
error("non-virtual functions cannot be abstract");
// https://github.com/donc/dmd/commit/9f7b2f8cfe5d7482f2de7f9678c176d54abe237f#commitcomment-321724
//if (isOverride() && !isVirtual())
//error("cannot override a non-virtual function");
if ((f->isConst() || f->isImmutable()) && !isThis())
error("without 'this' cannot be const/immutable");
@@ -862,6 +877,20 @@ void FuncDeclaration::semantic3(Scope *sc)
}
#endif
if (frequire)
{
for (int i = 0; i < foverrides.dim; i++)
{
FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
if (fdv->fbody && !fdv->frequire)
{
error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars());
break;
}
}
}
frequire = mergeFrequire(frequire);
fensure = mergeFensure(fensure);
@@ -1393,7 +1422,11 @@ void FuncDeclaration::semantic3(Scope *sc)
}
else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
error("has no return statement, but is expected to return a value of type %s", type->nextOf()->toChars());
else if (!inlineAsm)
else if (hasReturnExp & 8) // if inline asm
{
flags &= ~FUNCFLAGnothrowInprocess;
}
else
{
#if DMDV2
// Check for errors related to 'nothrow'.
@@ -1401,6 +1434,12 @@ void FuncDeclaration::semantic3(Scope *sc)
int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru;
if (f->isnothrow && (global.errors != nothrowErrors) )
error("'%s' is nothrow yet may throw", toChars());
if (flags & FUNCFLAGnothrowInprocess)
{
flags &= ~FUNCFLAGnothrowInprocess;
if (!(blockexit & BEthrow))
f->isnothrow = TRUE;
}
int offend = blockexit & BEfallthru;
#endif
@@ -1545,15 +1584,10 @@ void FuncDeclaration::semantic3(Scope *sc)
// Merge contracts together with body into one compound statement
#ifdef _DH
if (frequire && global.params.useIn)
{ frequire->incontract = 1;
a->push(frequire);
}
#else
if (frequire && global.params.useIn)
a->push(frequire);
#endif
// Precondition invariant
if (addPreInvariant())
@@ -1775,6 +1809,20 @@ void FuncDeclaration::semantic3(Scope *sc)
sc2->pop();
}
/* If function survived being marked as impure, then it is pure
*/
if (flags & FUNCFLAGpurityInprocess)
{
flags &= ~FUNCFLAGpurityInprocess;
f->purity = PUREfwdref;
}
if (flags & FUNCFLAGsafetyInprocess)
{
flags &= ~FUNCFLAGsafetyInprocess;
f->trust = TRUSTsafe;
}
if (global.gag && global.errors != nerrors)
semanticRun = PASSsemanticdone; // Ensure errors get reported again
else
@@ -1893,7 +1941,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf)
}
sf = fdv->mergeFrequire(sf);
if (fdv->fdrequire)
if (sf && fdv->fdrequire)
{
//printf("fdv->frequire: %s\n", fdv->frequire->toChars());
/* Make the call:
@@ -1904,15 +1952,13 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf)
Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire, 0), eresult);
Statement *s2 = new ExpStatement(loc, e);
if (sf)
{ Catch *c = new Catch(loc, NULL, NULL, sf);
Array *catches = new Array();
catches->push(c);
sf = new TryCatchStatement(loc, s2, catches);
}
else
sf = s2;
Catch *c = new Catch(loc, NULL, NULL, sf);
Array *catches = new Array();
catches->push(c);
sf = new TryCatchStatement(loc, s2, catches);
}
else
return NULL;
}
return sf;
}
@@ -2786,9 +2832,11 @@ enum PURE FuncDeclaration::isPure()
//printf("FuncDeclaration::isPure() '%s'\n", toChars());
assert(type->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)type;
enum PURE purity = tf->purity;
if (purity == PUREfwdref)
if (flags & FUNCFLAGpurityInprocess)
setImpure();
if (tf->purity == PUREfwdref)
tf->purityLevel();
enum PURE purity = tf->purity;
if (purity > PUREweak && needThis())
{ // The attribute of the 'this' reference affects purity strength
if (type->mod & (MODimmutable | MODwild))
@@ -2798,21 +2846,61 @@ enum PURE FuncDeclaration::isPure()
else
purity = PUREweak;
}
tf->purity = purity;
// ^ This rely on the current situation that every FuncDeclaration has a
// unique TypeFunction.
return purity;
}
/**************************************
* The function is doing something impure,
* so mark it as impure.
* If there's a purity error, return TRUE.
*/
bool FuncDeclaration::setImpure()
{
if (flags & FUNCFLAGpurityInprocess)
{
flags &= ~FUNCFLAGpurityInprocess;
}
else if (isPure())
return TRUE;
return FALSE;
}
int FuncDeclaration::isSafe()
{
assert(type->ty == Tfunction);
if (flags & FUNCFLAGsafetyInprocess)
setUnsafe();
return ((TypeFunction *)type)->trust == TRUSTsafe;
}
int FuncDeclaration::isTrusted()
{
assert(type->ty == Tfunction);
if (flags & FUNCFLAGsafetyInprocess)
setUnsafe();
return ((TypeFunction *)type)->trust == TRUSTtrusted;
}
/**************************************
* The function is doing something unsave,
* so mark it as unsafe.
* If there's a safe error, return TRUE.
*/
bool FuncDeclaration::setUnsafe()
{
if (flags & FUNCFLAGsafetyInprocess)
{
flags &= ~FUNCFLAGsafetyInprocess;
((TypeFunction *)type)->trust = TRUSTsystem;
}
else if (isSafe())
return TRUE;
return FALSE;
}
// Determine if function needs
// a static frame pointer to its lexically enclosing function
@@ -2924,6 +3012,8 @@ int FuncDeclaration::needsClosure()
* 1) is a virtual function
* 2) has its address taken
* 3) has a parent that escapes
* -or-
* 4) this function returns a local struct/class
*
* Note that since a non-virtual function can be called by
* a virtual one, if that non-virtual function accesses a closure
@@ -2954,6 +3044,25 @@ int FuncDeclaration::needsClosure()
}
}
}
/* Look for case (4)
*/
if (closureVars.dim)
{
assert(type->ty == Tfunction);
Type *tret = ((TypeFunction *)type)->next;
assert(tret);
tret = tret->toBasetype();
if (tret->ty == Tclass || tret->ty == Tstruct)
{ Dsymbol *st = tret->toDsymbol(NULL);
for (Dsymbol *s = st->parent; s; s = s->parent)
{
if (s == this)
goto Lyes;
}
}
}
return 0;
Lyes:
@@ -2978,12 +3087,6 @@ Parameters *FuncDeclaration::getParameters(int *pvarargs)
fparameters = fdtype->parameters;
fvarargs = fdtype->varargs;
}
else // Constructors don't have type's
{ CtorDeclaration *fctor = isCtorDeclaration();
assert(fctor);
fparameters = fctor->arguments;
fvarargs = fctor->varargs;
}
if (pvarargs)
*pvarargs = fvarargs;
return fparameters;
@@ -3074,17 +3177,15 @@ void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
/********************************* CtorDeclaration ****************************/
CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, Parameters *arguments, int varargs, StorageClass stc)
: FuncDeclaration(loc, endloc, Id::ctor, stc, NULL)
CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type)
: FuncDeclaration(loc, endloc, Id::ctor, stc, type)
{
this->arguments = arguments;
this->varargs = varargs;
//printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
}
Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
{
CtorDeclaration *f = new CtorDeclaration(loc, endloc, NULL, varargs, storage_class);
CtorDeclaration *f = new CtorDeclaration(loc, endloc, storage_class, type->syntaxCopy());
f->outId = outId;
f->frequire = frequire ? frequire->syntaxCopy() : NULL;
@@ -3092,7 +3193,6 @@ Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
f->fbody = fbody ? fbody->syntaxCopy() : NULL;
assert(!fthrows); // deprecated
f->arguments = Parameter::arraySyntaxCopy(arguments);
return f;
}
@@ -3100,6 +3200,10 @@ Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
void CtorDeclaration::semantic(Scope *sc)
{
//printf("CtorDeclaration::semantic() %s\n", toChars());
TypeFunction *tf = (TypeFunction *)type;
assert(tf && tf->ty == Tfunction);
Expressions *fargs = ((TypeFunction *)type)->fargs; // for auto ref
sc = sc->push();
sc->stc &= ~STCstatic; // not a static constructor
@@ -3118,15 +3222,16 @@ void CtorDeclaration::semantic(Scope *sc)
assert(tret);
tret = tret->addStorageClass(storage_class | sc->stc);
}
if (!type)
type = new TypeFunction(arguments, tret, varargs, LINKd, storage_class | sc->stc);
tf = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc);
tf->fargs = fargs;
type = tf;
#if STRUCTTHISREF
if (ad && ad->isStructDeclaration())
{ ((TypeFunction *)type)->isref = 1;
if (!originalType)
// Leave off the "ref"
originalType = new TypeFunction(arguments, tret, varargs, LINKd, storage_class | sc->stc);
originalType = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc);
}
#endif
if (!originalType)
@@ -3149,7 +3254,7 @@ void CtorDeclaration::semantic(Scope *sc)
sc->pop();
// See if it's the default constructor
if (ad && varargs == 0 && Parameter::dim(arguments) == 0)
if (ad && tf->varargs == 0 && Parameter::dim(tf->parameters) == 0)
{ if (ad->isStructDeclaration())
error("default constructor not allowed for structs");
else
@@ -3185,10 +3290,13 @@ int CtorDeclaration::addPostInvariant()
void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
TypeFunction *tf = (TypeFunction *)type;
assert(tf && tf->ty == Tfunction);
if (originalType && originalType->ty == Tfunction)
((TypeFunction *)originalType)->attributesToCBuffer(buf, 0);
buf->writestring("this");
Parameter::argsToCBuffer(buf, hgs, arguments, varargs);
Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
bodyToCBuffer(buf, hgs);
}

View File

@@ -10,8 +10,6 @@
// Routines to emit header files
#ifdef _DH
#define PRETTY_PRINT
#define TEST_EMIT_ALL 0 // For Testing
@@ -100,5 +98,3 @@ void Dsymbol::toHBuffer(OutBuffer *buf, HdrGenState *hgs)
/*************************************/
#endif // #ifdef _DH

View File

@@ -36,9 +36,7 @@ struct Identifier : Object
int compare(Object *o);
void print();
char *toChars();
#ifdef _DH
char *toHChars();
#endif
const char *toHChars2();
int dyncast();

View File

@@ -23,7 +23,6 @@ int integral_promotion(int t)
{
case Tchar:
case Twchar:
//case Tbit:
case Tbool:
case Tint8:
case Tuns8:
@@ -51,29 +50,6 @@ void init()
impcnvType1[t1][t2] = nt1; \
impcnvType2[t1][t2] = nt2;
/* ======================= */
#if 0
X(Tbit,Tbit, Tint32,Tint32, Tint32)
X(Tbit,Tint8, Tint32,Tint32, Tint32)
X(Tbit,Tuns8, Tint32,Tint32, Tint32)
X(Tbit,Tint16, Tint32,Tint32, Tint32)
X(Tbit,Tuns16, Tint32,Tint32, Tint32)
X(Tbit,Tint32, Tint32,Tint32, Tint32)
X(Tbit,Tuns32, Tuns32,Tuns32, Tuns32)
X(Tbit,Tint64, Tint64,Tint64, Tint64)
X(Tbit,Tuns64, Tuns64,Tuns64, Tuns64)
X(Tbit,Tfloat32, Tfloat32,Tfloat32, Tfloat32)
X(Tbit,Tfloat64, Tfloat64,Tfloat64, Tfloat64)
X(Tbit,Tfloat80, Tfloat80,Tfloat80, Tfloat80)
X(Tbit,Timaginary32, Tfloat32,Timaginary32, Tfloat32)
X(Tbit,Timaginary64, Tfloat64,Timaginary64, Tfloat64)
X(Tbit,Timaginary80, Tfloat80,Timaginary80, Tfloat80)
X(Tbit,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32)
X(Tbit,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64)
X(Tbit,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80)
#endif
/* ======================= */
@@ -322,17 +298,6 @@ void init()
#define Y(t1,t2) impcnvWarn[t1][t2] = 1;
#if 0
Y(Tint8, Tbit)
Y(Tuns8, Tbit)
Y(Tint16, Tbit)
Y(Tuns16, Tbit)
Y(Tint32, Tbit)
Y(Tuns32, Tbit)
Y(Tint64, Tbit)
Y(Tuns64, Tbit)
#endif
Y(Tuns8, Tint8)
Y(Tint16, Tint8)
Y(Tuns16, Tint8)

View File

@@ -35,9 +35,6 @@ Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
this->id = id;
this->aliasId = aliasId;
this->isstatic = isstatic;
#if IN_LLVM
protection = PROTundefined;
#endif
pkg = NULL;
mod = NULL;
@@ -65,12 +62,6 @@ const char *Import::kind()
return isstatic ? (char *)"static import" : (char *)"import";
}
#if IN_LLVM
enum PROT Import::prot()
{
return protection;
}
#endif
Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
@@ -207,14 +198,13 @@ void Import::semantic(Scope *sc)
sc = sc->push(mod);
for (size_t i = 0; i < aliasdecls.dim; i++)
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
{ Dsymbol *s = (Dsymbol *)aliasdecls.data[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, (Identifier *)names.data[i], 0))
error("%s not found", ((Identifier *)names.data[i])->toChars());
ad->importprot = protection;
ad->semantic(sc);
s->semantic(sc);
}
sc = sc->pop();
}
@@ -288,7 +278,7 @@ void Import::semantic(Scope *sc)
ob->writenl();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic2(Scope *sc)

View File

@@ -24,9 +24,7 @@ struct OutBuffer;
struct Module;
struct Package;
struct AliasDeclaration;
#ifdef _DH
struct HdrGenState;
#endif
struct Import : Dsymbol
{
@@ -34,9 +32,6 @@ struct Import : Dsymbol
Identifier *id; // module Identifier
Identifier *aliasId;
int isstatic; // !=0 if static import
#if IN_LLVM
enum PROT protection;
#endif
// Pairs of alias=name to bind into current namespace
Array names;
@@ -52,9 +47,6 @@ struct Import : Dsymbol
void addAlias(Identifier *name, Identifier *alias);
const char *kind();
#if IN_LLVM
enum PROT prot();
#endif
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
void load(Scope *sc);
void importAll(Scope *sc);

View File

@@ -1,6 +1,6 @@
/*
* Some portions copyright (c) 1994-1995 by Symantec
* Copyright (c) 1999-2009 by Digital Mars
* Copyright (c) 1999-2011 by Digital Mars
* All Rights Reserved
* http://www.digitalmars.com
* Written by Walter Bright
@@ -22,7 +22,7 @@
#if __APPLE__
#include <sys/syslimits.h>
#endif
#if __FreeBSD__ || __sun&&__SVR4
#if __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
// for PATH_MAX
#include <limits.h>
#endif
@@ -110,12 +110,12 @@ const char *inifile(const char *argv0x, const char *inifilex)
filename = (char *)FileName::replaceName(argv0, inifile);
if (!FileName::exists(filename))
{
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
#if __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 // This fix by Thomas Kuehne
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#if __GLIBC__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 // This fix by Thomas Kuehne
/* argv0 might be a symbolic link,
* so try again looking past it to the real path
*/
#if __APPLE__ || __FreeBSD__ || __sun&&__SVR4
#if __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
char resolved_name[PATH_MAX + 1];
char* real_argv0 = realpath(argv0, resolved_name);
#else

View File

@@ -726,6 +726,61 @@ Initializer *ExpInitializer::syntaxCopy()
return new ExpInitializer(loc, exp->syntaxCopy());
}
bool arrayHasNonConstPointers(Expressions *elems);
bool hasNonConstPointers(Expression *e)
{
if (e->op == TOKnull)
return false;
if (e->op == TOKstructliteral)
{
StructLiteralExp *se = (StructLiteralExp *)e;
return arrayHasNonConstPointers(se->elements);
}
if (e->op == TOKarrayliteral)
{
if (!e->type->nextOf()->hasPointers())
return false;
ArrayLiteralExp *ae = (ArrayLiteralExp *)e;
return arrayHasNonConstPointers(ae->elements);
}
if (e->op == TOKassocarrayliteral)
{
AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e;
if (ae->type->nextOf()->hasPointers() &&
arrayHasNonConstPointers(ae->values))
return true;
if (((TypeAArray *)ae->type)->index->hasPointers())
return arrayHasNonConstPointers(ae->keys);
return false;
}
if (e->type->ty== Tpointer && e->type->nextOf()->ty != Tfunction)
{
if (e->op == TOKsymoff) // address of a global is OK
return false;
if (e->op == TOKint64) // cast(void *)int is OK
return false;
if (e->op == TOKstring) // "abc".ptr is OK
return false;
return true;
}
return false;
}
bool arrayHasNonConstPointers(Expressions *elems)
{
for (size_t i = 0; i < elems->dim; i++)
{
if (!(Expression *)elems->data[i])
continue;
if (hasNonConstPointers((Expression *)elems->data[i]))
return true;
}
return false;
}
Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
{
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
@@ -737,6 +792,14 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
exp = exp->optimize(wantOptimize);
if (!global.gag && olderrors != global.errors)
return this; // Failed, suppress duplicate error messages
// Make sure all pointers are constants
if (needInterpret && hasNonConstPointers(exp))
{
exp->error("cannot use non-constant CTFE pointer in an initializer '%s'", exp->toChars());
return this;
}
Type *tb = t->toBasetype();
/* Look for case of initializing a static array with a too-short

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -26,9 +26,8 @@ struct VoidInitializer;
struct StructInitializer;
struct ArrayInitializer;
struct ExpInitializer;
#ifdef _DH
struct HdrGenState;
#endif
struct Initializer : Object
{

View File

@@ -134,6 +134,11 @@ int ReturnStatement::inlineCost(InlineCostState *ics)
return exp ? exp->inlineCost(ics) : 0;
}
int ImportStatement::inlineCost(InlineCostState *ics)
{
return 0;
}
/* -------------------------- */
int arrayInlineCost(InlineCostState *ics, Array *arguments)
@@ -464,6 +469,11 @@ Expression *ReturnStatement::doInline(InlineDoState *ids)
return exp ? exp->doInline(ids) : 0;
}
Expression *ImportStatement::doInline(InlineDoState *ids)
{
return NULL;
}
/* --------------------------------------------------------------- */
/******************************
@@ -1345,12 +1355,6 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
}
#if !IN_LLVM
// LDC: Only extern(C) varargs count, and ctors use extern(D).
else
{ CtorDeclaration *ctor = isCtorDeclaration();
if (ctor && ctor->varargs == 1)
goto Lno;
}
#endif
if (

File diff suppressed because it is too large Load Diff

1105
dmd2/intrange.c Normal file

File diff suppressed because it is too large Load Diff

149
dmd2/intrange.h Normal file
View File

@@ -0,0 +1,149 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by KennyTM
// 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.
#ifndef DMD_SXNUM_H
#define DMD_SXNUM_H
#include "mars.h" // for uinteger_t
struct Type;
struct Expression;
/**
This class represents a "sign-extended number", i.e. a 65-bit number, which can
represent all built-in integer types in D. This class is mainly used for
performing value-range propagation only, therefore all arithmetic are done with
saturation, not wrapping as usual.
*/
struct SignExtendedNumber
{
/// The lower 64-bit of the number.
uinteger_t value;
/// The sign (i.e. the most significant bit) of the number.
bool negative;
/// Create an uninitialized sign-extended number.
SignExtendedNumber() {}
/// Create a sign-extended number from an unsigned 64-bit number.
SignExtendedNumber(uinteger_t value_)
: value(value_), negative(false) {}
/// Create a sign-extended number from the lower 64-bit and the sign bit.
SignExtendedNumber(uinteger_t value_, bool negative_)
: value(value_), negative(negative_) {}
/// Create a sign-extended number from a signed 64-bit number.
static SignExtendedNumber fromInteger(uinteger_t value_);
/// Get the minimum or maximum value of a sign-extended number.
static SignExtendedNumber extreme(bool minimum);
static SignExtendedNumber max();
static SignExtendedNumber min() { return SignExtendedNumber(0, true); }
/// Check if the sign-extended number is minimum or zero.
bool isMinimum() const { return negative && value == 0; }
/// Compare two sign-extended number.
bool operator==(const SignExtendedNumber&) const;
bool operator!=(const SignExtendedNumber& a) const { return !(*this == a); }
bool operator<(const SignExtendedNumber&) const;
bool operator>(const SignExtendedNumber& a) const { return a < *this; }
bool operator<=(const SignExtendedNumber& a) const { return !(a < *this); }
bool operator>=(const SignExtendedNumber& a) const { return !(*this < a); }
/// Compute the saturated negation of a sign-extended number.
SignExtendedNumber operator-() const;
/// Compute the saturated sum of two sign-extended number.
SignExtendedNumber operator+(const SignExtendedNumber&) const;
/// Compute the saturated difference of two sign-extended number.
SignExtendedNumber operator-(const SignExtendedNumber& a) const;
/// Compute the saturated product of two sign-extended number.
SignExtendedNumber operator*(const SignExtendedNumber&) const;
/// Compute the saturated quotient of two sign-extended number.
SignExtendedNumber operator/(const SignExtendedNumber&) const;
/// Compute the saturated modulus of two sign-extended number.
SignExtendedNumber operator%(const SignExtendedNumber&) const;
/// Increase the sign-extended number by 1 (saturated).
SignExtendedNumber& operator++();
/// Compute the saturated shifts of two sign-extended number.
SignExtendedNumber operator<<(const SignExtendedNumber&) const;
SignExtendedNumber operator>>(const SignExtendedNumber&) const;
};
/**
This class represents a range of integers, denoted by its lower and upper bounds
(inclusive).
*/
struct IntRange
{
SignExtendedNumber imin, imax;
/// Create an uninitialized range.
IntRange() {}
/// Create a range consisting of a single number.
IntRange(const SignExtendedNumber& a)
: imin(a), imax(a) {}
/// Create a range with the lower and upper bounds.
IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper)
: imin(lower), imax(upper) {}
/// Create the tightest range containing all valid integers in the specified
/// type.
static IntRange fromType(Type *type);
/// Create the tightest range containing all valid integers in the type with
/// a forced signedness.
static IntRange fromType(Type *type, bool isUnsigned);
/// Create the tightest range containing all specified numbers.
static IntRange fromNumbers2(const SignExtendedNumber numbers[2]);
static IntRange fromNumbers4(const SignExtendedNumber numbers[4]);
/// Create the widest range possible.
static IntRange widest();
/// Cast the integer range to a signed type with the given size mask.
IntRange& castSigned(uinteger_t mask);
/// Cast the integer range to an unsigned type with the given size mask.
IntRange& castUnsigned(uinteger_t mask);
/// Cast the integer range to the dchar type.
IntRange& castDchar();
/// Cast the integer range to a specific type.
IntRange& cast(Type *type);
/// Cast the integer range to a specific type, forcing it to be unsigned.
IntRange& castUnsigned(Type *type);
/// Check if this range contains another range.
bool contains(const IntRange& a) const;
/// Check if this range contains 0.
bool containsZero() const;
/// Compute the range of the negated absolute values of the original range.
IntRange absNeg() const;
/// Compute the union of two ranges.
IntRange unionWith(const IntRange& other) const;
void unionOrAssign(const IntRange& other, bool& union_);
/// Dump the content of the integer range to the console.
const IntRange& dump(const char* funcName, Expression *e) const;
/// Split the range into two nonnegative- and negative-only subintervals.
void splitBySign(IntRange& negRange, bool& hasNegRange,
IntRange& nonNegRange, bool& hasNonNegRange) const;
};
#endif

View File

@@ -211,7 +211,6 @@ enum TOK
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
case TOKbit: t = Type::tbit; goto LabelX; \
case TOKbool: t = Type::tbool; goto LabelX; \
case TOKchar: t = Type::tchar; goto LabelX; \
case TOKwchar: t = Type::twchar; goto LabelX; \

View File

@@ -24,7 +24,7 @@
#include "id.h"
#include "module.h"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
char *cpp_mangle(Dsymbol *s);
#endif

View File

@@ -77,7 +77,7 @@ Global::Global()
#else
#if TARGET_WINDOS
obj_ext = "obj";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
obj_ext = "o";
#elif TARGET_NET
#else
@@ -86,7 +86,7 @@ Global::Global()
#if TARGET_WINDOS
lib_ext = "lib";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
lib_ext = "a";
#elif TARGET_NET
#else
@@ -100,7 +100,7 @@ Global::Global()
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.053";
version = "v2.054";
#if IN_LLVM
ldc_version = "LDC trunk";
llvm_version = "LLVM 2.9";
@@ -182,7 +182,7 @@ void verror(Loc loc, const char *format, va_list ap)
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
halt();
//halt();
}
global.errors++;
}
@@ -238,8 +238,8 @@ void halt()
#endif
}
extern signed char tyalignsize[];
/***********************************
* Parse and append contents of environment variable envvar
* to argc and argv[].

View File

@@ -37,6 +37,7 @@ Macros defined by the compiler, not the code:
linux Linux
__APPLE__ Mac OSX
__FreeBSD__ FreeBSD
__OpenBSD__ OpenBSD
__sun&&__SVR4 Solaris, OpenSolaris (yes, both macros are necessary)
For the target systems, there are the target operating system and
@@ -47,6 +48,7 @@ the target object file format:
TARGET_LINUX Covers 32 and 64 bit linux
TARGET_OSX Covers 32 and 64 bit Mac OSX
TARGET_FREEBSD Covers 32 and 64 bit FreeBSD
TARGET_OPENBSD Covers 32 and 64 bit OpenBSD
TARGET_SOLARIS Covers 32 and 64 bit Solaris
TARGET_NET Covers .Net
@@ -55,7 +57,7 @@ the target object file format:
Target object module format:
OMFOBJ Intel Object Module Format, used on Windows
ELFOBJ Elf Object Module Format, used on linux, FreeBSD and Solaris
ELFOBJ Elf Object Module Format, used on linux, FreeBSD, OpenBSD and Solaris
MACHOBJ Mach-O Object Module Format, used on Mac OSX
There are currently no macros for byte endianness order.
@@ -103,9 +105,9 @@ void unittests();
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
// Set if C++ mangling is done by the front end
#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS))
#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS))
/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and
/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD, TARGET_OPENBSD and
* TARGET_SOLARIS, which are
* set on the command line via the compiler makefile.
*/
@@ -115,7 +117,7 @@ void unittests();
#define OMFOBJ 1
#endif
#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
#ifndef ELFOBJ
#define ELFOBJ 1
#endif
@@ -192,6 +194,7 @@ struct Param
bool useInline; // inline expand functions
bool warnings; // enable warnings
ubyte Dversion; // D version number
char enforcePropertySyntax;
char *argv0; // program name
Array *imppath; // array of char*'s of where to look for import modules

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -544,7 +544,7 @@ void Module::read(Loc loc)
inline unsigned readwordLE(unsigned short *p)
{
#if __I86__
#if LITTLE_ENDIAN
return *p;
#else
return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0];
@@ -558,7 +558,7 @@ inline unsigned readwordBE(unsigned short *p)
inline unsigned readlongLE(unsigned *p)
{
#if __I86__
#if LITTLE_ENDIAN
return *p;
#else
return ((unsigned char *)p)[0] |

View File

@@ -154,9 +154,7 @@ struct Module : Package
#if !IN_LLVM
void setHdrfile(); // set hdrfile member
#endif
#ifdef _DH
void genhdrfile(); // generate D import file
#endif
// void gensymfile();
void gendocfile();
int needModuleInfo();

View File

@@ -52,7 +52,6 @@
#include "import.h"
#include "aggregate.h"
#include "hdrgen.h"
#include "doc.h"
#if IN_LLVM
//#include "gen/tollvm.h"
@@ -83,7 +82,7 @@ int PTRSIZE = 4;
int REALSIZE = 16;
int REALPAD = 6;
int REALALIGNSIZE = 16;
#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
int REALSIZE = 12;
int REALPAD = 2;
int REALALIGNSIZE = 4;
@@ -264,7 +263,6 @@ void Type::init()
mangleChar[Tdchar] = 'w';
// '@' shouldn't appear anywhere in the deco'd names
mangleChar[Tbit] = '@';
mangleChar[Tinstance] = '@';
mangleChar[Terror] = '@';
mangleChar[Ttypeof] = '@';
@@ -313,7 +311,7 @@ void Type::init()
#if TARGET_OSX
REALSIZE = 16;
REALPAD = 6;
#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
REALSIZE = 12;
REALPAD = 2;
#else
@@ -1244,6 +1242,8 @@ Type *Type::toHeadMutable()
Type *Type::pointerTo()
{
if (ty == Terror)
return this;
if (!pto)
{ Type *t;
@@ -1255,6 +1255,8 @@ Type *Type::pointerTo()
Type *Type::referenceTo()
{
if (ty == Terror)
return this;
if (!rto)
{ Type *t;
@@ -1266,6 +1268,8 @@ Type *Type::referenceTo()
Type *Type::arrayOf()
{
if (ty == Terror)
return this;
if (!arrayof)
{ Type *t;
@@ -1764,6 +1768,8 @@ Expression *Type::getProperty(Loc loc, Identifier *ident)
{
if (ty == Tvoid)
error(loc, "void does not have an initializer");
if (ty == Tfunction)
error(loc, "function does not have an initializer");
e = defaultInitLiteral(loc);
}
else if (ident == Id::mangleof)
@@ -1928,7 +1934,7 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident)
{ /* Rewrite e.ident as:
* e.opDot().ident
*/
e = build_overload(e->loc, sc, e, NULL, fd->ident);
e = build_overload(e->loc, sc, e, NULL, fd);
e = new DotIdExp(e->loc, e, ident);
return e->semantic(sc);
}
@@ -2562,7 +2568,7 @@ unsigned TypeBasic::alignsize()
if (ty == Tvoid)
return 1;
return GetTypeAlignment(sir, this);
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
case Tint64:
case Tuns64:
sz = global.params.isX86_64 ? 8 : 4;
@@ -3271,7 +3277,6 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
{
Expression *ec;
Expressions *arguments;
bool isBit = (n->ty == Tbit);
//LDC: Build arguments.
static FuncDeclaration *adSort_fd = NULL;
@@ -3281,18 +3286,8 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSort_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSort");
}
static FuncDeclaration *adSortBit_fd = NULL;
if(!adSortBit_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSortBit_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSortBit");
}
if(isBit)
ec = new VarExp(0, adSortBit_fd);
else
ec = new VarExp(0, adSort_fd);
ec = new VarExp(0, adSort_fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions();
@@ -3304,13 +3299,9 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
e = exp;
}
arguments->push(e);
if (next->ty != Tbit) {
// LDC, we don't support the getInternalTypeInfo
// optimization arbitrarily, not yet at least...
arguments->push(n->getTypeInfo(sc));
}
// LDC, we don't support the getInternalTypeInfo
// optimization arbitrarily, not yet at least...
arguments->push(n->getTypeInfo(sc));
e = new CallExp(e->loc, ec, arguments);
e->type = next->arrayOf();
}
@@ -3517,6 +3508,9 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
dim = dim->optimize(WANTvalue);
dinteger_t d2 = dim->toInteger();
if (dim->op == TOKerror)
goto Lerror;
if (d1 != d2)
goto Loverflow;
@@ -4142,7 +4136,6 @@ printf("index->ito->ito = x%x\n", index->ito->ito);
switch (index->toBasetype()->ty)
{
case Tbool:
case Tfunction:
case Tvoid:
case Tnone:
@@ -4920,6 +4913,11 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
}
void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{
toCBufferWithAttributes(buf, ident, hgs, this, NULL);
}
void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td)
{
//printf("TypeFunction::toCBuffer() this = %p\n", this);
const char *p = NULL;
@@ -4932,22 +4930,22 @@ void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs
/* Use 'storage class' style for attributes
*/
if (mod)
if (attrs->mod)
{
MODtoBuffer(buf, mod);
MODtoBuffer(buf, attrs->mod);
buf->writeByte(' ');
}
if (purity)
if (attrs->purity)
buf->writestring("pure ");
if (isnothrow)
if (attrs->isnothrow)
buf->writestring("nothrow ");
if (isproperty)
if (attrs->isproperty)
buf->writestring("@property ");
if (isref)
if (attrs->isref)
buf->writestring("ref ");
switch (trust)
switch (attrs->trust)
{
case TRUSTsystem:
buf->writestring("@system ");
@@ -4964,9 +4962,11 @@ void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs
if (next && (!ident || ident->toHChars2() == ident->toChars()))
next->toCBuffer2(buf, hgs, 0);
else if (hgs->ddoc && !next)
buf->writestring("auto");
if (hgs->ddoc != 1)
{
switch (linkage)
switch (attrs->linkage)
{
case LINKd: p = NULL; break;
case LINKc: p = "C "; break;
@@ -4988,6 +4988,17 @@ void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs
{ buf->writeByte(' ');
buf->writestring(ident->toHChars2());
}
if (td)
{ buf->writeByte('(');
for (int i = 0; i < td->origParameters->dim; i++)
{
TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
if (i)
buf->writestring(", ");
tp->toCBuffer(buf, hgs);
}
buf->writeByte(')');
}
Parameter::argsToCBuffer(buf, hgs, parameters, varargs);
inuse--;
}
@@ -5210,8 +5221,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
size_t tdim = tt->arguments->dim;
for (size_t j = 0; j < tdim; j++)
{ Parameter *narg = (Parameter *)tt->arguments->data[j];
narg->storageClass = fparam->storageClass;
narg->storageClass |= fparam->storageClass;
}
fparam->storageClass = 0;
}
/* Reset number of parameters, and back up one to do this fparam again,
@@ -5548,6 +5560,20 @@ Type *TypeFunction::reliesOnTident()
return next ? next->reliesOnTident() : NULL;
}
/********************************************
* Return TRUE if there are lazy parameters.
*/
bool TypeFunction::hasLazyParameters()
{
size_t dim = Parameter::dim(parameters);
for (size_t i = 0; i < dim; i++)
{ Parameter *fparam = Parameter::getNth(parameters, i);
if (fparam->storageClass & STClazy)
return TRUE;
}
return FALSE;
}
/***************************
* Examine function signature for parameter p and see if
* p can 'escape' the scope of the function.
@@ -5583,6 +5609,12 @@ bool TypeFunction::parameterEscapes(Parameter *p)
return TRUE;
}
Expression *TypeFunction::defaultInit(Loc loc)
{
error(loc, "function does not have a default initializer");
return new ErrorExp();
}
/***************************** TypeDelegate *****************************/
TypeDelegate::TypeDelegate(Type *t)
@@ -5644,7 +5676,7 @@ MATCH TypeDelegate::implicitConvTo(Type *to)
//printf("to : %s\n", to->toChars());
if (this == to)
return MATCHexact;
#if 0 // not allowing covariant conversions because it interferes with overriding
#if 1 // not allowing covariant conversions because it interferes with overriding
if (to->ty == Tdelegate && this->nextOf()->covariant(to->nextOf()) == 1)
return MATCHconvert;
#endif
@@ -6201,9 +6233,6 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc)
if (!t)
{
#ifdef DEBUG
printf("2: ");
#endif
error(loc, "%s is used as a type", toChars());
t = terror;
}
@@ -7380,15 +7409,37 @@ int TypeStruct::needsDestruction()
int TypeStruct::isAssignable()
{
int assignable = TRUE;
unsigned offset;
/* If any of the fields are const or invariant,
* then one cannot assign this struct.
*/
for (size_t i = 0; i < sym->fields.dim; i++)
{ VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
if (v->isConst() || v->isImmutable())
return FALSE;
//printf("%s [%d] v = (%s) %s, v->offset = %d, v->parent = %s", sym->toChars(), i, v->kind(), v->toChars(), v->offset, v->parent->kind());
if (i == 0)
;
else if (v->offset == offset)
{
/* If any fields of anonymous union are assignable,
* then regard union as assignable.
* This is to support unsafe things like Rebindable templates.
*/
if (assignable)
continue;
}
else
{
if (!assignable)
return FALSE;
}
assignable = v->type->isMutable() && v->type->isAssignable();
offset = v->offset;
//printf(" -> assignable = %d\n", assignable);
}
return TRUE;
return assignable;
}
int TypeStruct::hasPointers()
@@ -8442,12 +8493,7 @@ void Parameter::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Parameters *argu
if (arg->defaultArg)
{
argbuf.writestring(" = ");
unsigned o = argbuf.offset;
arg->defaultArg->toCBuffer(&argbuf, hgs);
if (hgs->ddoc)
{
escapeDdocString(&argbuf, o);
}
}
buf->write(&argbuf);
}

View File

@@ -96,7 +96,6 @@ enum ENUMTY
Tcomplex64,
Tcomplex80,
Tbit,
Tbool,
Tchar,
Twchar,
@@ -175,7 +174,6 @@ struct Type : Object
#define tcomplex64 basic[Tcomplex64]
#define tcomplex80 basic[Tcomplex80]
#define tbit basic[Tbit]
#define tbool basic[Tbool]
#define tchar basic[Tchar]
#define twchar basic[Twchar]
@@ -412,7 +410,6 @@ struct TypeBasic : Type
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
int isintegral();
int isbit();
int isfloating();
int isreal();
int isimaginary();
@@ -630,11 +627,13 @@ struct TypeFunction : TypeNext
void purityLevel();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void attributesToCBuffer(OutBuffer *buf, int mod);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
Type *reliesOnTident();
bool hasLazyParameters();
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
@@ -649,7 +648,11 @@ struct TypeFunction : TypeNext
#if IN_DMD
unsigned totym();
#elif IN_LLVM
#endif
Expression *defaultInit(Loc loc);
#if IN_LLVM
// LDC
IrFuncTy fty;
@@ -857,7 +860,6 @@ struct TypeTypedef : Type
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident);
int isbit();
int isintegral();
int isfloating();
int isreal();

View File

@@ -327,7 +327,7 @@ Expression *UnaExp::op_overload(Scope *sc)
else
{
// Rewrite +e1 as e1.add()
return build_overload(loc, sc, e1, NULL, fd->ident);
return build_overload(loc, sc, e1, NULL, fd);
}
}
}
@@ -418,7 +418,7 @@ Expression *CastExp::op_overload(Scope *sc)
#if 1 // Backwards compatibility with D1 if opCast is a function, not a template
if (fd->isFuncDeclaration())
{ // Rewrite as: e1.opCast()
return build_overload(loc, sc, e1, NULL, fd->ident);
return build_overload(loc, sc, e1, NULL, fd);
}
#endif
Objects *targsi = new Objects();
@@ -475,8 +475,10 @@ Expression *BinExp::op_overload(Scope *sc)
Objects *targsi = NULL;
#if DMDV2
if (!s && !s_r && op != TOKequal && op != TOKnotequal && op != TOKassign)
{ /* Try the new D2 scheme, opBinary and opBinaryRight
if (!s && !s_r && op != TOKequal && op != TOKnotequal && op != TOKassign &&
op != TOKplusplus && op != TOKminusminus)
{
/* Try the new D2 scheme, opBinary and opBinaryRight
*/
if (ad1)
s = search_function(ad1, Id::opBinary);
@@ -520,7 +522,7 @@ Expression *BinExp::op_overload(Scope *sc)
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, NULL, &args2);
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
}
}
@@ -535,7 +537,7 @@ Expression *BinExp::op_overload(Scope *sc)
}
else
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, NULL, &args1);
templateResolve(&m, td, sc, loc, targsi, e2, &args1);
}
}
@@ -560,13 +562,13 @@ Expression *BinExp::op_overload(Scope *sc)
// as unary, but it's implemented as a binary.
// Rewrite (e1 ++ e2) as e1.postinc()
// Rewrite (e1 -- e2) as e1.postdec()
e = build_overload(loc, sc, e1, NULL, id);
else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
e = build_overload(loc, sc, e1, NULL, m.lastf ? m.lastf : s);
else if (lastf && m.lastf == lastf || !s_r && m.last == MATCHnomatch)
// Rewrite (e1 op e2) as e1.opfunc(e2)
e = build_overload(loc, sc, e1, e2, id, targsi);
e = build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s);
else
// Rewrite (e1 op e2) as e2.opfunc_r(e1)
e = build_overload(loc, sc, e2, e1, id_r, targsi);
e = build_overload(loc, sc, e2, e1, m.lastf ? m.lastf : s_r);
return e;
}
@@ -613,7 +615,7 @@ L1:
}
else
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, NULL, &args2);
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
}
}
FuncDeclaration *lastf = m.lastf;
@@ -627,7 +629,7 @@ L1:
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, NULL, &args1);
templateResolve(&m, td, sc, loc, targsi, e2, &args1);
}
}
@@ -645,13 +647,12 @@ L1:
}
Expression *e;
if (lastf && m.lastf == lastf ||
id_r && m.last == MATCHnomatch)
if (lastf && m.lastf == lastf || !s && m.last == MATCHnomatch)
// Rewrite (e1 op e2) as e1.opfunc_r(e2)
e = build_overload(loc, sc, e1, e2, id_r, targsi);
e = build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s_r);
else
// Rewrite (e1 op e2) as e2.opfunc(e1)
e = build_overload(loc, sc, e2, e1, id, targsi);
e = build_overload(loc, sc, e2, e1, m.lastf ? m.lastf : s);
// When reversing operands of comparison operators,
// need to reverse the sense of the op
@@ -825,12 +826,12 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
}
Expression *e;
if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
if (lastf && m.lastf == lastf || !s_r && m.last == MATCHnomatch)
// Rewrite (e1 op e2) as e1.opfunc(e2)
e = build_overload(loc, sc, e1, e2, id, targsi);
e = build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s);
else
{ // Rewrite (e1 op e2) as e2.opfunc_r(e1)
e = build_overload(loc, sc, e2, e1, id, targsi);
e = build_overload(loc, sc, e2, e1, m.lastf ? m.lastf : s_r);
// When reversing operands of comparison operators,
// need to reverse the sense of the op
@@ -1011,6 +1012,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
#endif
BinExp::semantic(sc);
e1 = resolveProperties(sc, e1);
e2 = resolveProperties(sc, e2);
Identifier *id = opId();
@@ -1067,7 +1069,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, NULL, &args2);
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
}
}
@@ -1086,10 +1088,8 @@ Expression *BinAssignExp::op_overload(Scope *sc)
goto L1;
}
Expression *e;
// Rewrite (e1 op e2) as e1.opOpAssign(e2)
e = build_overload(loc, sc, e1, e2, id, targsi);
return e;
return build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s);
}
L1:
@@ -1130,22 +1130,20 @@ L1:
*/
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg,
Identifier *id, Objects *targsi)
Dsymbol *d)
{
assert(d);
Expression *e;
//printf("build_overload(id = '%s')\n", id->toChars());
//earg->print();
//earg->type->print();
if (targsi)
e = new DotTemplateInstanceExp(loc, ethis, id, targsi);
Declaration *decl = d->isDeclaration();
if (decl)
e = new DotVarExp(loc, ethis, decl, 0);
else
e = new DotIdExp(loc, ethis, id);
if (earg)
e = new CallExp(loc, e, earg);
else
e = new CallExp(loc, e);
e = new DotIdExp(loc, ethis, d->ident);
e = new CallExp(loc, e, earg);
e = e->semantic(sc);
return e;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -427,8 +427,10 @@ Dsymbols *Parser::parseDeclDefs(int once)
if (token.value == TOKidentifier &&
(tk = peek(&token))->value == TOKlparen &&
skipParens(tk, &tk) &&
(peek(tk)->value == TOKlparen ||
peek(tk)->value == TOKlcurly)
((tk = peek(tk)), 1) &&
skipAttributes(tk, &tk) &&
(tk->value == TOKlparen ||
tk->value == TOKlcurly)
)
{
a = parseDeclarations(storageClass, comment);
@@ -971,7 +973,8 @@ Dsymbol *Parser::parseCtor()
Expression *constraint = tpl ? parseConstraint() : NULL;
CtorDeclaration *f = new CtorDeclaration(loc, 0, parameters, varargs, stc);
Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto
CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf);
parseContracts(f);
// Wrap a template around it
@@ -987,7 +990,8 @@ Dsymbol *Parser::parseCtor()
int varargs;
Parameters *parameters = parseParameters(&varargs);
StorageClass stc = parsePostfix();
CtorDeclaration *f = new CtorDeclaration(loc, 0, parameters, varargs, stc);
Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto
CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf);
parseContracts(f);
return f;
}
@@ -2074,6 +2078,7 @@ Objects *Parser::parseTemplateArgument()
case TOKstring:
case TOKfile:
case TOKline:
case TOKthis:
{ // Template argument is an expression
Expression *ea = parsePrimaryExp();
tiargs->push(ea);
@@ -2473,7 +2478,7 @@ Type *Parser::parseBasicType2(Type *t)
return NULL;
}
Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl)
Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl, StorageClass storage_class)
{ Type *ts;
//printf("parseDeclarator(tpl = %p)\n", tpl);
@@ -2602,6 +2607,7 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters *
/* Parse const/immutable/shared/inout/nothrow/pure postfix
*/
StorageClass stc = parsePostfix();
stc |= storage_class; // merge prefix storage classes
Type *tf = new TypeFunction(arguments, t, varargs, linkage, stc);
if (stc & STCconst)
@@ -2816,7 +2822,7 @@ L2:
TemplateParameters *tpl = NULL;
ident = NULL;
t = parseDeclarator(ts, &ident, &tpl);
t = parseDeclarator(ts, &ident, &tpl, storage_class);
assert(t);
if (!tfirst)
tfirst = t;
@@ -2879,6 +2885,9 @@ L2:
tpl = new TemplateParameters();
}
#endif
//printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t->toChars(), storage_class);
FuncDeclaration *f =
new FuncDeclaration(loc, 0, ident, storage_class, t);
addComment(f, comment);
@@ -3184,6 +3193,8 @@ Initializer *Parser::parseInitializer()
break;
default:
if (comma == 1)
error("comma expected separating field initializers");
value = parseInitializer();
is->addInit(NULL, value);
comma = 1;
@@ -3427,9 +3438,8 @@ Statement *Parser::parseStatement(int flags)
case TOKstatic:
{ // Look ahead to see if it's static assert() or static if()
Token *t;
t = peek(&token);
Token *t = peek(&token);
if (t->value == TOKassert)
{
nextToken();
@@ -3452,6 +3462,13 @@ Statement *Parser::parseStatement(int flags)
s = new ScopeStatement(loc, s);
break;
}
if (t->value == TOKimport)
{ nextToken();
Dsymbols *imports = new Dsymbols();
parseImport(imports, 1); // static import ...
s = new ImportStatement(loc, imports);
break;
}
goto Ldeclaration;
}
@@ -3477,6 +3494,7 @@ Statement *Parser::parseStatement(int flags)
case TOKwild:
case TOKnothrow:
case TOKpure:
case TOKref:
case TOKtls:
case TOKgshared:
case TOKat:
@@ -4233,6 +4251,13 @@ Statement *Parser::parseStatement(int flags)
break;
}
case TOKimport:
{ Dsymbols *imports = new Dsymbols();
parseImport(imports, 0);
s = new ImportStatement(loc, imports);
break;
}
default:
error("found '%s' instead of statement", token.toChars());
goto Lerror;
@@ -4892,7 +4917,6 @@ int Parser::skipParens(Token *t, Token **pt)
break;
case TOKeof:
case TOKsemicolon:
goto Lfalse;
default:
@@ -4910,6 +4934,61 @@ int Parser::skipParens(Token *t, Token **pt)
return 0;
}
/*******************************************
* Skip attributes.
* Input:
* t is on a candidate attribute
* Output:
* *pt is set to first non-attribute token on success
* Returns:
* !=0 successful
* 0 some parsing error
*/
int Parser::skipAttributes(Token *t, Token **pt)
{
while (1)
{
switch (t->value)
{
case TOKconst:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKwild:
case TOKfinal:
case TOKauto:
case TOKscope:
case TOKoverride:
case TOKabstract:
case TOKsynchronized:
case TOKdeprecated:
case TOKnothrow:
case TOKpure:
case TOKref:
case TOKtls:
case TOKgshared:
//case TOKmanifest:
break;
case TOKat:
if (parseAttribute() == STCundefined)
break;
goto Lerror;
default:
goto Ldone;
}
t = peek(t);
}
Ldone:
if (*pt)
*pt = t;
return 1;
Lerror:
return 0;
}
/********************************* Expression Parser ***************************/
Expression *Parser::parsePrimaryExp()

View File

@@ -107,7 +107,7 @@ struct Parser : Lexer
Type *parseType(Identifier **pident = NULL, TemplateParameters **tpl = NULL);
Type *parseBasicType();
Type *parseBasicType2(Type *t);
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL);
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL, StorageClass storage_class = 0);
Dsymbols *parseDeclarations(StorageClass storage_class, unsigned char *comment);
void parseContracts(FuncDeclaration *f);
Statement *parseStatement(int flags);
@@ -124,6 +124,7 @@ struct Parser : Lexer
int isExpression(Token **pt);
int isTemplateInstance(Token *t, Token **pt);
int skipParens(Token *t, Token **pt);
int skipAttributes(Token *t, Token **pt);
Expression *parseExpression();
Expression *parsePrimaryExp();

View File

@@ -327,7 +327,7 @@ hash_t Dchar::calcHash(const dchar *str, size_t len)
case 2:
hash *= 37;
#if __I86__
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
@@ -336,7 +336,7 @@ hash_t Dchar::calcHash(const dchar *str, size_t len)
case 3:
hash *= 37;
#if __I86__
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
@@ -346,7 +346,7 @@ hash_t Dchar::calcHash(const dchar *str, size_t len)
default:
hash *= 37;
#if __I86__
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
@@ -379,7 +379,7 @@ hash_t Dchar::calcHash(const dchar *str, size_t len)
case 2:
hash *= 37;
#if __I86__
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
@@ -388,7 +388,7 @@ hash_t Dchar::calcHash(const dchar *str, size_t len)
case 3:
hash *= 37;
#if __I86__
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
@@ -398,7 +398,7 @@ hash_t Dchar::calcHash(const dchar *str, size_t len)
default:
hash *= 37;
#if __I86__
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];

View File

@@ -26,7 +26,7 @@ void browse(const char *url)
#endif
#if linux || __FreeBSD__ || __sun&&__SVR4
#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#include <sys/types.h>
#include <sys/wait.h>

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -70,6 +70,11 @@ double Port::pow(double x, double y)
return ::pow(x, y);
}
long double Port::fmodl(long double x, long double y)
{
return ::fmodl(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
{
return ::strtoull(p, pend, base);
@@ -201,6 +206,11 @@ double Port::pow(double x, double y)
return ::pow(x, y);
}
long double Port::fmodl(long double x, long double y)
{
return ::fmodl(x, y);
}
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
{
unsigned _int64 number = 0;
@@ -315,7 +325,7 @@ char *Port::strupr(char *s)
#endif
#if linux || __APPLE__ || __FreeBSD__ || __HAIKU__
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__
#include <math.h>
#if linux
@@ -332,6 +342,7 @@ char *Port::strupr(char *s)
#include <stdlib.h>
#include <ctype.h>
#include <float.h>
#include <assert.h>
static double zero = 0;
double Port::nan = NAN;
@@ -369,15 +380,15 @@ PortInitializer::PortInitializer()
}
#ifndef __HAIKU__
#undef isnan
#endif
int Port::isNan(double r)
{
#if __APPLE__
return __inline_isnan(r);
#elif defined __HAIKU__
#elif defined __HAIKU__ || __OpenBSD__
return isnan(r);
#else
#undef isnan
return ::isnan(r);
#endif
}
@@ -386,9 +397,10 @@ int Port::isNan(long double r)
{
#if __APPLE__
return __inline_isnan(r);
#elif defined __HAIKU__
#elif defined __HAIKU__ || __OpenBSD__
return isnan(r);
#else
#undef isnan
return ::isnan(r);
#endif
}
@@ -416,15 +428,15 @@ int Port::isFinite(double r)
}
#if !defined __HAIKU__
#undef isinf
#endif
int Port::isInfinity(double r)
{
#if __APPLE__
return fpclassify(r) == FP_INFINITE;
#elif defined __HAIKU__
#elif defined __HAIKU__ || __OpenBSD__
return isinf(r);
#else
#undef isinf
return ::isinf(r);
#endif
}
@@ -447,6 +459,15 @@ double Port::pow(double x, double y)
return ::pow(x, y);
}
long double Port::fmodl(long double x, long double y)
{
#if __FreeBSD__ || __OpenBSD__
return ::fmod(x, y); // hack for now, fix later
#else
return ::fmodl(x, y);
#endif
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
{
return ::strtoull(p, pend, base);
@@ -460,7 +481,11 @@ char *Port::ull_to_string(char *buffer, ulonglong ull)
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
{
#if __OpenBSD__
assert(0);
#else
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
#endif
return buffer;
}

View File

@@ -40,7 +40,8 @@ struct Port
static double dbl_min;
static long double ldbl_max;
#if __GNUC__ && !defined __HAIKU__
#if !defined __HAIKU__ || __OpenBSD__
#elif __GNUC__
// These conflict with macros in math.h, should rename them
#undef isnan
#undef isfinite
@@ -60,6 +61,8 @@ struct Port
static double floor(double);
static double pow(double x, double y);
static long double fmodl(long double x, long double y);
static ulonglong strtoull(const char *p, char **pend, int base);
static char *ull_to_string(char *buffer, ulonglong ull);

View File

@@ -19,7 +19,7 @@
#include <io.h>
#endif
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

View File

@@ -8,7 +8,7 @@
// See the included readme.txt for details.
#ifndef POSIX
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4)
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
#endif
#include <stdio.h>

View File

@@ -53,11 +53,9 @@ extern int os_critsecsize64();
Statement::Statement(Loc loc)
: loc(loc)
{
#ifdef _DH
// If this is an in{} contract scope statement (skip for determining
// inlineStatus of a function body for header content)
incontract = 0;
#endif
}
Statement *Statement::syntaxCopy()
@@ -178,6 +176,11 @@ int Statement::isEmpty()
return FALSE;
}
Statement *Statement::last()
{
return this;
}
/****************************************
* If this statement has code that needs to run in a finally clause
* at the end of the current scope, return that code in the form of
@@ -616,6 +619,22 @@ ReturnStatement *CompoundStatement::isReturnStatement()
return rs;
}
Statement *CompoundStatement::last()
{
Statement *s = NULL;
for (size_t i = statements->dim; i; --i)
{ s = (Statement *) statements->data[i - 1];
if (s)
{
s = s->last();
if (s)
break;
}
}
return s;
}
void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
for (int i = 0; i < statements->dim; i++)
@@ -639,12 +658,31 @@ int CompoundStatement::blockExit(bool mustNotThrow)
{
//printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
int result = BEfallthru;
Statement *slast = NULL;
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = (Statement *) statements->data[i];
if (s)
{
//printf("result = x%x\n", result);
//printf("%s\n", s->toChars());
//printf("result = x%x\n", result);
//printf("%s\n", s->toChars());
if (global.params.warnings && result & BEfallthru && slast)
{
slast = slast->last();
if (slast && (s->isCaseStatement() || s->isDefaultStatement()))
{
// Allow if last case/default was empty
CaseStatement *sc = slast->isCaseStatement();
DefaultStatement *sd = slast->isDefaultStatement();
if (sc && sc->statement->isEmpty())
;
else if (sd && sd->statement->isEmpty())
;
else
s->error("switch case fallthrough - use 'goto %s;' if intended",
s->isCaseStatement() ? "case" : "default");
}
}
if (!(result & BEfallthru) && !s->comeFrom())
{
if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty())
@@ -655,6 +693,7 @@ int CompoundStatement::blockExit(bool mustNotThrow)
result &= ~BEfallthru;
result |= s->blockExit(mustNotThrow);
}
slast = s;
}
}
return result;
@@ -1725,7 +1764,7 @@ Lagain:
// __r.next
e = new VarExp(loc, r);
Expression *increment = new DotIdExp(loc, e, idnext);
Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idnext));
/* Declaration statement for e:
* auto e = __r.idhead;
@@ -2399,9 +2438,6 @@ Statement *IfStatement::syntaxCopy()
Statement *IfStatement::semantic(Scope *sc)
{
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
// Evaluate at runtime
unsigned cs0 = sc->callSuper;
unsigned cs1;
@@ -2415,24 +2451,29 @@ Statement *IfStatement::semantic(Scope *sc)
sym->parent = sc->scopesym;
scd = sc->push(sym);
Type *t = arg->type ? arg->type : condition->type;
match = new VarDeclaration(loc, t, arg->ident, NULL);
match->noscope = 1;
match->semantic(scd);
if (!scd->insert(match))
assert(0);
match = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, condition));
match->parent = sc->func;
/* Generate:
* ((arg = condition), arg)
*/
VarExp *v = new VarExp(0, match);
condition = new AssignExp(loc, v, condition);
condition = new CommaExp(loc, condition, v);
DeclarationExp *de = new DeclarationExp(loc, match);
VarExp *ve = new VarExp(0, match);
condition = new CommaExp(loc, de, ve);
condition = condition->semantic(scd);
if (match->edtor)
{
Statement *sdtor = new ExpStatement(loc, match->edtor);
sdtor = new OnScopeStatement(loc, TOKon_scope_exit, sdtor);
ifbody = new CompoundStatement(loc, sdtor, ifbody);
match->noscope = 1;
}
}
else
{
condition = condition->semantic(sc);
condition = condition->addDtorHook(sc);
condition = resolveProperties(sc, condition);
scd = sc->push();
}
// Convert to boolean after declaring arg so this works:
// if (S arg = S()) {}
@@ -2913,7 +2954,8 @@ Statement *SwitchStatement::semantic(Scope *sc)
if (!sc->sw->sdefault && !isFinal)
{ hasNoDefault = 1;
warning("switch statement has no default");
if (!global.params.useDeprecated)
error("non-final switch statement without a default is deprecated");
// Generate runtime error if the default is hit
Statements *a = new Statements();
@@ -3007,7 +3049,7 @@ int SwitchStatement::blockExit(bool mustNotThrow)
void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("switch (");
buf->writestring(isFinal ? "final switch (" : "switch (");
condition->toCBuffer(buf, hgs);
buf->writebyte(')');
buf->writenl();
@@ -3510,7 +3552,8 @@ Statement *ReturnStatement::semantic(Scope *sc)
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
exp = exp->optimize(WANTvalue);
if (!((TypeFunction *)fd->type)->isref)
exp = exp->optimize(WANTvalue);
if (fd->nrvo_can && exp->op == TOKvar)
{ VarExp *ve = (VarExp *)exp;
@@ -3592,7 +3635,8 @@ Statement *ReturnStatement::semantic(Scope *sc)
else if (tbret->ty != Tvoid)
{
exp = exp->implicitCastTo(sc, tret);
exp = exp->optimize(WANTvalue);
if (!((TypeFunction *)fd->type)->isref)
exp = exp->optimize(WANTvalue);
}
}
else if (fd->inferRetType)
@@ -3745,6 +3789,17 @@ Statement *ReturnStatement::semantic(Scope *sc)
return new CompoundStatement(loc, s, this);
}
if (exp)
{ if (exp->op == TOKcall)
valueNoDtor(exp);
else
{
Expression *e = exp->isTemp();
if (e)
exp = e; // don't need temporary
}
}
return this;
}
@@ -4331,8 +4386,7 @@ int TryCatchStatement::blockExit(bool mustNotThrow)
/* If we're catching Object, then there is no throwing
*/
Identifier *id = c->type->toBasetype()->isClassHandle()->ident;
if (i == 0 &&
(id == Id::Object || id == Id::Throwable || id == Id::Exception))
if (id == Id::Object || id == Id::Throwable || id == Id::Exception)
{
result &= ~BEthrow;
}
@@ -4412,6 +4466,15 @@ void Catch::semantic(Scope *sc)
type = Type::terror;
}
}
else if (sc->func &&
!sc->intypeof &&
cd != ClassDeclaration::exception &&
!ClassDeclaration::exception->isBaseOf(cd, NULL) &&
sc->func->setUnsafe())
{
error(loc, "can only catch class objects derived from Exception in @safe code, not '%s'", type->toChars());
type = Type::terror;
}
else if (ident)
{
var = new VarDeclaration(loc, type, ident, NULL);
@@ -5014,3 +5077,50 @@ void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
#endif
/************************ ImportStatement ***************************************/
ImportStatement::ImportStatement(Loc loc, Dsymbols *imports)
: Statement(loc)
{
this->imports = imports;
}
Statement *ImportStatement::syntaxCopy()
{
Dsymbols *m = new Dsymbols();
m->setDim(imports->dim);
for (int i = 0; i < imports->dim; i++)
{ Dsymbol *s = (Dsymbol *)imports->data[i];
m->data[i] = (void *)s->syntaxCopy(NULL);
}
return new ImportStatement(loc, m);
}
Statement *ImportStatement::semantic(Scope *sc)
{
for (int i = 0; i < imports->dim; i++)
{ Dsymbol *s = (Dsymbol *)imports->data[i];
s->semantic(sc);
sc->insert(s);
}
return this;
}
int ImportStatement::blockExit(bool mustNotThrow)
{
return BEfallthru;
}
int ImportStatement::isEmpty()
{
return TRUE;
}
void ImportStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
for (int i = 0; i < imports->dim; i++)
{ Dsymbol *s = (Dsymbol *)imports->data[i];
s->toCBuffer(buf, hgs);
}
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -48,6 +48,9 @@ struct GotoStatement;
struct ScopeStatement;
struct TryCatchStatement;
struct TryFinallyStatement;
struct CaseStatement;
struct DefaultStatement;
struct LabelStatement;
struct HdrGenState;
struct InterState;
#if IN_LLVM
@@ -114,12 +117,7 @@ struct Statement : Object
void warning(const char *format, ...) IS_PRINTF(2);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
#if IN_LLVM
virtual LabelStatement *isLabelStatement() { return NULL; }
#endif
#ifdef _DH
int incontract;
#endif
virtual ScopeStatement *isScopeStatement() { return NULL; }
virtual Statement *semantic(Scope *sc);
Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
@@ -133,6 +131,7 @@ struct Statement : Object
virtual Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
virtual Statements *flatten(Scope *sc);
virtual Expression *interpret(InterState *istate);
virtual Statement *last();
virtual int inlineCost(InlineCostState *ics);
virtual Expression *doInline(InlineDoState *ids);
@@ -146,7 +145,9 @@ struct Statement : Object
virtual CompoundStatement *isCompoundStatement() { return NULL; }
virtual ReturnStatement *isReturnStatement() { return NULL; }
virtual IfStatement *isIfStatement() { return NULL; }
virtual CaseStatement* isCaseStatement() { return NULL; }
virtual CaseStatement *isCaseStatement() { return NULL; }
virtual DefaultStatement *isDefaultStatement() { return NULL; }
virtual LabelStatement *isLabelStatement() { return NULL; }
#if IN_LLVM
virtual void toNakedIR(IRState *irs);
@@ -216,6 +217,7 @@ struct CompoundStatement : Statement
virtual Statements *flatten(Scope *sc);
ReturnStatement *isReturnStatement();
Expression *interpret(InterState *istate);
Statement *last();
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
@@ -534,13 +536,12 @@ struct CaseStatement : Statement
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
CaseStatement *isCaseStatement() { return this; }
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
CaseStatement* isCaseStatement() { return this; }
#if IN_LLVM
llvm::BasicBlock* bodyBB;
llvm::Value* llvmIdx;
@@ -582,6 +583,7 @@ struct DefaultStatement : Statement
int comeFrom();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
DefaultStatement *isDefaultStatement() { return this; }
Statement *inlineScan(InlineScanState *iss);
@@ -885,13 +887,13 @@ struct LabelStatement : Statement
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
LabelStatement *isLabelStatement() { return this; }
void toIR(IRState *irs);
#if IN_LLVM
bool asmLabel; // for labels inside inline assembler
void toNakedIR(IRState *irs);
virtual LabelStatement *isLabelStatement() { return this; }
#endif
};
@@ -925,8 +927,8 @@ struct AsmStatement : Statement
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toIR(IRState *irs);
#if IN_LLVM
#if IN_LLVM
// non-zero if this is a branch, contains the target labels identifier
Identifier* isBranchToLabel;
@@ -934,6 +936,25 @@ struct AsmStatement : Statement
#endif
};
struct ImportStatement : Statement
{
Dsymbols *imports; // Array of Import's
ImportStatement(Loc loc, Dsymbols *imports);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int blockExit(bool mustNotThrow);
int isEmpty();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//void toIR(IRState *irs);
};
struct AsmBlockStatement : CompoundStatement
{
TryFinallyStatement* enclosingFinally;

View File

@@ -18,9 +18,7 @@
#include "dsymbol.h"
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct StaticAssert : Dsymbol
{

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -38,6 +38,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
structalign = 0; // struct member alignment in effect
hasUnions = 0;
sizeok = 0; // size not determined yet
deferred = NULL;
isdeprecated = 0;
inv = NULL;
aggNew = NULL;
@@ -348,7 +349,7 @@ void StructDeclaration::semantic(Scope *sc)
{
Scope *sc2;
//printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", this, toChars(), sizeok);
//printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);
//static int count; if (++count == 20) halt();
@@ -675,6 +676,11 @@ void StructDeclaration::semantic(Scope *sc)
semantic2(sc);
semantic3(sc);
}
if (deferred)
{
deferred->semantic2(sc);
deferred->semantic3(sc);
}
}
Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
@@ -730,6 +736,7 @@ const char *StructDeclaration::kind()
UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
: StructDeclaration(loc, id)
{
hasUnions = 1;
}
Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)

View File

@@ -376,6 +376,20 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->literal = 0;
this->ismixin = ismixin;
this->previous = NULL;
// Compute in advance for Ddoc's use
if (members)
{
Dsymbol *s;
if (Dsymbol::oneMembers(members, &s))
{
if (s && s->ident && s->ident->equals(ident))
{
onemember = s;
s->parent = this;
}
}
}
}
Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
@@ -500,6 +514,8 @@ void TemplateDeclaration::semantic(Scope *sc)
paramscope->pop();
// Compute again
onemember = NULL;
if (members)
{
Dsymbol *s;
@@ -1650,11 +1666,14 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
#if 0 // Should handle template functions
#if 0 // Should handle template functions for doc generation
if (onemember && onemember->isFuncDeclaration())
buf->writestring("foo ");
#endif
buf->writestring(kind());
if (hgs->ddoc)
buf->writestring(kind());
else
buf->writestring("template");
buf->writeByte(' ');
buf->writestring(ident->toChars());
buf->writeByte('(');
@@ -4126,7 +4145,13 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
{ Dsymbol *sd = (Dsymbol *)Module::deferred.data[i];
if (sd->parent == this)
{
//printf("deferred %s %s\n", sd->parent->toChars(), sd->toChars());
AggregateDeclaration *ad = sd->isAggregateDeclaration();
if (ad)
ad->deferred = this;
goto Laftersemantic;
}
}
/* The problem is when to parse the initializer for a variable.
@@ -4730,6 +4755,12 @@ Identifier *TemplateInstance::genIdent(Objects *args)
ea = NULL;
goto Lsa;
}
if (ea->op == TOKthis)
{
sa = ((ThisExp *)ea)->var;
ea = NULL;
goto Lsa;
}
if (ea->op == TOKfunction)
{
sa = ((FuncExp *)ea)->fd;

View File

@@ -163,7 +163,7 @@ Expression *TraitsExp::semantic(Scope *sc)
#if DMDV2
else if (ident == Id::isStaticFunction)
{
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis())
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis() && !f->isNested())
}
else if (ident == Id::isRef)
{

View File

@@ -162,7 +162,7 @@ Statement *AsmStatement::semantic(Scope *sc)
//puts(toChars());
sc->func->inlineAsm = 1;
sc->func->inlineAsm = true;
sc->func->inlineStatus = ILSno; // %% not sure
// %% need to set DECL_UNINLINABLE too?
sc->func->hasReturnExp = 1; // %% DMD does this, apparently...