diff -uNr dmd-0.166/dmd/src/dmd/array.c dmd-0.167/dmd/src/dmd/array.c --- dmd-0.166/dmd/src/dmd/array.c 2006-02-09 16:14:50.000000000 +0100 +++ dmd-0.167/dmd/src/dmd/array.c 2006-09-11 01:31:56.000000000 +0200 @@ -143,7 +143,7 @@ void Array::remove(unsigned i) { - memcpy(data + i, data + i + 1, (dim - i) * sizeof(data[0])); + memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0])); dim--; } diff -uNr dmd-0.166/dmd/src/dmd/cast.c dmd-0.167/dmd/src/dmd/cast.c --- dmd-0.166/dmd/src/dmd/cast.c 2006-08-26 23:55:48.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/cast.c 2006-09-06 01:24:48.000000000 +0200 @@ -1012,20 +1012,45 @@ t1 = e1->type; t2 = e2->type; assert(t1); + + //if (t1) printf("\tt1 = %s\n", t1->toChars()); + //if (t2) printf("\tt2 = %s\n", t2->toChars()); #ifdef DEBUG if (!t2) printf("\te2 = '%s'\n", e2->toChars()); #endif assert(t2); - ty = (TY)Type::impcnvResult[t1->ty][t2->ty]; + Type *t1b = t1->toBasetype(); + Type *t2b = t2->toBasetype(); + + ty = (TY)Type::impcnvResult[t1b->ty][t2b->ty]; if (ty != Terror) { TY ty1; TY ty2; + ty1 = (TY)Type::impcnvType1[t1b->ty][t2b->ty]; + ty2 = (TY)Type::impcnvType2[t1b->ty][t2b->ty]; + + if (t1b->ty == ty1) // if no promotions + { + if (t1 == t2) + { + if (!type) + type = t1; + return this; + } + + if (t1b == t2b) + { + if (!type) + type = t1b; + return this; + } + } + if (!type) type = Type::basic[ty]; - ty1 = (TY)Type::impcnvType1[t1->ty][t2->ty]; - ty2 = (TY)Type::impcnvType2[t1->ty][t2->ty]; + t1 = Type::basic[ty1]; t2 = Type::basic[ty2]; e1 = e1->castTo(sc, t1); @@ -1052,7 +1077,7 @@ } else if (t1->isintegral() && t2->isintegral()) { - //printf("t1 = %s, t2 = %s\n", t1->toChars(), t2->toChars()); + printf("t1 = %s, t2 = %s\n", t1->toChars(), t2->toChars()); int sz1 = t1->size(); int sz2 = t2->size(); int sign1 = t1->isunsigned() == 0; diff -uNr dmd-0.166/dmd/src/dmd/declaration.c dmd-0.167/dmd/src/dmd/declaration.c --- dmd-0.166/dmd/src/dmd/declaration.c 2006-08-28 12:41:04.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/declaration.c 2006-09-03 21:44:14.000000000 +0200 @@ -657,92 +657,95 @@ } } - // If inside function, there is no semantic3() call - if (sc->func && init && !init->isVoidInitializer()) + if (init) { - // If local variable, use AssignExp to handle all the various - // possibilities. - if (fd && !isStatic() && !isConst()) + // If inside function, there is no semantic3() call + if (sc->func) { - ExpInitializer *ie; - Expression *e1; - Type *t; - int dim; - - //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); - ie = init->isExpInitializer(); - if (!ie) + // If local variable, use AssignExp to handle all the various + // possibilities. + if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) { - error("is not a static and cannot have static initializer"); - return; - } + ExpInitializer *ie; + Expression *e1; + Type *t; + int dim; + + //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); + ie = init->isExpInitializer(); + if (!ie) + { + error("is not a static and cannot have static initializer"); + return; + } - e1 = new VarExp(loc, this); + e1 = new VarExp(loc, this); - t = type->toBasetype(); - if (t->ty == Tsarray) - { - dim = ((TypeSArray *)t)->dim->toInteger(); - // If multidimensional static array, treat as one large array - while (1) + t = type->toBasetype(); + if (t->ty == Tsarray) { - t = t->next->toBasetype(); - if (t->ty != Tsarray) - break; - if (t->next->toBasetype()->ty == Tbit) - // t->size() gives size in bytes, convert to bits - dim *= t->size() * 8; - else - dim *= ((TypeSArray *)t)->dim->toInteger(); - e1->type = new TypeSArray(t->next, new IntegerExp(0, dim, Type::tindex)); + dim = ((TypeSArray *)t)->dim->toInteger(); + // If multidimensional static array, treat as one large array + while (1) + { + t = t->next->toBasetype(); + if (t->ty != Tsarray) + break; + if (t->next->toBasetype()->ty == Tbit) + // t->size() gives size in bytes, convert to bits + dim *= t->size() * 8; + else + dim *= ((TypeSArray *)t)->dim->toInteger(); + e1->type = new TypeSArray(t->next, new IntegerExp(0, dim, Type::tindex)); + } + e1 = new SliceExp(loc, e1, NULL, NULL); } - e1 = new SliceExp(loc, e1, NULL, NULL); + ie->exp = new AssignExp(loc, e1, ie->exp); + ie->exp = ie->exp->semantic(sc); + ie->exp->optimize(WANTvalue); } - ie->exp = new AssignExp(loc, e1, ie->exp); - ie->exp = ie->exp->semantic(sc); - ie->exp->optimize(WANTvalue); - } - else - { - init = init->semantic(sc, type); - if (fd && isConst() && !isStatic()) - { // Make it static - storage_class |= STCstatic; + else + { + init = init->semantic(sc, type); + if (fd && isConst() && !isStatic()) + { // Make it static + storage_class |= STCstatic; + } } } - } - else if (isConst() and init) - { - /* Because we may need the results of a const declaration in a - * subsequent type, such as an array dimension, before semantic2() - * gets ordinarilly run, try to run semantic2() now. - * Ignore failure. - */ - - ExpInitializer *ei = init->isExpInitializer(); - if (ei && !global.errors && !inferred) + else if (isConst()) { - unsigned errors = global.errors; - global.gag++; - //printf("+gag\n"); - Expression *e = ei->exp->syntaxCopy(); - inuse++; - e = e->semantic(sc); - inuse--; - e = e->implicitCastTo(sc, type); - global.gag--; - //printf("-gag\n"); - if (errors != global.errors) // if errors happened - { - if (global.gag == 0) - global.errors = errors; // act as if nothing happened - } - else + /* Because we may need the results of a const declaration in a + * subsequent type, such as an array dimension, before semantic2() + * gets ordinarilly run, try to run semantic2() now. + * Ignore failure. + */ + + ExpInitializer *ei = init->isExpInitializer(); + if (ei && !global.errors && !inferred) { - e = e->optimize(WANTvalue); - if (e->op == TOKint64 || e->op == TOKstring) + unsigned errors = global.errors; + global.gag++; + //printf("+gag\n"); + Expression *e = ei->exp->syntaxCopy(); + inuse++; + e = e->semantic(sc); + inuse--; + e = e->implicitCastTo(sc, type); + global.gag--; + //printf("-gag\n"); + if (errors != global.errors) // if errors happened + { + if (global.gag == 0) + global.errors = errors; // act as if nothing happened + } + else { - ei->exp = e; // no errors, keep result + e = e->optimize(WANTvalue); + if (e->op == TOKint64 || e->op == TOKstring) + { + ei->exp = e; // no errors, keep result + } } } } diff -uNr dmd-0.166/dmd/src/dmd/delegatize.c dmd-0.167/dmd/src/dmd/delegatize.c --- dmd-0.166/dmd/src/dmd/delegatize.c 2006-08-27 00:08:26.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/delegatize.c 2006-09-10 13:06:00.000000000 +0200 @@ -161,6 +161,12 @@ } +void ArrayLiteralExp::scanForNestedRef(Scope *sc) +{ + arrayExpressionScanForNestedRef(sc, elements); +} + + void ArrayExp::scanForNestedRef(Scope *sc) { e1->scanForNestedRef(sc); diff -uNr dmd-0.166/dmd/src/dmd/expression.c dmd-0.167/dmd/src/dmd/expression.c --- dmd-0.166/dmd/src/dmd/expression.c 2006-08-30 22:47:26.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/expression.c 2006-09-14 16:20:54.000000000 +0200 @@ -98,6 +98,7 @@ precedence[TOKfloat64] = PREC_primary; precedence[TOKnull] = PREC_primary; precedence[TOKstring] = PREC_primary; + precedence[TOKarrayliteral] = PREC_primary; precedence[TOKtypedot] = PREC_primary; precedence[TOKtypeid] = PREC_primary; precedence[TOKis] = PREC_primary; @@ -519,6 +520,8 @@ { arg = arg->castTo(sc, tb->next->arrayOf()); } + + arg->rvalue(); } arg = arg->optimize(WANTvalue); arguments->data[i] = (void *) arg; @@ -818,14 +821,20 @@ /******************************** * Check for expressions that have no use. * Input: - * flag !=0 means we want the result + * flag 0 not going to use the result, so issue error message if no + * side effects + * 1 the result of the expression is used, but still check + * for useless subexpressions + * 2 do not issue error messages, just return !=0 if expression + * has side effects */ -void Expression::checkSideEffect(int flag) +int Expression::checkSideEffect(int flag) { - if (!flag) + if (flag == 0) error("%s has no effect in expression (%s)", Token::toChars(op), toChars()); + return 0; } /***************************** @@ -1496,6 +1505,8 @@ withsym = scopesym->isWithScopeSymbol(); if (withsym) { + s = s->toAlias(); + // Same as wthis.ident if (s->needThis()) { @@ -2220,6 +2231,78 @@ buf->printf("%02x", q[i]); } +/************************ ArrayLiteralExp ************************************/ + +// [ e1, e2, e3, ... ] + +ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements) + : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) +{ + this->elements = elements; +} + +Expression *ArrayLiteralExp::syntaxCopy() +{ + return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); +} + +Expression *ArrayLiteralExp::semantic(Scope *sc) +{ Expression *e; + Type *t0 = NULL; + +#if LOGSEMANTIC + printf("ArrayLiteralExp::semantic('%s')\n", toChars()); +#endif + + // Run semantic() on each element + for (int i = 0; i < elements->dim; i++) + { e = (Expression *)elements->data[i]; + + e = e->semantic(sc); + if (!e->type) + error("%s has no value", e->toChars()); + e = resolveProperties(sc, e); + if (!t0) + t0 = e->type; + else + e = e->implicitCastTo(sc, t0); + elements->data[i] = (void *)e; + } + + if (!t0) + t0 = Type::tvoid; + type = new TypeSArray(t0, new IntegerExp(elements->dim)); + type = type->semantic(loc, sc); + return this; +} + +int ArrayLiteralExp::checkSideEffect(int flag) +{ int f = 0; + + for (int i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + + f |= e->checkSideEffect(2); + } + if (flag == 0 && f == 0) + Expression::checkSideEffect(0); + return f; +} + +int ArrayLiteralExp::isBool(int result) +{ + size_t dim = elements ? elements->dim : 0; + return result ? (dim != 0) : (dim == 0); +} + +void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ int i; + + buf->writeByte('['); + argsToCBuffer(buf, elements, hgs); + buf->writeByte(']'); +} + /************************ TypeDotIdExp ************************************/ /* Things like: @@ -2406,7 +2489,9 @@ #if LOGSEMANTIC printf("NewExp::semantic() %s\n", toChars()); - printf("newtype: %s\n", newtype->toChars()); + if (thisexp) + printf("\tthisexp = %s\n", thisexp->toChars()); + printf("\tnewtype: %s\n", newtype->toChars()); #endif if (type) // if semantic() already run return this; @@ -2570,14 +2655,23 @@ type = type->pointerTo(); } else if (tb->ty == Tarray && (arguments && arguments->dim)) - { Expression *arg; + { + for (size_t i = 0; i < arguments->dim; i++) + { + if (tb->ty != Tarray) + { error("too many arguments for array"); + arguments->dim = i; + break; + } - arg = (Expression *)arguments->data[0]; - arg = resolveProperties(sc, arg); - arg = arg->implicitCastTo(sc, Type::tindex); - if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) - error("negative array index %s", arg->toChars()); - arguments->data[0] = (void *) arg; + Expression *arg = (Expression *)arguments->data[i]; + arg = resolveProperties(sc, arg); + arg = arg->implicitCastTo(sc, Type::tindex); + if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) + error("negative array index %s", arg->toChars()); + arguments->data[i] = (void *) arg; + tb = tb->next->toBasetype(); + } } else if (tb->isscalar()) { @@ -2598,8 +2692,9 @@ return this; } -void NewExp::checkSideEffect(int flag) +int NewExp::checkSideEffect(int flag) { + return 1; } void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -2663,8 +2758,9 @@ return c->semantic(sc); } -void NewAnonClassExp::checkSideEffect(int flag) +int NewAnonClassExp::checkSideEffect(int flag) { + return 1; } void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -3028,8 +3124,9 @@ return this; } -void DeclarationExp::checkSideEffect(int flag) +int DeclarationExp::checkSideEffect(int flag) { + return 1; } void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -3091,8 +3188,9 @@ return this; } -void HaltExp::checkSideEffect(int flag) +int HaltExp::checkSideEffect(int flag) { + return 1; } void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -3437,7 +3535,7 @@ return this; } -void BinExp::checkSideEffect(int flag) +int BinExp::checkSideEffect(int flag) { if (op == TOKplusplus || op == TOKminusminus || @@ -3454,12 +3552,10 @@ op == TOKandass || op == TOKorass || op == TOKxorass || - op == TOKoror || - op == TOKandand || op == TOKin || op == TOKremove) - return; - Expression::checkSideEffect(flag); + return 1; + return Expression::checkSideEffect(flag); } void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -3530,8 +3626,9 @@ return this; } -void AssertExp::checkSideEffect(int flag) +int AssertExp::checkSideEffect(int flag) { + return 1; } void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -4584,8 +4681,9 @@ return this; } -void CallExp::checkSideEffect(int flag) +int CallExp::checkSideEffect(int flag) { + return 1; } void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -4932,8 +5030,9 @@ return this; } -void DeleteExp::checkSideEffect(int flag) +int DeleteExp::checkSideEffect(int flag) { + return 1; } Expression *DeleteExp::checkToBoolean() @@ -4987,11 +5086,16 @@ return e1->castTo(sc, to); } -void CastExp::checkSideEffect(int flag) +int CastExp::checkSideEffect(int flag) { + /* if not: + * cast(void) + * cast(classtype)func() + */ if (!to->equals(Type::tvoid) && !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass)) - Expression::checkSideEffect(flag); + return Expression::checkSideEffect(flag); + return 1; } void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -5313,10 +5417,15 @@ return e2->isBool(result); } -void CommaExp::checkSideEffect(int flag) +int CommaExp::checkSideEffect(int flag) { - /* Don't check e1 until we cast(void) the a,b code generation */ - e2->checkSideEffect(flag); + if (flag == 2) + return e1->checkSideEffect(2) || e2->checkSideEffect(2); + else + { + // Don't check e1 until we cast(void) the a,b code generation + return e2->checkSideEffect(flag); + } } /************************** IndexExp **********************************/ @@ -6760,9 +6869,16 @@ return TRUE; } -void OrOrExp::checkSideEffect(int flag) +int OrOrExp::checkSideEffect(int flag) { - e2->checkSideEffect(flag); + if (flag == 2) + { + return e1->checkSideEffect(2) || e2->checkSideEffect(2); + } + else + { e1->checkSideEffect(1); + return e2->checkSideEffect(flag); + } } /************************************************************/ @@ -6818,9 +6934,17 @@ return TRUE; } -void AndAndExp::checkSideEffect(int flag) +int AndAndExp::checkSideEffect(int flag) { - e2->checkSideEffect(flag); + if (flag == 2) + { + return e1->checkSideEffect(2) || e2->checkSideEffect(2); + } + else + { + e1->checkSideEffect(1); + return e2->checkSideEffect(flag); + } } /************************************************************/ @@ -7173,11 +7297,20 @@ return this; } -void CondExp::checkSideEffect(int flag) +int CondExp::checkSideEffect(int flag) { - econd->checkSideEffect(TRUE); - e1->checkSideEffect(flag); - e2->checkSideEffect(flag); + if (flag == 2) + { + return econd->checkSideEffect(2) || + e1->checkSideEffect(2) || + e2->checkSideEffect(2); + } + else + { + econd->checkSideEffect(1); + e1->checkSideEffect(flag); + return e2->checkSideEffect(flag); + } } void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff -uNr dmd-0.166/dmd/src/dmd/expression.h dmd-0.167/dmd/src/dmd/expression.h --- dmd-0.166/dmd/src/dmd/expression.h 2006-08-28 11:33:52.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/expression.h 2006-09-12 00:33:02.000000000 +0200 @@ -116,7 +116,7 @@ virtual int isConst(); virtual int isBool(int result); virtual int isBit(); - virtual void checkSideEffect(int flag); + virtual int checkSideEffect(int flag); virtual int inlineCost(InlineCostState *ics); virtual Expression *doInline(InlineDoState *ids); @@ -301,6 +301,26 @@ dt_t **toDt(dt_t **pdt); }; +struct ArrayLiteralExp : Expression +{ + Expressions *elements; + + ArrayLiteralExp(Loc loc, Expressions *elements); + + Expression *syntaxCopy(); + Expression *semantic(Scope *sc); + int isBool(int result); + elem *toElem(IRState *irs); + int checkSideEffect(int flag); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + void scanForNestedRef(Scope *sc); + Expression *optimize(int result); + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Expression *inlineScan(InlineScanState *iss); +}; + struct TypeDotIdExp : Expression { Identifier *ident; @@ -355,7 +375,7 @@ Expression *syntaxCopy(); Expression *semantic(Scope *sc); elem *toElem(IRState *irs); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void scanForNestedRef(Scope *sc); @@ -377,7 +397,7 @@ ClassDeclaration *cd, Expressions *arguments); Expression *syntaxCopy(); Expression *semantic(Scope *sc); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -454,7 +474,7 @@ DeclarationExp(Loc loc, Dsymbol *declaration); Expression *syntaxCopy(); Expression *semantic(Scope *sc); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); void scanForNestedRef(Scope *sc); @@ -479,7 +499,7 @@ HaltExp(Loc loc); Expression *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - void checkSideEffect(int flag); + int checkSideEffect(int flag); elem *toElem(IRState *irs); }; @@ -533,7 +553,7 @@ Expression *semanticp(Scope *sc); Expression *commonSemanticAssign(Scope *sc); Expression *commonSemanticAssignIntegral(Scope *sc); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *scaleFactor(Scope *sc); Expression *typeCombine(Scope *sc); @@ -555,7 +575,7 @@ struct BinAssignExp : BinExp { BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2); - void checkSideEffect(int flag); + int checkSideEffect(int flag); }; /****************************************************************/ @@ -567,7 +587,7 @@ AssertExp(Loc loc, Expression *e, Expression *msg = NULL); Expression *syntaxCopy(); Expression *semantic(Scope *sc); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); }; @@ -650,7 +670,7 @@ Expression *syntaxCopy(); Expression *semantic(Scope *sc); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); void scanForNestedRef(Scope *sc); @@ -737,7 +757,7 @@ DeleteExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); Expression *checkToBoolean(); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); }; @@ -751,7 +771,7 @@ Expression *syntaxCopy(); Expression *semantic(Scope *sc); Expression *optimize(int result); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *constFold(); elem *toElem(IRState *irs); @@ -830,7 +850,7 @@ Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); int isBool(int result); - void checkSideEffect(int flag); + int checkSideEffect(int flag); Expression *optimize(int result); elem *toElem(IRState *irs); }; @@ -1180,7 +1200,7 @@ int isBit(); Expression *constFold(); Expression *optimize(int result); - void checkSideEffect(int flag); + int checkSideEffect(int flag); elem *toElem(IRState *irs); }; @@ -1192,7 +1212,7 @@ int isBit(); Expression *constFold(); Expression *optimize(int result); - void checkSideEffect(int flag); + int checkSideEffect(int flag); elem *toElem(IRState *irs); }; @@ -1272,7 +1292,7 @@ Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); Expression *checkToBoolean(); - void checkSideEffect(int flag); + int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); diff -uNr dmd-0.166/dmd/src/dmd/func.c dmd-0.167/dmd/src/dmd/func.c --- dmd-0.166/dmd/src/dmd/func.c 2006-08-30 14:01:50.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/func.c 2006-09-17 12:42:58.000000000 +0200 @@ -526,6 +526,7 @@ sc2->explicitProtection = 0; sc2->structalign = 8; sc2->incontract = 0; + sc2->tf = NULL; // Declare 'this' ad = isThis(); @@ -956,7 +957,10 @@ { // Call invariant virtually ThisExp *v = new ThisExp(0); v->type = vthis->type; - e = new AssertExp(0, v); + Expression *se = new StringExp(0, "null this"); + se = se->semantic(sc); + se->type = Type::tchar->arrayOf(); + e = new AssertExp(loc, v, se); } if (e) { diff -uNr dmd-0.166/dmd/src/dmd/idgen.c dmd-0.167/dmd/src/dmd/idgen.c --- dmd-0.166/dmd/src/dmd/idgen.c 2006-06-07 00:50:38.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/idgen.c 2006-09-15 23:48:30.000000000 +0200 @@ -187,8 +187,9 @@ { "msg" }, { "GNU_asm" }, - // For toHash + // For toHash/toString { "tohash", "toHash" }, + { "tostring", "toString" }, // Special functions { "alloca" }, diff -uNr dmd-0.166/dmd/src/dmd/import.c dmd-0.167/dmd/src/dmd/import.c --- dmd-0.166/dmd/src/dmd/import.c 2006-07-27 01:36:52.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/import.c 2006-09-15 00:17:40.000000000 +0200 @@ -116,10 +116,11 @@ if (mod) { if (mod->loc.linnum != 0) - /* If the line number is not 0, then this is not + { /* If the line number is not 0, then this is not * a 'root' module, i.e. it was not specified on the command line. */ mod->importedFrom = sc->module->importedFrom; + } if (!isstatic && !aliasId && !names.dim) { diff -uNr dmd-0.166/dmd/src/dmd/init.c dmd-0.167/dmd/src/dmd/init.c --- dmd-0.166/dmd/src/dmd/init.c 2006-08-15 13:25:32.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/init.c 2006-09-14 01:47:42.000000000 +0200 @@ -77,6 +77,7 @@ Initializer *VoidInitializer::semantic(Scope *sc, Type *t) { + //printf("VoidInitializer::semantic(t = %p)\n", t); type = t; return this; } @@ -84,6 +85,9 @@ Expression *VoidInitializer::toExpression() { +#ifdef DEBUG + *(char*)0=0; +#endif assert(0); return NULL; } diff -uNr dmd-0.166/dmd/src/dmd/inline.c dmd-0.167/dmd/src/dmd/inline.c --- dmd-0.166/dmd/src/dmd/inline.c 2006-08-27 19:36:14.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/inline.c 2006-09-10 01:11:12.000000000 +0200 @@ -154,6 +154,11 @@ return 1; } +int ArrayLiteralExp::inlineCost(InlineCostState *ics) +{ + return 1 + arrayInlineCost(ics, elements); +} + int FuncExp::inlineCost(InlineCostState *ics) { // Right now, this makes the function be output to the .obj file twice. @@ -587,6 +592,16 @@ } +Expression *ArrayLiteralExp::doInline(InlineDoState *ids) +{ + ArrayLiteralExp *ce; + + ce = (ArrayLiteralExp *)copy(); + ce->elements = arrayExpressiondoInline(elements, ids); + return ce; +} + + Expression *ArrayExp::doInline(InlineDoState *ids) { ArrayExp *ce; @@ -930,6 +945,16 @@ } +Expression *ArrayLiteralExp::inlineScan(InlineScanState *iss) +{ Expression *e = this; + + //printf("ArrayLiteralExp::inlineScan()\n"); + arrayInlineScan(iss, elements); + + return e; +} + + Expression *ArrayExp::inlineScan(InlineScanState *iss) { Expression *e = this; diff -uNr dmd-0.166/dmd/src/dmd/lexer.c dmd-0.167/dmd/src/dmd/lexer.c --- dmd-0.166/dmd/src/dmd/lexer.c 2006-08-25 19:03:44.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/lexer.c 2006-09-10 00:53:22.000000000 +0200 @@ -2679,6 +2679,7 @@ Token::tochars[TOKsymoff] = "symoff"; Token::tochars[TOKtypedot] = "typedot"; Token::tochars[TOKarraylength] = "arraylength"; + Token::tochars[TOKarrayliteral] = "arrayliteral"; Token::tochars[TOKstring] = "string"; Token::tochars[TOKdsymbol] = "symbol"; } diff -uNr dmd-0.166/dmd/src/dmd/lexer.h dmd-0.167/dmd/src/dmd/lexer.h --- dmd-0.166/dmd/src/dmd/lexer.h 2006-08-28 01:10:06.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/lexer.h 2006-09-10 00:53:02.000000000 +0200 @@ -66,6 +66,7 @@ TOKtypeid, TOKuadd, TOKiftype, TOKremove, TOKnewanonclass, TOKcomment, + TOKarrayliteral, // Operators TOKlt, TOKgt, diff -uNr dmd-0.166/dmd/src/dmd/mars.c dmd-0.167/dmd/src/dmd/mars.c --- dmd-0.166/dmd/src/dmd/mars.c 2006-08-21 14:37:14.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/mars.c 2006-09-03 21:02:36.000000000 +0200 @@ -58,7 +58,7 @@ copyright = "Copyright (c) 1999-2006 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.166"; + version = "v0.167"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); diff -uNr dmd-0.166/dmd/src/dmd/mtype.c dmd-0.167/dmd/src/dmd/mtype.c --- dmd-0.166/dmd/src/dmd/mtype.c 2006-08-30 22:49:30.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/mtype.c 2006-09-16 15:52:06.000000000 +0200 @@ -235,7 +235,7 @@ d_uns64 Type::size(Loc loc) { error(loc, "no size for type %s", toChars()); - return 0; + return 1; } unsigned Type::alignsize() @@ -1699,6 +1699,11 @@ return next->defaultInit(); } +int TypeSArray::isZeroInit() +{ + return next->isZeroInit(); +} + /***************************** TypeDArray *****************************/ TypeDArray::TypeDArray(Type *t) @@ -1734,11 +1739,12 @@ { Type *tn = next; tn = next->semantic(loc,sc); - switch (tn->ty) + Type *tbn = tn->toBasetype(); + switch (tbn->ty) { case Tfunction: case Tnone: - error(loc, "can't have array of %s", tn->toChars()); + error(loc, "can't have array of %s", tbn->toChars()); tn = next = tint32; break; } @@ -1866,11 +1872,11 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc) { - //printf("TypeAArray::semantic()\n"); + //printf("TypeAArray::semantic() index->ty = %d\n", index->ty); // Deal with the case where we thought the index was a type, but // in reality it was an expression. - if (index->ty == Tident) + if (index->ty == Tident || index->ty == Tinstance) { Expression *e; Type *t; @@ -3662,6 +3668,8 @@ { if (sym->init) { + if (sym->init->isVoidInitializer()) + return 1; // initialize voids to 0 if (sym->init->toExpression()->isBool(FALSE)) return 1; return 0; // assume not diff -uNr dmd-0.166/dmd/src/dmd/mtype.h dmd-0.167/dmd/src/dmd/mtype.h --- dmd-0.166/dmd/src/dmd/mtype.h 2006-08-27 00:08:28.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/mtype.h 2006-09-14 12:58:48.000000000 +0200 @@ -298,6 +298,7 @@ void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); int isString(); + int isZeroInit(); unsigned memalign(unsigned salign); int implicitConvTo(Type *to); Expression *defaultInit(); diff -uNr dmd-0.166/dmd/src/dmd/optimize.c dmd-0.167/dmd/src/dmd/optimize.c --- dmd-0.166/dmd/src/dmd/optimize.c 2006-04-26 12:09:06.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/optimize.c 2006-09-13 02:34:20.000000000 +0200 @@ -27,6 +27,20 @@ return this; } +Expression *ArrayLiteralExp::optimize(int result) +{ + if (elements) + { + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + + e = e->optimize(WANTvalue); + elements->data[i] = (void *)e; + } + } + return this; +} + Expression *UnaExp::optimize(int result) { Expression *e; @@ -114,7 +128,7 @@ Expression *CastExp::optimize(int result) { //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); - if (e1->op == TOKstring && + if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && type->next->equals(e1->type->next) ) @@ -220,6 +234,13 @@ e = new IntegerExp(loc, es1->len, type); } + else if (e1->op == TOKarrayliteral) + { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; + size_t dim; + + dim = ale->elements ? ale->elements->dim : 0; + e = new IntegerExp(loc, dim, type); + } return e; } @@ -245,8 +266,42 @@ value ^= 1; e = new IntegerExp(loc, value, type); } + else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral) + { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; + int value; + + if ((!es1->elements || !es1->elements->dim) && + (!es2->elements || !es2->elements->dim)) + value = 1; // both arrays are empty + else if (!es1->elements || !es2->elements) + value = 0; + else if (es1->elements->dim != es2->elements->dim) + value = 0; + else + { + for (size_t i = 0; i < es1->elements->dim; i++) + { Expression *ee1 = (Expression *)es1->elements->data[i]; + Expression *ee2 = (Expression *)es2->elements->data[i]; + + if (!ee1->isConst() || !ee2->isConst()) + return e; + + EqualExp eq(TOKequal, 0, ee1, ee2); + Expression *v = eq.constFold(); + value = v->toInteger(); + if (value) + break; + } + } + if (op == TOKnotequal) + value ^= 1; + e = new IntegerExp(loc, value, type); + } else if (e1->isConst() == 1 && e2->isConst() == 1) + { e = constFold(); + } return e; } @@ -293,7 +348,15 @@ uinteger_t i = e2->toInteger(); if (i >= length) - error("array index %llu is out of bounds [0 .. %llu]", i, length); + { error("array index %llu is out of bounds [0 .. %llu]", i, length); + i = 0; + } + + if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) + { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; + e = (Expression *)ale->elements->data[i]; + e->type = type; + } } return e; } @@ -333,6 +396,24 @@ e = es; } } + else if (e1->op == TOKarrayliteral && + lwr->op == TOKint64 && upr->op == TOKint64 && + !e1->checkSideEffect(2)) + { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + uinteger_t ilwr = lwr->toInteger(); + uinteger_t iupr = upr->toInteger(); + + if (iupr > es1->elements->dim || ilwr > iupr) + error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr); + else + { + memmove(es1->elements->data, + es1->elements->data + ilwr, + (iupr - ilwr) * sizeof(es1->elements->data[0])); + es1->elements->dim = iupr - ilwr; + e = es1; + } + } return e; } @@ -478,6 +559,32 @@ es->type = type; e = es; } + else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral && + e1->type->equals(e2->type)) + { + // Concatenate the arrays + ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; + + es1->elements->insert(es1->elements->dim, es2->elements); + e = es1; + } + else if (e1->op == TOKarrayliteral && + e1->type->toBasetype()->next->equals(e2->type)) + { + ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; + + es1->elements->push(e2); + e = es1; + } + else if (e2->op == TOKarrayliteral && + e2->type->toBasetype()->next->equals(e1->type)) + { + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; + + es2->elements->shift(e1); + e = es2; + } else e = this; return e; diff -uNr dmd-0.166/dmd/src/dmd/parse.c dmd-0.167/dmd/src/dmd/parse.c --- dmd-0.166/dmd/src/dmd/parse.c 2006-08-25 19:06:18.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/parse.c 2006-09-15 00:26:00.000000000 +0200 @@ -2418,6 +2418,7 @@ case TOKfunction: case TOKtypeid: case TOKis: + case TOKlbracket: Lexp: { Expression *exp; @@ -3923,6 +3924,13 @@ check(TOKrparen); break; + case TOKlbracket: + { Expressions *elements = parseArguments(); + + e = new ArrayLiteralExp(loc, elements); + break; + } + case TOKlcurly: // { statements... } save = TOKdelegate; @@ -4566,30 +4574,35 @@ /************************* * Collect argument list. - * Assume current token is '('. + * Assume current token is '(' or '['. */ Expressions *Parser::parseArguments() { // function call Expressions *arguments; Expression *arg; + enum TOK endtok; arguments = new Expressions(); - //if (token.value == TOKlparen) + if (token.value == TOKlbracket) + endtok = TOKrbracket; + else + endtok = TOKrparen; + { nextToken(); - if (token.value != TOKrparen) + if (token.value != endtok) { while (1) { arg = parseAssignExp(); arguments->push(arg); - if (token.value == TOKrparen) + if (token.value == endtok) break; check(TOKcomma); } } - check(TOKrparen); + check(endtok); } return arguments; } diff -uNr dmd-0.166/dmd/src/dmd/statement.c dmd-0.167/dmd/src/dmd/statement.c --- dmd-0.166/dmd/src/dmd/statement.c 2006-08-27 20:43:16.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/statement.c 2006-09-12 00:45:58.000000000 +0200 @@ -2065,6 +2065,7 @@ exp = exp->semantic(sc); exp = resolveProperties(sc, exp); + exp = exp->optimize(WANTvalue); if (fd->returnLabel && tbret->ty != Tvoid) { diff -uNr dmd-0.166/dmd/src/dmd/template.c dmd-0.167/dmd/src/dmd/template.c --- dmd-0.166/dmd/src/dmd/template.c 2006-08-30 14:26:04.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/template.c 2006-09-15 00:34:30.000000000 +0200 @@ -1971,9 +1971,11 @@ a = sc->scopesym->members; } else - { - //printf("\t2: adding to module %s\n", sc->module->importedFrom->toChars()); - a = sc->module->importedFrom->members; + { Module *m = sc->module->importedFrom; + while (m->loc.linnum != 0 && m != m->importedFrom) + m = m->importedFrom; + //printf("\t2: adding to module %s\n", m->toChars()); + a = m->members; } for (i = 0; 1; i++) { diff -uNr dmd-0.166/dmd/src/dmd/typinf.c dmd-0.167/dmd/src/dmd/typinf.c --- dmd-0.166/dmd/src/dmd/typinf.c 2006-08-28 11:38:22.000000000 +0200 +++ dmd-0.167/dmd/src/dmd/typinf.c 2006-09-15 23:48:00.000000000 +0200 @@ -340,6 +340,7 @@ * uint function(void*) xtoHash; * int function(void*,void*) xopEquals; * int function(void*,void*) xopCmp; + * char[] function(void*) xtoString; */ char *name = sd->toPrettyChars(); @@ -356,12 +357,17 @@ Dsymbol *s; static TypeFunction *tftohash; + static TypeFunction *tftostring; if (!tftohash) { Scope sc; + tftohash = new TypeFunction(NULL, Type::tuns32, 0, LINKd); tftohash = (TypeFunction *)tftohash->semantic(0, &sc); + + tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); + tftostring = (TypeFunction *)tftostring->semantic(0, &sc); } TypeFunction *tfeqptr; @@ -419,6 +425,19 @@ s = search_function(sd, Id::cmp); fdx = s ? s->isFuncDeclaration() : NULL; } + + s = search_function(sd, Id::tostring); + fdx = s ? s->isFuncDeclaration() : NULL; + if (fdx) + { fd = fdx->overloadExactMatch(tftostring); + if (fd) + dtxoff(pdt, fd->toSymbol(), 0, TYnptr); + else + //fdx->error("must be declared as extern (D) char[] toString()"); + dtdword(pdt, 0); + } + else + dtdword(pdt, 0); } void TypeInfoClassDeclaration::toDt(dt_t **pdt) diff -uNr dmd-0.166/dmd/src/phobos/internal/arraycat.d dmd-0.167/dmd/src/phobos/internal/arraycat.d --- dmd-0.166/dmd/src/phobos/internal/arraycat.d 2006-08-31 11:15:02.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/internal/arraycat.d 2006-09-18 12:03:44.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -27,6 +27,7 @@ import std.string; import std.c.string; import std.c.stdio; +import std.c.stdarg; extern (C): @@ -179,3 +180,37 @@ return ba; } +void* _d_arrayliteral(size_t size, size_t length, ...) +{ + byte[] result; + + //printf("_d_arrayliteral(size = %d, length = %d)\n", size, length); + if (length == 0 || size == 0) + result = null; + else + { + result = new byte[length * size]; + *cast(size_t *)&result = length; // jam length + + va_list q; + va_start!(size_t)(q, length); + + size_t stacksize = (size + int.sizeof - 1) & ~(int.sizeof - 1); + + if (stacksize == size) + { + memcpy(result.ptr, q, length * size); + } + else + { + for (size_t i = 0; i < length; i++) + { + memcpy(result.ptr + i * size, q, size); + q += stacksize; + } + } + + va_end(q); + } + return result.ptr; +} diff -uNr dmd-0.166/dmd/src/phobos/internal/gc/gc.d dmd-0.167/dmd/src/phobos/internal/gc/gc.d --- dmd-0.166/dmd/src/phobos/internal/gc/gc.d 2006-08-31 11:15:02.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/internal/gc/gc.d 2006-09-18 12:03:46.000000000 +0200 @@ -241,6 +241,113 @@ return result; } +ulong _d_newm(size_t size, int ndims, ...) +{ + ulong result; + + //debug(PRINTF) + //printf("_d_newm(size = %d, ndims = %d)\n", size, ndims); + if (size == 0 || ndims == 0) + result = 0; + else + { va_list q; + va_start!(int)(q, ndims); + + void[] foo(size_t* pdim, int ndims) + { + size_t dim = *pdim; + void[] p; + + if (ndims == 1) + { p = _gc.malloc(dim * size + 1)[0 .. dim]; + memset(p.ptr, 0, dim * size + 1); + } + else + { + p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; + for (int i = 0; i < dim; i++) + { + (cast(void[]*)p.ptr)[i] = foo(pdim + 1, ndims - 1); + } + } + return p; + } + + size_t* pdim = cast(size_t *)q; + result = cast(ulong)foo(pdim, ndims); + //printf("result = %llx\n", result); + + version (none) + { + for (int i = 0; i < ndims; i++) + { + printf("index %d: %d\n", i, va_arg!(int)(q)); + } + } + va_end(q); + } + return result; +} + +ulong _d_newarraymi(size_t size, int ndims, ...) +{ + ulong result; + + //debug(PRINTF) + //printf("_d_newarraymi(size = %d, ndims = %d)\n", size, ndims); + if (size == 0 || ndims == 0) + result = 0; + else + { void* pinit; // pointer to initializer + va_list q; + va_start!(int)(q, ndims); + + void[] foo(size_t* pdim, int ndims) + { + size_t dim = *pdim; + void[] p; + + if (ndims == 1) + { p = _gc.malloc(dim * size + 1)[0 .. dim]; + if (size == 1) + memset(p.ptr, *cast(ubyte*)pinit, dim); + else + { + for (size_t u = 0; u < dim; u++) + { + memcpy(p.ptr + u * size, pinit, size); + } + } + } + else + { + p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; + for (int i = 0; i < dim; i++) + { + (cast(void[]*)p.ptr)[i] = foo(pdim + 1, ndims - 1); + } + } + return p; + } + + size_t* pdim = cast(size_t *)q; + pinit = pdim + ndims; + result = cast(ulong)foo(pdim, ndims); + //printf("result = %llx\n", result); + + version (none) + { + for (int i = 0; i < ndims; i++) + { + printf("index %d: %d\n", i, va_arg!(int)(q)); + printf("init = %d\n", va_arg!(int)(q)); + } + } + va_end(q); + } + return result; +} + ulong _d_newbitarray(size_t length, bit value) { void *p; @@ -338,7 +445,7 @@ /****************************** - * Resize dynamic arrays other than bit[]. + * Resize dynamic arrays with 0 initializers. */ extern (C) @@ -417,7 +524,8 @@ } /** - * For non-zero initializers + * Resize arrays for non-zero initializers. + * (obsolete, replaced by _d_arraysetlength3) */ extern (C) byte[] _d_arraysetlength2(size_t newlength, size_t sizeelem, Array *p, ...) @@ -486,7 +594,10 @@ if (newsize > size) { if (sizeelem == 1) + { + //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); newdata[size .. newsize] = *(cast(byte*)q); + } else { for (size_t u = size; u < newsize; u += sizeelem) @@ -509,6 +620,111 @@ _d_OutOfMemory(); } +/** + * Resize arrays for non-zero initializers. + * p pointer to array lvalue to be updated + * newlength new .length property of array + * sizeelem size of each element of array + * initsize size of initializer + * ... initializer + */ +extern (C) +byte[] _d_arraysetlength3(size_t newlength, size_t sizeelem, Array *p, + size_t initsize, ...) +in +{ + assert(sizeelem); + assert(initsize); + assert(initsize <= sizeelem); + assert((sizeelem / initsize) * initsize == sizeelem); + assert(!p.length || p.data); +} +body +{ + byte* newdata; + + debug(PRINTF) + { + printf("_d_arraysetlength3(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize); + if (p) + printf("\tp.data = %p, p.length = %d\n", p.data, p.length); + } + + if (newlength) + { + version (D_InlineAsm_X86) + { + size_t newsize = void; + + asm + { + mov EAX,newlength ; + mul EAX,sizeelem ; + mov newsize,EAX ; + jc Loverflow ; + } + } + else + { + size_t newsize = sizeelem * newlength; + + if (newsize / newlength != sizeelem) + goto Loverflow; + } + //printf("newsize = %x, newlength = %x\n", newsize, newlength); + + size_t size = p.length * sizeelem; + if (p.length) + { + newdata = p.data; + if (newlength > p.length) + { + size_t cap = _gc.capacity(p.data); + + if (cap <= newsize) + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + newdata[0 .. size] = p.data[0 .. size]; + } + } + } + else + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + } + + va_list q; + va_start!(size_t)(q, initsize); // q is pointer to initializer + + if (newsize > size) + { + if (initsize == 1) + { + //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); + newdata[size .. newsize] = *(cast(byte*)q); + } + else + { + for (size_t u = size; u < newsize; u += initsize) + { + memcpy(newdata + u, q, initsize); + } + } + } + } + else + { + newdata = null; + } + + p.data = newdata; + p.length = newlength; + return newdata[0 .. newlength]; + +Loverflow: + _d_OutOfMemory(); +} + /*************************** * Resize bit[] arrays. */ @@ -583,6 +799,8 @@ return *cast(long*)px; } +version (none) +{ extern (C) long _d_arrayappendb(Array *px, bit[] y) { @@ -613,7 +831,7 @@ } return *cast(long*)px; } - +} size_t newCapacity(size_t newlength, size_t size) { @@ -758,7 +976,8 @@ } - +version (none) +{ extern (C) bit[] _d_arrayappendcb(inout bit[] x, bit b) { @@ -773,3 +992,4 @@ x[x.length - 1] = b; return x; } +} diff -uNr dmd-0.166/dmd/src/phobos/internal/gc/testgc.d dmd-0.167/dmd/src/phobos/internal/gc/testgc.d --- dmd-0.166/dmd/src/phobos/internal/gc/testgc.d 2006-08-31 11:15:02.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/internal/gc/testgc.d 2006-09-18 12:03:46.000000000 +0200 @@ -1,5 +1,5 @@ -// Copyright (C) 2001-2004 by Digital Mars +// Copyright (C) 2001-2006 by Digital Mars // All Rights Reserved // Written by Walter Bright // www.digitalmars.com @@ -8,6 +8,7 @@ import std.c.stdio; import std.c.stdlib; +import std.c.string; import std.string; import gcstats; diff -uNr dmd-0.166/dmd/src/phobos/internal/object.d dmd-0.167/dmd/src/phobos/internal/object.d --- dmd-0.166/dmd/src/phobos/internal/object.d 2006-08-31 11:15:02.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/internal/object.d 2006-09-18 12:03:44.000000000 +0200 @@ -42,7 +42,7 @@ void* memcpy(void *, void *, size_t); } -/// Standard boolean type. Implemented as a $(B bit) type. +/// Standard boolean type. alias bool bit; version (X86_64) @@ -569,6 +569,7 @@ hash_t function(void*) xtoHash; int function(void*,void*) xopEquals; int function(void*,void*) xopCmp; + char[] function(void*) xtoString; } /** diff -uNr dmd-0.166/dmd/src/phobos/linux.mak dmd-0.167/dmd/src/phobos/linux.mak --- dmd-0.166/dmd/src/phobos/linux.mak 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/linux.mak 2006-09-18 12:03:42.000000000 +0200 @@ -135,7 +135,7 @@ std/windows/iunknown.d std/windows/charset.d SRC_STD_C_WIN= std/c/windows/windows.d std/c/windows/com.d \ - std/c/windows/winsock.d + std/c/windows/winsock.d std/c/windows/stat.d SRC_STD_C_LINUX= std/c/linux/linux.d std/c/linux/linuxextern.d \ std/c/linux/socket.d diff -uNr dmd-0.166/dmd/src/phobos/object.d dmd-0.167/dmd/src/phobos/object.d --- dmd-0.166/dmd/src/phobos/object.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/object.d 2006-09-18 12:03:42.000000000 +0200 @@ -108,6 +108,7 @@ uint function(void*) xtoHash; int function(void*,void*) xopEquals; int function(void*,void*) xopCmp; + char[] function(void*) xtoString; } // Recoverable errors diff -uNr dmd-0.166/dmd/src/phobos/std/asserterror.d dmd-0.167/dmd/src/phobos/std/asserterror.d --- dmd-0.166/dmd/src/phobos/std/asserterror.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/asserterror.d 2006-09-18 12:03:42.000000000 +0200 @@ -31,7 +31,7 @@ len = 23 + filename.length + uint.sizeof * 3 + msg.length + 1; buffer = cast(char*)std.c.stdlib.malloc(len); if (buffer == null) - super("AssertError internal failure"); + super("AssertError no memory"); else { version (Win32) alias _snprintf snprintf; @@ -71,7 +71,7 @@ extern (C) static void _d_assert_msg(char[] msg, char[] filename, uint line) { - //printf("_d_assert(%s, %d)\n", cast(char *)filename, line); + //printf("_d_assert_msg(%s, %d)\n", cast(char *)filename, line); AssertError a = new AssertError(filename, line, msg); //printf("assertion %p created\n", a); throw a; diff -uNr dmd-0.166/dmd/src/phobos/std/c/linux/linux.d dmd-0.167/dmd/src/phobos/std/c/linux/linux.d --- dmd-0.166/dmd/src/phobos/std/c/linux/linux.d 2006-08-31 11:15:02.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/c/linux/linux.d 2006-09-18 12:03:44.000000000 +0200 @@ -68,24 +68,25 @@ struct struct_stat // distinguish it from the stat() function { - ulong st_dev; + ulong st_dev; /// device ushort __pad1; - uint st_ino; - uint st_mode; - uint st_nlink; - uint st_uid; - uint st_gid; - ulong st_rdev; + uint st_ino; /// file serial number + uint st_mode; /// file mode + uint st_nlink; /// link count + uint st_uid; /// user ID of file's owner + uint st_gid; /// user ID of group's owner + ulong st_rdev; /// if device then device number ushort __pad2; - int st_size; - int st_blksize; - int st_blocks; + int st_size; /// file size in bytes + int st_blksize; /// optimal I/O block size + int st_blocks; /// number of allocated 512 byte blocks int st_atime; - uint __unused1; + uint st_atimensec; int st_mtime; - uint __unused2; + uint st_mtimensec; int st_ctime; - uint __unused3; + uint st_ctimensec; + uint __unused4; uint __unused5; } @@ -105,7 +106,11 @@ S_IFLNK = 0120000, S_IFSOCK = 0140000, - S_IFMT = 0170000 + S_IFMT = 0170000, + + S_IREAD = 0000400, + S_IWRITE = 0000200, + S_IEXEC = 0000100, } extern (C) @@ -494,3 +499,16 @@ int sem_destroy(sem_t*); } +extern (C) +{ + /* from utime.h + */ + + struct utimbuf + { + __time_t actime; + __time_t modtime; + } + + int utime(char* filename, utimbuf* buf); +} diff -uNr dmd-0.166/dmd/src/phobos/std/c/time.d dmd-0.167/dmd/src/phobos/std/c/time.d --- dmd-0.166/dmd/src/phobos/std/c/time.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/c/time.d 2006-09-18 12:03:44.000000000 +0200 @@ -4,7 +4,7 @@ * Authors: Walter Bright, Digital Mars, www.digitalmars.com * License: Public Domain * Macros: - * WIKI=Phobos/StdCString + * WIKI=Phobos/StdCTime */ module std.c.time; @@ -13,25 +13,39 @@ extern (C): +alias int clock_t; + version (Windows) -{ const uint CLOCKS_PER_SEC = 1000; +{ const clock_t CLOCKS_PER_SEC = 1000; } else version (linux) -{ const uint CLOCKS_PER_SEC = 1000000; +{ const clock_t CLOCKS_PER_SEC = 1000000; } else version (darwin) { - const uint CLOCKS_PER_SEC = 100; + const clock_t CLOCKS_PER_SEC = 100; +} +else +{ + static assert(0); +} + +version (Windows) +{ + const clock_t CLK_TCK = 1000; +} +else version (linux) +{ + extern (C) int sysconf(int); + const clock_t CLK_TCK = cast(clock_t) sysconf(2); } else { static assert(0); } -const uint CLK_TCK = 1000; const uint TIMEOFFSET = 315558000; -alias int clock_t; alias int time_t; extern int daylight; diff -uNr dmd-0.166/dmd/src/phobos/std/c/windows/stat.d dmd-0.167/dmd/src/phobos/std/c/windows/stat.d --- dmd-0.166/dmd/src/phobos/std/c/windows/stat.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.167/dmd/src/phobos/std/c/windows/stat.d 2006-09-18 12:03:44.000000000 +0200 @@ -0,0 +1,49 @@ + +/// Placed into public domain +/// Author: Walter Bright + +module std.c.windows.stat; + +extern (C): + +// linux version is in std.c.linux.linux + +version (Windows) +{ +const S_IFMT = 0xF000; +const S_IFDIR = 0x4000; +const S_IFCHR = 0x2000; +const S_IFIFO = 0x1000; +const S_IFREG = 0x8000; +const S_IREAD = 0x0100; +const S_IWRITE = 0x0080; +const S_IEXEC = 0x0040; +const S_IFBLK = 0x6000; +const S_IFNAM = 0x5000; + +int S_ISREG(int m) { return (m & S_IFMT) == S_IFREG; } +int S_ISBLK(int m) { return (m & S_IFMT) == S_IFBLK; } +int S_ISNAM(int m) { return (m & S_IFMT) == S_IFNAM; } +int S_ISDIR(int m) { return (m & S_IFMT) == S_IFDIR; } +int S_ISCHR(int m) { return (m & S_IFMT) == S_IFCHR; } + +struct struct_stat +{ + short st_dev; + ushort st_ino; + ushort st_mode; + short st_nlink; + ushort st_uid; + ushort st_gid; + short st_rdev; + short dummy; + int st_size; + int st_atime; + int st_mtime; + int st_ctime; +} + +int stat(char *, struct_stat *); +int fstat(int, struct_stat *); +int _wstat(wchar *, struct_stat *); +} diff -uNr dmd-0.166/dmd/src/phobos/std/file.d dmd-0.167/dmd/src/phobos/std/file.d --- dmd-0.166/dmd/src/phobos/std/file.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/file.d 2006-09-18 12:03:42.000000000 +0200 @@ -294,6 +294,42 @@ return (cast(ulong)resulth << 32) + resultl; } +/************************* + * Get creation/access/modified times of file name[]. + * Throws: FileException on error. + */ + +void getTimes(char[] name, out d_time ftc, out d_time fta, out d_time ftm) +{ + HANDLE findhndl; + + if (useWfuncs) + { + WIN32_FIND_DATAW filefindbuf; + + findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); + ftc = std.date.FILETIME2d_time(&filefindbuf.ftCreationTime); + fta = std.date.FILETIME2d_time(&filefindbuf.ftLastAccessTime); + ftm = std.date.FILETIME2d_time(&filefindbuf.ftLastWriteTime); + } + else + { + WIN32_FIND_DATA filefindbuf; + + findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); + ftc = std.date.FILETIME2d_time(&filefindbuf.ftCreationTime); + fta = std.date.FILETIME2d_time(&filefindbuf.ftLastAccessTime); + ftm = std.date.FILETIME2d_time(&filefindbuf.ftLastWriteTime); + } + + if (findhndl == cast(HANDLE)-1) + { + throw new FileException(name, GetLastError()); + } + FindClose(findhndl); +} + + /*************************************************** * Does file name[] (or directory) exist? * Return 1 if it does, 0 if not. @@ -1046,6 +1082,28 @@ return statbuf.st_mode; } +/************************* + * Get creation/access/modified times of file name[]. + * Throws: FileException on error. + */ + +void getTimes(char[] name, out d_time ftc, out d_time fta, out d_time ftm) +{ + struct_stat statbuf; + char *namez; + + namez = toStringz(name); + if (std.c.linux.linux.stat(namez, &statbuf)) + { + throw new FileException(name, getErrno()); + } + + ftc = cast(d_time)statbuf.st_ctime * std.date.TicksPerSecond; + fta = cast(d_time)statbuf.st_atime * std.date.TicksPerSecond; + ftm = cast(d_time)statbuf.st_mtime * std.date.TicksPerSecond; +} + + /**************************************************** * Does file/directory exist? */ @@ -1331,19 +1389,114 @@ /*************************************************** - * Copy a file. - * Bugs: - * If the file is very large, this won't work. - * Doesn't maintain the file timestamps. + * Copy a file. File timestamps are preserved. */ void copy(char[] from, char[] to) { + version (all) + { + struct_stat statbuf; + + char* fromz = toStringz(from); + char* toz = toStringz(to); + //printf("file.copy(from='%s', to='%s')\n", fromz, toz); + + int fd = std.c.linux.linux.open(fromz, O_RDONLY); + if (fd == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err1; + } + + //printf("\tfile opened\n"); + if (std.c.linux.linux.fstat(fd, &statbuf)) + { + //printf("\tfstat error, errno = %d\n",getErrno()); + goto err2; + } + + int fdw = std.c.linux.linux.open(toz, O_CREAT | O_WRONLY | O_TRUNC, 0660); + if (fdw == -1) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err2; + } + + size_t BUFSIZ = 4069 * 16; + void* buf = std.c.stdlib.malloc(BUFSIZ); + if (!buf) + { BUFSIZ = 4096; + buf = std.c.stdlib.malloc(BUFSIZ); + } + if (!buf) + { + //printf("\topen error, errno = %d\n",getErrno()); + goto err4; + } + + for (size_t size = statbuf.st_size; size; ) + { size_t toread = (size > BUFSIZ) ? BUFSIZ : size; + + auto n = std.c.linux.linux.read(fd, buf, toread); + if (n != toread) + { + //printf("\tread error, errno = %d\n",getErrno()); + goto err5; + } + n = std.c.linux.linux.write(fdw, buf, toread); + if (n != toread) + { + //printf("\twrite error, errno = %d\n",getErrno()); + goto err5; + } + size -= toread; + } + + std.c.stdlib.free(buf); + + if (std.c.linux.linux.close(fdw) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err2; + } + + utimbuf utim; + utim.actime = cast(__time_t)statbuf.st_atime; + utim.modtime = cast(__time_t)statbuf.st_mtime; + if (utime(toz, &utim) == -1) + { + //printf("\tutime error, errno = %d\n",getErrno()); + goto err3; + } + + if (std.c.linux.linux.close(fd) == -1) + { + //printf("\tclose error, errno = %d\n",getErrno()); + goto err1; + } + + return; + +err5: + std.c.stdlib.free(buf); +err4: + std.c.linux.linux.close(fdw); +err3: + std.c.stdio.remove(toz); +err2: + std.c.linux.linux.close(fd); +err1: + throw new FileException(from, getErrno()); + } + else + { void[] buffer; buffer = read(from); write(to, buffer); delete buffer; + } } @@ -1352,6 +1505,29 @@ unittest { + //printf("std.file.unittest\n"); + void[] buf; + + buf = new void[10]; + (cast(byte[])buf)[] = 3; + write("unittest_write.tmp", buf); + void buf2[] = read("unittest_write.tmp"); + assert(buf == buf2); + + copy("unittest_write.tmp", "unittest_write2.tmp"); + buf2 = read("unittest_write2.tmp"); + assert(buf == buf2); + + remove("unittest_write.tmp"); + if (exists("unittest_write.tmp")) + assert(0); + remove("unittest_write2.tmp"); + if (exists("unittest_write2.tmp")) + assert(0); +} + +unittest +{ listdir (".", delegate bool (DirEntry * de) { auto s = std.string.format("%s : c %s, w %s, a %s", de.name, diff -uNr dmd-0.166/dmd/src/phobos/std/format.d dmd-0.167/dmd/src/phobos/std/format.d --- dmd-0.166/dmd/src/phobos/std/format.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/format.d 2006-09-18 12:03:42.000000000 +0200 @@ -789,6 +789,13 @@ formatArg(fc); return; + case Mangle.Tstruct: + { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; + s = tis.xtoString(argptr); + argptr += (tis.tsize() + 3) & ~3; + goto Lputstr; + } + default: goto Lerror; } diff -uNr dmd-0.166/dmd/src/phobos/std/math.d dmd-0.167/dmd/src/phobos/std/math.d --- dmd-0.166/dmd/src/phobos/std/math.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/math.d 2006-09-18 12:03:42.000000000 +0200 @@ -732,7 +732,7 @@ * $(TABLE_SV * x ilogb(x) Range error? * 0 FP_ILOGB0 yes - * ±∞ +∞ no + * ±∞ int.max no * $(NAN) FP_ILOGBNAN no * ) */ diff -uNr dmd-0.166/dmd/src/phobos/std/string.d dmd-0.167/dmd/src/phobos/std/string.d --- dmd-0.166/dmd/src/phobos/std/string.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/string.d 2006-09-18 12:03:42.000000000 +0200 @@ -175,19 +175,19 @@ int result; debug(string) printf("string.cmp.unittest\n"); - result = cmp("abc", "abc"); + result = icmp("abc", "abc"); assert(result == 0); - result = cmp(null, null); + result = icmp(null, null); assert(result == 0); - result = cmp("", ""); + result = icmp("", ""); assert(result == 0); - result = cmp("abc", "abcd"); + result = icmp("abc", "abcd"); assert(result < 0); - result = cmp("abcd", "abc"); + result = icmp("abcd", "abc"); assert(result > 0); - result = cmp("abc", "abd"); + result = icmp("abc", "abd"); assert(result < 0); - result = cmp("bbc", "abc"); + result = icmp("bbc", "abc"); assert(result > 0); } diff -uNr dmd-0.166/dmd/src/phobos/std/thread.d dmd-0.167/dmd/src/phobos/std/thread.d --- dmd-0.166/dmd/src/phobos/std/thread.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/std/thread.d 2006-09-18 12:03:42.000000000 +0200 @@ -664,6 +664,18 @@ { if (this is getThis()) error("wait on self"); + + /* Sean Kelly writes: + * Change to: + * if (state != TS.INITIAL) + * Because it is not only legal to call pthread_join on a thread that + * has run and finished, but calling pthread_join or pthread_detach is + * required for the thread resources to be released. However, it is + * illegal to call pthread_join more than once, and I believe it is also + * illegal to detach a thread that has already been joined, so 'id' + * should probably be cleared after join/detach is called, and this + * value tested along with 'state' before performing thread ops. + */ if (state == TS.RUNNING) { int result; void *value; diff -uNr dmd-0.166/dmd/src/phobos/unittest.d dmd-0.167/dmd/src/phobos/unittest.d --- dmd-0.166/dmd/src/phobos/unittest.d 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/unittest.d 2006-09-18 12:03:42.000000000 +0200 @@ -49,6 +49,7 @@ import std.boxer; import std.bitarray; import std.uni; +import std.file; int main(char[][] args) { @@ -111,6 +112,8 @@ std.uni.isUniAlpha('A'); + std.file.exists("foo"); + printf("Success\n!"); return 0; } diff -uNr dmd-0.166/dmd/src/phobos/win32.mak dmd-0.167/dmd/src/phobos/win32.mak --- dmd-0.166/dmd/src/phobos/win32.mak 2006-08-31 11:15:00.000000000 +0200 +++ dmd-0.167/dmd/src/phobos/win32.mak 2006-09-18 12:03:42.000000000 +0200 @@ -65,7 +65,7 @@ dmain2.obj outofmemory.obj aaA.obj adi.obj aApply.obj file.obj \ compiler.obj system.obj moduleinit.obj md5.obj base64.obj \ cast.obj syserror.obj path.obj string.obj memset.obj math.obj \ - outbuffer.obj ctype.obj regexp.obj random.obj windows.obj \ + outbuffer.obj ctype.obj regexp.obj random.obj windows.obj stat.obj \ stream.obj switcherr.obj com.obj array.obj gc.obj mmfile.obj \ qsort.obj math2.obj date.obj dateparse.obj thread.obj obj.obj \ iunknown.obj crc32.obj conv.obj arraycast.obj utf.obj uri.obj \ @@ -185,7 +185,7 @@ std\windows\iunknown.d std\windows\syserror.d std\windows\charset.d SRC_STD_C_WIN= std\c\windows\windows.d std\c\windows\com.d \ - std\c\windows\winsock.d + std\c\windows\winsock.d std\c\windows\stat.d SRC_STD_C_LINUX= std\c\linux\linux.d std\c\linux\linuxextern.d \ std\c\linux\socket.d @@ -487,6 +487,9 @@ com.obj : std\c\windows\com.d $(DMD) -c $(DFLAGS) std\c\windows\com.d +stat.obj : std\c\windows\stat.d + $(DMD) -c $(DFLAGS) std\c\windows\stat.d + winsock.obj : std\c\windows\winsock.d $(DMD) -c $(DFLAGS) std\c\windows\winsock.d