mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-17 12:23:14 +01:00
Updated to dmdfe 2.054
This commit is contained in:
44
dmd/mtype.c
44
dmd/mtype.c
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,9 +23,7 @@ struct LabelDsymbol;
|
||||
struct Initializer;
|
||||
struct Module;
|
||||
struct Condition;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
|
||||
422
dmd2/cast.c
422
dmd2/cast.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
16
dmd2/class.c
16
dmd2/class.c
@@ -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)
|
||||
|
||||
53
dmd2/clone.c
53
dmd2/clone.c
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
70
dmd2/doc.c
70
dmd2/doc.c
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
190
dmd2/func.c
190
dmd2/func.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
63
dmd2/init.c
63
dmd2/init.c
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 (
|
||||
|
||||
2464
dmd2/interpret.c
2464
dmd2/interpret.c
File diff suppressed because it is too large
Load Diff
1105
dmd2/intrange.c
Normal file
1105
dmd2/intrange.c
Normal file
File diff suppressed because it is too large
Load Diff
149
dmd2/intrange.h
Normal file
149
dmd2/intrange.h
Normal 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
|
||||
@@ -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; \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
10
dmd2/mars.c
10
dmd2/mars.c
@@ -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[].
|
||||
|
||||
11
dmd2/mars.h
11
dmd2/mars.h
@@ -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
|
||||
|
||||
@@ -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] |
|
||||
|
||||
@@ -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();
|
||||
|
||||
140
dmd2/mtype.c
140
dmd2/mtype.c
@@ -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);
|
||||
}
|
||||
|
||||
12
dmd2/mtype.h
12
dmd2/mtype.h
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
99
dmd2/parse.c
99
dmd2/parse.c
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
162
dmd2/statement.c
162
dmd2/statement.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Expression;
|
||||
#ifdef _DH
|
||||
struct HdrGenState;
|
||||
#endif
|
||||
|
||||
struct StaticAssert : Dsymbol
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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...
|
||||
|
||||
Reference in New Issue
Block a user