diff --git a/dmd/access.c b/dmd/access.c index 1c360951..8937bbd0 100644 --- a/dmd/access.c +++ b/dmd/access.c @@ -84,8 +84,8 @@ enum PROT ClassDeclaration::getAccess(Dsymbol *smember) access_ret = smember->prot(); } - for (i = 0; i < baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)baseclasses.data[i]; + for (i = 0; i < baseclasses->dim; i++) + { BaseClass *b = (BaseClass *)baseclasses->data[i]; access = b->base->getAccess(smember); switch (access) @@ -153,8 +153,8 @@ static int accessCheckX( ClassDeclaration *cdthis = dthis->isClassDeclaration(); if (cdthis) { - for (int i = 0; i < cdthis->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; + for (int i = 0; i < cdthis->baseclasses->dim; i++) + { BaseClass *b = (BaseClass *)cdthis->baseclasses->data[i]; enum PROT access; access = b->base->getAccess(smember); @@ -174,8 +174,8 @@ static int accessCheckX( ClassDeclaration *cdthis = dthis->isClassDeclaration(); if (cdthis) { - for (int i = 0; i < cdthis->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; + 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; diff --git a/dmd/aggregate.h b/dmd/aggregate.h index f1fb5aff..47be2648 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -237,7 +237,7 @@ struct ClassDeclaration : AggregateDeclaration Array vtbl; // Array of FuncDeclaration's making up the vtbl[] Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[] - BaseClasses baseclasses; // Array of BaseClass's; first is super, + BaseClasses *baseclasses; // Array of BaseClass's; first is super, // rest are Interface's int interfaces_dim; diff --git a/dmd/arrayop.c b/dmd/arrayop.c index bab96c9e..5e2e5780 100644 --- a/dmd/arrayop.c +++ b/dmd/arrayop.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -34,6 +34,46 @@ extern int binary(const char *p , const char **tab, int high); StringTable arrayfuncs; #endif +/********************************************** + * Check that there are no uses of arrays without []. + */ +bool isArrayOpValid(Expression *e) +{ + if (e->op == TOKslice) + return true; + Type *tb = e->type->toBasetype(); + + if ( (tb->ty == Tarray) || (tb->ty == Tsarray) ) + { + switch (e->op) + { + case TOKadd: + case TOKmin: + case TOKmul: + case TOKdiv: + case TOKmod: + case TOKxor: + case TOKand: + case TOKor: +#if DMDV2 + case TOKpow: +#endif + return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2); + + case TOKcall: + return false; // TODO: Decide if [] is required after arrayop calls. + + case TOKneg: + case TOKtilde: + return isArrayOpValid(((UnaExp *)e)->e1); + + default: + return false; + } + } + return true; +} + /*********************************** * Construct the array operation expression. */ @@ -48,6 +88,12 @@ Expression *BinExp::arrayOp(Scope *sc) return new ErrorExp(); } + if (!isArrayOpValid(e2)) + { + e2->error("invalid array operation %s (did you forget a [] ?)", toChars()); + return new ErrorExp(); + } + Expressions *arguments = new Expressions(); /* The expression to generate an array operation for is mangled diff --git a/dmd/attrib.c b/dmd/attrib.c index 7799fab7..a8883aab 100644 --- a/dmd/attrib.c +++ b/dmd/attrib.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -468,7 +468,27 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc) { if (stc & table[i].stc) { - buf->writestring(Token::toChars(table[i].tok)); + enum TOK tok = table[i].tok; +#if DMDV2 + if (tok == TOKat) + { Identifier *id; + + if (stc & STCproperty) + id = Id::property; + else if (stc & STCsafe) + id = Id::safe; + else if (stc & STCtrusted) + id = Id::trusted; + else if (stc & STCdisable) + id = Id::disable; + else + assert(0); + buf->writeByte('@'); + buf->writestring(id->toChars()); + } + else +#endif + buf->writestring(Token::toChars(tok)); buf->writeByte(' '); } } @@ -963,7 +983,7 @@ void PragmaDeclaration::semantic(Scope *sc) fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); } else - fprintf(stdmsg, e->toChars()); + fprintf(stdmsg, "%s", e->toChars()); } fprintf(stdmsg, "\n"); } diff --git a/dmd/cast.c b/dmd/cast.c index b7650c76..23f653c1 100644 --- a/dmd/cast.c +++ b/dmd/cast.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -84,22 +84,25 @@ printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco); //printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t); fflush(stdout); #endif - if (!t->deco) - { /* Can happen with: - * enum E { One } - * class A - * { static void fork(EDG dg) { dg(E.One); } - * alias void delegate(E) EDG; - * } - * Should eventually make it work. - */ - error("forward reference to type %s", t->toChars()); - } - else if (t->reliesOnTident()) - error("forward reference to type %s", t->reliesOnTident()->toChars()); + if (t->ty != Terror && type->ty != Terror) + { + if (!t->deco) + { /* Can happen with: + * enum E { One } + * class A + * { static void fork(EDG dg) { dg(E.One); } + * alias void delegate(E) EDG; + * } + * Should eventually make it work. + */ + error("forward reference to type %s", t->toChars()); + } + else if (t->reliesOnTident()) + error("forward reference to type %s", t->reliesOnTident()->toChars()); - error("cannot implicitly convert expression (%s) of type %s to %s", - toChars(), type->toChars(), t->toChars()); + error("cannot implicitly convert expression (%s) of type %s to %s", + toChars(), type->toChars(), t->toChars()); + } return new ErrorExp(); } @@ -828,7 +831,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t) case X(Tchar, Twchar): for (size_t u = 0; u < len;) { unsigned c; - char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); + const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); if (p) error("%s", p); else @@ -841,7 +844,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t) case X(Tchar, Tdchar): for (size_t u = 0; u < len;) { unsigned c; - char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); + const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); if (p) error("%s", p); buffer.write4(c); @@ -853,7 +856,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t) case X(Twchar,Tchar): for (size_t u = 0; u < len;) { unsigned c; - char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); + const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); if (p) error("%s", p); else @@ -866,7 +869,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t) case X(Twchar,Tdchar): for (size_t u = 0; u < len;) { unsigned c; - char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); + const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); if (p) error("%s", p); buffer.write4(c); @@ -1550,6 +1553,7 @@ Expression *BinExp::typeCombine(Scope *sc) type = Type::terror; e1 = new ErrorExp(); e2 = new ErrorExp(); + return new ErrorExp(); } Lret: if (!type) diff --git a/dmd/class.c b/dmd/class.c index 4ecbee44..f5808287 100644 --- a/dmd/class.c +++ b/dmd/class.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -38,7 +38,10 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla static char msg[] = "only object.d can define this reserved class name"; if (baseclasses) - this->baseclasses = *baseclasses; + // Actually, this is a transfer + this->baseclasses = baseclasses; + else + this->baseclasses = new BaseClasses(); baseClass = NULL; interfaces_dim = 0; @@ -46,7 +49,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla vtblInterfaces = NULL; - //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim); + //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->dim); // For forward references type = new TypeClass(this); @@ -209,12 +212,12 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) cd->storage_class |= storage_class; - cd->baseclasses.setDim(this->baseclasses.dim); - for (int i = 0; i < cd->baseclasses.dim; i++) + cd->baseclasses->setDim(this->baseclasses->dim); + for (int i = 0; i < cd->baseclasses->dim; i++) { - BaseClass *b = (BaseClass *)this->baseclasses.data[i]; + BaseClass *b = (BaseClass *)this->baseclasses->data[i]; BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); - cd->baseclasses.data[i] = b2; + cd->baseclasses->data[i] = b2; } ScopeDsymbol::syntaxCopy(cd); @@ -275,20 +278,20 @@ void ClassDeclaration::semantic(Scope *sc) } // Expand any tuples in baseclasses[] - for (i = 0; i < baseclasses.dim; ) - { BaseClass *b = (BaseClass *)baseclasses.data[i]; + for (i = 0; i < baseclasses->dim; ) + { BaseClass *b = (BaseClass *)baseclasses->data[i]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); if (tb->ty == Ttuple) { TypeTuple *tup = (TypeTuple *)tb; enum PROT protection = b->protection; - baseclasses.remove(i); + baseclasses->remove(i); size_t dim = Parameter::dim(tup->arguments); for (size_t j = 0; j < dim; j++) { Parameter *arg = Parameter::getNth(tup->arguments, j); b = new BaseClass(arg->type, protection); - baseclasses.insert(i + j, b); + baseclasses->insert(i + j, b); } } else @@ -296,17 +299,17 @@ void ClassDeclaration::semantic(Scope *sc) } // See if there's a base class as first in baseclasses[] - if (baseclasses.dim) + if (baseclasses->dim) { TypeClass *tc; BaseClass *b; Type *tb; - b = (BaseClass *)baseclasses.data[0]; + b = (BaseClass *)baseclasses->data[0]; //b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty != Tclass) { error("base type must be class or interface, not %s", b->type->toChars()); - baseclasses.remove(0); + baseclasses->remove(0); } else { @@ -332,7 +335,7 @@ void ClassDeclaration::semantic(Scope *sc) if (cdb == this) { error("circular inheritance"); - baseclasses.remove(0); + baseclasses->remove(0); goto L7; } } @@ -365,12 +368,12 @@ void ClassDeclaration::semantic(Scope *sc) // Treat the remaining entries in baseclasses as interfaces // Check for errors, handle forward references - for (i = (baseClass ? 1 : 0); i < baseclasses.dim; ) + for (i = (baseClass ? 1 : 0); i < baseclasses->dim; ) { TypeClass *tc; BaseClass *b; Type *tb; - b = (BaseClass *)baseclasses.data[i]; + b = (BaseClass *)baseclasses->data[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) @@ -380,7 +383,7 @@ void ClassDeclaration::semantic(Scope *sc) if (!tc || !tc->sym->isInterfaceDeclaration()) { error("base type must be interface, not %s", b->type->toChars()); - baseclasses.remove(i); + baseclasses->remove(i); continue; } else @@ -399,7 +402,7 @@ void ClassDeclaration::semantic(Scope *sc) // Check for duplicate interfaces for (size_t j = (baseClass ? 1 : 0); j < i; j++) { - BaseClass *b2 = (BaseClass *)baseclasses.data[j]; + BaseClass *b2 = (BaseClass *)baseclasses->data[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } @@ -444,7 +447,7 @@ void ClassDeclaration::semantic(Scope *sc) } bt = tbase->semantic(loc, sc)->toBasetype(); b = new BaseClass(bt, PROTpublic); - baseclasses.shift(b); + baseclasses->shift(b); assert(b->type->ty == Tclass); tc = (TypeClass *)(b->type); baseClass = tc->sym; @@ -452,8 +455,8 @@ void ClassDeclaration::semantic(Scope *sc) b->base = baseClass; } - interfaces_dim = baseclasses.dim; - interfaces = (BaseClass **)baseclasses.data; + interfaces_dim = baseclasses->dim; + interfaces = (BaseClass **)baseclasses->data; if (baseClass) @@ -665,13 +668,14 @@ void ClassDeclaration::semantic(Scope *sc) if (!ctor && baseClass && baseClass->ctor) { //printf("Creating default this(){} for class %s\n", toChars()); - ctor = new CtorDeclaration(loc, 0, NULL, 0); + CtorDeclaration *ctor = new CtorDeclaration(loc, 0, NULL, 0); ctor->fbody = new CompoundStatement(0, new Statements()); members->push(ctor); ctor->addMember(sc, this, 1); *sc = scsave; // why? What about sc->nofree? sc->offset = structsize; ctor->semantic(sc); + this->ctor = ctor; defaultCtor = ctor; } @@ -731,12 +735,12 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->printf("%s ", kind()); buf->writestring(toChars()); - if (baseclasses.dim) + if (baseclasses->dim) buf->writestring(" : "); } - for (int i = 0; i < baseclasses.dim; i++) + for (int i = 0; i < baseclasses->dim; i++) { - BaseClass *b = (BaseClass *)baseclasses.data[i]; + BaseClass *b = (BaseClass *)baseclasses->data[i]; if (i) buf->writeByte(','); @@ -784,8 +788,8 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) if (!cd) return 0; //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); - for (int i = 0; i < cd->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; + for (int i = 0; i < cd->baseclasses->dim; i++) + { BaseClass *b = (BaseClass *)cd->baseclasses->data[i]; if (b->base == this || isBaseOf2(b->base)) return 1; @@ -809,7 +813,7 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) /* cd->baseClass might not be set if cd is forward referenced. */ - if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration()) + if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration()) { cd->error("base class is forward referenced by %s", toChars()); } @@ -845,9 +849,9 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) int i; - for (i = 0; i < baseclasses.dim; i++) + for (i = 0; i < baseclasses->dim; i++) { - BaseClass *b = (BaseClass *)baseclasses.data[i]; + BaseClass *b = (BaseClass *)baseclasses->data[i]; if (b->base) { @@ -1096,20 +1100,20 @@ void InterfaceDeclaration::semantic(Scope *sc) } // Expand any tuples in baseclasses[] - for (i = 0; i < baseclasses.dim; ) - { BaseClass *b = (BaseClass *)baseclasses.data[0]; + for (i = 0; i < baseclasses->dim; ) + { BaseClass *b = (BaseClass *)baseclasses->data[0]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); if (tb->ty == Ttuple) { TypeTuple *tup = (TypeTuple *)tb; enum PROT protection = b->protection; - baseclasses.remove(i); + baseclasses->remove(i); size_t dim = Parameter::dim(tup->arguments); for (size_t j = 0; j < dim; j++) { Parameter *arg = Parameter::getNth(tup->arguments, j); b = new BaseClass(arg->type, protection); - baseclasses.insert(i + j, b); + baseclasses->insert(i + j, b); } } else @@ -1117,12 +1121,12 @@ void InterfaceDeclaration::semantic(Scope *sc) } // Check for errors, handle forward references - for (i = 0; i < baseclasses.dim; ) + for (i = 0; i < baseclasses->dim; ) { TypeClass *tc; BaseClass *b; Type *tb; - b = (BaseClass *)baseclasses.data[i]; + b = (BaseClass *)baseclasses->data[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) @@ -1132,7 +1136,7 @@ void InterfaceDeclaration::semantic(Scope *sc) if (!tc || !tc->sym->isInterfaceDeclaration()) { error("base type must be interface, not %s", b->type->toChars()); - baseclasses.remove(i); + baseclasses->remove(i); continue; } else @@ -1140,7 +1144,7 @@ void InterfaceDeclaration::semantic(Scope *sc) // Check for duplicate interfaces for (size_t j = 0; j < i; j++) { - BaseClass *b2 = (BaseClass *)baseclasses.data[j]; + BaseClass *b2 = (BaseClass *)baseclasses->data[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } @@ -1149,7 +1153,7 @@ void InterfaceDeclaration::semantic(Scope *sc) if (b->base == this || isBaseOf2(b->base)) { error("circular inheritance of interface"); - baseclasses.remove(i); + baseclasses->remove(i); continue; } if (!b->base->symtab) @@ -1171,8 +1175,8 @@ void InterfaceDeclaration::semantic(Scope *sc) i++; } - interfaces_dim = baseclasses.dim; - interfaces = (BaseClass **)baseclasses.data; + interfaces_dim = baseclasses->dim; + interfaces = (BaseClass **)baseclasses->data; interfaceSemantic(sc); diff --git a/dmd/constfold.c b/dmd/constfold.c index af6f496c..e3671bd4 100644 --- a/dmd/constfold.c +++ b/dmd/constfold.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -1150,8 +1150,9 @@ Expression *Cast(Type *type, Type *to, Expression *e1) } else { - error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars()); - e = new IntegerExp(loc, 0, Type::tint32); + if (type != Type::terror) + error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars()); + e = new ErrorExp(); } return e; } diff --git a/dmd/declaration.c b/dmd/declaration.c index 7954e48d..f38fe632 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -97,7 +97,10 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t) if (sc->incontract && isParameter()) error(loc, "cannot modify parameter '%s' in contract", toChars()); - if (isCtorinit()) + if (sc->incontract && isResult()) + error(loc, "cannot modify result '%s' in contract", toChars()); + + if (isCtorinit() && !t->isMutable()) { // It's only modifiable if inside the right constructor Dsymbol *s = sc->func; while (1) @@ -479,11 +482,11 @@ void AliasDeclaration::semantic(Scope *sc) #if DMDV2 type = type->addStorageClass(storage_class); - if (storage_class & (STCref | STCnothrow | STCpure)) + if (storage_class & (STCref | STCnothrow | STCpure | STCdisable)) { // For 'ref' to be attached to function types, and picked // up by Type::resolve(), it has to go into sc. sc = sc->push(); - sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared); + sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared | STCdisable); type->resolve(loc, sc, &e, &t, &s); sc = sc->pop(); } @@ -552,8 +555,8 @@ void AliasDeclaration::semantic(Scope *sc) s = NULL; } } - if (!aliassym) - aliassym = s; + //printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars()); + aliassym = s; this->inSemantic = 0; } @@ -673,7 +676,10 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer #endif this->loc = loc; offset = 0; - noscope = 0; + noauto = 0; +#if DMDV2 + isargptr = FALSE; +#endif #if DMDV1 nestedref = 0; #endif @@ -951,11 +957,11 @@ void VarDeclaration::semantic(Scope *sc) } #endif - if (type->isscope() && !noscope) + if (type->isscope() && !noauto) { if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) { - error("globals, statics, fields, ref and out parameters cannot be scope"); + error("globals, statics, fields, ref and out parameters cannot be auto"); } if (!(storage_class & STCscope)) @@ -1394,7 +1400,7 @@ int VarDeclaration::isCTFE() { //printf("VarDeclaration::isCTFE(%p, '%s')\n", this, toChars()); //printf("%llx\n", storage_class); - return (storage_class & STCctfe) || !isDataseg(); + return (storage_class & STCctfe) != 0; // || !isDataseg(); } int VarDeclaration::hasPointers() @@ -1420,7 +1426,7 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc) { Expression *e = NULL; //printf("VarDeclaration::callScopeDtor() %s\n", toChars()); - if (storage_class & STCscope && !noscope) + if (storage_class & STCscope && !noauto) { for (ClassDeclaration *cd = type->isClassHandle(); cd; @@ -1630,7 +1636,7 @@ TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) ThisDeclaration::ThisDeclaration(Loc loc, Type *t) : VarDeclaration(loc, t, Id::This, NULL) { - noscope = 1; + noauto = 1; } Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) diff --git a/dmd/declaration.h b/dmd/declaration.h index c91ac035..42955ac2 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -265,7 +265,7 @@ struct VarDeclaration : Declaration { Initializer *init; unsigned offset; - int noscope; // no scope semantics + int noauto; // no scope semantics #if DMDV2 FuncDeclarations nestedrefs; // referenced by these lexically nested functions bool isargptr; // if parameter that _argptr points to diff --git a/dmd/doc.c b/dmd/doc.c index a22f506d..20cac454 100644 --- a/dmd/doc.c +++ b/dmd/doc.c @@ -856,8 +856,8 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf) buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); } int any = 0; - for (int i = 0; i < baseclasses.dim; i++) - { BaseClass *bc = (BaseClass *)baseclasses.data[i]; + for (int i = 0; i < baseclasses->dim; i++) + { BaseClass *bc = (BaseClass *)baseclasses->data[i]; if (bc->protection == PROTprivate) continue; diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index e21943e1..2f9653d5 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -845,7 +845,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) { Declaration *d = s->isDeclaration(); if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin()) - error("%s is private", d->toPrettyChars()); + error(loc, "%s is private", d->toPrettyChars()); } } return s; diff --git a/dmd/expression.c b/dmd/expression.c index 64366fc9..d384d11c 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -1059,18 +1059,24 @@ char *Expression::toChars() void Expression::error(const char *format, ...) { - va_list ap; - va_start(ap, format); - ::verror(loc, format, ap); - va_end( ap ); + if (type != Type::terror) + { + va_list ap; + va_start(ap, format); + ::verror(loc, format, ap); + va_end( ap ); + } } void Expression::warning(const char *format, ...) { - va_list ap; - va_start(ap, format); - ::vwarning(loc, format, ap); - va_end( ap ); + if (type != Type::terror) + { + va_list ap; + va_start(ap, format); + ::vwarning(loc, format, ap); + va_end( ap ); + } } void Expression::rvalue() @@ -1403,7 +1409,8 @@ IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type) if (type && !type->isscalar()) { //printf("%s, loc = %d\n", toChars(), loc.linnum); - error("integral constant must be scalar type, not %s", type->toChars()); + if (type->ty != Terror) + error("integral constant must be scalar type, not %s", type->toChars()); type = Type::terror; } this->type = type; @@ -4160,8 +4167,8 @@ void VarExp::checkEscape() // if reference type if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass) { - if (v->isScope() && !v->noscope) - error("escaping reference to scope local %s", v->toChars()); + if (v->isScope() && !v->noauto) + error("escaping reference to auto local %s", v->toChars()); else if (v->storage_class & STCvariadic) error("escaping reference to variadic parameter %s", v->toChars()); } @@ -4824,9 +4831,9 @@ Expression *IsExp::semantic(Scope *sc) else { ClassDeclaration *cd = ((TypeClass *)targ)->sym; Parameters *args = new Parameters; - args->reserve(cd->baseclasses.dim); - for (size_t i = 0; i < cd->baseclasses.dim; i++) - { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; + args->reserve(cd->baseclasses->dim); + for (size_t i = 0; i < cd->baseclasses->dim; i++) + { BaseClass *b = (BaseClass *)cd->baseclasses->data[i]; args->push(new Parameter(STCin, b->type, NULL, NULL)); } tded = new TypeTuple(args); @@ -5246,9 +5253,12 @@ int BinExp::canThrow() void BinExp::incompatibleTypes() { - error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", - e1->toChars(), Token::toChars(op), e2->toChars(), - e1->type->toChars(), e2->type->toChars()); + if (e1->type->toBasetype() != Type::terror && + e2->type->toBasetype() != Type::terror + ) + error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", + e1->toChars(), Token::toChars(op), e2->toChars(), + e1->type->toChars(), e2->type->toChars()); } /************************************************************/ @@ -5550,13 +5560,13 @@ Expression *DotIdExp::semantic(Scope *sc) if (e1->op == TOKdottd) { error("template %s does not have property %s", e1->toChars(), ident->toChars()); - return e1; + return new ErrorExp(); } if (!e1->type) { error("expression %s does not have property %s", e1->toChars(), ident->toChars()); - return e1; + return new ErrorExp(); } if (eright->op == TOKimport) // also used for template alias's @@ -6005,7 +6015,27 @@ L1: Dsymbol *s = ti->inst->toAlias(); Declaration *v = s->isDeclaration(); if (v) - { e = new DotVarExp(loc, eleft, v); + { + /* Fix for Bugzilla 4003 + * The problem is a class template member function v returning a reference to the same + * type as the enclosing template instantiation. This results in a nested instantiation, + * which of course gets short circuited. The return type then gets set to + * the template instance type before instantiation, rather than after. + * We can detect this by the deco not being set. If so, go ahead and retry + * the return type semantic. + * The offending code is the return type from std.typecons.Tuple.slice: + * ref Tuple!(Types[from .. to]) slice(uint from, uint to)() + * { + * return *cast(typeof(return) *) &(field[from]); + * } + * and this line from the following unittest: + * auto s = a.slice!(1, 3); + * where s's type wound up not having semantic() run on it. + */ + if (v->type && !v->type->deco) + v->type = v->type->semantic(v->loc, sc); + + e = new DotVarExp(loc, eleft, v); e = e->semantic(sc); return e; } @@ -7074,6 +7104,7 @@ Expression *PtrExp::semantic(Scope *sc) default: error("can only * a pointer, not a '%s'", e1->type->toChars()); + case Terror: return new ErrorExp(); } rvalue(); @@ -7479,26 +7510,7 @@ void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) to->toCBuffer(buf, NULL, hgs); else { - switch (mod) - { case 0: - break; - case MODconst: - buf->writestring(Token::tochars[TOKconst]); - break; - case MODimmutable: - buf->writestring(Token::tochars[TOKimmutable]); - break; - case MODshared: - buf->writestring(Token::tochars[TOKshared]); - break; - case MODshared | MODconst: - buf->writestring(Token::tochars[TOKshared]); - buf->writeByte(' '); - buf->writestring(Token::tochars[TOKconst]); - break; - default: - assert(0); - } + MODtoBuffer(buf, mod); } #endif buf->writeByte(')'); @@ -7550,7 +7562,9 @@ Expression *SliceExp::semantic(Scope *sc) if (t->ty == Tpointer) { if (!lwr || !upr) - error("need upper and lower bound to slice pointer"); + { error("need upper and lower bound to slice pointer"); + return new ErrorExp(); + } } else if (t->ty == Tarray) { @@ -7611,11 +7625,15 @@ Expression *SliceExp::semantic(Scope *sc) { lwr = lwr->semantic(sc); lwr = resolveProperties(sc, lwr); lwr = lwr->implicitCastTo(sc, Type::tsize_t); + if (lwr->type == Type::terror) + goto Lerr; } if (upr) { upr = upr->semantic(sc); upr = resolveProperties(sc, upr); upr = upr->implicitCastTo(sc, Type::tsize_t); + if (lwr->type == Type::terror) + goto Lerr; } if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) @@ -7670,7 +7688,7 @@ Expression *SliceExp::semantic(Scope *sc) else { error("string slice [%ju .. %ju] is out of bounds", i1, i2); - e = new IntegerExp(0); + goto Lerr; } return e; } @@ -7684,12 +7702,15 @@ Expression *SliceExp::semantic(Scope *sc) return e; Lerror: + if (e1->op == TOKerror) + return e1; char *s; if (t->ty == Tvoid) s = e1->toChars(); else s = t->toChars(); error("%s cannot be sliced with []", s); +Lerr: e = new ErrorExp(); return e; } @@ -7798,7 +7819,9 @@ Expression *ArrayExp::semantic(Scope *sc) if (t1->ty != Tclass && t1->ty != Tstruct) { // Convert to IndexExp if (arguments->dim != 1) - error("only one index allowed to index %s", t1->toChars()); + { error("only one index allowed to index %s", t1->toChars()); + goto Lerr; + } e = new IndexExp(loc, e1, (Expression *)arguments->data[0]); return e->semantic(sc); } @@ -7809,7 +7832,11 @@ Expression *ArrayExp::semantic(Scope *sc) e = e->semantic(sc); if (!e->type) - error("%s has no value", e->toChars()); + { error("%s has no value", e->toChars()); + goto Lerr; + } + else if (e->type == Type::terror) + goto Lerr; arguments->data[i] = (void *)e; } @@ -7819,9 +7846,12 @@ Expression *ArrayExp::semantic(Scope *sc) e = op_overload(sc); if (!e) { error("no [] operator overload for type %s", e1->type->toChars()); - e = e1; + goto Lerr; } return e; + +Lerr: + return new ErrorExp(); } #if DMDV2 @@ -7987,9 +8017,11 @@ Expression *IndexExp::semantic(Scope *sc) if (!e2->type) { error("%s has no value", e2->toChars()); - e2->type = Type::terror; + goto Lerr; } e2 = resolveProperties(sc, e2); + if (e2->type == Type::terror) + goto Lerr; if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) sc = sc->pop(); @@ -8074,10 +8106,13 @@ Expression *IndexExp::semantic(Scope *sc) default: error("%s must be an array or pointer type, not %s", e1->toChars(), e1->type->toChars()); - type = Type::tint32; - break; + case Terror: + goto Lerr; } return e; + +Lerr: + return new ErrorExp(); } #if DMDV2 @@ -8408,6 +8443,14 @@ Expression *AssignExp::checkToBoolean() /************************************************************/ +ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2) + : AssignExp(loc, e1, e2) +{ + op = TOKconstruct; +} + +/************************************************************/ + AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) { @@ -8588,7 +8631,9 @@ Expression *CatAssignExp::semantic(Scope *sc) { SliceExp *se = (SliceExp *)e1; if (se->e1->type->toBasetype()->ty == Tsarray) - error("cannot append to static array %s", se->e1->type->toChars()); + { error("cannot append to static array %s", se->e1->type->toChars()); + return new ErrorExp(); + } } e1 = e1->modifiableLvalue(sc, e1); @@ -8638,7 +8683,8 @@ Expression *CatAssignExp::semantic(Scope *sc) } else { - error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); + if (tb1 != Type::terror && tb2 != Type::terror) + error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); e = new ErrorExp(); } return e; @@ -9710,20 +9756,30 @@ Expression *InExp::semantic(Scope *sc) //type = Type::tboolean; Type *t2b = e2->type->toBasetype(); - if (t2b->ty != Taarray) + switch (t2b->ty) { - error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); - type = Type::terror; - } - else - { - TypeAArray *ta = (TypeAArray *)t2b; + case Taarray: + { + TypeAArray *ta = (TypeAArray *)t2b; - // Convert key to type of key - e1 = e1->implicitCastTo(sc, ta->index); +#if DMDV2 + // Special handling for array keys + if (!arrayTypeCompatible(e1->loc, e1->type, ta->index)) +#endif + { + // Convert key to type of key + e1 = e1->implicitCastTo(sc, ta->index); + } - // Return type is pointer to value - type = ta->nextOf()->pointerTo(); + // Return type is pointer to value + type = ta->nextOf()->pointerTo(); + break; + } + + default: + error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); + case Terror: + return new ErrorExp(); } return this; } diff --git a/dmd/expression.h b/dmd/expression.h index 939c35af..6af35e5d 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -606,6 +606,7 @@ struct NewExp : Expression Type *newtype, Expressions *arguments); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); Expression *optimize(int result); #if IN_DMD elem *toElem(IRState *irs); @@ -1399,6 +1400,11 @@ struct AssignExp : BinExp AssignExp* isAssignExp() { return this; } }; +struct ConstructExp : AssignExp +{ + ConstructExp(Loc loc, Expression *e1, Expression *e2); +}; + #if IN_DMD #define ASSIGNEXP_TOELEM elem *toElem(IRState *irs); #elif IN_LLVM diff --git a/dmd/func.c b/dmd/func.c index 826dad4b..0e0f7f00 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -184,6 +184,8 @@ void FuncDeclaration::semantic(Scope *sc) foverrides.setDim(0); // reset in case semantic() is being retried for this function + if (!originalType) + originalType = type; if (!type->deco) { type = type->semantic(loc, sc); @@ -1019,7 +1021,7 @@ void FuncDeclaration::semantic3(Scope *sc) loc = fensure->loc; v = new VarDeclaration(loc, type->nextOf(), outId, NULL); - v->noscope = 1; + v->noauto = 1; #if DMDV2 if (!isVirtual()) v->storage_class |= STCconst; @@ -1264,6 +1266,7 @@ void FuncDeclaration::semantic3(Scope *sc) assert(v->init); ExpInitializer *ie = v->init->isExpInitializer(); assert(ie); + ie->exp->op = TOKassign; // construction occurred in parameter processing a->push(new ExpStatement(0, ie->exp)); } } @@ -1294,6 +1297,8 @@ void FuncDeclaration::semantic3(Scope *sc) offset = p->type->size(); offset = (offset + 3) & ~3; // assume stack aligns on 4 Expression *e = new SymOffExp(0, p, offset); + e->type = Type::tvoidptr; + //e = e->semantic(sc); e = new AssignExp(0, e1, e); e->type = t; a->push(new ExpStatement(0, e)); diff --git a/dmd/inline.c b/dmd/inline.c index 2fb7fc50..43104f60 100644 --- a/dmd/inline.c +++ b/dmd/inline.c @@ -1374,6 +1374,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan) } #if !IN_LLVM +#if !SARRAYVALUE /* If any parameters are Tsarray's (which are passed by reference) * or out parameters (also passed by reference), don't do inlining. */ @@ -1382,10 +1383,11 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan) for (int i = 0; i < parameters->dim; i++) { VarDeclaration *v = (VarDeclaration *)parameters->data[i]; - if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray) + if (/*v->isOut() || v->isRef() ||*/ v->type->toBasetype()->ty == Tsarray) goto Lno; } } +#endif #endif memset(&ics, 0, sizeof(ics)); @@ -1517,6 +1519,7 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A ve->type = arg->type; ei->exp = new AssignExp(vto->loc, ve, arg); + ei->exp->op = TOKconstruct; ei->exp->type = ve->type; //ve->type->print(); //arg->type->print(); @@ -1538,7 +1541,50 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A //eb->type->print(); //eb->print(); //eb->dump(0); - return Expression::combine(e, eb); + e = Expression::combine(e, eb); + + /* There's a problem if what the function returns is used subsequently as an + * lvalue, as in a struct return that is then used as a 'this'. + * If we take the address of the return value, we will be taking the address + * of the original, not the copy. Fix this by assigning the return value to + * a temporary, then returning the temporary. If the temporary is used as an + * lvalue, it will work. + * This only happens with struct returns. + * See Bugzilla 2127 for an example. + */ + TypeFunction *tf = (TypeFunction*)type; + if (tf->next->ty == Tstruct) + { + /* Generate a new variable to hold the result and initialize it with the + * inlined body of the function: + * tret __inlineretval = e; + */ + ExpInitializer* ei = new ExpInitializer(loc, e); + + Identifier* tmp = Identifier::generateId("__inlineretval"); + VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei); + vd->storage_class = 0; + vd->linkage = tf->linkage; + vd->parent = iss->fd; + + VarExp *ve = new VarExp(loc, vd); + ve->type = tf->next; + + ei->exp = new AssignExp(loc, ve, e); + ei->exp->op = TOKconstruct; + ei->exp->type = ve->type; + + DeclarationExp* de = new DeclarationExp(0, vd); + de->type = Type::tvoid; + + // Chain the two together: + // ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval + e = Expression::combine(de, ve); + + //fprintf(stderr, "CallExp::inlineScan: e = "); e->print(); + } + + return e; } diff --git a/dmd/interpret.c b/dmd/interpret.c index 9491904d..1be11d35 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -55,6 +55,7 @@ Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclarati ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim); Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference = NULL); +Expression *getVarExp(Loc loc, InterState *istate, Declaration *d); /************************************* * Attempt to interpret a function given the arguments. @@ -118,18 +119,6 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument return NULL; } - // Ensure there are no lazy parameters - if (tf->parameters) - { size_t dim = Parameter::dim(tf->parameters); - for (size_t i = 0; i < dim; i++) - { Parameter *arg = Parameter::getNth(tf->parameters, i); - if (arg->storageClass & STClazy) - { cantInterpret = 1; - return NULL; - } - } - } - InterState istatex; istatex.caller = istate; istatex.fd = this; @@ -143,6 +132,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument error("need 'this' to access member %s", toChars()); return NULL; } + if (thisarg && !istate) + { // Check that 'this' aleady has a value + if (thisarg->interpret(istate) == EXP_CANT_INTERPRET) + return NULL; + } if (arguments) { dim = arguments->dim; @@ -159,7 +153,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument { Expression *earg = (Expression *)arguments->data[i]; Parameter *arg = Parameter::getNth(tf->parameters, i); - if (arg->storageClass & (STCout | STCref | STClazy)) + if (arg->storageClass & (STCout | STCref)) + { + if (!istate) + { + earg->error("%s cannot be passed by reference at compile time", earg->toChars()); + return NULL; + } + } + else if (arg->storageClass & STClazy) { } else @@ -173,7 +175,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument */ earg = ((AddrExp *)earg)->e1; } - earg = earg->interpret(istate ? istate : &istatex); + earg = earg->interpret(istate); // ? istate : &istatex); if (earg == EXP_CANT_INTERPRET) { cantInterpret = 1; return NULL; @@ -1251,7 +1253,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) if (e && !e->type) e->type = v->type; } - else if (v->isCTFE() && !v->value) + else if ((v->isCTFE() || (!v->isDataseg() && istate)) && !v->value) { if (v->init) { @@ -1266,9 +1268,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) else e = v->type->defaultInitLiteral(loc); } + else if (!v->isDataseg() && !istate) { + error(loc, "variable %s cannot be read at compile time", v->toChars()); + return EXP_CANT_INTERPRET; + } else { e = v->value; - if (!v->isCTFE()) + if (!v->isCTFE() && v->isDataseg()) { error(loc, "static variable %s cannot be read at compile time", v->toChars()); e = EXP_CANT_INTERPRET; } @@ -1579,6 +1585,24 @@ Expression *StructLiteralExp::interpret(InterState *istate) return this; } +Expression *NewExp::interpret(InterState *istate) +{ +#if LOG + printf("NewExp::interpret() %s\n", toChars()); +#endif + if (newtype->ty == Tarray && arguments && arguments->dim == 1) + { + Expression *lenExpr = ((Expression *)(arguments->data[0]))->interpret(istate); + if (lenExpr == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + return createBlockDuplicatedArrayLiteral(newtype, + ((TypeArray *)newtype)->next->defaultInitLiteral(), + lenExpr->toInteger()); + } + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; +} + Expression *UnaExp::interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *)) { Expression *e; Expression *e1; @@ -1841,7 +1865,7 @@ Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, * set arr[index] = newval and return the new array. * */ -Expression * assignArrayElement(Expression *arr, Expression *index, Expression *newval) +Expression * assignArrayElement(Loc loc, Expression *arr, Expression *index, Expression *newval) { ArrayLiteralExp *ae = NULL; AssocArrayLiteralExp *aae = NULL; @@ -1859,7 +1883,7 @@ Expression * assignArrayElement(Expression *arr, Expression *index, Expression * int elemi = index->toInteger(); if (elemi >= ae->elements->dim) { - error("array index %d is out of bounds %s[0..%d]", elemi, + error(loc, "array index %d is out of bounds %s[0..%d]", elemi, arr->toChars(), ae->elements->dim); return EXP_CANT_INTERPRET; } @@ -1874,6 +1898,12 @@ Expression * assignArrayElement(Expression *arr, Expression *index, Expression * /* Create new string literal reflecting updated elem */ int elemi = index->toInteger(); + if (elemi >= se->len) + { + error(loc, "array index %d is out of bounds %s[0..%d]", elemi, + arr->toChars(), se->len); + return EXP_CANT_INTERPRET; + } unsigned char *s; s = (unsigned char *)mem.calloc(se->len + 1, se->sz); memcpy(s, se->string, se->len * se->sz); @@ -2087,6 +2117,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) if (e1 == EXP_CANT_INTERPRET) return e1; + assert(istate); + // ---------------------------------------------------- // Deal with read-modify-write assignments. // Set 'newval' to the final assignment value @@ -2097,7 +2129,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) if (newval == EXP_CANT_INTERPRET) return newval; - if (fp) + if (fp || e1->op == TOKarraylength) { // If it isn't a simple assignment, we need the existing value Expression * oldval = e1->interpret(istate); @@ -2105,17 +2137,72 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) return EXP_CANT_INTERPRET; while (oldval->op == TOKvar) { - oldval = resolveReferences(oldval, istate->localThis); - oldval = oldval->interpret(istate); - if (oldval == EXP_CANT_INTERPRET) return oldval; + oldval = resolveReferences(oldval, istate->localThis); + oldval = oldval->interpret(istate); + if (oldval == EXP_CANT_INTERPRET) + return oldval; + } + + if (fp) + { + newval = (*fp)(type, oldval, newval); + if (newval == EXP_CANT_INTERPRET) + { + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + // Determine the return value + e = Cast(type, type, post ? oldval : newval); + if (e == EXP_CANT_INTERPRET) + return e; + } + else + e = newval; + + if (e1->op == TOKarraylength) + { + size_t oldlen = oldval->toInteger(); + size_t newlen = newval->toInteger(); + if (oldlen == newlen) // no change required -- we're done! + return e; + // Now change the assignment from arr.length = n into arr = newval + e1 = ((ArrayLengthExp *)e1)->e1; + if (oldlen != 0) + { // Get the old array literal. + oldval = e1->interpret(istate); + while (oldval->op == TOKvar) + { oldval = resolveReferences(oldval, istate->localThis); + oldval = oldval->interpret(istate); + } + } + Type *t = e1->type->toBasetype(); + if (t->ty == Tarray) + { + Type *elemType= NULL; + elemType = ((TypeArray *)t)->next; + assert(elemType); + Expression *defaultElem = elemType->defaultInitLiteral(); + + Expressions *elements = new Expressions(); + elements->setDim(newlen); + size_t copylen = oldlen < newlen ? oldlen : newlen; + ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval; + for (size_t i = 0; i < copylen; i++) + elements->data[i] = ae->elements->data[i]; + + for (size_t i = copylen; i < newlen; i++) + elements->data[i] = defaultElem; + ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements); + aae->type = t; + newval = aae; + } + else + { + error("%s is not yet supported at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + } - newval = (*fp)(type, oldval, newval); - if (newval == EXP_CANT_INTERPRET) - return EXP_CANT_INTERPRET; - // Determine the return value - e = Cast(type, type, post ? oldval : newval); - if (e == EXP_CANT_INTERPRET) - return e; } else if (e1->op != TOKslice) { /* Look for special case of struct being initialized with 0. @@ -2136,7 +2223,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) // Make sure we're not trying to modify a global or static variable // We do this by locating the ultimate parent variable which gets modified. VarDeclaration * ultimateVar = findParentVar(e1, istate->localThis); - if (ultimateVar && !ultimateVar->isCTFE()) + if (ultimateVar && ultimateVar->isDataseg() && !ultimateVar->isCTFE()) { // Can't modify global or static data error("%s cannot be modified at compile time", ultimateVar->toChars()); return EXP_CANT_INTERPRET; @@ -2283,7 +2370,9 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) Expression *index = ie->e2->interpret(istate); if (index == EXP_CANT_INTERPRET) return EXP_CANT_INTERPRET; - newval = assignArrayElement(v->value, index, newval); + newval = assignArrayElement(loc, v->value, index, newval); + if (newval == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; v->value = newval; return e; } @@ -2444,7 +2533,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) if (((PtrExp *)e1)->e1->op == TOKsymoff) { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; VarDeclaration *v = soe->var->isVarDeclaration(); - if (!v->isCTFE()) + if (v->isDataseg() && !v->isCTFE()) { error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; @@ -2743,17 +2832,22 @@ Expression *CommaExp::interpret(InterState *istate) #if LOG printf("CommaExp::interpret() %s\n", toChars()); #endif + + CommaExp * firstComma = this; + while (firstComma->e1->op == TOKcomma) + firstComma = (CommaExp *)firstComma->e1; + + // If it creates a variable, and there's no context for + // the variable to be created in, we need to create one now. + InterState istateComma; + if (!istate && firstComma->e1->op == TOKdeclaration) + istate = &istateComma; + // If the comma returns a temporary variable, it needs to be an lvalue // (this is particularly important for struct constructors) if (e1->op == TOKdeclaration && e2->op == TOKvar && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var) { - // If there's no context for the variable to be created in, - // we need to create one now. - InterState istateComma; - if (!istate) - istate = &istateComma; - VarExp* ve = (VarExp *)e2; VarDeclaration *v = ve->var->isVarDeclaration(); if (!v->init && !v->value) @@ -2845,7 +2939,10 @@ Expression *IndexExp::interpret(InterState *istate) e2 = this->e2->interpret(istate); if (e2 == EXP_CANT_INTERPRET) goto Lcant; - return Index(type, e1, e2); + e = Index(type, e1, e2); + if (e == EXP_CANT_INTERPRET) + error("%s cannot be interpreted at compile time", toChars()); + return e; Lcant: return EXP_CANT_INTERPRET; @@ -2887,7 +2984,10 @@ Expression *SliceExp::interpret(InterState *istate) if (upr == EXP_CANT_INTERPRET) goto Lcant; - return Slice(type, e1, lwr, upr); + e = Slice(type, e1, lwr, upr); + if (e == EXP_CANT_INTERPRET) + error("%s cannot be interpreted at compile time", toChars()); + return e; Lcant: return EXP_CANT_INTERPRET; @@ -2910,7 +3010,10 @@ Expression *CatExp::interpret(InterState *istate) e2 = this->e2->interpret(istate); if (e2 == EXP_CANT_INTERPRET) goto Lcant; - return Cat(type, e1, e2); + e = Cat(type, e1, e2); + if (e == EXP_CANT_INTERPRET) + error("%s cannot be interpreted at compile time", toChars()); + return e; Lcant: #if LOG @@ -2930,7 +3033,10 @@ Expression *CastExp::interpret(InterState *istate) e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; - return Cast(type, to, e1); + e = Cast(type, to, e1); + if (e == EXP_CANT_INTERPRET) + error("%s cannot be interpreted at compile time", toChars()); + return e; Lcant: #if LOG @@ -3071,7 +3177,7 @@ Expression *DotVarExp::interpret(InterState *istate) } } else - error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); + error("%s.%s is not yet implemented at compile time", e1->toChars(), var->toChars()); } #if LOG diff --git a/dmd/json.c b/dmd/json.c index 7db921b0..195a10a3 100644 --- a/dmd/json.c +++ b/dmd/json.c @@ -71,8 +71,9 @@ void json_generate(Array *modules) arg = fn->toChars(); } else if (arg[0] == '-' && arg[1] == 0) - { // Write to stdout - fwrite(buf.data, 1, buf.offset, stdout); + { // Write to stdout; assume it succeeds + int n = fwrite(buf.data, 1, buf.offset, stdout); + assert(n == buf.offset); // keep gcc happy about return values return; } // if (!FileName::absolute(arg)) diff --git a/dmd/lexer.c b/dmd/lexer.c index c070a77a..5b2dd923 100644 --- a/dmd/lexer.c +++ b/dmd/lexer.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -48,6 +48,8 @@ extern int HtmlNamedEntity(unsigned char *p, int length); #define LS 0x2028 // UTF line separator #define PS 0x2029 // UTF paragraph separator +void unittest_lexer(); + /******************************************** * Do our own char maps */ @@ -384,6 +386,16 @@ TOK Lexer::peekNext() return peek(&token)->value; } +/*********************** + * Look 2 tokens ahead at value. + */ + +TOK Lexer::peekNext2() +{ + Token *t = peek(&token); + return peek(t)->value; +} + /********************************* * tk is on the opening (. * Look ahead and return token that is past the closing ). @@ -581,8 +593,10 @@ void Lexer::scan(Token *t) t->value = escapeStringConstant(t,0); return; +#if ! TEXTUAL_ASSEMBLY_OUT case '\\': // escaped string literal { unsigned c; + unsigned char *pstart = p; stringbuffer.reset(); do @@ -609,8 +623,13 @@ void Lexer::scan(Token *t) memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); t->postfix = 0; t->value = TOKstring; +#if DMDV2 + if (!global.params.useDeprecated) + error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart); +#endif return; } +#endif case 'l': case 'L': @@ -1148,6 +1167,27 @@ void Lexer::scan(Token *t) t->value = TOKtilde; // ~ return; +#if DMDV2 + case '^': + p++; + if (*p == '^') + { p++; + if (*p == '=') + { p++; + t->value = TOKpowass; // ^^= + } + else + t->value = TOKpow; // ^^ + } + else if (*p == '=') + { p++; + t->value = TOKxorass; // ^= + } + else + t->value = TOKxor; // ^ + return; +#endif + #define SINGLE(c,tok) case c: p++; t->value = tok; return; SINGLE('(', TOKlparen) @@ -1161,7 +1201,9 @@ void Lexer::scan(Token *t) SINGLE(';', TOKsemicolon) SINGLE(':', TOKcolon) SINGLE('$', TOKdollar) - +#if DMDV2 + SINGLE('@', TOKat) +#endif #undef SINGLE #define DOUBLE(c1,tok1,c2,tok2) \ @@ -1177,8 +1219,9 @@ void Lexer::scan(Token *t) DOUBLE('*', TOKmul, '=', TOKmulass) DOUBLE('%', TOKmod, '=', TOKmodass) +#if DMDV1 DOUBLE('^', TOKxor, '=', TOKxorass) - +#endif #undef DOUBLE case '#': @@ -1219,11 +1262,14 @@ void Lexer::scan(Token *t) */ unsigned Lexer::escapeSequence() -{ unsigned c; +{ unsigned c = *p; + +#ifdef TEXTUAL_ASSEMBLY_OUT + return c; +#endif int n; int ndigits; - c = *p; switch (c) { case '\'': @@ -1580,6 +1626,10 @@ TOK Lexer::delimitedStringConstant(Token *t) else { delimright = c; nest = 0; +#if DMDV2 + if (isspace(c)) + error("delimiter cannot be whitespace"); +#endif } } else @@ -1601,7 +1651,11 @@ TOK Lexer::delimitedStringConstant(Token *t) } else if (c == delimright) goto Ldone; - if (startline && isalpha(c)) + if (startline && isalpha(c) +#if DMDV2 + && hereid +#endif + ) { Token t; unsigned char *psave = p; p--; @@ -1710,6 +1764,7 @@ TOK Lexer::escapeStringConstant(Token *t, int wide) c = *p++; switch (c) { +#if !( TEXTUAL_ASSEMBLY_OUT ) case '\\': switch (*p) { @@ -1725,7 +1780,7 @@ TOK Lexer::escapeStringConstant(Token *t, int wide) break; } break; - +#endif case '\n': loc.linnum++; break; @@ -1786,6 +1841,7 @@ TOK Lexer::charConstant(Token *t, int wide) c = *p++; switch (c) { +#if ! TEXTUAL_ASSEMBLY_OUT case '\\': switch (*p) { @@ -1805,7 +1861,7 @@ TOK Lexer::charConstant(Token *t, int wide) break; } break; - +#endif case '\n': L1: loc.linnum++; @@ -2954,6 +3010,7 @@ static Keyword keywords[] = { "pure", TOKpure }, { "nothrow", TOKnothrow }, { "__thread", TOKtls }, + { "__gshared", TOKgshared }, { "__traits", TOKtraits }, { "__overloadset", TOKoverloadset }, { "__FILE__", TOKfile }, @@ -3058,6 +3115,8 @@ void Lexer::initKeywords() Token::tochars[TOKcast] = "cast"; Token::tochars[TOKplusplus] = "++"; Token::tochars[TOKminusminus] = "--"; + Token::tochars[TOKpreplusplus] = "++"; + Token::tochars[TOKpreminusminus] = "--"; Token::tochars[TOKtype] = "type"; Token::tochars[TOKquestion] = "?"; Token::tochars[TOKneg] = "-"; @@ -3081,6 +3140,11 @@ void Lexer::initKeywords() Token::tochars[TOKorass] = "|="; Token::tochars[TOKidentifier] = "identifier"; +#if DMDV2 + Token::tochars[TOKat] = "@"; + Token::tochars[TOKpow] = "^^"; + Token::tochars[TOKpowass] = "^^="; +#endif // For debugging Token::tochars[TOKerror] = "error"; @@ -3101,4 +3165,30 @@ void Lexer::initKeywords() Token::tochars[TOKon_scope_exit] = "scope(exit)"; Token::tochars[TOKon_scope_success] = "scope(success)"; Token::tochars[TOKon_scope_failure] = "scope(failure)"; + +#if UNITTEST + unittest_lexer(); +#endif } + +#if UNITTEST + +void unittest_lexer() +{ + //printf("unittest_lexer()\n"); + + /* Not much here, just trying things out. + */ + const unsigned char text[] = "int"; + Lexer lex1(NULL, (unsigned char *)text, 0, sizeof(text), 0, 0); + TOK tok; + tok = lex1.nextToken(); + //printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOKint32); + assert(tok == TOKint32); + tok = lex1.nextToken(); + assert(tok == TOKeof); + tok = lex1.nextToken(); + assert(tok == TOKeof); +} + +#endif diff --git a/dmd/lexer.h b/dmd/lexer.h index 6f4f3f06..a598b69a 100644 --- a/dmd/lexer.h +++ b/dmd/lexer.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -31,7 +31,8 @@ struct Module; + - += -= * / % *= /= %= & | ^ &= |= ^= - = ! ~ + = ! ~ @ + ^^ ^^= ++ -- . -> : , ? && || @@ -95,8 +96,9 @@ enum TOK TOKplusplus, TOKminusminus, TOKconstruct, TOKblit, TOKdot, TOKarrow, TOKcomma, TOKquestion, TOKandand, TOKoror, + TOKpreplusplus, TOKpreminusminus, -// 104 +// 106 // Numeric literals TOKint32v, TOKuns32v, TOKint64v, TOKuns64v, @@ -124,7 +126,7 @@ enum TOK TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool, TOKcent, TOKucent, -// 150 +// 152 // Aggregates TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport, TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction, @@ -133,7 +135,7 @@ enum TOK TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport, TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile, TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy, - TOKauto, TOKpackage, TOKmanifest, + TOKauto, TOKpackage, TOKmanifest, TOKimmutable, // Statements TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch, @@ -158,9 +160,13 @@ enum TOK TOKpure, TOKnothrow, TOKtls, + TOKgshared, TOKline, TOKfile, - TOKshared, + TOKshared, + TOKat, + TOKpow, + TOKpowass, #endif // LDC specific @@ -171,6 +177,8 @@ enum TOK TOKMAX }; +#define TOKwild TOKinout + #define BASIC_TYPES \ TOKwchar: case TOKdchar: \ case TOKbit: case TOKbool: case TOKchar: \ @@ -278,6 +286,7 @@ struct Lexer TOK nextToken(); TOK peekNext(); + TOK peekNext2(); void scan(Token *t); Token *peek(Token *t); Token *peekPastParen(Token *t); diff --git a/dmd/mars.c b/dmd/mars.c index 24e82ff4..8fdaee87 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -63,7 +63,7 @@ Global::Global() copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.061"; + version = "v1.062"; ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; global.structalign = 8; diff --git a/dmd/module.c b/dmd/module.c index ec1d65d6..6a67c024 100644 --- a/dmd/module.c +++ b/dmd/module.c @@ -672,9 +672,16 @@ void Module::parse() Dsymbol *prev = dst->lookup(ident); assert(prev); Module *mprev = prev->isModule(); - assert(mprev); - error(loc, "from file %s conflicts with another module %s from file %s", - srcname, mprev->toChars(), mprev->srcfile->toChars()); + if (mprev) + error(loc, "from file %s conflicts with another module %s from file %s", + srcname, mprev->toChars(), mprev->srcfile->toChars()); + else + { + Package *pkg = prev->isPackage(); + assert(pkg); + error(loc, "from file %s conflicts with package name %s", + srcname, pkg->toChars()); + } } else { diff --git a/dmd/mtype.c b/dmd/mtype.c index b5fb873f..ab8762e2 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -231,6 +231,7 @@ void Type::init() mangleChar[Twchar] = 'u'; mangleChar[Tdchar] = 'w'; + // '@' shouldn't appear anywhere in the deco'd names mangleChar[Tbit] = '@'; mangleChar[Tinstance] = '@'; mangleChar[Terror] = '@'; @@ -256,7 +257,7 @@ void Type::init() for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++) basic[basetab[i]] = new TypeBasic(basetab[i]); - basic[Terror] = basic[Tint32]; + basic[Terror] = new TypeError(); tvoidptr = tvoid->pointerTo(); @@ -881,6 +882,24 @@ int Type::hasPointers() return FALSE; } +/* ============================= TypeError =========================== */ + +TypeError::TypeError() + : Type(Terror, NULL) +{ +} + +void TypeError::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) +{ + buf->writestring("_error_"); +} + +d_uns64 TypeError::size(Loc loc) { return 1; } +Expression *TypeError::getProperty(Loc loc, Identifier *ident) { return new ErrorExp(); } +Expression *TypeError::dotExp(Scope *sc, Expression *e, Identifier *ident) { return new ErrorExp(); } +Expression *TypeError::defaultInit(Loc loc) { return new ErrorExp(); } +Expression *TypeError::defaultInitLiteral(Loc loc) { return new ErrorExp(); } + /* ============================= TypeBasic =========================== */ TypeBasic::TypeBasic(TY ty) @@ -1436,9 +1455,6 @@ Expression *TypeBasic::defaultInit(Loc loc) #endif switch (ty) { - case Tvoid: - return new IntegerExp(loc, value, Type::tbool); - case Tchar: value = 0xFF; break; @@ -1458,6 +1474,10 @@ Expression *TypeBasic::defaultInit(Loc loc) case Tcomplex64: case Tcomplex80: return getProperty(loc, Id::nan); + + case Tvoid: + error(loc, "void does not have a default initializer"); + return new ErrorExp(); } return new IntegerExp(loc, value, this); } @@ -1530,6 +1550,13 @@ MATCH TypeBasic::implicitConvTo(Type *to) if (this == to) return MATCHexact; +#if DMDV2 + if (ty == to->ty) + { + return (mod == to->mod) ? MATCHexact : MATCHconst; + } +#endif + if (ty == Tvoid || to->ty == Tvoid) return MATCHnomatch; if (to->ty == Tbool) @@ -1545,16 +1572,18 @@ MATCH TypeBasic::implicitConvTo(Type *to) return MATCHnomatch; #if DMDV2 - // If converting to integral - if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral) + // If converting from integral to integral + if (1 && tob->flags & TFLAGSintegral) { d_uns64 sz = size(0); d_uns64 tosz = tob->size(0); - /* Can't convert to smaller size or, if same size, change sign + /* Can't convert to smaller size */ if (sz > tosz) return MATCHnomatch; + /* Can't change sign if same size + */ /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned) return MATCHnomatch;*/ } @@ -2822,7 +2851,7 @@ int Type::covariant(Type *t) // If t1n is forward referenced: ClassDeclaration *cd = ((TypeClass *)t1n)->sym; - if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration()) + if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration()) { return 3; } @@ -3973,6 +4002,11 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) { sc->intypeof++; exp = exp->semantic(sc); +#if DMDV2 + if (exp->type && exp->type->ty == Tfunction && + ((TypeFunction *)exp->type)->isproperty) + exp = resolveProperties(sc, exp); +#endif sc->intypeof--; if (exp->op == TOKtype) { @@ -4141,7 +4175,7 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident) if (ident == Id::max || ident == Id::min || ident == Id::init || - ident == Id::stringof || + ident == Id::mangleof || !sym->memtype ) { @@ -4186,6 +4220,10 @@ Expression *TypeEnum::getProperty(Loc loc, Identifier *ident) Scope sc; e = e->semantic(&sc); } + else if (ident == Id::mangleof) + { + e = Type::getProperty(loc, ident); + } else { if (!sym->memtype) @@ -5448,7 +5486,8 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc) args->push(arg); } - return new TypeTuple(args); + Type *t = (new TypeTuple(args))->semantic(loc, sc); + return t; } void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) diff --git a/dmd/mtype.h b/dmd/mtype.h index bc6c1cbd..9ce20a7f 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -122,8 +122,10 @@ struct Type : Object /* pick this order of numbers so switch statements work better */ #define MODconst 1 // type is const - #define MODimmutable 4 // type is invariant + #define MODimmutable 4 // type is immutable #define MODshared 2 // type is shared + #define MODwild 8 // type is wild + #define MODmutable 0x10 // type is mutable (only used in wildcard matching) char *deco; Type *pto; // merged pointer to this type Type *rto; // reference to this type @@ -288,6 +290,43 @@ struct Type : Object #endif }; +struct TypeError : Type +{ + TypeError(); + + void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); + + d_uns64 size(Loc loc); + Expression *getProperty(Loc loc, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *defaultInit(Loc loc); + Expression *defaultInitLiteral(Loc loc); +}; + +#if DMDV2 +struct TypeNext : Type +{ + Type *next; + + TypeNext(TY ty, Type *next); + void toDecoBuffer(OutBuffer *buf, int flag); + void checkDeprecated(Loc loc, Scope *sc); + Type *reliesOnTident(); + int hasWild(); + unsigned wildMatch(Type *targ); + Type *nextOf(); + Type *makeConst(); + Type *makeInvariant(); + Type *makeShared(); + Type *makeSharedConst(); + Type *makeWild(); + Type *makeSharedWild(); + Type *makeMutable(); + MATCH constConv(Type *to); + void transitive(); +}; +#endif + struct TypeBasic : Type { const char *dstring; diff --git a/dmd/parse.c b/dmd/parse.c index 3958bb8a..af78ff3b 100644 --- a/dmd/parse.c +++ b/dmd/parse.c @@ -2652,6 +2652,7 @@ Initializer *Parser::parseInitializer() { t = peek(t); if (t->value != TOKsemicolon && t->value != TOKcomma && + t->value != TOKrbracket && t->value != TOKrcurly) goto Lexpression; break; @@ -2976,7 +2977,7 @@ Statement *Parser::parseStatement(int flags) s = new CompoundStatement(loc, statements); if (flags & (PSscope | PScurlyscope)) s = new ScopeStatement(loc, s); - nextToken(); + check(TOKrcurly, "compound statement"); break; } @@ -3638,7 +3639,7 @@ void Parser::check(Loc loc, enum TOK value) void Parser::check(enum TOK value, const char *string) { if (token.value != value) - error("found '%s' when expecting '%s' following '%s'", + error("found '%s' when expecting '%s' following %s", token.toChars(), Token::toChars(value), string); nextToken(); } diff --git a/dmd/root/array.c b/dmd/root/array.c index 5efa1dc6..50b31f21 100644 --- a/dmd/root/array.c +++ b/dmd/root/array.c @@ -1,8 +1,8 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://www.digitalmars.com // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. @@ -48,14 +48,15 @@ Array::Array() { - data = NULL; + data = SMALLARRAYCAP ? &smallarray[0] : NULL; dim = 0; - allocdim = 0; + allocdim = SMALLARRAYCAP; } Array::~Array() { - mem.free(data); + if (data != &smallarray[0]) + mem.free(data); } void Array::mark() @@ -68,11 +69,30 @@ void Array::mark() void Array::reserve(unsigned nentries) { - //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); + //printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries); if (allocdim - dim < nentries) { - allocdim = dim + nentries; - data = (void **)mem.realloc(data, allocdim * sizeof(*data)); + if (allocdim == 0) + { // Not properly initialized, someone memset it to zero + if (nentries <= SMALLARRAYCAP) + { allocdim = SMALLARRAYCAP; + data = SMALLARRAYCAP ? &smallarray[0] : NULL; + } + else + { allocdim = nentries; + data = (void **)mem.malloc(allocdim * sizeof(*data)); + } + } + else if (allocdim == SMALLARRAYCAP) + { + allocdim = dim + nentries; + data = (void **)mem.malloc(allocdim * sizeof(*data)); + memcpy(data, &smallarray[0], dim * sizeof(*data)); + } + else + { allocdim = dim + nentries; + data = (void **)mem.realloc(data, allocdim * sizeof(*data)); + } } } @@ -88,7 +108,17 @@ void Array::setDim(unsigned newdim) void Array::fixDim() { if (dim != allocdim) - { data = (void **)mem.realloc(data, dim * sizeof(*data)); + { + if (allocdim >= SMALLARRAYCAP) + { + if (dim <= SMALLARRAYCAP) + { + memcpy(&smallarray[0], data, dim * sizeof(*data)); + mem.free(data); + } + else + data = (void **)mem.realloc(data, dim * sizeof(*data)); + } allocdim = dim; } } diff --git a/dmd/root/port.c b/dmd/root/port.c index 2a0ec6f1..3dd8aa38 100644 --- a/dmd/root/port.c +++ b/dmd/root/port.c @@ -427,7 +427,9 @@ int Port::isInfinity(double r) #undef signbit int Port::Signbit(double r) { - return (long)(((long *)&r)[1] & 0x80000000); + union { double d; long long ll; } u; + u.d = r; + return u.ll < 0; } double Port::floor(double d) diff --git a/dmd/root/root.h b/dmd/root/root.h index f74bf88a..1d19048f 100644 --- a/dmd/root/root.h +++ b/dmd/root/root.h @@ -318,11 +318,17 @@ struct OutBuffer : Object struct Array : Object { unsigned dim; - unsigned allocdim; void **data; + private: + unsigned allocdim; + #define SMALLARRAYCAP 1 + void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays + + public: Array(); ~Array(); + //Array(const Array&); void mark(); char *toChars(); diff --git a/dmd/scope.c b/dmd/scope.c index 1217f6d4..bbabc0c9 100644 --- a/dmd/scope.c +++ b/dmd/scope.c @@ -377,7 +377,10 @@ void *scope_search_fp(void *arg, const char *seed) /* If not in the lexer's string table, it certainly isn't in the symbol table. * Doing this first is a lot faster. */ - StringValue *sv = Lexer::stringtable.lookup(seed, strlen(seed)); + size_t len = strlen(seed); + if (!len) + return NULL; + StringValue *sv = Lexer::stringtable.lookup(seed, len); if (!sv) return NULL; Identifier *id = (Identifier *)sv->ptrvalue; diff --git a/dmd/statement.c b/dmd/statement.c index 0453f68e..f4cf761a 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -75,18 +75,28 @@ Statement *Statement::semantic(Scope *sc) return this; } -// Same as semantic(), but do create a new scope +Statement *Statement::semanticNoScope(Scope *sc) +{ + //printf("Statement::semanticNoScope() %s\n", toChars()); + Statement *s = this; + if (!s->isCompoundStatement() && !s->isScopeStatement()) + { + s = new CompoundStatement(loc, this); // so scopeCode() gets called + } + s = s->semantic(sc); + return s; +} + +// Same as semanticNoScope(), but do create a new scope Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue) -{ Scope *scd; - Statement *s; - - scd = sc->push(); +{ + Scope *scd = sc->push(); if (sbreak) scd->sbreak = sbreak; if (scontinue) scd->scontinue = scontinue; - s = semantic(scd); + Statement *s = semanticNoScope(scd); scd->pop(); return s; } @@ -394,6 +404,13 @@ CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2) statements->push(s2); } +CompoundStatement::CompoundStatement(Loc loc, Statement *s1) + : Statement(loc) +{ + statements = new Statements(); + statements->push(s1); +} + Statement *CompoundStatement::syntaxCopy() { Statements *a = new Statements(); @@ -859,6 +876,7 @@ Statement *ScopeStatement::semantic(Scope *sc) if (sfinally) { //printf("adding sfinally\n"); + sfinally = sfinally->semantic(sc); statement = new CompoundStatement(loc, statement, sfinally); } } @@ -1065,7 +1083,8 @@ int DoStatement::blockExit() else result = BEfallthru; if (result & BEfallthru) - { if (condition->canThrow()) + { + if (condition->canThrow()) result |= BEthrow; if (!(result & BEbreak) && condition->isBool(TRUE)) result &= ~BEfallthru; @@ -1148,7 +1167,7 @@ Statement *ForStatement::semantic(Scope *sc) sc->sbreak = this; sc->scontinue = this; if (body) - body = body->semantic(sc); + body = body->semanticNoScope(sc); sc->noctor--; sc->pop(); @@ -1266,10 +1285,14 @@ ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, this->value = NULL; this->func = NULL; + + this->cases = NULL; + this->gotos = NULL; } Statement *ForeachStatement::syntaxCopy() { + //printf("ForeachStatement::syntaxCopy()\n"); Parameters *args = Parameter::arraySyntaxCopy(arguments); Expression *exp = aggr->syntaxCopy(); ForeachStatement *s = new ForeachStatement(loc, op, args, exp, @@ -1661,28 +1684,21 @@ Statement *ForeachStatement::semantic(Scope *sc) #endif case Tdelegate: Lapply: - { FuncDeclaration *fdapply; - Parameters *args; + { Expression *ec; Expression *e; - FuncLiteralDeclaration *fld; Parameter *a; - Type *t; - Expression *flde; - Identifier *id; - Type *tret; TypeDelegate* dgty; TypeDelegate* dgty2; TypeDelegate* fldeTy; - tret = func->type->nextOf(); + Type *tret = func->type->nextOf(); // Need a variable to hold value from any return statements in body. if (!sc->func->vresult && tret && tret != Type::tvoid) - { VarDeclaration *v; - - v = new VarDeclaration(loc, tret, Id::result, NULL); - v->noscope = 1; + { + VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); + v->noauto = 1; v->semantic(sc); if (!sc->insert(v)) assert(0); @@ -1693,9 +1709,10 @@ Statement *ForeachStatement::semantic(Scope *sc) /* Turn body into the function literal: * int delegate(ref T arg) { body } */ - args = new Parameters(); + Parameters *args = new Parameters(); for (size_t i = 0; i < dim; i++) { Parameter *arg = (Parameter *)arguments->data[i]; + Identifier *id; arg->type = arg->type->semantic(loc, sc); if (arg->storageClass & STCref) @@ -1703,34 +1720,33 @@ Statement *ForeachStatement::semantic(Scope *sc) else { // Make a copy of the ref argument so it isn't // a reference. - VarDeclaration *v; - Initializer *ie; id = Lexer::uniqueId("__applyArg", i); - - ie = new ExpInitializer(0, new IdentifierExp(0, id)); - v = new VarDeclaration(0, arg->type, arg->ident, ie); + Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id)); + VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie); s = new DeclarationStatement(0, v); body = new CompoundStatement(loc, s, body); } a = new Parameter(STCref, arg->type, id, NULL); args->push(a); } - t = new TypeFunction(args, Type::tint32, 0, LINKd); - fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); + Type *t = new TypeFunction(args, Type::tint32, 0, LINKd); + cases = new Array(); + gotos = new Array(); + FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); fld->fbody = body; - flde = new FuncExp(loc, fld); + Expression *flde = new FuncExp(loc, fld); flde = flde->semantic(sc); // Resolve any forward referenced goto's - for (int i = 0; i < gotos.dim; i++) - { CompoundStatement *cs = (CompoundStatement *)gotos.data[i]; + for (size_t i = 0; i < gotos->dim; i++) + { CompoundStatement *cs = (CompoundStatement *)gotos->data[i]; GotoStatement *gs = (GotoStatement *)cs->statements->data[0]; if (!gs->label->statement) { // 'Promote' it to this scope, and replace with a return - cases.push(gs); - s = new ReturnStatement(0, new IntegerExp(cases.dim + 1)); + cases->push(gs); + s = new ReturnStatement(0, new IntegerExp(cases->dim + 1)); cs->statements->data[0] = (void *)s; } } @@ -1779,6 +1795,7 @@ Statement *ForeachStatement::semantic(Scope *sc) args->push(new Parameter(STCin, aaApply_dg, NULL, NULL)); aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply"); } + FuncDeclaration *fdapply; if (dim == 2) { fdapply = aaApply2_fd; fldeTy = aaApply2_dg; @@ -1838,6 +1855,7 @@ Statement *ForeachStatement::semantic(Scope *sc) #endif assert(j < sizeof(fdname)); //LDC: Build arguments. + FuncDeclaration *fdapply; Parameters* args = new Parameters; args->push(new Parameter(STCin, tn->arrayOf(), NULL, NULL)); if (dim == 2) { @@ -1899,7 +1917,7 @@ Statement *ForeachStatement::semantic(Scope *sc) error("opApply() function for %s must return an int", tab->toChars()); } - if (!cases.dim) + if (!cases->dim) // Easy case, a clean exit from the loop s = new ExpStatement(loc, e); else @@ -1913,9 +1931,9 @@ Statement *ForeachStatement::semantic(Scope *sc) a->push(s); // cases 2... - for (int i = 0; i < cases.dim; i++) + for (int i = 0; i < cases->dim; i++) { - s = (Statement *)cases.data[i]; + s = (Statement *)cases->data[i]; s = new CaseStatement(0, new IntegerExp(i + 2), s); a->push(s); } @@ -2064,7 +2082,9 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) /* Must infer types from lwr and upr */ AddExp ea(loc, lwr, upr); - ea.typeCombine(sc); + Expression *e = ea.typeCombine(sc); + if (e->op == TOKerror) + return this; arg->type = ea.type->mutableOf(); lwr = ea.e1; upr = ea.e2; @@ -2265,7 +2285,7 @@ Statement *IfStatement::semantic(Scope *sc) Type *t = arg->type ? arg->type : condition->type; match = new VarDeclaration(loc, t, arg->ident, NULL); - match->noscope = 1; + match->noauto = 1; match->semantic(scd); if (!scd->insert(match)) assert(0); @@ -2280,7 +2300,7 @@ Statement *IfStatement::semantic(Scope *sc) } else scd = sc->push(); - ifbody = ifbody->semantic(scd); + ifbody = ifbody->semanticNoScope(scd); scd->pop(); cs1 = sc->callSuper; @@ -2482,21 +2502,14 @@ Statement *PragmaStatement::semantic(Scope *sc) Expression *e = (Expression *)args->data[i]; e = e->semantic(sc); -#if 1 e = e->optimize(WANTvalue | WANTinterpret); -#else - e = e->interpret(NULL); - if (e == EXP_CANT_INTERPRET) - fprintf(stdmsg, ((Expression *)args->data[i])->toChars()); - else -#endif if (e->op == TOKstring) { StringExp *se = (StringExp *)e; fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); } else - fprintf(stdmsg, e->toChars()); + fprintf(stdmsg, "%s", e->toChars()); } fprintf(stdmsg, "\n"); } @@ -3368,18 +3381,18 @@ Statement *ReturnStatement::semantic(Scope *sc) exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull || exp->op == TOKstring) { - sc->fes->cases.push(this); - // Construct: return cases.dim+1; - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); + sc->fes->cases->push(this); + // Construct: return cases->dim+1; + s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); } else if (fd->type->nextOf()->toBasetype() == Type::tvoid) { s = new ReturnStatement(0, NULL); - sc->fes->cases.push(s); + sc->fes->cases->push(s); - // Construct: { exp; return cases.dim + 1; } + // Construct: { exp; return cases->dim + 1; } Statement *s1 = new ExpStatement(loc, exp); - Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); + Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); s = new CompoundStatement(loc, s1, s2); } else @@ -3388,7 +3401,7 @@ Statement *ReturnStatement::semantic(Scope *sc) if (!fd->vresult) { // Declare vresult VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); - v->noscope = 1; + v->noauto = 1; v->semantic(scx); if (!scx->insert(v)) assert(0); @@ -3397,14 +3410,13 @@ Statement *ReturnStatement::semantic(Scope *sc) } s = new ReturnStatement(0, new VarExp(0, fd->vresult)); - sc->fes->cases.push(s); + sc->fes->cases->push(s); - // Construct: { vresult = exp; return cases.dim + 1; } - exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); - exp->op = TOKconstruct; + // Construct: { vresult = exp; return cases->dim + 1; } + exp = new ConstructExp(loc, new VarExp(0, fd->vresult), exp); exp = exp->semantic(sc); Statement *s1 = new ExpStatement(loc, exp); - Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); + Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); s = new CompoundStatement(loc, s1, s2); } return s; @@ -3529,8 +3541,8 @@ Statement *BreakStatement::semantic(Scope *sc) * and 1 is break. */ Statement *s; - sc->fes->cases.push(this); - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); + sc->fes->cases->push(this); + s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); return s; } break; // can't break to it @@ -3632,8 +3644,8 @@ Statement *ContinueStatement::semantic(Scope *sc) * and 1 is break. */ Statement *s; - sc->fes->cases.push(this); - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); + sc->fes->cases->push(this); + s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); return s; } break; // can't continue to it @@ -4083,7 +4095,7 @@ void Catch::semantic(Scope *sc) type = new TypeIdentifier(0, Id::Object); type = type->semantic(loc, sc); if (!type->toBasetype()->isClassHandle()) - error("can only catch class objects, not '%s'", type->toChars()); + error(loc, "can only catch class objects, not '%s'", type->toChars()); else if (ident) { var = new VarDeclaration(loc, type, ident, NULL); @@ -4136,17 +4148,12 @@ Statement *TryFinallyStatement::syntaxCopy() Statement *TryFinallyStatement::semantic(Scope *sc) { //printf("TryFinallyStatement::semantic()\n"); - - Statement* oldScopeExit = sc->enclosingScopeExit; - sc->enclosingScopeExit = this; body = body->semantic(sc); - sc->enclosingScopeExit = oldScopeExit; - sc = sc->push(); sc->enclosingFinally = this; sc->sbreak = NULL; sc->scontinue = NULL; // no break or continue out of finally block - finalbody = finalbody->semantic(sc); + finalbody = finalbody->semanticNoScope(sc); sc->pop(); return this; } @@ -4414,7 +4421,7 @@ Statement *GotoStatement::semantic(Scope *sc) a->push(this); s = new CompoundStatement(loc, a); - sc->fes->gotos.push(s); // 'look at this later' list + sc->fes->gotos->push(s); // 'look at this later' list return s; } if (label->statement && label->statement->enclosingFinally != sc->enclosingFinally) @@ -4476,7 +4483,7 @@ Statement *LabelStatement::semantic(Scope *sc) sc->callSuper |= CSXlabel; sc->slabel = this; if (statement) - statement = statement->semantic(sc); + statement = statement->semanticNoScope(sc); sc->pop(); // LDC put in labmap diff --git a/dmd/statement.h b/dmd/statement.h index ddd3c0dd..cfbffa30 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -118,6 +118,7 @@ struct Statement : Object virtual ScopeStatement *isScopeStatement() { return NULL; } virtual Statement *semantic(Scope *sc); Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue); + Statement *semanticNoScope(Scope *sc); virtual int hasBreak(); virtual int hasContinue(); virtual int usesEH(); @@ -210,6 +211,7 @@ struct CompoundStatement : Statement Statements *statements; CompoundStatement(Loc loc, Statements *s); + CompoundStatement(Loc loc, Statement *s1); CompoundStatement(Loc loc, Statement *s1, Statement *s2); virtual Statement *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -367,8 +369,8 @@ struct ForeachStatement : Statement FuncDeclaration *func; // function we're lexically in - Array cases; // put breaks, continues, gotos and returns here - Array gotos; // forward referenced goto's go here + Array *cases; // put breaks, continues, gotos and returns here + Array *gotos; // forward referenced goto's go here ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, Expression *aggr, Statement *body); Statement *syntaxCopy(); diff --git a/dmd/struct.c b/dmd/struct.c index fcd5b675..7d6d3936 100644 --- a/dmd/struct.c +++ b/dmd/struct.c @@ -200,11 +200,22 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) memsize = v->type->size(loc); memalignsize = v->type->alignsize(); xalign = v->type->memalign(sc->structalign); +#if 0 alignmember(xalign, memalignsize, &sc->offset); v->offset = sc->offset; sc->offset += memsize; if (sc->offset > structsize) structsize = sc->offset; +#else + unsigned ofs = sc->offset; + alignmember(xalign, memalignsize, &ofs); + v->offset = ofs; + ofs += memsize; + if (ofs > structsize) + structsize = ofs; + if (!isUnionDeclaration()) + sc->offset = ofs; +#endif if (sc->structalign < memalignsize) memalignsize = sc->structalign; if (alignsize < memalignsize) @@ -337,8 +348,6 @@ void StructDeclaration::semantic(Scope *sc) { Dsymbol *s = (Dsymbol *)members->data[i]; s->semantic(sc2); - if (isUnionDeclaration()) - sc2->offset = 0; #if 0 if (sizeok == 2) { //printf("forward reference\n"); diff --git a/dmd/template.c b/dmd/template.c index 048ce23c..628a8022 100644 --- a/dmd/template.c +++ b/dmd/template.c @@ -75,6 +75,36 @@ Tuple *isTuple(Object *o) return (Tuple *)o; } +/************************************** + * Is this Object an error? + */ +int isError(Object *o) +{ + Type *t = isType(o); + if (t) + return (t->ty == Terror); + Expression *e = isExpression(o); + if (e) + return (e->op == TOKerror); + Tuple *v = isTuple(o); + if (v) + return arrayObjectIsError(&v->objects); + return 0; +} + +/************************************** + * Are any of the Objects an error? + */ +int arrayObjectIsError(Objects *args) +{ + for (size_t i = 0; i < args->dim; i++) + { + Object *o = (Object *)args->data[i]; + if (isError(o)) + return 1; + } + return 0; +} /*********************** * Try to get arg as a type. @@ -1366,8 +1396,10 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, } if (td_ambig) { - error(loc, "matches more than one function template declaration:\n %s\nand:\n %s", - td_best->toChars(), td_ambig->toChars()); + error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", + toChars(), + td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), + td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); } /* The best match is td_best with arguments tdargs. @@ -3892,8 +3924,10 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc) } if (td_ambig) { - error("%s matches more than one template declaration, %s and %s", - toChars(), td_best->toChars(), td_ambig->toChars()); + error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", + toChars(), + td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), + td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); } /* The best match is td_best diff --git a/dmd/template.h b/dmd/template.h index f03362c6..e43d51dd 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -374,6 +374,8 @@ Expression *isExpression(Object *o); Dsymbol *isDsymbol(Object *o); Type *isType(Object *o); Tuple *isTuple(Object *o); +int arrayObjectIsError(Objects *args); +int isError(Object *o); Type *getType(Object *o); Dsymbol *getDsymbol(Object *o); diff --git a/dmd/utf.c b/dmd/utf.c index 0438bdba..6467c65b 100644 --- a/dmd/utf.c +++ b/dmd/utf.c @@ -1,5 +1,5 @@ // utf.c -// Copyright (c) 2003 by Digital Mars +// Copyright (c) 2003-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -28,12 +28,14 @@ int utf_isValidDchar(dchar_t c) * !=NULL error message string */ -char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult) +const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult) { dchar_t V; size_t i = *pidx; unsigned char u = s[i]; + //printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len); + assert(i >= 0 && i < len); if (u & 0x80) @@ -117,10 +119,10 @@ char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presul * !=NULL error message string */ -char *utf_validateString(unsigned char *s, size_t len) +const char *utf_validateString(unsigned char *s, size_t len) { size_t idx; - char *err = NULL; + const char *err = NULL; dchar_t dc; for (idx = 0; idx < len; ) @@ -141,9 +143,9 @@ char *utf_validateString(unsigned char *s, size_t len) */ -char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult) +const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult) { - char *msg; + const char *msg; size_t i = *pidx; unsigned u = s[i]; diff --git a/dmd/utf.h b/dmd/utf.h index 26f161bb..6c9eb06a 100644 --- a/dmd/utf.h +++ b/dmd/utf.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language // utf.h -// Copyright (c) 2003-2006 by Digital Mars +// Copyright (c) 2003-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -16,10 +16,10 @@ typedef unsigned dchar_t; int utf_isValidDchar(dchar_t c); -char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult); -char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult); +const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult); +const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult); -char *utf_validateString(unsigned char *s, size_t len); +const char *utf_validateString(unsigned char *s, size_t len); extern int isUniAlpha(dchar_t);