diff -uNr dmd-0.128/dmd/src/dmd/access.c dmd-0.129/dmd/src/dmd/access.c --- dmd-0.128/dmd/src/dmd/access.c 2005-04-02 10:51:42.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/access.c 2005-07-19 12:01:30.000000000 +0200 @@ -33,9 +33,29 @@ */ /**************************************** - * Return PROT access for Dsymbol smember in this class. + * Return PROT access for Dsymbol smember in this declaration. */ +enum PROT AggregateDeclaration::getAccess(Dsymbol *smember) +{ + return PROTpublic; +} + +enum PROT StructDeclaration::getAccess(Dsymbol *smember) +{ + enum PROT access_ret = PROTnone; + +#if LOG + printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n", + toChars(), smember->toChars()); +#endif + if (smember->toParent() == this) + { + access_ret = smember->prot(); + } + return access_ret; +} + enum PROT ClassDeclaration::getAccess(Dsymbol *smember) { enum PROT access_ret = PROTnone; @@ -101,50 +121,54 @@ static int accessCheckX( Dsymbol *smember, Dsymbol *sfunc, - ClassDeclaration *cdthis, - ClassDeclaration *cdscope) + AggregateDeclaration *dthis, + AggregateDeclaration *cdscope) { - assert(cdthis); + assert(dthis); #if 0 printf("accessCheckX for %s.%s in function %s() in scope %s\n", - cdthis->toChars(), smember->toChars(), + dthis->toChars(), smember->toChars(), sfunc ? sfunc->toChars() : "NULL", cdscope ? cdscope->toChars() : "NULL"); #endif - if (cdthis->hasPrivateAccess(sfunc) || - cdthis->isFriendOf(cdscope)) + if (dthis->hasPrivateAccess(sfunc) || + dthis->isFriendOf(cdscope)) { - if (smember->toParent() == cdthis) + if (smember->toParent() == dthis) return 1; else { - int i; - - for (i = 0; i < cdthis->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; - enum PROT access; - - access = b->base->getAccess(smember); - if (access >= PROTprotected || - accessCheckX(smember, sfunc, b->base, cdscope) - ) - return 1; + ClassDeclaration *cdthis = dthis->isClassDeclaration(); + if (cdthis) + { + for (int i = 0; i < cdthis->baseclasses.dim; i++) + { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; + enum PROT access; + + access = b->base->getAccess(smember); + if (access >= PROTprotected || + accessCheckX(smember, sfunc, b->base, cdscope) + ) + return 1; + } } } } else { - if (smember->toParent() != cdthis) + if (smember->toParent() != dthis) { - int i; - - for (i = 0; i < cdthis->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; + ClassDeclaration *cdthis = dthis->isClassDeclaration(); + if (cdthis) + { + for (int i = 0; i < cdthis->baseclasses.dim; i++) + { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; - if (accessCheckX(smember, sfunc, b->base, cdscope)) - return 1; + if (accessCheckX(smember, sfunc, b->base, cdscope)) + return 1; + } } } } @@ -156,25 +180,26 @@ * type of the 'this' pointer used to access smember. */ -void ClassDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) +void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) { int result; FuncDeclaration *f = sc->func; - ClassDeclaration *cdscope = sc->getClassScope(); + AggregateDeclaration *cdscope = sc->getStructClassScope(); enum PROT access; #if LOG - printf("ClassDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n", + printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n", toChars(), smember->toChars(), f ? f->toChars() : NULL, cdscope ? cdscope->toChars() : NULL); #endif - if (!smember->isClassMember()) // if not a member of a class + Dsymbol *smemberparent = smember->toParent(); + if (!smemberparent || !smemberparent->isAggregateDeclaration()) { #if LOG - printf("not a class member\n"); + printf("not an aggregate member\n"); #endif return; // then it is accessible } @@ -182,7 +207,7 @@ // BUG: should enable this check //assert(smember->parent->isBaseOf(this, NULL)); - if (smember->toParent() == this) + if (smemberparent == this) { enum PROT access = smember->prot(); result = access >= PROTpublic || @@ -224,10 +249,10 @@ * Determine if this is the same or friend of cd. */ -int ClassDeclaration::isFriendOf(ClassDeclaration *cd) +int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd) { #if LOG - printf("ClassDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null"); + printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null"); #endif if (this == cd) return 1; @@ -260,10 +285,10 @@ * Determine if scope sc has package level access to 'this'. */ -int ClassDeclaration::hasPackageAccess(Scope *sc) +int AggregateDeclaration::hasPackageAccess(Scope *sc) { #if LOG - printf("ClassDeclaration::hasPackageAccess(this = '%s', sc = '%p')\n", toChars(), sc); + printf("AggregateDeclaration::hasPackageAccess(this = '%s', sc = '%p')\n", toChars(), sc); #endif Dsymbol *mthis; @@ -293,16 +318,19 @@ } /********************************** - * Determine if smember has access to private members of this class. + * Determine if smember has access to private members of this declaration. */ -int ClassDeclaration::hasPrivateAccess(Dsymbol *smember) +int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember) { if (smember) - { ClassDeclaration *cd = smember->isClassMember(); + { AggregateDeclaration *cd = NULL; + Dsymbol *smemberparent = smember->toParent(); + if (smemberparent) + cd = smemberparent->isAggregateDeclaration(); #if LOG - printf("ClassDeclaration::hasPrivateAccess(class %s, member %s)\n", + printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n", toChars(), smember->toChars()); #endif @@ -342,6 +370,10 @@ void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d) { +#if LOG + printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars()); + printf("\te->type = %s\n", e->type->toChars()); +#endif if (e->type->ty == Tclass) { // Do access check ClassDeclaration *cd; @@ -358,4 +390,11 @@ #endif cd->accessCheck(loc, sc, d); } + else if (e->type->ty == Tstruct) + { // Do access check + StructDeclaration *cd; + + cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym); + cd->accessCheck(loc, sc, d); + } } diff -uNr dmd-0.128/dmd/src/dmd/aggregate.h dmd-0.129/dmd/src/dmd/aggregate.h --- dmd-0.128/dmd/src/dmd/aggregate.h 2005-06-03 01:21:54.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/aggregate.h 2005-07-19 11:26:06.000000000 +0200 @@ -65,6 +65,13 @@ void addField(Scope *sc, VarDeclaration *v); int isDeprecated(); // is aggregate deprecated? + // For access checking + virtual PROT getAccess(Dsymbol *smember); // determine access to smember + int isFriendOf(AggregateDeclaration *cd); + int hasPackageAccess(Scope *sc); + int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class? + void accessCheck(Loc loc, Scope *sc, Dsymbol *smember); + // Back end Symbol *stag; // tag symbol for debug data Symbol *sinit; @@ -94,6 +101,8 @@ char *mangle(); char *kind(); + PROT getAccess(Dsymbol *smember); // determine access to smember + void toObjFile(); // compile to .obj file void toDt(dt_t **pdt); void toDebug(); // to symbolic debug info @@ -182,10 +191,7 @@ char *mangle(); PROT getAccess(Dsymbol *smember); // determine access to smember - int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class? - void accessCheck(Loc loc, Scope *sc, Dsymbol *smember); - int isFriendOf(ClassDeclaration *cd); - int hasPackageAccess(Scope *sc); + void addLocalClass(Array *); // Back end diff -uNr dmd-0.128/dmd/src/dmd/attrib.c dmd-0.129/dmd/src/dmd/attrib.c --- dmd-0.128/dmd/src/dmd/attrib.c 2005-05-15 01:05:44.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/attrib.c 2005-07-23 10:21:40.000000000 +0200 @@ -178,6 +178,22 @@ return NULL; } +void AttribDeclaration::checkCtorConstInit() +{ + unsigned i; + Array *d = include(NULL, NULL); + + if (d) + { + for (i = 0; i < d->dim; i++) + { Dsymbol *s; + + s = (Dsymbol *)d->data[i]; + s->checkCtorConstInit(); + } + } +} + /**************************************** */ diff -uNr dmd-0.128/dmd/src/dmd/attrib.h dmd-0.129/dmd/src/dmd/attrib.h --- dmd-0.128/dmd/src/dmd/attrib.h 2005-05-15 01:04:52.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/attrib.h 2005-07-23 10:20:38.000000000 +0200 @@ -38,6 +38,7 @@ void inlineScan(); char *kind(); Dsymbol *oneMember(); + void checkCtorConstInit(); void addLocalClass(Array *); void toCBuffer(OutBuffer *buf); diff -uNr dmd-0.128/dmd/src/dmd/class.c dmd-0.129/dmd/src/dmd/class.c --- dmd-0.128/dmd/src/dmd/class.c 2005-06-14 14:47:00.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/class.c 2005-08-01 19:25:20.000000000 +0200 @@ -373,6 +373,7 @@ sc = sc->push(this); sc->stc &= ~(STCauto | STCstatic | STCabstract); sc->parent = this; + sc->inunion = 0; if (isCOMclass()) sc->linkage = LINKwindows; diff -uNr dmd-0.128/dmd/src/dmd/declaration.c dmd-0.129/dmd/src/dmd/declaration.c --- dmd-0.128/dmd/src/dmd/declaration.c 2005-06-14 01:09:34.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/declaration.c 2005-07-24 22:33:16.000000000 +0200 @@ -368,6 +368,7 @@ noauto = 0; nestedref = 0; inuse = 0; + ctorinit = 0; } Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) @@ -423,6 +424,10 @@ tb = type; } + if (storage_class & STCconst && !init && !fd) + // Initialize by constructor only + storage_class = (storage_class & ~STCconst) | STCctorinit; + if (isConst()) { } @@ -629,6 +634,12 @@ return FALSE; } +void VarDeclaration::checkCtorConstInit() +{ + if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) + error("missing initializer in static constructor for const variable"); +} + /******************************* * Does symbol go into data segment? */ diff -uNr dmd-0.128/dmd/src/dmd/declaration.h dmd-0.129/dmd/src/dmd/declaration.h --- dmd-0.128/dmd/src/dmd/declaration.h 2005-05-22 02:14:34.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/declaration.h 2005-07-23 10:16:08.000000000 +0200 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2004 by Digital Mars +// Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -51,6 +51,7 @@ STCforeach = 0x2000, // variable for foreach loop STCcomdat = 0x4000, // should go into COMDAT record STCvariadic = 0x8000, // variadic function argument + STCctorinit = 0x10000, // can only be set inside constructor }; struct Match @@ -85,17 +86,18 @@ virtual int isDelete(); virtual int isDataseg(); virtual int isCodeseg(); - int isFinal() { return storage_class & STCfinal; } - int isAbstract() { return storage_class & STCabstract; } - int isConst() { return storage_class & STCconst; } - int isAuto() { return storage_class & STCauto; } + int isCtorinit() { return storage_class & STCctorinit; } + int isFinal() { return storage_class & STCfinal; } + int isAbstract() { return storage_class & STCabstract; } + int isConst() { return storage_class & STCconst; } + int isAuto() { return storage_class & STCauto; } int isSynchronized() { return storage_class & STCsynchronized; } - int isParameter() { return storage_class & STCparameter; } - int isDeprecated() { return storage_class & STCdeprecated; } - int isOverride() { return storage_class & STCoverride; } + int isParameter() { return storage_class & STCparameter; } + int isDeprecated() { return storage_class & STCdeprecated; } + int isOverride() { return storage_class & STCoverride; } - int isIn() { return storage_class & STCin; } - int isOut() { return storage_class & STCout; } + int isIn() { return storage_class & STCin; } + int isOut() { return storage_class & STCout; } int isInOut() { return (storage_class & (STCin | STCout)) == (STCin | STCout); } enum PROT prot(); @@ -154,6 +156,7 @@ int noauto; // no auto semantics int nestedref; // referenced by a lexically nested function int inuse; + int ctorinit; // it has been initialized in a ctor VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); @@ -166,6 +169,7 @@ int isDataseg(); Expression *callAutoDtor(); ExpInitializer *getExpInitializer(); + void checkCtorConstInit(); Symbol *toSymbol(); void toObjFile(); // compile to .obj file @@ -444,6 +448,8 @@ int isVirtual(); int addPreInvariant(); int addPostInvariant(); + + StaticCtorDeclaration *isStaticCtorDeclaration() { return this; } }; struct StaticDtorDeclaration : FuncDeclaration @@ -456,6 +462,8 @@ int isVirtual(); int addPreInvariant(); int addPostInvariant(); + + StaticDtorDeclaration *isStaticDtorDeclaration() { return this; } }; struct InvariantDeclaration : FuncDeclaration diff -uNr dmd-0.128/dmd/src/dmd/dsymbol.h dmd-0.129/dmd/src/dmd/dsymbol.h --- dmd-0.128/dmd/src/dmd/dsymbol.h 2005-05-18 22:30:54.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/dsymbol.h 2005-07-23 10:15:42.000000000 +0200 @@ -36,6 +36,8 @@ struct FuncLiteralDeclaration; struct CtorDeclaration; struct DtorDeclaration; +struct StaticCtorDeclaration; +struct StaticDtorDeclaration; struct InvariantDeclaration; struct UnitTestDeclaration; struct NewDeclaration; @@ -126,6 +128,7 @@ virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual Dsymbol *oneMember() { return this; } virtual void addLocalClass(Array *) { } + virtual void checkCtorConstInit() { } // Backend @@ -154,6 +157,8 @@ virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; } virtual CtorDeclaration *isCtorDeclaration() { return NULL; } virtual DtorDeclaration *isDtorDeclaration() { return NULL; } + virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; } + virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; } virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; } virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; } virtual NewDeclaration *isNewDeclaration() { return NULL; } diff -uNr dmd-0.128/dmd/src/dmd/enum.c dmd-0.129/dmd/src/dmd/enum.c --- dmd-0.128/dmd/src/dmd/enum.c 2005-05-12 18:51:14.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/enum.c 2005-07-24 01:26:56.000000000 +0200 @@ -102,8 +102,17 @@ // Add to symbol table only after evaluating 'value' if (isAnonymous()) { - sce->enclosing->insert(em); - em->parent = sce->enclosing->parent; + //sce->enclosing->insert(em); + for (Scope *scx = sce->enclosing; scx; scx = scx->enclosing) + { + if (scx->scopesym) + { + if (!scx->scopesym->symtab) + scx->scopesym->symtab = new DsymbolTable(); + em->addMember(sce, scx->scopesym); + break; + } + } } else em->addMember(sc, this); diff -uNr dmd-0.128/dmd/src/dmd/expression.c dmd-0.129/dmd/src/dmd/expression.c --- dmd-0.128/dmd/src/dmd/expression.c 2005-07-01 22:21:16.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/expression.c 2005-07-23 11:44:12.000000000 +0200 @@ -514,7 +514,6 @@ else if (!loc.filename) loc = e->loc; error("%s is not an lvalue", e->toChars()); -*(char*)0=0; return this; } @@ -1447,6 +1446,17 @@ this->len = len; this->sz = 1; this->committed = 0; + this->postfix = 0; +} + +StringExp::StringExp(Loc loc, void *string, unsigned len, unsigned char postfix) + : Expression(loc, TOKstring, sizeof(StringExp)) +{ + this->string = string; + this->len = len; + this->sz = 1; + this->committed = 0; + this->postfix = postfix; } int StringExp::equals(Object *o) @@ -1480,8 +1490,62 @@ printf("StringExp::semantic()\n"); #endif if (!type) - { - type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); + { OutBuffer buffer; + unsigned newlen = 0; + char *p; + unsigned u; + unsigned c; + + switch (postfix) + { + case 'd': + for (u = 0; u < len;) + { + p = utf_decodeChar((unsigned char *)string, len, &u, &c); + if (p) + { error(p); + break; + } + else + { buffer.write4(c); + newlen++; + } + } + buffer.write4(0); + string = buffer.extractData(); + len = newlen; + sz = 4; + type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex)); + committed = 1; + break; + + case 'w': + for (u = 0; u < len;) + { + p = utf_decodeChar((unsigned char *)string, len, &u, &c); + if (p) + { error(p); + break; + } + else + { buffer.writeUTF16(c); + newlen++; + } + } + buffer.writeUTF16(0); + string = buffer.extractData(); + len = newlen; + sz = 2; + type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex)); + committed = 1; + break; + + case 'c': + committed = 1; + default: + type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); + break; + } type = type->semantic(loc, sc); } return this; @@ -1591,6 +1655,8 @@ break; } buf->writeByte('"'); + if (postfix) + buf->writeByte(postfix); } /************************ TypeDotIdExp ************************************/ @@ -2124,6 +2190,24 @@ if (var->isConst()) error("cannot modify const variable '%s'", var->toChars()); + if (var->isCtorinit()) + { // It's only modifiable if inside the right constructor + if (sc->func && + ((sc->func->isCtorDeclaration() && var->storage_class & STCfield) || + (sc->func->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && + sc->func->toParent() == var->toParent()) + { + VarDeclaration *v = var->isVarDeclaration(); + assert(v); + v->ctorinit = 1; + //printf("setting ctorinit\n"); + } + else + { + error("can only initialize const %s inside constructor", var->toChars()); + } + } + // See if this expression is a modifiable lvalue (i.e. not const) return toLvalue(e); } @@ -2969,6 +3053,33 @@ Expression *DotVarExp::toLvalue(Expression *e) { + //printf("DotVarExp::toLvalue(%s)\n", toChars()); + return this; +} + +Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) +{ + //printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); + + if (var->isCtorinit()) + { // It's only modifiable if inside the right constructor + if (sc->func && + ((sc->func->isCtorDeclaration() && var->storage_class & STCfield) || + (sc->func->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && + sc->func->toParent() == var->toParent() && + e1->op == TOKthis + ) + { + VarDeclaration *v = var->isVarDeclaration(); + assert(v); + v->ctorinit = 1; + //printf("setting ctorinit\n"); + } + else + { + error("can only initialize const %s inside constructor", var->toChars()); + } + } return this; } @@ -4262,6 +4373,12 @@ return this; } +Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e) +{ + e2 = e2->modifiableLvalue(sc, e); + return this; +} + int CommaExp::isBool(int result) { return e2->isBool(result); @@ -5939,6 +6056,12 @@ return e; } +Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e) +{ + error("conditional expression %s is not a modifiable lvalue", toChars()); + return this; +} + void CondExp::checkEscape() { e1->checkEscape(); diff -uNr dmd-0.128/dmd/src/dmd/expression.h dmd-0.129/dmd/src/dmd/expression.h --- dmd-0.128/dmd/src/dmd/expression.h 2005-06-06 14:58:16.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/expression.h 2005-07-19 16:14:20.000000000 +0200 @@ -268,7 +268,9 @@ unsigned len; // number of chars, wchars, or dchars unsigned char sz; // 1: char, 2: wchar, 4: dchar unsigned char committed; // !=0 if type is committed + unsigned char postfix; // 'c', 'w', 'd' + StringExp(Loc loc, void *s, unsigned len, unsigned char postfix); StringExp(Loc loc, void *s, unsigned len); int equals(Object *o); char *toChars(); @@ -528,6 +530,7 @@ DotVarExp(Loc loc, Expression *e, Declaration *var); Expression *semantic(Scope *sc); Expression *toLvalue(Expression *e); + Expression *modifiableLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf); void dump(int indent); elem *toElem(IRState *irs); @@ -758,6 +761,7 @@ Expression *semantic(Scope *sc); void checkEscape(); Expression *toLvalue(Expression *e); + Expression *modifiableLvalue(Scope *sc, Expression *e); int isBool(int result); Expression *optimize(int result); elem *toElem(IRState *irs); @@ -1188,6 +1192,7 @@ Expression *constFold(); void checkEscape(); Expression *toLvalue(Expression *e); + Expression *modifiableLvalue(Scope *sc, Expression *e); Expression *checkToBoolean(); void toCBuffer(OutBuffer *buf); int implicitConvTo(Type *t); diff -uNr dmd-0.128/dmd/src/dmd/func.c dmd-0.129/dmd/src/dmd/func.c --- dmd-0.128/dmd/src/dmd/func.c 2005-06-05 10:09:34.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/func.c 2005-07-23 10:26:40.000000000 +0200 @@ -615,18 +615,50 @@ sc2->incontract--; if (fbody) - { + { ClassDeclaration *cd = isClassMember(); + + if (isCtorDeclaration() && cd) + { + for (int i = 0; i < cd->fields.dim; i++) + { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i]; + + v->ctorinit = 0; + } + } + fbody = fbody->semantic(sc2); int offend = fbody ? fbody->fallOffEnd() : TRUE; - if (isCtorDeclaration()) + if (isStaticCtorDeclaration()) + { /* It's a static constructor. Ensure that all + * ctor consts were initialized. + */ + + ScopeDsymbol *ad = toParent()->isScopeDsymbol(); + assert(ad); + for (int i = 0; i < ad->members->dim; i++) + { Dsymbol *s = (Dsymbol *)ad->members->data[i]; + + s->checkCtorConstInit(); + } + } + + if (isCtorDeclaration() && cd) { - ClassDeclaration *cd = isClassMember(); //printf("callSuper = x%x\n", sc2->callSuper); - assert(cd || global.errors); + // Verify that all the ctorinit fields got initialized + if (!(sc->callSuper & CSXthis_ctor)) + { + for (int i = 0; i < cd->fields.dim; i++) + { VarDeclaration *v = (VarDeclaration *)cd->fields.data[i]; - if (cd && !(sc2->callSuper & CSXany_ctor) && + if (v->ctorinit == 0 && v->isCtorinit()) + error("missing initializer for const field %s", v->toChars()); + } + } + + if (!(sc2->callSuper & CSXany_ctor) && cd->baseClass && cd->baseClass->ctor) { sc2->callSuper = 0; @@ -1565,13 +1597,8 @@ void StaticCtorDeclaration::semantic(Scope *sc) { - ClassDeclaration *cd; - Type *tret; + //printf("StaticCtorDeclaration::semantic()\n"); - cd = sc->scopesym->isClassDeclaration(); - if (!cd) - { - } type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); FuncDeclaration::semantic(sc); diff -uNr dmd-0.128/dmd/src/dmd/lexer.c dmd-0.129/dmd/src/dmd/lexer.c --- dmd-0.128/dmd/src/dmd/lexer.c 2005-06-13 02:30:40.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/lexer.c 2005-07-19 09:47:48.000000000 +0200 @@ -403,6 +403,7 @@ stringbuffer.writeByte(0); t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); + t->postfix = 0; t->value = TOKstring; return; } @@ -486,6 +487,7 @@ t->value = TOKstring; t->ustring = (unsigned char *)timestamp; Llen: + t->postfix = 0; t->len = strlen((char *)t->ustring); } } @@ -1057,6 +1059,7 @@ error("unterminated string constant starting at %s", start.toChars()); t->ustring = (unsigned char *)""; t->len = 0; + t->postfix = 0; return TOKstring; case '"': @@ -1067,6 +1070,7 @@ stringbuffer.writeByte(0); t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); + stringPostfix(t); return TOKstring; } break; @@ -1124,6 +1128,7 @@ error("unterminated string constant starting at %s", start.toChars()); t->ustring = (unsigned char *)""; t->len = 0; + t->postfix = 0; return TOKstring; case '"': @@ -1135,6 +1140,7 @@ stringbuffer.writeByte(0); t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); + stringPostfix(t); return TOKstring; default: @@ -1213,6 +1219,7 @@ stringbuffer.writeByte(0); t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); + stringPostfix(t); return TOKstring; case 0: @@ -1221,6 +1228,7 @@ error("unterminated string constant starting at %s", start.toChars()); t->ustring = (unsigned char *)""; t->len = 0; + t->postfix = 0; return TOKstring; default: @@ -1311,6 +1319,27 @@ } /*************************************** + * Get postfix of string literal. + */ + +void Lexer::stringPostfix(Token *t) +{ + switch (*p) + { + case 'c': + case 'w': + case 'd': + t->postfix = *p; + p++; + break; + + default: + t->postfix = 0; + break; + } +} + +/*************************************** * Read \u or \U unicode sequence * Input: * u 'u' or 'U' diff -uNr dmd-0.128/dmd/src/dmd/lexer.h dmd-0.129/dmd/src/dmd/lexer.h --- dmd-0.128/dmd/src/dmd/lexer.h 2005-06-06 14:47:12.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/lexer.h 2005-07-18 10:27:38.000000000 +0200 @@ -199,6 +199,7 @@ struct { unsigned char *ustring; // UTF8 string unsigned len; + unsigned char postfix; // 'c', 'w', 'd' }; Identifier *ident; }; @@ -238,6 +239,7 @@ TOK hexStringConstant(Token *t); TOK escapeStringConstant(Token *t, int wide); TOK charConstant(Token *t, int wide); + void stringPostfix(Token *t); unsigned wchar(unsigned u); TOK number(Token *t); TOK inreal(Token *t); diff -uNr dmd-0.128/dmd/src/dmd/mars.c dmd-0.129/dmd/src/dmd/mars.c --- dmd-0.128/dmd/src/dmd/mars.c 2005-06-25 15:10:06.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/mars.c 2005-08-06 22:00:30.000000000 +0200 @@ -49,7 +49,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.128"; + version = "v0.129"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -230,6 +230,8 @@ global.params.link = 0; else if (strcmp(p + 1, "g") == 0) global.params.symdebug = 1; + else if (strcmp(p + 1, "gc") == 0) + global.params.symdebug = 2; else if (strcmp(p + 1, "gt") == 0) { error("use -profile instead of -gt\n"); global.params.trace = 1; diff -uNr dmd-0.128/dmd/src/dmd/mtype.c dmd-0.129/dmd/src/dmd/mtype.c --- dmd-0.128/dmd/src/dmd/mtype.c 2005-06-14 14:47:24.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/mtype.c 2005-07-19 10:44:06.000000000 +0200 @@ -3641,11 +3641,14 @@ return new VarExp(e->loc, d); } - if (d->isStatic()) + if (d->isDataseg()) { // (e, d) - b = new VarExp(e->loc, d); - e = new CommaExp(e->loc, e, b); + VarExp *ve; + + accessCheck(e->loc, sc, e, d); + ve = new VarExp(e->loc, d); + e = new CommaExp(e->loc, e, ve); e->type = d->type; return e; } @@ -3656,6 +3659,7 @@ sym->error(e->loc, "'%s' is not a member", v->toChars()); // *(&e + offset) + accessCheck(e->loc, sc, e, d); b = new AddrExp(e->loc, e); b->type = e->type->pointerTo(); b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32)); diff -uNr dmd-0.128/dmd/src/dmd/parse.c dmd-0.129/dmd/src/dmd/parse.c --- dmd-0.128/dmd/src/dmd/parse.c 2005-07-01 22:13:12.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/parse.c 2005-07-18 10:32:46.000000000 +0200 @@ -3651,10 +3651,12 @@ case TOKstring: { unsigned char *s; unsigned len; + unsigned char postfix; // cat adjacent strings s = token.ustring; len = token.len; + postfix = token.postfix; while (1) { nextToken(); @@ -3663,6 +3665,12 @@ unsigned len2; unsigned char *s2; + if (token.postfix) + { if (token.postfix != postfix) + error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix); + postfix = token.postfix; + } + len1 = len; len2 = token.len; len = len1 + len2; @@ -3674,7 +3682,7 @@ else break; } - e = new StringExp(loc, s, len); + e = new StringExp(loc, s, len, postfix); break; } diff -uNr dmd-0.128/dmd/src/dmd/scope.h dmd-0.129/dmd/src/dmd/scope.h --- dmd-0.128/dmd/src/dmd/scope.h 2005-05-26 17:22:08.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/scope.h 2005-07-19 15:21:02.000000000 +0200 @@ -52,6 +52,7 @@ int incontract; // we're inside contract code int nofree; // set if shouldn't free it int noctor; // set if constructor calls aren't allowed + unsigned callSuper; // primitive flow analysis for constructors #define CSXthis_ctor 1 // called this() #define CSXsuper_ctor 2 // called super() @@ -65,6 +66,7 @@ enum LINK linkage; // linkage for external functions enum PROT protection; // protection for class members unsigned stc; // storage class + unsigned flags; #define SCOPEctor 1 // constructor type #define SCOPEstaticif 2 // inside static if diff -uNr dmd-0.128/dmd/src/dmd/struct.c dmd-0.129/dmd/src/dmd/struct.c --- dmd-0.128/dmd/src/dmd/struct.c 2005-06-03 01:22:34.000000000 +0200 +++ dmd-0.129/dmd/src/dmd/struct.c 2005-08-01 19:25:20.000000000 +0200 @@ -250,10 +250,12 @@ sizeok = 0; sc2 = sc->push(this); + sc2->stc = 0; sc2->parent = this; if (isUnionDeclaration()) sc2->inunion = 1; - sc2->stc = 0; + sc2->protection = PROTpublic; + int members_dim = members->dim; for (i = 0; i < members_dim; i++) { diff -uNr dmd-0.128/dmd/src/phobos/std/c/linux/linux.d dmd-0.129/dmd/src/phobos/std/c/linux/linux.d --- dmd-0.128/dmd/src/phobos/std/c/linux/linux.d 2005-07-10 23:31:58.000000000 +0200 +++ dmd-0.129/dmd/src/phobos/std/c/linux/linux.d 2005-08-06 21:57:12.000000000 +0200 @@ -8,6 +8,7 @@ import std.c.linux.linuxextern; +alias int pid_t; alias int off_t; alias uint mode_t; @@ -118,6 +119,12 @@ int rmdir(char*); char* getcwd(char*, int); int chmod(char*, mode_t); + int fork(); + int dup(int); + int dup2(int, int); + int pipe(int[2]); + pid_t wait(int*); + int waitpid(pid_t, int*, int); } struct timeval diff -uNr dmd-0.128/dmd/src/phobos/std/c/windows/windows.d dmd-0.129/dmd/src/phobos/std/c/windows/windows.d --- dmd-0.128/dmd/src/phobos/std/c/windows/windows.d 2005-07-10 23:31:58.000000000 +0200 +++ dmd-0.129/dmd/src/phobos/std/c/windows/windows.d 2005-08-06 21:57:10.000000000 +0200 @@ -525,21 +525,6 @@ enum { - KEY_QUERY_VALUE = (0x0001), - KEY_SET_VALUE = (0x0002), - KEY_CREATE_SUB_KEY = (0x0004), - KEY_ENUMERATE_SUB_KEYS = (0x0008), - KEY_NOTIFY = (0x0010), - KEY_CREATE_LINK = (0x0020), - - KEY_READ = cast(int)((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & (~SYNCHRONIZE)), - KEY_WRITE = cast(int)((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE)), - KEY_EXECUTE = cast(int)(KEY_READ & ~SYNCHRONIZE), - KEY_ALL_ACCESS = cast(int)((STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK) & (~SYNCHRONIZE)), -} - -enum -{ REG_OPTION_RESERVED = (0x00000000), // Parameter is reserved REG_OPTION_NON_VOLATILE = (0x00000000), // Key is preserved @@ -560,23 +545,6 @@ REG_LEGAL_OPTION = (REG_OPTION_RESERVED | REG_OPTION_NON_VOLATILE | REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK | REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK), } -enum -{ - REG_NONE = ( 0 ), // No value type - REG_SZ = ( 1 ), // Unicode nul terminated string - REG_EXPAND_SZ = ( 2 ), // Unicode nul terminated string - // (with environment variable references) - REG_BINARY = ( 3 ), // Free form binary - REG_DWORD = ( 4 ), // 32-bit number - REG_DWORD_LITTLE_ENDIAN = ( 4 ), // 32-bit number (same as REG_DWORD) - REG_DWORD_BIG_ENDIAN = ( 5 ), // 32-bit number - REG_LINK = ( 6 ), // Symbolic Link (unicode) - REG_MULTI_SZ = ( 7 ), // Multiple Unicode strings - REG_RESOURCE_LIST = ( 8 ), // Resource list in the resource map - REG_FULL_RESOURCE_DESCRIPTOR = ( 9 ), // Resource list in the hardware description - REG_RESOURCE_REQUIREMENTS_LIST = ( 10 ), -} - export LONG RegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey); export LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName); diff -uNr dmd-0.128/dmd/src/phobos/std/file.d dmd-0.129/dmd/src/phobos/std/file.d --- dmd-0.128/dmd/src/phobos/std/file.d 2005-07-10 23:31:52.000000000 +0200 +++ dmd-0.129/dmd/src/phobos/std/file.d 2005-08-06 21:57:06.000000000 +0200 @@ -819,6 +819,11 @@ +/ } +unittest +{ + assert(exists(".")); +} + /**************************************************** * Is name a file? */ diff -uNr dmd-0.128/dmd/src/phobos/std/format.d dmd-0.129/dmd/src/phobos/std/format.d --- dmd-0.128/dmd/src/phobos/std/format.d 2005-07-10 23:31:54.000000000 +0200 +++ dmd-0.129/dmd/src/phobos/std/format.d 2005-08-06 21:57:06.000000000 +0200 @@ -90,6 +90,64 @@ Tdelegate = 'D', } +// return the TypeInfo for a primitive type and null otherwise. +// This is required since for arrays of ints we only have the mangled +// char to work from. If arrays always subclassed TypeInfo_Array this +// routine could go away. +private TypeInfo primitiveTypeInfo(Mangle m) +{ + TypeInfo ti; + switch (m) + { + case Mangle.Tvoid: + ti = typeid(void);break; + case Mangle.Tbit: + ti = typeid(bit);break; + case Mangle.Tbyte: + ti = typeid(byte);break; + case Mangle.Tubyte: + ti = typeid(ubyte);break; + case Mangle.Tshort: + ti = typeid(short);break; + case Mangle.Tushort: + ti = typeid(ushort);break; + case Mangle.Tint: + ti = typeid(int);break; + case Mangle.Tuint: + ti = typeid(uint);break; + case Mangle.Tlong: + ti = typeid(long);break; + case Mangle.Tulong: + ti = typeid(ulong);break; + case Mangle.Tfloat: + ti = typeid(float);break; + case Mangle.Tdouble: + ti = typeid(double);break; + case Mangle.Treal: + ti = typeid(real);break; + case Mangle.Tifloat: + ti = typeid(ifloat);break; + case Mangle.Tidouble: + ti = typeid(idouble);break; + case Mangle.Tireal: + ti = typeid(ireal);break; + case Mangle.Tcfloat: + ti = typeid(cfloat);break; + case Mangle.Tcdouble: + ti = typeid(cdouble);break; + case Mangle.Tcreal: + ti = typeid(creal);break; + case Mangle.Tchar: + ti = typeid(char);break; + case Mangle.Twchar: + ti = typeid(wchar);break; + case Mangle.Tdchar: + ti = typeid(dchar); + default: + ti = null; + } + return ti; +} /************************************ * Convert arguments to tchar's according to format strings and feed to putc(). @@ -251,6 +309,16 @@ return; } + void putArray(void* p, size_t len, TypeInfo ti) { + putc('['); + size_t tsize = ti.tsize(); + while (len--) { + doFormat(putc, (&ti)[0 .. 1], p); + p += tsize; + if (len > 0) putc(','); + } + putc(']'); + } //printf("formatArg(fc = '%c', m = '%c')\n", fc, m); switch (m) @@ -385,8 +453,14 @@ vcreal = va_arg!(creal)(argptr); goto Lcomplex; - case Mangle.Tarray: + if (ti.classinfo.name.length == 14 && + ti.classinfo.name[9..14] == "Array") + { // array of non-primitive types + void[] va = va_arg!(void[])(argptr); + putArray(va.ptr, va.length, (cast(TypeInfo_Array)ti).next); + return; + } m2 = cast(Mangle)ti.classinfo.name[10]; switch (m2) { @@ -408,8 +482,12 @@ putstr(s); break; - default: - goto Lerror; + default: + TypeInfo ti2 = primitiveTypeInfo(m2); + if (!ti2) + goto Lerror; + void[] va = va_arg!(void[])(argptr); + putArray(va.ptr, va.length, ti2); } return; @@ -813,5 +891,22 @@ assert(r == "hello"); r = std.string.format("%8s", s[0..5]); assert(r == " hello"); + + int[] arr = new int[4]; + arr[0] = 100; + arr[1] = -999; + arr[3] = 0; + r = std.string.format(arr); + assert(r == "[100,-999,0,0]"); + r = std.string.format("%s",arr); + assert(r == "[100,-999,0,0]"); + + char[][] arr2 = new char[][4]; + arr2[0] = "hello"; + arr2[1] = "world"; + arr2[3] = "foo"; + r = std.string.format(arr2); + assert(r == "[hello,world,,foo]"); + } diff -uNr dmd-0.128/dmd/src/phobos/std/stdio.d dmd-0.129/dmd/src/phobos/std/stdio.d --- dmd-0.128/dmd/src/phobos/std/stdio.d 2005-07-10 23:31:54.000000000 +0200 +++ dmd-0.129/dmd/src/phobos/std/stdio.d 2005-08-06 21:57:06.000000000 +0200 @@ -40,7 +40,7 @@ void __fp_unlock(FILE* fp) { } } -private void writex(FILE* fp, TypeInfo[] arguments, void* argptr, int newline) +void writefx(FILE* fp, TypeInfo[] arguments, void* argptr, int newline=false) { int orientation; orientation = fwide(fp, 0); @@ -120,21 +120,20 @@ void writef(...) { - writex(stdout, _arguments, _argptr, 0); + writefx(stdout, _arguments, _argptr, 0); } void writefln(...) { - writex(stdout, _arguments, _argptr, 1); + writefx(stdout, _arguments, _argptr, 1); } void fwritef(FILE* fp, ...) { - writex(fp, _arguments, _argptr, 0); + writefx(fp, _arguments, _argptr, 0); } void fwritefln(FILE* fp, ...) { - writex(fp, _arguments, _argptr, 1); + writefx(fp, _arguments, _argptr, 1); } - diff -uNr dmd-0.128/dmd/src/phobos/std/stream.d dmd-0.129/dmd/src/phobos/std/stream.d --- dmd-0.128/dmd/src/phobos/std/stream.d 2005-07-10 23:31:54.000000000 +0200 +++ dmd-0.129/dmd/src/phobos/std/stream.d 2005-08-06 21:57:06.000000000 +0200 @@ -1,4 +1,3 @@ - /* * Copyright (c) 2001-2005 * Pavel "EvilOne" Minayev @@ -163,7 +162,7 @@ // has effect on further calls to getc() and getcw() wchar ungetcw(wchar c); - int vreadf(TypeInfo[] arguments, va_list args); + int vreadf(TypeInfo[] arguments, void* args); int readf(...); @@ -237,6 +236,9 @@ // writes data with trailing newline and returns self OutputStream writefln(...); + // writes data with optional trailing newline and returns self + OutputStream writefx(TypeInfo[] arguments, void* argptr, int newline = false); + void flush(); void close(); bool isOpen(); @@ -542,7 +544,7 @@ return c; } - int vreadf(TypeInfo[] arguments, va_list args) { + int vreadf(TypeInfo[] arguments, void* args) { char[] fmt; int j = 0; int count = 0, i = 0; @@ -1023,14 +1025,19 @@ // writes data to stream using writef() syntax, OutputStream writef(...) { - doFormat(&doFormatCallback,_arguments,_argptr); - return this; + return writefx(_arguments,_argptr,0); } // writes data with trailing newline OutputStream writefln(...) { - doFormat(&doFormatCallback,_arguments,_argptr); - writeLine(""); + return writefx(_arguments,_argptr,1); + } + + // writes data with optional trailing newline + OutputStream writefx(TypeInfo[] arguments, void* argptr, int newline=false) { + doFormat(&doFormatCallback,arguments,argptr); + if (newline) + writeLine(""); return this; } diff -uNr dmd-0.128/dmd/src/phobos/std/typeinfo/ti_C.d dmd-0.129/dmd/src/phobos/std/typeinfo/ti_C.d --- dmd-0.128/dmd/src/phobos/std/typeinfo/ti_C.d 2005-07-10 23:31:56.000000000 +0200 +++ dmd-0.129/dmd/src/phobos/std/typeinfo/ti_C.d 2005-08-06 21:57:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -39,7 +39,7 @@ Object o1 = *cast(Object*)p1; Object o2 = *cast(Object*)p2; - return o1 == o2 || (o1 && o1.opCmp(o2) == 0); + return o1 == o2; } int compare(void *p1, void *p2)