From 1c6ff32d507218acf2ac02f2bb4eaeec3a6b2fce Mon Sep 17 00:00:00 2001 From: kai Date: Fri, 13 Apr 2012 21:07:31 +0200 Subject: [PATCH] Merge dmd-1.074 into ldc. --- dmd/aggregate.h | 29 +- dmd/attrib.c | 333 +++++---- dmd/attrib.h | 9 +- dmd/cast.c | 7 +- dmd/class.c | 112 ++-- dmd/cond.c | 22 +- dmd/cond.h | 5 +- dmd/declaration.c | 126 +++- dmd/declaration.h | 3 + dmd/doc.c | 3 + dmd/dsymbol.c | 68 +- dmd/dsymbol.h | 9 +- dmd/expression.c | 316 ++++----- dmd/expression.h | 29 +- dmd/func.c | 38 +- dmd/html.c | 8 +- dmd/import.c | 26 +- dmd/init.c | 74 +- dmd/inline.c | 22 +- dmd/interpret.c | 390 ++++++++--- dmd/lexer.c | 34 +- dmd/lexer.h | 2 + dmd/mars.c | 7 +- dmd/mars.h | 6 + dmd/module.c | 45 +- dmd/module.h | 5 +- dmd/mtype.c | 75 ++- dmd/mtype.h | 8 +- dmd/parse.c | 5 +- dmd/root/aav.c | 376 +++++------ dmd/root/aav.h | 22 +- dmd/root/array.c | 514 +++++++------- dmd/root/async.c | 650 +++++++++--------- dmd/root/async.h | 66 +- dmd/root/dchar.c | 964 +++++++++++++------------- dmd/root/dchar.h | 388 +++++------ dmd/root/longdouble.c | 636 ++++++++++++++++++ dmd/root/longdouble.h | 254 +++++++ dmd/root/lstring.c | 126 ++-- dmd/root/lstring.h | 146 ++-- dmd/root/man.c | 200 +++--- dmd/root/port.c | 1451 ++++++++++++++++++---------------------- dmd/root/port.h | 164 ++--- dmd/root/root.c | 58 +- dmd/root/root.h | 853 +++++++++++------------ dmd/root/stringtable.c | 278 ++++---- dmd/root/stringtable.h | 96 +-- dmd/scope.c | 2 - dmd/scope.h | 7 +- dmd/speller.c | 7 +- dmd/statement.c | 24 +- dmd/struct.c | 188 +++--- dmd/template.c | 271 +++++--- dmd/template.h | 10 +- 54 files changed, 5533 insertions(+), 4034 deletions(-) create mode 100644 dmd/root/longdouble.c create mode 100644 dmd/root/longdouble.h diff --git a/dmd/aggregate.h b/dmd/aggregate.h index f0a30ec3..5cac12aa 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -51,6 +51,13 @@ namespace llvm } #endif +enum Sizeok +{ + SIZEOKnone, // size of aggregate is not computed yet + SIZEOKdone, // size of aggregate is set correctly + SIZEOKfwd, // error in computing size of aggregate +}; + struct AggregateDeclaration : ScopeDsymbol { Type *type; @@ -62,10 +69,7 @@ struct AggregateDeclaration : ScopeDsymbol unsigned structalign; // struct member alignment in effect int hasUnions; // set if aggregate has overlapping fields VarDeclarations fields; // VarDeclaration fields - unsigned sizeok; // set when structsize contains valid data - // 0: no size - // 1: size is correct - // 2: cannot determine size; fwd referenced + enum Sizeok sizeok; // set when structsize contains valid data int isdeprecated; // !=0 if deprecated #if DMDV2 @@ -89,7 +93,8 @@ struct AggregateDeclaration : ScopeDsymbol FuncDeclaration *dtor; // aggregate destructor #ifdef IN_GCC - Array methods; // flat list of all methods for debug information + Expressions *attributes; // GCC decl/type attributes + FuncDeclarations methods; // flat list of all methods for debug information #endif AggregateDeclaration(Loc loc, Identifier *id); @@ -98,8 +103,10 @@ struct AggregateDeclaration : ScopeDsymbol void inlineScan(); unsigned size(Loc loc); static void alignmember(unsigned salign, unsigned size, unsigned *poffset); + static unsigned placeField(unsigned *nextoffset, + unsigned memsize, unsigned memalignsize, unsigned memalign, + unsigned *paggsize, unsigned *paggalignsize, bool isunion); Type *getType(); - void addField(Scope *sc, VarDeclaration *v); int firstFieldInUnion(int indx); // first field in union that includes indx int numFieldsInUnion(int firstIndex); // #fields in union starting at index int isDeprecated(); // is aggregate deprecated? @@ -163,14 +170,19 @@ struct StructDeclaration : AggregateDeclaration void toCBuffer(OutBuffer *buf, HdrGenState *hgs); char *mangle(); const char *kind(); + void finalizeSize(Scope *sc); #if DMDV1 Expression *cloneMembers(); #endif #if DMDV2 int needOpAssign(); + int needOpEquals(); FuncDeclaration *buildOpAssign(Scope *sc); + FuncDeclaration *buildOpEquals(Scope *sc); FuncDeclaration *buildPostBlit(Scope *sc); FuncDeclaration *buildCpCtor(Scope *sc); + + FuncDeclaration *buildXopEquals(Scope *sc); #endif void toDocBuffer(OutBuffer *buf); @@ -222,7 +234,8 @@ struct BaseClass }; #if DMDV2 -#define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size +#define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size +#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size #else #define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size #define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size diff --git a/dmd/attrib.c b/dmd/attrib.c index dc194bfb..2d8f71ac 100644 --- a/dmd/attrib.c +++ b/dmd/attrib.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -54,6 +54,24 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) return decl; } +int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param) +{ + Dsymbols *d = include(NULL, NULL); + + if (d) + { + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; + if (s) + { + if (s->apply(fp, param)) + return 1; + } + } + } + return 0; +} + int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { int m = 0; @@ -61,8 +79,8 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars()); m |= s->addMember(sc, sd, m | memnum); } @@ -92,8 +110,8 @@ void AttribDeclaration::setScopeNewSc(Scope *sc, newsc->explicitProtection = explicitProtection; newsc->structalign = structalign; } - for (unsigned i = 0; i < decl->dim; i++) - { Dsymbol *s = decl->tdata()[i]; + for (size_t i = 0; i < decl->dim; i++) + { Dsymbol *s = (*decl)[i]; s->setScope(newsc); // yes, the only difference from semanticNewSc() } @@ -127,8 +145,8 @@ void AttribDeclaration::semanticNewSc(Scope *sc, newsc->explicitProtection = explicitProtection; newsc->structalign = structalign; } - for (unsigned i = 0; i < decl->dim; i++) - { Dsymbol *s = decl->tdata()[i]; + for (size_t i = 0; i < decl->dim; i++) + { Dsymbol *s = (*decl)[i]; s->semantic(newsc); } @@ -149,7 +167,7 @@ void AttribDeclaration::semantic(Scope *sc) { for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->semantic(sc); } @@ -163,7 +181,7 @@ void AttribDeclaration::semantic2(Scope *sc) if (d) { for (size_t i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = (*d)[i]; s->semantic2(sc); } } @@ -176,7 +194,7 @@ void AttribDeclaration::semantic3(Scope *sc) if (d) { for (size_t i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = (*d)[i]; s->semantic3(sc); } } @@ -188,8 +206,8 @@ void AttribDeclaration::inlineScan() if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("AttribDeclaration::inlineScan %s\n", s->toChars()); s->inlineScan(); } @@ -205,8 +223,8 @@ void AttribDeclaration::addComment(unsigned char *comment) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("AttribDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } @@ -230,8 +248,8 @@ void AttribDeclaration::emitComment(Scope *sc) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("AttribDeclaration::emitComment %s\n", s->toChars()); s->emitComment(sc); } @@ -246,32 +264,27 @@ void AttribDeclaration::toObjFile(int multiobj) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->toObjFile(multiobj); } } } -int AttribDeclaration::cvMember(unsigned char *p) +#endif + +void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) { - int nwritten = 0; - int n; Dsymbols *d = include(NULL, NULL); if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; - n = s->cvMember(p); - if (p) - p += n; - nwritten += n; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; + s->setFieldOffset(ad, poffset, isunion); } } - return nwritten; } -#endif int AttribDeclaration::hasPointers() { @@ -281,7 +294,7 @@ int AttribDeclaration::hasPointers() { for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; if (s->hasPointers()) return 1; } @@ -323,8 +336,8 @@ void AttribDeclaration::checkCtorConstInit() if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->checkCtorConstInit(); } } @@ -339,8 +352,8 @@ void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->addLocalClass(aclasses); } } @@ -354,15 +367,15 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (decl->dim == 0) buf->writestring("{}"); else if (decl->dim == 1) - (decl->tdata()[0])->toCBuffer(buf, hgs); + ((*decl)[0])->toCBuffer(buf, hgs); else { buf->writenl(); buf->writeByte('{'); buf->writenl(); - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -467,6 +480,7 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc) { STCout, TOKout }, { STCin, TOKin }, #if DMDV2 + { STCmanifest, TOKenum }, { STCimmutable, TOKimmutable }, { STCshared, TOKshared }, { STCnothrow, TOKnothrow }, @@ -474,10 +488,11 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc) { STCref, TOKref }, { STCtls, TOKtls }, { STCgshared, TOKgshared }, - { STCproperty, TOKat }, - { STCsafe, TOKat }, - { STCtrusted, TOKat }, - { STCdisable, TOKat }, + { STCproperty, TOKat, Id::property }, + { STCsafe, TOKat, Id::safe }, + { STCtrusted, TOKat, Id::trusted }, + { STCsystem, TOKat, Id::system }, + { STCdisable, TOKat, Id::disable }, #endif }; @@ -488,20 +503,9 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc) 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()); + buf->writestring(table[i].id->toChars()); } else #endif @@ -560,9 +564,9 @@ void LinkDeclaration::semantic3(Scope *sc) { enum LINK linkage_save = sc->linkage; sc->linkage = linkage; - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; s->semantic3(sc); } @@ -738,6 +742,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl) : AttribDeclaration(decl) { this->loc = loc; + this->alignment = 0; this->isunion = isunion; this->sem = 0; } @@ -755,21 +760,6 @@ void AnonDeclaration::semantic(Scope *sc) { //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); - if (sem == 1) - { //printf("already completed\n"); - scope = NULL; - return; // semantic() already completed - } - - Scope *scx = NULL; - if (scope) - { sc = scope; - scx = scope; - scope = NULL; - } - - unsigned dprogress_save = Module::dprogress; - assert(sc->parent); Dsymbol *parent = sc->parent->pastMixin(); @@ -781,106 +771,85 @@ void AnonDeclaration::semantic(Scope *sc) return; } + alignment = sc->structalign; if (decl) { - AnonymousAggregateDeclaration aad; - int adisunion; - - if (sc->anonAgg) - { ad = sc->anonAgg; - adisunion = sc->inunion; - } - else - adisunion = ad->isUnionDeclaration() != NULL; - -// printf("\tsc->anonAgg = %p\n", sc->anonAgg); -// printf("\tad = %p\n", ad); -// printf("\taad = %p\n", &aad); - sc = sc->push(); - sc->anonAgg = &aad; sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared); sc->inunion = isunion; sc->offset = 0; sc->flags = 0; - aad.structalign = sc->structalign; - aad.parent = ad; - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; - + Dsymbol *s = (*decl)[i]; s->semantic(sc); - if (isunion) - sc->offset = 0; - if (aad.sizeok == 2) - { - break; - } } sc = sc->pop(); + } +} - // If failed due to forward references, unwind and try again later - if (aad.sizeok == 2) + +void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ + //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this); + + if (decl) + { + /* This works by treating an AnonDeclaration as an aggregate 'member', + * so in order to place that member we need to compute the member's + * size and alignment. + */ + + size_t fieldstart = ad->fields.dim; + + /* Hackishly hijack ad's structsize and alignsize fields + * for use in our fake anon aggregate member. + */ + unsigned savestructsize = ad->structsize; + unsigned savealignsize = ad->alignsize; + ad->structsize = 0; + ad->alignsize = 0; + + unsigned offset = 0; + for (size_t i = 0; i < decl->dim; i++) { - ad->sizeok = 2; - //printf("\tsetting ad->sizeok %p to 2\n", ad); - if (!sc->anonAgg) - { - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - } - Module::dprogress = dprogress_save; - //printf("\tforward reference %p\n", this); - return; + Dsymbol *s = (*decl)[i]; + + s->setFieldOffset(ad, &offset, this->isunion); + if (this->isunion) + offset = 0; } - if (sem == 0) - { Module::dprogress++; - sem = 1; - //printf("\tcompleted %p\n", this); - } - else - ;//printf("\talready completed %p\n", this); + + unsigned anonstructsize = ad->structsize; + unsigned anonalignsize = ad->alignsize; + ad->structsize = savestructsize; + ad->alignsize = savealignsize; // 0 sized structs are set to 1 byte - if (aad.structsize == 0) + if (anonstructsize == 0) { - aad.structsize = 1; - aad.alignsize = 1; + anonstructsize = 1; + anonalignsize = 1; } - // Align size of anonymous aggregate -//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset); - ad->alignmember(aad.structalign, aad.alignsize, &sc->offset); - //ad->structsize = sc->offset; -//printf("sc->offset = %d\n", sc->offset); + /* Given the anon 'member's size and alignment, + * go ahead and place it. + */ + unsigned anonoffset = AggregateDeclaration::placeField( + poffset, + anonstructsize, anonalignsize, alignment, + &ad->structsize, &ad->alignsize, + isunion); - // Add members of aad to ad - //printf("\tadding members of aad (%p) to '%s'\n", &aad, ad->toChars()); - for (unsigned i = 0; i < aad.fields.dim; i++) + // Add to the anon fields the base offset of this anonymous aggregate + //printf("anon fields, anonoffset = %d\n", anonoffset); + for (size_t i = fieldstart; i < ad->fields.dim; i++) { - VarDeclaration *v = (VarDeclaration *)aad.fields.data[i]; - - v->offset += sc->offset; - ad->fields.push(v); + VarDeclaration *v = ad->fields[i]; + //printf("\t[%d] %s %d\n", i, v->toChars(), v->offset); + v->offset += anonoffset; } - - // Add size of aad to ad - if (adisunion) - { - if (aad.structsize > ad->structsize) - ad->structsize = aad.structsize; - sc->offset = 0; - } - else - { - ad->structsize = sc->offset + aad.structsize; - sc->offset = ad->structsize; - } - - if (ad->alignsize < aad.alignsize) - ad->alignsize = aad.alignsize; } } @@ -891,9 +860,9 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("\n{\n"); if (decl) { - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; //buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -953,10 +922,10 @@ void PragmaDeclaration::setScope(Scope *sc) } else { - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->tdata()[0] = e; + (*args)[0] = e; StringExp* se = e->toString(); if (!se) { @@ -991,7 +960,7 @@ void PragmaDeclaration::semantic(Scope *sc) { for (size_t i = 0; i < args->dim; i++) { - Expression *e = args->tdata()[i]; + Expression *e = (*args)[i]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); @@ -1013,11 +982,11 @@ void PragmaDeclaration::semantic(Scope *sc) error("string expected for library name"); else { - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->tdata()[0] = e; + (*args)[0] = e; if (e->op == TOKerror) goto Lnodecl; StringExp *se = e->toString(); @@ -1045,7 +1014,7 @@ void PragmaDeclaration::semantic(Scope *sc) Declaration *d = NULL; StringExp *s = NULL; - e = (Expression *)args->data[0]; + e = (*args)[0]; e = e->semantic(sc); if (e->op == TOKvar) { @@ -1056,14 +1025,14 @@ void PragmaDeclaration::semantic(Scope *sc) if (!d) error("first argument of GNU_asm must be a function or variable declaration"); - e = args->tdata()[1]; + e = (*args)[1]; e = e->semantic(sc); e = e->optimize(WANTvalue); e = e->toString(); if (e && ((StringExp *)e)->sz == 1) s = ((StringExp *)e); else - error("second argument of GNU_asm must be a char string"); + error("second argument of GNU_asm must be a character string"); if (d && s) d->c_ident = Lexer::idPool((char*) s->string); @@ -1078,10 +1047,10 @@ void PragmaDeclaration::semantic(Scope *sc) error("function name expected for start address"); else { - Expression *e = (Expression *)args->data[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->data[0] = (void *)e; + (*args)[0] = e; Dsymbol *sa = getDsymbol(e); if (!sa || !sa->isFuncDeclaration()) error("function name expected for start address, not '%s'", e->toChars()); @@ -1111,11 +1080,13 @@ void PragmaDeclaration::semantic(Scope *sc) { for (size_t i = 0; i < args->dim; i++) { +#if IN_LLVM // ignore errors in ignored pragmas. global.gag++; unsigned errors_save = global.errors; +#endif - Expression *e = (Expression *)args->data[i]; + Expression *e = (*args)[i]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); if (i == 0) @@ -1124,9 +1095,11 @@ void PragmaDeclaration::semantic(Scope *sc) printf(","); printf("%s", e->toChars()); +#if IN_LLVM // restore error state. global.gag--; global.errors = errors_save; +#endif } if (args->dim) printf(")"); @@ -1141,9 +1114,9 @@ void PragmaDeclaration::semantic(Scope *sc) Ldecl: if (decl) { - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; s->semantic(sc); @@ -1180,7 +1153,7 @@ void PragmaDeclaration::toObjFile(int multiobj) { assert(args && args->dim == 1); - Expression *e = (Expression *)args->data[0]; + Expression *e = (*args)[0]; assert(e->op == TOKstring); @@ -1208,7 +1181,7 @@ void PragmaDeclaration::toObjFile(int multiobj) else if (ident == Id::startaddress) { assert(args && args->dim == 1); - Expression *e = (Expression *)args->data[0]; + Expression *e = (*args)[0]; Dsymbol *sa = getDsymbol(e); FuncDeclaration *f = sa->isFuncDeclaration(); assert(f); @@ -1285,8 +1258,8 @@ void ConditionalDeclaration::emitComment(Scope *sc) * a template, then include(NULL, NULL) will fail. */ Dsymbols *d = decl ? decl : elsedecl; - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->emitComment(sc); } } @@ -1308,9 +1281,9 @@ void ConditionalDeclaration::setScope(Scope *sc) //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d); if (d) { - for (unsigned i = 0; i < d->dim; i++) + for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->setScope(sc); } @@ -1324,9 +1297,9 @@ void ConditionalDeclaration::importAll(Scope *sc) //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d); if (d) { - for (unsigned i = 0; i < d->dim; i++) + for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->importAll(sc); } @@ -1349,10 +1322,8 @@ void ConditionalDeclaration::addComment(unsigned char *comment) { if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } @@ -1372,9 +1343,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); if (decl) { - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -1388,9 +1359,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); buf->writeByte('{'); buf->writenl(); - for (unsigned i = 0; i < elsedecl->dim; i++) + for (size_t i = 0; i < elsedecl->dim; i++) { - Dsymbol *s = elsedecl->tdata()[i]; + Dsymbol *s = (*elsedecl)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -1474,9 +1445,9 @@ void StaticIfDeclaration::semantic(Scope *sc) addisdone = 1; } - for (unsigned i = 0; i < d->dim; i++) + for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->semantic(sc); } diff --git a/dmd/attrib.h b/dmd/attrib.h index 02db2a3b..27c71f86 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -33,6 +33,7 @@ struct AttribDeclaration : Dsymbol AttribDeclaration(Dsymbols *decl); virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s); + int apply(Dsymbol_apply_ft_t fp, void *param); int addMember(Scope *sc, ScopeDsymbol *s, int memnum); void setScopeNewSc(Scope *sc, StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection, @@ -48,6 +49,7 @@ struct AttribDeclaration : Dsymbol void emitComment(Scope *sc); const char *kind(); int oneMember(Dsymbol **ps); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); int hasPointers(); bool hasStaticCtorOrDtor(); void checkCtorConstInit(); @@ -58,7 +60,6 @@ struct AttribDeclaration : Dsymbol #if IN_DMD void toObjFile(int multiobj); // compile to .obj file - int cvMember(unsigned char *p); #endif #if IN_LLVM @@ -119,12 +120,14 @@ struct AlignDeclaration : AttribDeclaration struct AnonDeclaration : AttribDeclaration { - int isunion; + bool isunion; + unsigned alignment; int sem; // 1 if successful semantic() AnonDeclaration(Loc loc, int isunion, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); const char *kind(); }; diff --git a/dmd/cast.c b/dmd/cast.c index f5e4989f..562d09dc 100644 --- a/dmd/cast.c +++ b/dmd/cast.c @@ -1166,17 +1166,16 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t) Expression *DelegateExp::castTo(Scope *sc, Type *t) { - Type *tb; #if 0 printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", toChars(), type->toChars(), t->toChars()); #endif - Expression *e = this; static char msg[] = "cannot form delegate due to covariant return type"; - tb = t->toBasetype(); + Expression *e = this; + Type *tb = t->toBasetype(); type = type->toBasetype(); - if (tb != type) + if (tb != type || hasOverloads) { // Look for delegates to functions where the functions are overloaded. FuncDeclaration *f; diff --git a/dmd/class.c b/dmd/class.c index bf793906..5f9a60c1 100644 --- a/dmd/class.c +++ b/dmd/class.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -228,9 +228,9 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) cd->baseclasses->setDim(this->baseclasses->dim); for (size_t i = 0; i < cd->baseclasses->dim; i++) { - BaseClass *b = (BaseClass *)this->baseclasses->data[i]; + BaseClass *b = this->baseclasses->tdata()[i]; BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); - cd->baseclasses->data[i] = b2; + cd->baseclasses->tdata()[i] = b2; } ScopeDsymbol::syntaxCopy(cd); @@ -264,7 +264,7 @@ void ClassDeclaration::semantic(Scope *sc) return; } if (symtab) - { if (sizeok == 1 || !scope) + { if (sizeok == SIZEOKdone || !scope) { //printf("\tsemantic for '%s' is already completed\n", toChars()); return; // semantic() already completed } @@ -290,7 +290,7 @@ void ClassDeclaration::semantic(Scope *sc) // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) - { BaseClass *b = (BaseClass *)baseclasses->data[i]; + { BaseClass *b = baseclasses->tdata()[i]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -315,11 +315,12 @@ void ClassDeclaration::semantic(Scope *sc) BaseClass *b; Type *tb; - b = (BaseClass *)baseclasses->data[0]; + b = baseclasses->tdata()[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()); + { if (b->type != Type::terror) + error("base type must be class or interface, not %s", b->type->toChars()); baseclasses->remove(0); } else @@ -331,7 +332,7 @@ void ClassDeclaration::semantic(Scope *sc) if (!isDeprecated()) { // Deriving from deprecated class makes this one deprecated too - isdeprecated = 1; + isdeprecated = true; tc->checkDeprecated(loc, sc); } @@ -350,12 +351,12 @@ void ClassDeclaration::semantic(Scope *sc) goto L7; } } - if (!tc->sym->symtab || tc->sym->sizeok == 0) + if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone) { // Try to resolve forward reference if (/*sc->mustsemantic &&*/ tc->sym->scope) tc->sym->semantic(NULL); } - if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0) + if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone) { //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars()); //error("forward reference of base class %s", baseClass->toChars()); @@ -384,7 +385,7 @@ void ClassDeclaration::semantic(Scope *sc) BaseClass *b; Type *tb; - b = (BaseClass *)baseclasses->data[i]; + b = baseclasses->tdata()[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) @@ -392,7 +393,7 @@ void ClassDeclaration::semantic(Scope *sc) else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) - { + { if (b->type != Type::terror) error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; @@ -404,7 +405,7 @@ void ClassDeclaration::semantic(Scope *sc) if (!isDeprecated()) { // Deriving from deprecated class makes this one deprecated too - isdeprecated = 1; + isdeprecated = true; tc->checkDeprecated(loc, sc); } @@ -413,7 +414,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 = baseclasses->tdata()[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } @@ -467,7 +468,7 @@ void ClassDeclaration::semantic(Scope *sc) } interfaces_dim = baseclasses->dim; - interfaces = (BaseClass **)baseclasses->data; + interfaces = baseclasses->tdata(); if (baseClass) @@ -480,7 +481,7 @@ void ClassDeclaration::semantic(Scope *sc) // Copy vtbl[] from base class vtbl.setDim(baseClass->vtbl.dim); - memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim); + memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim); // Inherit properties from base class com = baseClass->isCOMclass(); @@ -503,7 +504,7 @@ void ClassDeclaration::semantic(Scope *sc) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (Dsymbol *)members->data[i]; + Dsymbol *s = (*members)[i]; s->addMember(sc, this, 1); } @@ -606,17 +607,20 @@ void ClassDeclaration::semantic(Scope *sc) structsize = sc->offset; Scope scsave = *sc; size_t members_dim = members->dim; - sizeok = 0; + sizeok = SIZEOKnone; /* Set scope so if there are forward references, we still might be able to * resolve individual members like enums. */ for (size_t i = 0; i < members_dim; i++) - { Dsymbol *s = (Dsymbol *)members->data[i]; + { Dsymbol *s = (*members)[i]; /* There are problems doing this in the general case because * Scope keeps track of things like 'offset' */ - if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) + if (s->isEnumDeclaration() || + (s->isAggregateDeclaration() && s->ident) || + s->isTemplateMixin() || + s->isAliasDeclaration()) { //printf("setScope %s %s\n", s->kind(), s->toChars()); s->setScope(sc); @@ -624,13 +628,35 @@ void ClassDeclaration::semantic(Scope *sc) } for (size_t i = 0; i < members_dim; i++) - { Dsymbol *s = (Dsymbol *)members->data[i]; + { Dsymbol *s = (*members)[i]; s->semantic(sc); } - if (sizeok == 2) - { // semantic() failed because of forward references. + // Set the offsets of the fields and determine the size of the class + + unsigned offset = structsize; + bool isunion = isUnionDeclaration() != NULL; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setFieldOffset(this, &offset, false); + } + sc->offset = structsize; + + if (global.gag && global.gaggedErrors != errors) + { // The type is no good, yet the error messages were gagged. + type = Type::terror; + } + + if (sizeok == 2) // failed due to forward references + { // semantic() failed due to forward references // Unwind what we did, and defer it for later + + for (size_t i = 0; i < fields.dim; i++) + { Dsymbol *s = fields[i]; + VarDeclaration *vd = s->isVarDeclaration(); + if (vd) + vd->offset = 0; + } fields.setDim(0); structsize = 0; alignsize = 0; @@ -650,7 +676,6 @@ void ClassDeclaration::semantic(Scope *sc) //printf("\tsemantic('%s') successful\n", toChars()); - structsize = sc->offset; //members->print(); /* Look for special member functions. @@ -683,7 +708,6 @@ void ClassDeclaration::semantic(Scope *sc) 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; @@ -699,9 +723,10 @@ void ClassDeclaration::semantic(Scope *sc) #endif // Allocate instance of each new interface + sc->offset = structsize; for (size_t i = 0; i < vtblInterfaces->dim; i++) { - BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; + BaseClass *b = (*vtblInterfaces)[i]; unsigned thissize = PTRSIZE; alignmember(structalign, thissize, &sc->offset); @@ -720,7 +745,7 @@ void ClassDeclaration::semantic(Scope *sc) alignsize = thissize; } structsize = sc->offset; - sizeok = 1; + sizeok = SIZEOKdone; Module::dprogress++; dtor = buildDtor(sc); @@ -731,7 +756,7 @@ void ClassDeclaration::semantic(Scope *sc) // Fill in base class vtbl[]s for (i = 0; i < vtblInterfaces->dim; i++) { - BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; + BaseClass *b = vtblInterfaces->tdata()[i]; //b->fillVtbl(this, &b->vtbl, 1); } @@ -750,7 +775,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } for (size_t i = 0; i < baseclasses->dim; i++) { - BaseClass *b = (BaseClass *)baseclasses->data[i]; + BaseClass *b = baseclasses->tdata()[i]; if (i) buf->writeByte(','); @@ -764,7 +789,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (Dsymbol *)members->data[i]; + Dsymbol *s = members->tdata()[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -799,7 +824,7 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) return 0; //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); for (size_t i = 0; i < cd->baseclasses->dim; i++) - { BaseClass *b = (BaseClass *)cd->baseclasses->data[i]; + { BaseClass *b = cd->baseclasses->tdata()[i]; if (b->base == this || isBaseOf2(b->base)) return 1; @@ -845,7 +870,7 @@ int ClassDeclaration::isBaseInfoComplete() if (!baseClass) return ident == Id::Object; for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *b = (BaseClass *)baseclasses->data[i]; + { BaseClass *b = baseclasses->tdata()[i]; if (!b->base || !b->base->isBaseInfoComplete()) return 0; } @@ -860,7 +885,12 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) if (scope && !symtab) { Scope *sc = scope; sc->mustsemantic++; + // If speculatively gagged, ungag now. + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging()) + global.gag = 0; semantic(sc); + global.gag = oldgag; sc->mustsemantic--; } @@ -878,7 +908,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) for (size_t i = 0; i < baseclasses->dim; i++) { - BaseClass *b = (BaseClass *)baseclasses->data[i]; + BaseClass *b = baseclasses->tdata()[i]; if (b->base) { @@ -1178,12 +1208,12 @@ void InterfaceDeclaration::semantic(Scope *sc) if (sc->stc & STCdeprecated) { - isdeprecated = 1; + isdeprecated = true; } // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) - { BaseClass *b = (BaseClass *)baseclasses->data[0]; + { BaseClass *b = (*baseclasses)[0]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -1208,7 +1238,7 @@ void InterfaceDeclaration::semantic(Scope *sc) BaseClass *b; Type *tb; - b = (BaseClass *)baseclasses->data[i]; + b = baseclasses->tdata()[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) @@ -1216,7 +1246,7 @@ void InterfaceDeclaration::semantic(Scope *sc) else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) - { + { if (b->type != Type::terror) error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; @@ -1226,7 +1256,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 = baseclasses->tdata()[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } @@ -1311,10 +1341,10 @@ void InterfaceDeclaration::semantic(Scope *sc) sc->explicitProtection = 0; structalign = sc->structalign; sc->offset = PTRSIZE * 2; + structsize = sc->offset; inuse++; for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *s = (*members)[i]; + { Dsymbol *s = (*members)[i]; s->semantic(sc); } inuse--; @@ -1408,7 +1438,7 @@ int InterfaceDeclaration::isBaseInfoComplete() { assert(!baseClass); for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *b = (BaseClass *)baseclasses->data[i]; + { BaseClass *b = baseclasses->tdata()[i]; if (!b->base || !b->base->isBaseInfoComplete ()) return 0; } diff --git a/dmd/cond.c b/dmd/cond.c index 80d92742..afce513e 100644 --- a/dmd/cond.c +++ b/dmd/cond.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -225,6 +225,7 @@ StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp) : Condition(loc) { this->exp = exp; + this->nest = 0; } Condition *StaticIfCondition::syntaxCopy() @@ -235,7 +236,7 @@ Condition *StaticIfCondition::syntaxCopy() int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) { #if 0 - printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s); + printf("StaticIfCondition::include(sc = %p, s = %p) this=%p inc = %d\n", sc, s, this, inc); if (s) { printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind()); @@ -243,6 +244,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) #endif if (inc == 0) { + if (exp->op == TOKerror || nest > 100) + { + error(loc, (nest > 1000) ? "unresolvable circular static if expression" + : "error evaluating static if expression"); + if (!global.gag) + inc = 2; // so we don't see the error message again + return 0; + } + if (!sc) { error(loc, "static if conditional cannot be at global scope"); @@ -250,13 +260,19 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) return 0; } + ++nest; sc = sc->push(sc->scopesym); sc->sd = s; // s gets any addMember() sc->flags |= SCOPEstaticif; Expression *e = exp->semantic(sc); sc->pop(); e = e->optimize(WANTvalue | WANTinterpret); - if (e->isBool(TRUE)) + --nest; + if (e->op == TOKerror) + { exp = e; + inc = 0; + } + else if (e->isBool(TRUE)) inc = 1; else if (e->isBool(FALSE)) inc = 2; diff --git a/dmd/cond.h b/dmd/cond.h index 745dab23..71400314 100644 --- a/dmd/cond.h +++ b/dmd/cond.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -36,6 +36,7 @@ struct Condition virtual Condition *syntaxCopy() = 0; virtual int include(Scope *sc, ScopeDsymbol *s) = 0; virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; + virtual DebugCondition *isDebugCondition() { return NULL; } }; struct DVCondition : Condition @@ -59,6 +60,7 @@ struct DebugCondition : DVCondition int include(Scope *sc, ScopeDsymbol *s); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + DebugCondition *isDebugCondition() { return this; } }; struct VersionCondition : DVCondition @@ -77,6 +79,7 @@ struct VersionCondition : DVCondition struct StaticIfCondition : Condition { Expression *exp; + int nest; // limit circular dependencies StaticIfCondition(Loc loc, Expression *exp); Condition *syntaxCopy(); diff --git a/dmd/declaration.c b/dmd/declaration.c index 4de203d8..c22096c8 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -530,7 +530,8 @@ void AliasDeclaration::semantic(Scope *sc) goto L2; } else - { error("cannot alias an expression %s", e->toChars()); + { if (e->op != TOKerror) + error("cannot alias an expression %s", e->toChars()); t = e->type; } } @@ -543,7 +544,7 @@ void AliasDeclaration::semantic(Scope *sc) ScopeDsymbol::multiplyDefined(0, this, overnext); this->inSemantic = 0; - if (errors != global.errors) + if (global.gag && errors != global.errors) type = savedtype; return; @@ -580,7 +581,7 @@ void AliasDeclaration::semantic(Scope *sc) assert(global.errors); s = NULL; } - if (errors != global.errors) + if (global.gag && errors != global.errors) { type = savedtype; overnext = savedovernext; @@ -728,6 +729,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer #if DMDV1 nestedref = 0; #endif + alignment = 0; ctorinit = 0; aliassym = NULL; onstack = 0; @@ -767,6 +769,7 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); sv->storage_class = storage_class; } + // Syntax copy for header file if (!htype) // Don't overwrite original { if (type) // Make copy for both old and new instances @@ -955,9 +958,7 @@ void VarDeclaration::semantic(Scope *sc) } else { - AggregateDeclaration *aad = sc->anonAgg; - if (!aad) - aad = parent->isAggregateDeclaration(); + AggregateDeclaration *aad = parent->isAggregateDeclaration(); if (aad) { #if DMDV2 @@ -970,7 +971,15 @@ void VarDeclaration::semantic(Scope *sc) } else #endif - aad->addField(sc, this); + { + storage_class |= STCfield; + alignment = sc->structalign; +#if DMDV2 + if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor || + tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor) + aad->noDefaultCtor = TRUE; +#endif + } } InterfaceDeclaration *id = parent->isInterfaceDeclaration(); @@ -1305,6 +1314,31 @@ ExpInitializer *VarDeclaration::getExpInitializer() void VarDeclaration::semantic2(Scope *sc) { //printf("VarDeclaration::semantic2('%s')\n", toChars()); + // Inside unions, default to void initializers + if (!init && sc->inunion && !toParent()->isFuncDeclaration()) + { + AggregateDeclaration *aad = parent->isAggregateDeclaration(); + if (aad) + { + if (aad->fields[0] == this) + { + int hasinit = 0; + for (size_t i = 1; i < aad->fields.dim; i++) + { + if (aad->fields[i]->init && + !aad->fields[i]->init->isVoidInitializer()) + { + hasinit = 1; + break; + } + } + if (!hasinit) + init = new ExpInitializer(loc, type->defaultInitLiteral(loc)); + } + else + init = new VoidInitializer(loc); + } + } if (init && !toParent()->isFuncDeclaration()) { inuse++; #if 0 @@ -1330,6 +1364,82 @@ void VarDeclaration::semantic3(Scope *sc) Declaration::semantic3(sc); } +void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ + //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad->toChars(), toChars()); + + if (aliassym) + { // If this variable was really a tuple, set the offsets for the tuple fields + TupleDeclaration *v2 = aliassym->isTupleDeclaration(); + assert(v2); + for (size_t i = 0; i < v2->objects->dim; i++) + { Object *o = (*v2->objects)[i]; + assert(o->dyncast() == DYNCAST_EXPRESSION); + Expression *e = (Expression *)o; + assert(e->op == TOKdsymbol); + DsymbolExp *se = (DsymbolExp *)e; + se->s->setFieldOffset(ad, poffset, isunion); + } + return; + } + + if (!(storage_class & STCfield)) + return; + assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls))); + + /* Fields that are tuples appear both as part of TupleDeclarations and + * as members. That means ignore them if they are already a field. + */ + if (offset) + return; // already a field + for (size_t i = 0; i < ad->fields.dim; i++) + { + if (ad->fields[i] == this) + return; // already a field + } + + // Check for forward referenced types which will fail the size() call + Type *t = type->toBasetype(); + if (storage_class & STCref) + { // References are the size of a pointer + t = Type::tvoidptr; + } + if (t->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)t; +#if DMDV2 + if (ts->sym == ad) + { + ad->error("cannot have field %s with same struct type", toChars()); + } +#endif + + if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope) + ts->sym->semantic(NULL); + if (ts->sym->sizeok != SIZEOKdone) + { + ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced + return; + } + } + if (t->ty == Tident) + { + ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced + return; + } + + unsigned memsize = t->size(loc); // size of member + unsigned memalignsize = t->alignsize(); // size of member for alignment purposes + unsigned memalign = t->memalign(alignment); // alignment boundaries + + offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign, + &ad->structsize, &ad->alignsize, isunion); + + //printf("\t%s: alignsize = %d\n", toChars(), alignsize); + + //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad->toChars(), offset, memsize); + ad->fields.push(this); +} + const char *VarDeclaration::kind() { return "variable"; diff --git a/dmd/declaration.h b/dmd/declaration.h index 40239743..5fdd1d00 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -279,6 +279,7 @@ struct VarDeclaration : Declaration #else int nestedref; // referenced by a lexically nested function #endif + unsigned short alignment; int ctorinit; // it has been initialized in a ctor int onstack; // 1: it has been allocated on the stack // 2: on stack, run destructor anyway @@ -305,6 +306,7 @@ struct VarDeclaration : Declaration VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); void semantic2(Scope *sc); const char *kind(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -795,6 +797,7 @@ struct FuncDeclaration : Declaration int isAbstract(); int isCodeseg(); int isOverloadable(); + int hasOverloads(); int isPure(); int isSafe(); int isTrusted(); diff --git a/dmd/doc.c b/dmd/doc.c index 2d7a48a5..cff0fd43 100644 --- a/dmd/doc.c +++ b/dmd/doc.c @@ -261,6 +261,9 @@ void Module::gendocfile() Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); } + char *srcfilename = srcfile->toChars(); + Macro::define(¯otable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename)); + char *docfilename = docfile->toChars(); Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename)); diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index 1318299e..2689022c 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -50,6 +50,7 @@ Dsymbol::Dsymbol() this->loc = 0; this->comment = NULL; this->scope = NULL; + this->errors = false; #if IN_LLVM this->llvmInternal = LLVMnone; this->irsym = NULL; @@ -69,6 +70,7 @@ Dsymbol::Dsymbol(Identifier *ident) this->loc = 0; this->comment = NULL; this->scope = NULL; + this->errors = false; #if IN_LLVM this->llvmInternal = LLVMnone; this->irsym = NULL; @@ -169,6 +171,10 @@ bool Dsymbol::hasStaticCtorOrDtor() return FALSE; } +void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ +} + char *Dsymbol::toChars() { return ident ? ident->toChars() : (char *)"__anonymous"; @@ -283,6 +289,23 @@ TemplateInstance *Dsymbol::inTemplateInstance() return NULL; } +// Check if this function is a member of a template which has only been +// instantiated speculatively, eg from inside is(typeof()). +// Return the speculative template instance it is part of, +// or NULL if not speculative. +TemplateInstance *Dsymbol::isSpeculative() +{ + Dsymbol * par = parent; + while (par) + { + TemplateInstance *ti = par->isTemplateInstance(); + if (ti && ti->speculative) + return ti; + par = par->toParent(); + } + return NULL; +} + int Dsymbol::isAnonymous() { return ident ? 0 : 1; @@ -367,11 +390,21 @@ Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags) void *symbol_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. + */ + 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; + assert(id); + Dsymbol *s = (Dsymbol *)arg; - Identifier id(seed, 0); Module::clearCache(); - s = s->search(0, &id, 4|2); - return s; + return s->search(0, id, 4|2); } Dsymbol *Dsymbol::search_correct(Identifier *ident) @@ -409,7 +442,13 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) id = ti->name; sm = s->search(loc, id, 0); if (!sm) - { error("template identifier %s is not a member of %s %s", + { + sm = s->search_correct(id); + if (sm) + error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?", + id->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars()); + else + error("template identifier '%s' is not a member of '%s %s'", id->toChars(), s->kind(), s->toChars()); return NULL; } @@ -495,6 +534,11 @@ int Dsymbol::isOverloadable() } #endif +int Dsymbol::hasOverloads() +{ + return 0; +} + LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? { return NULL; @@ -518,6 +562,11 @@ int Dsymbol::needThis() return FALSE; } +int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param) +{ + return (*fp)(this, param); +} + int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { //printf("Dsymbol::addMember('%s')\n", toChars()); @@ -634,19 +683,16 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc) Module *Dsymbol::getModule() { - Module *m; - Dsymbol *s; - //printf("Dsymbol::getModule()\n"); TemplateDeclaration *td = getFuncTemplateDecl(this); if (td) return td->getModule(); - s = this; + Dsymbol *s = this; while (s) { - //printf("\ts = '%s'\n", s->toChars()); - m = s->isModule(); + //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars()); + Module *m = s->isModule(); if (m) return m; s = s->parent; diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 55264a78..7e4fce98 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -128,6 +128,8 @@ enum PASS PASSobj, // toObjFile() run }; +typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *); + struct Dsymbol : Object { Identifier *ident; @@ -140,6 +142,7 @@ struct Dsymbol : Object unsigned char *comment; // documentation comment for this Dsymbol Loc loc; // where defined Scope *scope; // !=NULL means context to use for semantic() + bool errors; // this symbol failed to pass semantic() Dsymbol(); Dsymbol(Identifier *); @@ -157,6 +160,7 @@ struct Dsymbol : Object Dsymbol *toParent(); Dsymbol *toParent2(); TemplateInstance *inTemplateInstance(); + TemplateInstance *isSpeculative(); int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol() @@ -165,6 +169,7 @@ struct Dsymbol : Object virtual const char *toPrettyChars(); virtual const char *kind(); virtual Dsymbol *toAlias(); // resolve real symbol + virtual int apply(Dsymbol_apply_ft_t fp, void *param); virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum); virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); @@ -193,6 +198,7 @@ struct Dsymbol : Object #if DMDV2 virtual int isOverloadable(); #endif + virtual int hasOverloads(); virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol? virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration? virtual Type *getType(); // is this a type? @@ -202,6 +208,7 @@ struct Dsymbol : Object virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual int oneMember(Dsymbol **ps); static int oneMembers(Dsymbols *members, Dsymbol **ps); + virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); virtual int hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addLocalClass(ClassDeclarations *) { } diff --git a/dmd/expression.c b/dmd/expression.c index 74eede68..f11893df 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -345,10 +345,10 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt */ Type *t0 = NULL; for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (Expression *)exps->data[i]; + { Expression *e = (*exps)[i]; if (!e->type) - { error("%s has no value", e->toChars()); + { error(e->loc, "%s has no value", e->toChars()); e = new ErrorExp(); } e = resolveProperties(sc, e); @@ -357,7 +357,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt t0 = e->type; else e = e->implicitCastTo(sc, t0); - exps->data[i] = (void *)e; + (*exps)[i] = e; } if (!t0) @@ -384,11 +384,11 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt Expression *e0; int j0; for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (Expression *)exps->data[i]; + { Expression *e = (*exps)[i]; e = resolveProperties(sc, e); if (!e->type) - { error("%s has no value", e->toChars()); + { e->error("%s has no value", e->toChars()); e = new ErrorExp(); } @@ -401,8 +401,9 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt condexp.type = NULL; condexp.e1 = e0; condexp.e2 = e; + condexp.loc = e->loc; condexp.semantic(sc); - exps->data[j0] = (void *)condexp.e1; + (*exps)[j0] = condexp.e1; e = condexp.e2; j0 = i; e0 = e; @@ -414,15 +415,15 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt e0 = e; t0 = e->type; } - exps->data[i] = (void *)e; + (*exps)[i] = e; } if (t0) { for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (Expression *)exps->data[i]; + { Expression *e = (*exps)[i]; e = e->implicitCastTo(sc, t0); - exps->data[i] = (void *)e; + (*exps)[i] = e; } } else @@ -525,23 +526,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e) } #endif -// Check if this function is a member of a template which has only been -// instantiated speculatively, eg from inside is(typeof()). -// Return the speculative template instance it is part of, -// or NULL if not speculative. -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd) -{ - Dsymbol * par = fd->parent; - while (par) - { - TemplateInstance *ti = par->isTemplateInstance(); - if (ti && ti->speculative) - return ti; - par = par->toParent(); - } - return NULL; -} - /**************************************** * Now that we know the exact type of the function we're calling, * the arguments[] need to be adjusted: @@ -565,7 +549,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum // If inferring return type, and semantic3() needs to be run if not already run if (!tf->next && fd->inferRetType) { - TemplateInstance *spec = isSpeculativeFunction(fd); + TemplateInstance *spec = fd->isSpeculative(); int olderrs = global.errors; fd->semantic3(fd->scope); // Update the template instantiation with the number @@ -583,10 +567,9 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum Expression *arg; if (i < nargs) - arg = (Expression *)arguments->data[i]; + arg = (*arguments)[i]; else arg = NULL; - Type *tb; if (i < nparams) { @@ -613,12 +596,13 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum if (tf->varargs == 2 && i + 1 == nparams) { //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); - if (arg->implicitConvTo(p->type)) + MATCH m; + if ((m = arg->implicitConvTo(p->type)) != MATCHnomatch) { - if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf())) + if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m) goto L2; else if (nargs != nparams) - { error(loc, "expected %zu function arguments, not %zu", nparams, nargs); + { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); return; } goto L1; @@ -661,9 +645,6 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum Expression *e = new VarExp(loc, v); e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); AssignExp *ae = new AssignExp(loc, e, a); -#if DMDV2 - ae->op = TOKconstruct; -#endif if (c) c = new CommaExp(loc, c, ae); else @@ -723,7 +704,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum // LDC we don't want this! #if !IN_LLVM // Convert static arrays to pointers - tb = arg->type->toBasetype(); + Type *tb = arg->type->toBasetype(); if (tb->ty == Tsarray) { arg = arg->checkToPointer(); @@ -732,7 +713,19 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum #if DMDV2 if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout))) { - arg = callCpCtor(loc, sc, arg); + if (arg->op == TOKcall) + { + /* The struct value returned from the function is transferred + * to the function, so the callee should not call the destructor + * on it. + */ + valueNoDtor(arg); + } + else + { /* Not transferring it, so call the copy constructor + */ + arg = callCpCtor(loc, sc, arg, 1); + } } #endif @@ -801,7 +794,8 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum } // Convert static arrays to dynamic arrays - tb = arg->type->toBasetype(); + // BUG: I don't think this is right for D2 + Type *tb = arg->type->toBasetype(); if (tb->ty == Tsarray) { TypeSArray *ts = (TypeSArray *)tb; Type *ta = ts->next->arrayOf(); @@ -2222,6 +2216,7 @@ Lagain: if (em) { e = em->value->copy(); + e->loc = loc; e = e->semantic(sc); return e; } @@ -2234,8 +2229,8 @@ Lagain: v->semantic(v->scope); type = v->type; if (!v->type) - { error("forward reference of %s", v->toChars()); - type = Type::terror; + { error("forward reference of %s %s", v->kind(), v->toChars()); + return new ErrorExp(); } } if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray) @@ -2245,8 +2240,7 @@ Lagain: if (v->inuse) { error("circular reference to '%s'", v->toChars()); - type = Type::tint32; - return this; + return new ErrorExp(); } ExpInitializer *ei = v->init->isExpInitializer(); if (ei) @@ -2282,13 +2276,19 @@ Lagain: { //printf("'%s' is a function\n", f->toChars()); if (!f->originalType && f->scope) // semantic not yet run + { + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging() && !f->isSpeculative()) + global.gag = 0; f->semantic(f->scope); + global.gag = oldgag; + } #if DMDV2 // if inferring return type, sematic3 needs to be run if (f->inferRetType && f->scope && f->type && !f->type->nextOf()) { - TemplateInstance *spec = isSpeculativeFunction(f); + TemplateInstance *spec = f->isSpeculative(); int olderrs = global.errors; f->semantic3(f->scope); // Update the template instantiation with the number @@ -2362,10 +2362,10 @@ Lagain: } TemplateInstance *ti = s->isTemplateInstance(); - if (ti && !global.errors) + if (ti) { if (!ti->semanticRun) ti->semantic(sc); - s = ti->inst->toAlias(); + s = ti->toAlias(); if (!s->isTemplateInstance()) goto Lagain; e = new ScopeExp(loc, ti); @@ -3224,6 +3224,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc) printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); #endif + if (type) + return this; + // Run semantic() on each element arrayExpressionSemantic(keys, sc); arrayExpressionSemantic(values, sc); @@ -3232,8 +3235,7 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc) if (keys->dim != values->dim) { error("number of keys is %u, must match number of values %u", keys->dim, values->dim); - keys->setDim(0); - values->setDim(0); + return new ErrorExp(); } Type *tkey = NULL; @@ -3241,6 +3243,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc) keys = arrayExpressionToCommonType(sc, keys, &tkey); values = arrayExpressionToCommonType(sc, values, &tvalue); + if (tkey == Type::terror || tvalue == Type::terror) + return new ErrorExp; + type = new TypeAArray(tvalue, tkey); type = type->semantic(loc, sc); return this; @@ -3629,8 +3634,9 @@ Expression *ScopeExp::semantic(Scope *sc) #endif Lagain: ti = sds->isTemplateInstance(); - if (ti && !global.errors) + if (ti && !ti->errors) { + unsigned olderrs = global.errors; if (!ti->semanticRun) ti->semantic(sc); if (ti->inst) @@ -3660,7 +3666,7 @@ Lagain: } //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); } - if (global.errors) + if (olderrs != global.errors) return new ErrorExp(); } else @@ -5471,6 +5477,32 @@ void BinExp::incompatibleTypes() /************************************************************/ +Expression *BinAssignExp::semantic(Scope *sc) +{ Expression *e; + + //printf("BinAssignExp::semantic()\n"); + if (type) + return this; + BinExp::semantic(sc); + e2 = resolveProperties(sc, e2); + + e = op_overload(sc); + if (e) + return e; + + e1 = e1->modifiableLvalue(sc, e1); + e1->checkScalar(); + e1->checkNoBool(); + type = e1->type; + typeCombine(sc); + e1->checkIntegral(); + e2 = e2->checkIntegral(); + e2 = e2->castTo(sc, Type::tshiftcnt); + return this; +} + +/************************************************************/ + CompileExp::CompileExp(Loc loc, Expression *e) : UnaExp(loc, TOKmixin, sizeof(CompileExp), e) { @@ -5921,7 +5953,9 @@ Expression *DotIdExp::semantic(Scope *sc) if (tup) { if (eleft) - error("cannot have e.tuple"); + { error("cannot have e.tuple"); + return new ErrorExp(); + } e = new TupleExp(loc, tup); e = e->semantic(sc); return e; @@ -5959,7 +5993,12 @@ Expression *DotIdExp::semantic(Scope *sc) e = e->semantic(sc); return e; } - error("undefined identifier %s", toChars()); + s = ie->sds->search_correct(ident); + if (s) + error("undefined identifier '%s', did you mean '%s %s'?", + ident->toChars(), s->kind(), s->toChars()); + else + error("undefined identifier '%s'", ident->toChars()); return new ErrorExp(); } else if (e1->type->ty == Tpointer && @@ -6239,8 +6278,8 @@ L1: return e; if (e->op == TOKdottd) { - if (global.errors) - return new ErrorExp(); // TemplateInstance::semantic() will fail anyway + if (ti->errors) + return new ErrorExp(); DotTemplateExp *dte = (DotTemplateExp *)e; TemplateDeclaration *td = dte->td; eleft = dte->e1; @@ -6248,8 +6287,8 @@ L1: #if DMDV2 if (ti->needsTypeInference(sc)) { - e = new CallExp(loc, this); - return e->semantic(sc); + e1 = eleft; // save result of semantic() + return this; } else #endif @@ -6451,6 +6490,7 @@ DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f) : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) { this->func = f; + this->hasOverloads = 0; m = NULL; } @@ -6828,6 +6868,17 @@ Lagain: arrayExpressionSemantic(arguments, sc); preFunctionParameters(loc, sc, arguments); + // If there was an error processing any template argument, + // return an error without trying to resolve the template. + if (targsi && targsi->dim) + { + for (size_t k = 0; k < targsi->dim; k++) + { Object *o = targsi->tdata()[k]; + if (isError(o)) + return new ErrorExp(); + } + } + if (e1->op == TOKdotvar && t1->ty == Tfunction || e1->op == TOKdottd) { @@ -7336,11 +7387,24 @@ Expression *AddrExp::semantic(Scope *sc) return this; } - if (f && f->isNested()) + if (f) { - Expression *e = new DelegateExp(loc, e1, f); - e = e->semantic(sc); - return e; + if (f->isNested()) + { + if (f->isFuncLiteralDeclaration()) + { + if (!f->FuncDeclaration::isNested()) + { /* Supply a 'null' for a this pointer if no this is available + */ + Expression *e = new DelegateExp(loc, new NullExp(loc, Type::tvoidptr), f); + e = e->semantic(sc); + return e; + } + } + Expression *e = new DelegateExp(loc, e1, f); + e = e->semantic(sc); + return e; + } } } else if (e1->op == TOKarray) @@ -8554,10 +8618,11 @@ Expression *AssignExp::semantic(Scope *sc) if (e1->op == TOKarray) { ArrayExp *ae = (ArrayExp *)e1; - AggregateDeclaration *ad; + AggregateDeclaration *ad = NULL; Identifier *id = Id::index; ae->e1 = ae->e1->semantic(sc); + ae->e1 = resolveProperties(sc, ae->e1); Type *t1 = ae->e1->type->toBasetype(); if (t1->ty == Tstruct) { @@ -8585,7 +8650,9 @@ Expression *AssignExp::semantic(Scope *sc) { Expression *e = new DotIdExp(loc, ae->e1, id); if (1 || !global.params.useDeprecated) - error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); + { error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); + return new ErrorExp(); + } e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2); e = e->semantic(sc); @@ -8601,7 +8668,7 @@ Expression *AssignExp::semantic(Scope *sc) if (e1->op == TOKslice) { Type *t1; SliceExp *ae = (SliceExp *)e1; - AggregateDeclaration *ad; + AggregateDeclaration *ad = NULL; Identifier *id = Id::index; ae->e1 = ae->e1->semantic(sc); @@ -8697,8 +8764,9 @@ Expression *AssignExp::semantic(Scope *sc) * check for operator overloading. */ if (t1->ty == Tclass || t1->ty == Tstruct) - { - if (!e2->type->implicitConvTo(e1->type)) + { // Disallow assignment operator overloads for same type + if (/*op == TOKassign &&*/ // construction shouldn't be allowed, but OK to avoid breaking existing code + !e2->implicitConvTo(e1->type)) { Expression *e = op_overload(sc); if (e) @@ -8725,8 +8793,16 @@ Expression *AssignExp::semantic(Scope *sc) e1 = e1->modifiableLvalue(sc, e1old); } + // If it is a array, get the element type. Note that it may be + // multi-dimensional. + Type *telem = t1; + while (telem->ty == Tarray) + telem = telem->nextOf(); + + // Check for block assignment. If it is of type void[], void[][], etc, + // '= null' is the only allowable block assignment (Bug 7493) if (e1->op == TOKslice && - t1->nextOf() && + t1->nextOf() && (telem->ty != Tvoid || e2->op == TOKnull) && e2->implicitConvTo(t1->nextOf()) // !(t1->nextOf()->equals(e2->type->nextOf())) ) @@ -8792,7 +8868,7 @@ ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2) /************************************************************/ AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) + : BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) { } @@ -8903,7 +8979,7 @@ Expression *AddAssignExp::semantic(Scope *sc) /************************************************************/ MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) + : BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) { } @@ -8957,7 +9033,7 @@ Expression *MinAssignExp::semantic(Scope *sc) /************************************************************/ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) + : BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) { } @@ -8981,6 +9057,8 @@ Expression *CatAssignExp::semantic(Scope *sc) } e1 = e1->modifiableLvalue(sc, e1); + if (e1->op == TOKerror) + return e1; Type *tb1 = e1->type->toBasetype(); Type *tb2 = e2->type->toBasetype(); @@ -9039,13 +9117,15 @@ Expression *CatAssignExp::semantic(Scope *sc) /************************************************************/ MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) + : BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) { } Expression *MulAssignExp::semantic(Scope *sc) { Expression *e; + if (type) + return this; BinExp::semantic(sc); e2 = resolveProperties(sc, e2); @@ -9117,13 +9197,15 @@ Expression *MulAssignExp::semantic(Scope *sc) /************************************************************/ DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) + : BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) { } Expression *DivAssignExp::semantic(Scope *sc) { Expression *e; + if (type) + return this; BinExp::semantic(sc); e2 = resolveProperties(sc, e2); @@ -9198,12 +9280,14 @@ Expression *DivAssignExp::semantic(Scope *sc) /************************************************************/ ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) + : BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) { } Expression *ModAssignExp::semantic(Scope *sc) { + if (type) + return this; BinExp::semantic(sc); checkComplexMulAssign(); return commonSemanticAssign(sc); @@ -9212,104 +9296,28 @@ Expression *ModAssignExp::semantic(Scope *sc) /************************************************************/ ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) + : BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) { } -Expression *ShlAssignExp::semantic(Scope *sc) -{ Expression *e; - - //printf("ShlAssignExp::semantic()\n"); - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); -#if !IN_LLVM - e2 = e2->castTo(sc, Type::tshiftcnt); -#else - e2 = e2->castTo(sc, e1->type); -#endif - return this; -} - /************************************************************/ ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) + : BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) { } -Expression *ShrAssignExp::semantic(Scope *sc) -{ Expression *e; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); -#if !IN_LLVM - e2 = e2->castTo(sc, Type::tshiftcnt); -#else - e2 = e2->castTo(sc, e1->type); -#endif - return this; -} - /************************************************************/ UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) + : BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) { } -Expression *UshrAssignExp::semantic(Scope *sc) -{ Expression *e; - - BinExp::semantic(sc); - e2 = resolveProperties(sc, e2); - - e = op_overload(sc); - if (e) - return e; - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); -#if !IN_LLVM - e2 = e2->castTo(sc, Type::tshiftcnt); -#else - e2 = e2->castTo(sc, e1->type); -#endif - return this; -} - /************************************************************/ AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) + : BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) { } @@ -9321,7 +9329,7 @@ Expression *AndAssignExp::semantic(Scope *sc) /************************************************************/ OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) + : BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) { } @@ -9333,7 +9341,7 @@ Expression *OrAssignExp::semantic(Scope *sc) /************************************************************/ XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) - : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) + : BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) { } diff --git a/dmd/expression.h b/dmd/expression.h index b42f3178..5fe30801 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -932,8 +932,12 @@ struct BinExp : Expression struct BinAssignExp : BinExp { - BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2); - int checkSideEffect(int flag); + BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) + : BinExp(loc, op, size, e1, e2) + { + } + + Expression *semantic(Scope *sc); }; /****************************************************************/ @@ -1031,6 +1035,7 @@ struct DelegateExp : UnaExp { FuncDeclaration *func; Module* m; // starting point for overload resolution + int hasOverloads; DelegateExp(Loc loc, Expression *e, FuncDeclaration *func); Expression *semantic(Scope *sc); @@ -1446,10 +1451,10 @@ struct ConstructExp : AssignExp #endif #define ASSIGNEXP(op) \ -struct op##AssignExp : BinExp \ +struct op##AssignExp : BinAssignExp \ { \ op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ - Expression *semantic(Scope *sc); \ + S(Expression *semantic(Scope *sc);) \ Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \ X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \ X(Expression *buildArrayLoop(Parameters *fparams);) \ @@ -1460,6 +1465,7 @@ struct op##AssignExp : BinExp \ }; #define X(a) a +#define S(a) a ASSIGNEXP(Add) ASSIGNEXP(Min) ASSIGNEXP(Mul) @@ -1468,15 +1474,28 @@ ASSIGNEXP(Mod) ASSIGNEXP(And) ASSIGNEXP(Or) ASSIGNEXP(Xor) +#undef S + +#if DMDV2 +#define S(a) a +ASSIGNEXP(Pow) +#undef S +#endif + #undef X #define X(a) +#define S(a) ASSIGNEXP(Shl) ASSIGNEXP(Shr) ASSIGNEXP(Ushr) +#undef S + +#define S(a) a ASSIGNEXP(Cat) +#undef S #undef X #undef ASSIGNEXP #undef ASSIGNEXP_TOELEM diff --git a/dmd/func.c b/dmd/func.c index 982bb573..426bad52 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -306,7 +306,7 @@ void FuncDeclaration::semantic(Scope *sc) (pd = toParent2()) != NULL && (id = pd->isInterfaceDeclaration()) != NULL) { - error("template member function not allowed in interface %s", id->toChars()); + error("template member functions are not allowed in interface %s", id->toChars()); } cd = parent->isClassDeclaration(); @@ -362,6 +362,9 @@ void FuncDeclaration::semantic(Scope *sc) //printf("\tnot virtual\n"); goto Ldone; } + // Suppress further errors if the return type is an error + if (type->nextOf() == Type::terror) + goto Ldone; /* Find index of existing function in base class's vtbl[] to override * (the index will be the same as in cd's current vtbl[]) @@ -407,7 +410,7 @@ void FuncDeclaration::semantic(Scope *sc) break; case -2: // can't determine because of fwd refs - cd->sizeok = 2; // can't finish due to forward reference + cd->sizeok = SIZEOKfwd; // can't finish due to forward reference Module::dprogress = dprogress_save; return; @@ -488,18 +491,26 @@ void FuncDeclaration::semantic(Scope *sc) break; case -2: - cd->sizeok = 2; // can't finish due to forward reference + cd->sizeok = SIZEOKfwd; // can't finish due to forward reference Module::dprogress = dprogress_save; return; default: - { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; + { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi]; Type *ti = NULL; /* Remember which functions this overrides */ foverrides.push(fdv); +#if DMDV2 + /* Should we really require 'override' when implementing + * an interface function? + */ + //if (!isOverride()) + //warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); +#endif + if (fdv->tintro) ti = fdv->tintro; else if (!type->equals(fdv->type)) @@ -513,7 +524,7 @@ void FuncDeclaration::semantic(Scope *sc) if (global.endGagging(errors)) { // any error in isBaseOf() is a forward reference error, so we bail out - cd->sizeok = 2; // can't finish due to forward reference + cd->sizeok = SIZEOKfwd; // can't finish due to forward reference Module::dprogress = dprogress_save; return; } @@ -524,10 +535,15 @@ void FuncDeclaration::semantic(Scope *sc) } if (ti) { - if (tintro && !tintro->equals(ti)) + if (tintro) + { + if (!tintro->nextOf()->equals(ti->nextOf()) && + !tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) && + !ti->nextOf()->isBaseOf(tintro->nextOf(), NULL)) { error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars()); } + } tintro = ti; } goto L2; @@ -601,7 +617,7 @@ void FuncDeclaration::semantic(Scope *sc) if (f->varargs) { Lmainerr: - error("parameters must be main() or main(char[][] args)"); + error("parameters must be main() or main(string[] args)"); } } @@ -2508,6 +2524,10 @@ int FuncDeclaration::isCodeseg() return TRUE; // functions are always in the code segment } +int FuncDeclaration::hasOverloads() +{ + return overnext != NULL; +} // Determine if function needs // a static frame pointer to its lexically enclosing function @@ -3175,7 +3195,7 @@ int StaticCtorDeclaration::addPostInvariant() void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - if (hgs->hdrgen) + if (hgs->hdrgen && !hgs->tpltMember) { buf->writestring("static this();"); buf->writenl(); return; diff --git a/dmd/html.c b/dmd/html.c index d26ce48a..93b752ee 100644 --- a/dmd/html.c +++ b/dmd/html.c @@ -104,15 +104,15 @@ void Html::error(const char *format, ...) { if (!global.gag) { - printf("%s(%d) : HTML Error: ", sourcename, linnum); + fprintf(stderr, "%s(%d) : HTML Error: ", sourcename, linnum); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); } global.errors++; diff --git a/dmd/import.c b/dmd/import.c index 7cbed18f..6497adf2 100644 --- a/dmd/import.c +++ b/dmd/import.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -79,7 +79,16 @@ void Import::load(Scope *sc) // See if existing module DsymbolTable *dst = Package::resolve(packages, NULL, &pkg); - +#if TARGET_NET //dot net needs modules and packages with same name +#else + if (pkg && pkg->isModule()) + { + ::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?", + pkg->toChars(), pkg->toPrettyChars(), id->toChars()); + mod = pkg->isModule(); // Error recovery - treat as import of that module + return; + } +#endif Dsymbol *s = dst->lookup(id); if (s) { @@ -89,7 +98,8 @@ void Import::load(Scope *sc) if (s->isModule()) mod = (Module *)s; else - error("package and module have the same name"); + ::error(loc, "can only import from a module, not from package %s.%s", + pkg->toPrettyChars(), id->toChars()); #endif } @@ -97,11 +107,14 @@ void Import::load(Scope *sc) { // Load module mod = Module::load(loc, packages, id); + if (mod) + { dst->insert(id, mod); // id may be different from mod->ident, // if so then insert alias if (!mod->importedFrom) mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule; } + } if (!pkg) pkg = mod; @@ -151,7 +164,8 @@ void Import::semantic(Scope *sc) // Load if not already done so if (!mod) { load(sc); - mod->importAll(0); + if (mod) + mod->importAll(0); } if (mod) @@ -200,7 +214,9 @@ void Import::semantic(Scope *sc) } //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); - if (global.params.moduleDeps != NULL) + if (global.params.moduleDeps != NULL && + // object self-imports itself, so skip that (Bugzilla 7547) + !(id == Id::object && sc->module->ident == Id::object)) { /* The grammar of the file is: * ImportDeclaration diff --git a/dmd/init.c b/dmd/init.c index 760424a9..c8dab487 100644 --- a/dmd/init.c +++ b/dmd/init.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -53,10 +53,10 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai) a = new Initializers(); a->setDim(ai->dim); for (size_t i = 0; i < a->dim; i++) - { Initializer *e = (Initializer *)ai->data[i]; + { Initializer *e = (*ai)[i]; e = e->syntaxCopy(); - a->data[i] = e; + (*a)[i] = e; } } return a; @@ -128,11 +128,11 @@ Initializer *StructInitializer::syntaxCopy() ai->value.setDim(value.dim); for (size_t i = 0; i < field.dim; i++) { - ai->field.data[i] = field.data[i]; + ai->field[i] = field[i]; - Initializer *init = (Initializer *)value.data[i]; + Initializer *init = value[i]; init = init->syntaxCopy(); - ai->value.data[i] = init; + ai->value[i] = init; } return ai; } @@ -189,7 +189,12 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) s = ad->search(loc, id, 0); if (!s) { - error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); + s = ad->search_correct(id); + if (s) + error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", + id->toChars(), t->toChars(), s->kind(), s->toChars()); + else + error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); errors = 1; continue; } @@ -212,8 +217,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) if (s && (v = s->isVarDeclaration()) != NULL) { val = val->semantic(sc, v->type, needInterpret); - value.data[i] = (void *)val; - vars.data[i] = (void *)v; + value[i] = val; + vars[i] = v; } else { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); @@ -273,7 +278,7 @@ Expression *StructInitializer::toExpression() elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) { - elements->data[i] = NULL; + (*elements)[i] = NULL; } unsigned fieldi = 0; for (size_t i = 0; i < value.dim; i++) @@ -305,37 +310,37 @@ Expression *StructInitializer::toExpression() { error(loc, "too many initializers for '%s'", ad->toChars()); goto Lno; } - Initializer *iz = (Initializer *)value.data[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) goto Lno; - if (elements->data[fieldi]) + if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", - ((Dsymbol *)ad->fields.data[fieldi])->toChars()); + ad->fields[fieldi]->toChars()); goto Lno; } - elements->data[fieldi] = ex; + (*elements)[fieldi] = ex; ++fieldi; } // Now, fill in any missing elements with default initializers. // We also need to validate any anonymous unions for (size_t i = 0; i < elements->dim; ) { - VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration(); + VarDeclaration * vd = ad->fields[i]->isVarDeclaration(); int unionSize = ad->numFieldsInUnion(i); if (unionSize == 1) { // Not a union -- default initialize if missing - if (!elements->data[i]) - elements->data[i] = vd->type->defaultInit(); + if (!(*elements)[i]) + (*elements)[i] = vd->type->defaultInit(); } else { // anonymous union -- check for errors int found = -1; // index of the first field with an initializer - for (int j = i; j < i + unionSize; ++j) + for (size_t j = i; j < i + unionSize; ++j) { - if (!elements->data[j]) + if (!(*elements)[j]) continue; if (found >= 0) { @@ -375,13 +380,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i > 0) buf->writebyte(','); - Identifier *id = (Identifier *)field.data[i]; + Identifier *id = field[i]; if (id) { buf->writestring(id->toChars()); buf->writebyte(':'); } - Initializer *iz = (Initializer *)value.data[i]; + Initializer *iz = value[i]; if (iz) iz->toCBuffer(buf, hgs); } @@ -408,14 +413,14 @@ Initializer *ArrayInitializer::syntaxCopy() ai->index.setDim(index.dim); ai->value.setDim(value.dim); for (size_t i = 0; i < ai->value.dim; i++) - { Expression *e = (Expression *)index.data[i]; + { Expression *e = index[i]; if (e) e = e->syntaxCopy(); - ai->index.data[i] = e; + ai->index[i] = e; - Initializer *init = (Initializer *)value.data[i]; + Initializer *init = value[i]; init = init->syntaxCopy(); - ai->value.data[i] = init; + ai->value[i] = init; } return ai; } @@ -532,7 +537,7 @@ Expression *ArrayInitializer::toExpression() for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index[i]) - j = (index[i])->toInteger(); + j = index[i]->toInteger(); if (j >= edim) edim = j + 1; } @@ -584,6 +589,7 @@ Lno: return new ErrorExp(); } + /******************************** * If possible, convert array initializer to associative array initializer. */ @@ -601,18 +607,18 @@ Initializer *ArrayInitializer::toAssocArrayInitializer() for (size_t i = 0; i < value.dim; i++) { - e = index.tdata()[i]; + e = index[i]; if (!e) goto Lno; - keys->tdata()[i] = e; + (*keys)[i] = e; - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; e = iz->toExpression(); if (!e) goto Lno; - values->tdata()[i] = e; + (*values)[i] = e; } e = new AssocArrayLiteralExp(loc, keys, values); return new ExpInitializer(loc, e); @@ -668,13 +674,13 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i > 0) buf->writebyte(','); - Expression *ex = index.tdata()[i]; + Expression *ex = index[i]; if (ex) { ex->toCBuffer(buf, hgs); buf->writebyte(':'); } - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (iz) iz->toCBuffer(buf, hgs); } @@ -707,7 +713,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) return this; // Failed, suppress duplicate error messages if (exp->op == TOKtype) - error("initializer must be an expression, not '%s'", exp->toChars()); + exp->error("initializer must be an expression, not '%s'", exp->toChars()); Type *tb = t->toBasetype(); /* Look for case of initializing a static array with a too-short @@ -767,7 +773,7 @@ Type *ExpInitializer::inferType(Scope *sc) // Give error for overloaded function addresses if (exp->op == TOKdelegate) { DelegateExp *se = (DelegateExp *)exp; - if ( + if (se->hasOverloads && se->func->isFuncDeclaration() && !se->func->isFuncDeclaration()->isUnique()) exp->error("cannot infer type from overloaded function symbol %s", exp->toChars()); diff --git a/dmd/inline.c b/dmd/inline.c index 82013857..b567ea5a 100644 --- a/dmd/inline.c +++ b/dmd/inline.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -196,6 +196,8 @@ int lambdaInlineCost(Expression *e, void *param) int expressionInlineCost(Expression *e, InlineCostState *ics) { + //printf("expressionInlineCost()\n"); + //e->dump(0); ICS2 ics2; ics2.cost = 0; ics2.ics = ics; @@ -340,6 +342,7 @@ struct InlineDoState Dsymbols from; // old Dsymbols Dsymbols to; // parallel array of new Dsymbols Dsymbol *parent; // new parent + FuncDeclaration *fd; // function being inlined (old parent) }; /* -------------------------------------------------------------------- */ @@ -1486,6 +1489,9 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) if ( !fbody || ident == Id::ensure || // ensure() has magic properties the inliner loses + (ident == Id::require && // require() has magic properties too + toParent()->isFuncDeclaration() && // see bug 7699 + toParent()->isFuncDeclaration()->needThis()) || !hdrscan && ( #if 0 @@ -1600,6 +1606,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi memset(&ids, 0, sizeof(ids)); ids.parent = iss->fd; + ids.fd = this; if (ps) as = new Statements(); @@ -1786,6 +1793,18 @@ Expression *Expression::inlineCopy(Scope *sc) */ return copy(); #else + if (op == TOKdelegate) + { DelegateExp *de = (DelegateExp *)this; + + if (de->func->isNested()) + { /* See Bugzilla 4820 + * Defer checking until later if we actually need the 'this' pointer + */ + Expression *e = de->copy(); + return e; + } + } + InlineCostState ics; memset(&ics, 0, sizeof(ics)); @@ -1802,3 +1821,4 @@ Expression *Expression::inlineCopy(Scope *sc) return e; #endif } + diff --git a/dmd/interpret.c b/dmd/interpret.c index 05ce3359..26d04fac 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -27,7 +27,6 @@ #include "attrib.h" // for AttribDeclaration #include "template.h" -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd); #define LOG 0 @@ -45,6 +44,10 @@ private: together with the VarDeclaration, and the previous stack address of that variable, so that we can restore it when we leave the stack frame. + Note that when a function is forward referenced, the interpreter must + run semantic3, and that may start CTFE again with a NULL istate. Thus + the stack might not be empty when CTFE begins. + Ctfe Stack addresses are just 0-based integers, but we save them as 'void *' because ArrayBase can only do pointers. */ @@ -143,7 +146,11 @@ public: } void saveGlobalConstant(VarDeclaration *v, Expression *e) { - assert(v->isDataseg() && !v->isCTFE()); +#if DMDV2 + assert( v->init && (v->isConst() || v->isImmutable()) && !v->isCTFE()); +#else + assert( v->init && v->isConst() && !v->isCTFE()); +#endif v->ctfeAdrOnStack = globalValues.dim; globalValues.push(e); } @@ -208,7 +215,7 @@ VarDeclaration *findParentVar(Expression *e, Expression *thisval); bool needToCopyLiteral(Expression *expr); Expression *copyLiteral(Expression *e); Expression *paintTypeOntoLiteral(Type *type, Expression *lit); -Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2); +Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2); Expression *evaluateIfBuiltin(InterState *istate, Loc loc, FuncDeclaration *fd, Expressions *arguments, Expression *pthis); Expression *scrubReturnValue(Loc loc, Expression *e); @@ -243,6 +250,16 @@ struct ClassReferenceExp : Expression { return value->sd->isClassDeclaration(); } + VarDeclaration *getFieldAt(int index) + { + ClassDeclaration *cd = originalClass(); + size_t fieldsSoFar = 0; + while (index - fieldsSoFar >= cd->fields.dim) + { fieldsSoFar += cd->fields.dim; + cd = cd->baseClass; + } + return cd->fields.tdata()[index - fieldsSoFar]; + } // Return index of the field, or -1 if not found int getFieldIndex(Type *fieldtype, size_t fieldoffset) { @@ -283,6 +300,28 @@ struct ClassReferenceExp : Expression } }; +struct VoidInitExp : Expression +{ + VarDeclaration *var; + + VoidInitExp(VarDeclaration *var, Type *type) + : Expression(var->loc, TOKvoid, sizeof(VoidInitExp)) + { + this->var = var; + this->type = var->type; + } + char *toChars() + { + return (char *)"void"; + } + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue) + { + error("CTFE internal error: trying to read uninitialized variable"); + assert(0); + return EXP_CANT_INTERPRET; + } +}; + // Return index of the field, or -1 if not found // Same as getFieldIndex, but checks for a direct match with the VarDeclaration int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v) @@ -456,7 +495,8 @@ void showCtfeExpr(Expression *e, int level = 0) * arguments function arguments * thisarg 'this', if a needThis() function, NULL if not. * - * Return result expression if successful, EXP_CANT_INTERPRET if not. + * Return result expression if successful, EXP_CANT_INTERPRET if not, + * or EXP_VOID_INTERPRET if function returned void. */ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) @@ -475,7 +515,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument */ int olderrors = global.errors; int oldgag = global.gag; - TemplateInstance *spec = isSpeculativeFunction(this); + TemplateInstance *spec = isSpeculative(); if (global.gag && !spec) global.gag = 0; semantic3(scope); @@ -576,6 +616,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument --evaluatingArgs; if (earg == EXP_CANT_INTERPRET) return earg; + /* Struct literals are passed by value, but we don't need to + * copy them if they are passed as const + */ + if (earg->op == TOKstructliteral +#if DMDV2 + && !(arg->storageClass & (STCconst | STCimmutable)) +#endif + ) + earg = copyLiteral(earg); } if (earg->op == TOKthrownexception) { @@ -675,6 +724,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument // If fell off the end of a void function, return void if (!e && type->toBasetype()->nextOf()->ty == Tvoid) return EXP_VOID_INTERPRET; + + // If result is void, return void + if (e == EXP_VOID_INTERPRET) + return e; + // If it generated an exception, return it if (exceptionOrCantInterpret(e)) { @@ -683,6 +737,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument ((ThrownExceptionExp *)e)->generateUncaughtError(); return EXP_CANT_INTERPRET; } + + // If we're about to leave CTFE, make sure we don't crash the + // compiler by returning a CTFE-internal expression. if (!istate && !evaluatingArgs) { e = scrubReturnValue(loc, e); @@ -896,13 +953,16 @@ uinteger_t resolveArrayLength(Expression *e) } // As Equal, but resolves slices before comparing -Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2) +Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) { if (e1->op == TOKslice) e1 = resolveSlice(e1); if (e2->op == TOKslice) e2 = resolveSlice(e2); - return Equal(op, type, e1, e2); + Expression *e = Equal(op, type, e1, e2); + if (e == EXP_CANT_INTERPRET) + error(loc, "cannot evaluate %s==%s at compile time", e1->toChars(), e2->toChars()); + return e; } Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) @@ -973,7 +1033,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) return Cat(type, e1, e2); } -void scrubArray(Loc loc, Expressions *elems); +bool scrubArray(Loc loc, Expressions *elems, bool structlit = false); /* All results destined for use outside of CTFE need to have their CTFE-specific * features removed. @@ -986,6 +1046,11 @@ Expression *scrubReturnValue(Loc loc, Expression *e) error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars()); return EXP_CANT_INTERPRET; } + if (e->op == TOKvoid) + { + error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars()); + e = new ErrorExp(); + } if (e->op == TOKslice) { e = resolveSlice(e); @@ -994,7 +1059,8 @@ Expression *scrubReturnValue(Loc loc, Expression *e) { StructLiteralExp *se = (StructLiteralExp *)e; se->ownedByCtfe = false; - scrubArray(loc, se->elements); + if (!scrubArray(loc, se->elements, true)) + return EXP_CANT_INTERPRET; } if (e->op == TOKstring) { @@ -1003,29 +1069,38 @@ Expression *scrubReturnValue(Loc loc, Expression *e) if (e->op == TOKarrayliteral) { ((ArrayLiteralExp *)e)->ownedByCtfe = false; - scrubArray(loc, ((ArrayLiteralExp *)e)->elements); + if (!scrubArray(loc, ((ArrayLiteralExp *)e)->elements)) + return EXP_CANT_INTERPRET; } if (e->op == TOKassocarrayliteral) { AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; aae->ownedByCtfe = false; - scrubArray(loc, aae->keys); - scrubArray(loc, aae->values); + if (!scrubArray(loc, aae->keys)) + return EXP_CANT_INTERPRET; + if (!scrubArray(loc, aae->values)) + return EXP_CANT_INTERPRET; } return e; } -// Scrub all members of an array -void scrubArray(Loc loc, Expressions *elems) +// Scrub all members of an array. Return false if error +bool scrubArray(Loc loc, Expressions *elems, bool structlit) { for (size_t i = 0; i < elems->dim; i++) { Expression *m = elems->tdata()[i]; if (!m) continue; - m = scrubReturnValue(loc, m); + if (m && m->op == TOKvoid && structlit) + m = NULL; + if (m) + m = scrubReturnValue(loc, m); + if (m == EXP_CANT_INTERPRET) + return false; elems->tdata()[i] = m; } + return true; } @@ -1360,7 +1435,7 @@ Expression *SwitchStatement::interpret(InterState *istate) Expression * caseExp = cs->exp->interpret(istate); if (exceptionOrCantInterpret(caseExp)) return caseExp; - e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp); + e = ctfeEqual(caseExp->loc, TOKequal, Type::tint32, econdition, caseExp); if (exceptionOrCantInterpret(e)) return e; if (e->isBool(TRUE)) @@ -1475,25 +1550,25 @@ Expression *TryCatchStatement::interpret(InterState *istate) ThrownExceptionExp *ex = (ThrownExceptionExp *)e; Type *extype = ex->thrown->originalClass()->type; // Search for an appropriate catch clause. - for (size_t i = 0; i < catches->dim; i++) - { + for (size_t i = 0; i < catches->dim; i++) + { #if DMDV1 - Catch *ca = (Catch *)catches->data[i]; + Catch *ca = (Catch *)catches->data[i]; #else - Catch *ca = catches->tdata()[i]; + Catch *ca = catches->tdata()[i]; #endif - Type *catype = ca->type; + Type *catype = ca->type; - if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) - { // Execute the handler + if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) + { // Execute the handler if (ca->var) { ctfeStack.push(ca->var); ca->var->setValue(ex->thrown); } - return ca->handler->interpret(istate); - } + return ca->handler ? ca->handler->interpret(istate) : NULL; } + } return e; } @@ -1734,6 +1809,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) } Type *pointee = ((TypePointer *)type)->next; Expression *val = getVarExp(loc, istate, var, goal); + if (val == EXP_CANT_INTERPRET) + return val; if (val->type->ty == Tarray || val->type->ty == Tsarray) { // Check for unsupported type painting operations @@ -1907,10 +1984,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) { e = copyLiteral(e); - if (v->isDataseg()) - ctfeStack.saveGlobalConstant(v, e); - else - v->setValueWithoutChecking(e); + ctfeStack.saveGlobalConstant(v, e); } } else if (v->isCTFE() && !v->hasValue()) @@ -1919,11 +1993,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal { if (v->init->isVoidInitializer()) { - error(loc, "variable %s is used before initialization", v->toChars()); - return EXP_CANT_INTERPRET; + // var should have been initialized when it was created + error(loc, "CTFE internal error - trying to access uninitialized var"); + assert(0); + e = EXP_CANT_INTERPRET; + } + else + { + e = v->init->toExpression(); + e = e->interpret(istate); } - e = v->init->toExpression(); - e = e->interpret(istate); } else e = v->type->defaultInitLiteral(loc); @@ -1939,7 +2018,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal e = EXP_CANT_INTERPRET; } else if (!e) - error(loc, "variable %s is used before initialization", v->toChars()); + { + assert(0); + assert(v->init && v->init->isVoidInitializer()); + e = v->type->voidInitLiteral(v); + } else if (exceptionOrCantInterpret(e)) return e; else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex) @@ -1958,6 +2041,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal || e->op == TOKassocarrayliteral || e->op == TOKslice || e->type->toBasetype()->ty == Tpointer) return e; // it's already an Lvalue + else if (e->op == TOKvoid) + { + VoidInitExp *ve = (VoidInitExp *)e; + error(loc, "cannot read uninitialized variable %s in ctfe", v->toPrettyChars()); + errorSupplemental(ve->var->loc, "%s was uninitialized and used before set", ve->var->toChars()); + e = EXP_CANT_INTERPRET; + } else e = e->interpret(istate, goal); } @@ -1971,10 +2061,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal if (s->dsym->toInitializer() == s->sym) { #endif - e = s->dsym->type->defaultInitLiteral(); + e = s->dsym->type->defaultInitLiteral(loc); e = e->semantic(NULL); if (e->op == TOKerror) e = EXP_CANT_INTERPRET; + else // Convert NULL to VoidExp + e = e->interpret(istate, goal); #if !IN_LLVM } else @@ -2045,7 +2137,12 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) if (ie) e = ie->exp->interpret(istate); else if (v->init->isVoidInitializer()) - e = NULL; + { + e = v->type->voidInitLiteral(v); + // There is no AssignExp for void initializers, + // so set it here. + v->setValue(e); + } else { error("Declaration %s is not yet implemented in CTFE", toChars()); @@ -2274,7 +2371,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) ekey = resolveSlice(ekey); for (size_t j = i; j < keysx->dim; j++) { Expression *ekey2 = keysx->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, ekey2); if (ex == EXP_CANT_INTERPRET) goto Lerr; if (ex->isBool(TRUE)) // if a match @@ -2448,10 +2545,10 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is if (elemType->ty == Tchar || elemType->ty == Twchar || elemType->ty == Tdchar) return createBlockDuplicatedStringLiteral(loc, newtype, - (unsigned)(elemType->defaultInitLiteral()->toInteger()), + (unsigned)(elemType->defaultInitLiteral(loc)->toInteger()), len, elemType->size()); return createBlockDuplicatedArrayLiteral(loc, newtype, - elemType->defaultInitLiteral(), + elemType->defaultInitLiteral(loc), len); } @@ -2465,7 +2562,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) if (newtype->toBasetype()->ty == Tstruct) { - Expression *se = newtype->defaultInitLiteral(); + Expression *se = newtype->defaultInitLiteral(loc); #if DMDV2 if (member) { @@ -2502,7 +2599,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) Dsymbol *s = c->fields.tdata()[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); - Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(); + Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(loc); if (exceptionOrCantInterpret(m)) return m; elems->tdata()[fieldsSoFar+i] = copyLiteral(m); @@ -2672,7 +2769,7 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type, } if (indx < 0 || indx > len) { - error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len); + error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", indx, len); return EXP_CANT_INTERPRET; } @@ -2974,7 +3071,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expressi for (size_t j = valuesx->dim; j; ) { j--; Expression *ekey = aae->keys->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index); if (exceptionOrCantInterpret(ex)) return ex; if (ex->isBool(TRUE)) @@ -3144,7 +3241,7 @@ Expression *copyLiteral(Expression *e) assert(v); // If it is a void assignment, use the default initializer if (!m) - m = v->type->defaultInitLiteral(e->loc); + m = v->type->voidInitLiteral(v); if (m->op == TOKslice) m = resolveSlice(m); if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray) @@ -3171,7 +3268,8 @@ Expression *copyLiteral(Expression *e) || e->op == TOKsymoff || e->op == TOKnull || e->op == TOKvar || e->op == TOKint64 || e->op == TOKfloat64 - || e->op == TOKchar || e->op == TOKcomplex80) + || e->op == TOKchar || e->op == TOKcomplex80 + || e->op == TOKvoid) { // Simple value types Expression *r = e->syntaxCopy(); r->type = e->type; @@ -3341,7 +3439,7 @@ void assignInPlace(Expression *dest, Expression *src) assert(o->op == e->op); assignInPlace(o, e); } - else if (e->type->ty == Tsarray && o->type->ty == Tsarray) + else if (e->type->ty == Tsarray && o->type->ty == Tsarray && e->op != TOKvoid) { assignInPlace(o, e); } @@ -3636,7 +3734,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ Type *elemType= NULL; elemType = ((TypeArray *)t)->next; assert(elemType); - Expression *defaultElem = elemType->defaultInitLiteral(); + Expression *defaultElem = elemType->defaultInitLiteral(loc); Expressions *elements = new Expressions(); elements->setDim(newlen); @@ -3744,7 +3842,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // only modifying part of the variable. So we need to make sure // that the parent variable exists. if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue()) - ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral())); + ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral(loc))); // --------------------------------------- // Deal with reference assignment @@ -3822,7 +3920,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ indx = resolveSlice(indx); // Look up this index in it up in the existing AA, to get the next level of AA. - AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx); + AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(loc, existingAA, indx); if (exceptionOrCantInterpret(newAA)) return newAA; if (!newAA) @@ -3968,14 +4066,29 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ? (StructLiteralExp *)exx : ((ClassReferenceExp *)exx)->value; int fieldi = exx->op == TOKstructliteral - ? se->getFieldIndex(member->type, member->offset) - : ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset); + ? findFieldIndexByName(se->sd, member) + : ((ClassReferenceExp *)exx)->findFieldIndexByName(member); if (fieldi == -1) { error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars()); return EXP_CANT_INTERPRET; } - assert(fieldi>=0 && fieldi < se->elements->dim); + assert(fieldi >= 0 && fieldi < se->elements->dim); + // If it's a union, set all other members of this union to void + if (exx->op == TOKstructliteral) + { + assert(se->sd); + int unionStart = se->sd->firstFieldInUnion(fieldi); + int unionSize = se->sd->numFieldsInUnion(fieldi); + for(int i = unionStart; i < unionStart + unionSize; ++i) + { if (i == fieldi) + continue; + Expression **el = &se->elements->tdata()[i]; + if ((*el)->op != TOKvoid) + *el = (*el)->type->voidInitLiteral(member); + } + } + if (newval->op == TOKstructliteral) assignInPlace(se->elements->tdata()[fieldi], newval); else @@ -4050,6 +4163,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ } aggregate = getAggregateFromPointer(aggregate, &ofs); indexToModify += ofs; + if (aggregate->op != TOKslice && aggregate->op != TOKstring && + aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral) + { + if (indexToModify != 0) + { + error("pointer index [%lld] lies outside memory block [0..1]", indexToModify); + return EXP_CANT_INTERPRET; + } + // It is equivalent to *aggregate = newval. + // Aggregate could be varexp, a dotvar, ... + // TODO: we could support this + error("indexed assignment of non-array pointers is not yet supported at compile time; use *%s = %s instead", + ie->e1->toChars(), e2->toChars()); + return EXP_CANT_INTERPRET; + } destarraylen = resolveArrayLength(aggregate); } if (indexToModify >= destarraylen) @@ -4075,7 +4203,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) { IndexExp *ix = (IndexExp *)aggregate; - aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); + aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2); if (!aggregate) { error("key %s not found in associative array %s", @@ -4177,6 +4305,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (isPointer(oldval->type)) { // Slicing a pointer oldval = oldval->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(oldval)) + return oldval; dinteger_t ofs; oldval = getAggregateFromPointer(oldval, &ofs); assignmentToSlicedPointer = true; @@ -4186,7 +4316,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (oldval->op != TOKarrayliteral && oldval->op != TOKstring && oldval->op != TOKslice && oldval->op != TOKnull) { - error("CTFE ICE: cannot resolve array length"); + if (assignmentToSlicedPointer) + { + error("pointer %s cannot be sliced at compile time (it does not point to an array)", + sexp->e1->toChars()); + } + else + error("CTFE ICE: cannot resolve array length"); return EXP_CANT_INTERPRET; } uinteger_t dollar = resolveArrayLength(oldval); @@ -4249,7 +4385,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) { IndexExp *ix = (IndexExp *)aggregate; - aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); + aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2); if (!aggregate) { error("key %s not found in associative array %s", @@ -4273,7 +4409,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ firstIndex = lowerbound + sexpold->lwr->toInteger(); if (hi > sexpold->upr->toInteger()) { - error("slice [%d..%d] exceeds array bounds [0..%jd]", + error("slice [%d..%d] exceeds array bounds [0..%lld]", lowerbound, upperbound, sexpold->upr->toInteger() - sexpold->lwr->toInteger()); return EXP_CANT_INTERPRET; @@ -4285,11 +4421,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue); dinteger_t ofs; aggregate = getAggregateFromPointer(aggregate, &ofs); + if (aggregate->op == TOKnull) + { + error("cannot slice null pointer %s", sexp->e1->toChars()); + return EXP_CANT_INTERPRET; + } dinteger_t hi = upperbound + ofs; firstIndex = lowerbound + ofs; if (firstIndex < 0 || hi > dim) { - error("slice [%d..%jd] exceeds memory block bounds [0..%jd]", + error("slice [lld..%lld] exceeds memory block bounds [0..%lld]", firstIndex, hi, dim); return EXP_CANT_INTERPRET; } @@ -4430,9 +4571,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ else { error("%s cannot be evaluated at compile time", toChars()); -#ifdef DEBUG - dump(0); -#endif } return returnValue; } @@ -4812,6 +4950,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) if (!global.gag) showCtfeBackTrace(istate, this, fd); } + else if (eresult == EXP_VOID_INTERPRET) + ; + else + eresult->loc = loc; return eresult; } @@ -4830,7 +4972,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) InterState istateComma; if (!istate && firstComma->e1->op == TOKdeclaration) { - assert(ctfeStack.stackPointer() == 0); ctfeStack.startFrame(); istate = &istateComma; } @@ -4848,7 +4989,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) ctfeStack.push(v); if (!v->init && !v->getValue()) { - v->setValue(copyLiteral(v->type->defaultInitLiteral())); + v->setValue(copyLiteral(v->type->defaultInitLiteral(loc))); } if (!v->getValue()) { Expression *newval = v->init->toExpression(); @@ -4944,7 +5085,7 @@ Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal) * Return ae[e2] if present, or NULL if not found. * Return EXP_CANT_INTERPRET on error. */ -Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) +Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2) { /* Search the keys backwards, in case there are duplicate keys */ @@ -4952,13 +5093,9 @@ Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) { i--; Expression *ekey = ae->keys->tdata()[i]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, e2); if (ex == EXP_CANT_INTERPRET) - { - error("cannot evaluate %s==%s at compile time", - ekey->toChars(), e2->toChars()); return ex; - } if (ex->isBool(TRUE)) { return ae->values->tdata()[i]; @@ -5013,23 +5150,37 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) if (exceptionOrCantInterpret(e2)) return e2; dinteger_t indx = e2->toInteger(); + dinteger_t ofs; Expression *agg = getAggregateFromPointer(e1, &ofs); + if (agg->op == TOKnull) { error("cannot index null pointer %s", this->e1->toChars()); return EXP_CANT_INTERPRET; } - assert(agg->op == TOKarrayliteral || agg->op == TOKstring); - dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); - Type *pointee = ((TypePointer *)agg->type)->next; - if ((indx + ofs) < 0 || (indx+ofs) > len) + if ( agg->op == TOKarrayliteral || agg->op == TOKstring) { - error("pointer index [%jd] exceeds allocated memory block [0..%jd]", - indx+ofs, len); - return EXP_CANT_INTERPRET; + dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); + Type *pointee = ((TypePointer *)agg->type)->next; + if ((indx + ofs) < 0 || (indx+ofs) > len) + { + error("pointer index [%lld] exceeds allocated memory block [0..%lld]", + indx+ofs, len); + return EXP_CANT_INTERPRET; + } + return ctfeIndex(loc, type, agg, indx+ofs); + } + else + { // Pointer to a non-array variable + if ((indx + ofs) != 0) + { + error("pointer index [%lld] lies outside memory block [0..1]", + indx+ofs); + return EXP_CANT_INTERPRET; + } + return agg->interpret(istate); } - return ctfeIndex(loc, type, agg, indx+ofs); } e1 = this->e1; if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe)) @@ -5070,7 +5221,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) if (indx > iup - ilo) { - error("index %ju exceeds array length %ju", indx, iup - ilo); + error("index %llu exceeds array length %llu", indx, iup - ilo); return EXP_CANT_INTERPRET; } indx += ilo; @@ -5091,7 +5242,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) { if (e2->op == TOKslice) e2 = resolveSlice(e2); - e = findKeyInAA((AssocArrayLiteralExp *)e1, e2); + e = findKeyInAA(loc, (AssocArrayLiteralExp *)e1, e2); if (!e) { error("key %s not found in associative array %s", @@ -5112,6 +5263,12 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) return e; if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar)) e = e->interpret(istate); + if (goal == ctfeNeedRvalue && e->op == TOKvoid) + { + error("%s is used before initialized", toChars()); + errorSupplemental(e->loc, "originally uninitialized here"); + return EXP_CANT_INTERPRET; + } e = paintTypeOntoLiteral(type, e); return e; } @@ -5166,12 +5323,18 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) error("cannot slice null pointer %s", this->e1->toChars()); return EXP_CANT_INTERPRET; } + if (agg->op != TOKarrayliteral && agg->op != TOKstring) + { + error("pointer %s cannot be sliced at compile time (it does not point to an array)", + this->e1->toChars()); + return EXP_CANT_INTERPRET; + } assert(agg->op == TOKarrayliteral || agg->op == TOKstring); dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); Type *pointee = ((TypePointer *)agg->type)->next; if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr) { - error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]", + error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]", ilwr+ofs, iupr+ofs, len); return EXP_CANT_INTERPRET; } @@ -5235,7 +5398,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) { if (ilwr== 0 && iupr == 0) return e1; - e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr); + e1->error("slice [%llu..%llu] is out of bounds", ilwr, iupr); return EXP_CANT_INTERPRET; } if (e1->op == TOKslice) @@ -5247,7 +5410,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) uinteger_t up1 = se->upr->toInteger(); if (ilwr > iupr || iupr > up1 - lo1) { - error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]", + error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]", ilwr, iupr, lo1, up1); return EXP_CANT_INTERPRET; } @@ -5264,7 +5427,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) { if (iupr < ilwr || ilwr < 0 || iupr > dollar) { - error("slice [%jd..%jd] exceeds array bounds [0..%jd]", + error("slice [%lld..%lld] exceeds array bounds [0..%lld]", ilwr, iupr, dollar); return EXP_CANT_INTERPRET; } @@ -5295,7 +5458,7 @@ Expression *InExp::interpret(InterState *istate, CtfeGoal goal) } if (e1->op == TOKslice) e1 = resolveSlice(e1); - e = findKeyInAA((AssocArrayLiteralExp *)e2, e1); + e = findKeyInAA(loc, (AssocArrayLiteralExp *)e2, e1); if (exceptionOrCantInterpret(e)) return e; if (!e) @@ -5354,8 +5517,12 @@ bool isAssocArray(Type *t) if (t->ty != Tstruct) return false; StructDeclaration *sym = ((TypeStruct *)t)->sym; - if (sym->ident == Id::AssociativeArray) + if (sym->ident == Id::AssociativeArray && sym->parent && + sym->parent->parent && + sym->parent->parent->ident == Id::object) + { return true; + } #endif return false; } @@ -5510,9 +5677,15 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) e->type = type; return e; } - error("pointer cast from %s to %s is not supported at compile time", + + // Check if we have a null pointer (eg, inside a struct) + e1 = e1->interpret(istate); + if (e1->op != TOKnull) + { + error("pointer cast from %s to %s is not supported at compile time", e1->type->toChars(), to->toChars()); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; + } } if (to->ty == Tarray && e1->op == TOKslice) { @@ -5660,7 +5833,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) assert(indx >=0 && indx <= len); // invalid pointer if (indx == len) { - error("dereference of pointer %s one past end of memory block limits [0..%jd]", + error("dereference of pointer %s one past end of memory block limits [0..%lld]", toChars(), len); return EXP_CANT_INTERPRET; } @@ -5705,7 +5878,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) } else if (e->op == TOKaddress) e = ((AddrExp*)e)->e1; // *(&x) ==> x - if (e->op == TOKnull) + else if (e->op == TOKnull) { error("dereference of null pointer '%s'", e1->toChars()); return EXP_CANT_INTERPRET; @@ -5794,6 +5967,13 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) if (e->op == TOKstructliteral || e->op == TOKarrayliteral || e->op == TOKassocarrayliteral || e->op == TOKstring) return e; + if (e->op == TOKvoid) + { + VoidInitExp *ve = (VoidInitExp *)e; + error("cannot read uninitialized variable %s in ctfe", toChars()); + ve->var->error("was uninitialized and used before set"); + return EXP_CANT_INTERPRET; + } if ( isPointer(type) ) { return paintTypeOntoLiteral(type, e); @@ -5838,7 +6018,7 @@ Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal) size_t removed = 0; for (size_t j = 0; j < valuesx->dim; ++j) { Expression *ekey = keysx->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index); if (exceptionOrCantInterpret(ex)) return ex; if (ex->isBool(TRUE)) @@ -6017,7 +6197,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del else if (str->op == TOKarrayliteral) ale = (ArrayLiteralExp *)str; else - { error("CTFE internal error: cannot foreach %s", str->toChars()); + { str->error("CTFE internal error: cannot foreach %s", str->toChars()); return EXP_CANT_INTERPRET; } Expressions args; @@ -6472,6 +6652,10 @@ bool isCtfeValueValid(Expression *newval) assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe); return true; } + if (newval->op == TOKvoid) + { + return true; + } newval->error("CTFE internal error: illegal value %s\n", newval->toChars()); return false; } @@ -6504,3 +6688,29 @@ void VarDeclaration::setValue(Expression *newval) assert(isCtfeValueValid(newval)); ctfeStack.setValue(this, newval); } + + +Expression *Type::voidInitLiteral(VarDeclaration *var) +{ + return new VoidInitExp(var, this); +} + +Expression *TypeSArray::voidInitLiteral(VarDeclaration *var) +{ + return createBlockDuplicatedArrayLiteral(var->loc, this, next->voidInitLiteral(var), dim->toInteger()); +} + +Expression *TypeStruct::voidInitLiteral(VarDeclaration *var) +{ + Expressions *exps = new Expressions(); + exps->setDim(sym->fields.dim); + for (size_t i = 0; i < sym->fields.dim; i++) + { + //(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type); + (*exps)[i] = sym->fields[i]->type->voidInitLiteral(var); + } + StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps); + se->type = this; + se->ownedByCtfe = true; + return se; +} diff --git a/dmd/lexer.c b/dmd/lexer.c index 72959b8a..c1531c7a 100644 --- a/dmd/lexer.c +++ b/dmd/lexer.c @@ -304,7 +304,7 @@ void Lexer::error(const char *format, ...) { va_list ap; va_start(ap, format); - verror(loc, format, ap); + verror(tokenLoc(), format, ap); va_end(ap); } @@ -2870,6 +2870,38 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2) return c; } +/******************************************* + * Search actual location of current token + * even when infinite look-ahead was done. + */ +Loc Lexer::tokenLoc() +{ + Loc result = this->loc; + Token* last = &token; + while (last->next) + last = last->next; + + unsigned char* start = token.ptr; + unsigned char* stop = last->ptr; + + for (unsigned char* p = start; p < stop; ++p) + { + switch (*p) + { + case '\n': + result.linnum--; + break; + case '\r': + if (p[1] != '\n') + result.linnum--; + break; + default: + break; + } + } + return result; +} + /******************************************** * Create an identifier in the string table. */ diff --git a/dmd/lexer.h b/dmd/lexer.h index 8fb90863..9919e11d 100644 --- a/dmd/lexer.h +++ b/dmd/lexer.h @@ -312,6 +312,8 @@ struct Lexer static int isValidIdentifier(char *p); static unsigned char *combineComments(unsigned char *c1, unsigned char *c2); + + Loc tokenLoc(); }; #endif /* DMD_LEXER_H */ diff --git a/dmd/mars.c b/dmd/mars.c index 6be6fa51..9fb526cb 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -72,7 +72,7 @@ Global::Global() copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.073"; + version = "v1.074"; ldc_version = "LDC trunk"; llvm_version = "LLVM 3.0"; global.structalign = 8; @@ -102,6 +102,11 @@ bool Global::endGagging(unsigned oldGagged) return anyErrs; } +bool Global::isSpeculativeGagging() +{ + return gag && gag == speculativeGag; +} + char *Loc::toChars() const { diff --git a/dmd/mars.h b/dmd/mars.h index 53b61d83..4110ccd2 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -347,6 +347,12 @@ struct Global unsigned gag; // !=0 means gag reporting of errors & warnings unsigned gaggedErrors; // number of errors reported while gagged + /* Gagging can either be speculative (is(typeof()), etc) + * or because of forward references + */ + unsigned speculativeGag; // == gag means gagging is for is(typeof); + bool isSpeculativeGagging(); + // Start gagging. Return the current number of gagged errors unsigned startGagging(); diff --git a/dmd/module.c b/dmd/module.c index b10357c3..f8b12287 100644 --- a/dmd/module.c +++ b/dmd/module.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -387,7 +387,9 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident) printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); } - m->read(loc); + if (!m->read(loc)) + return NULL; + m->parse(); #ifdef IN_GCC @@ -397,7 +399,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident) return m; } -void Module::read(Loc loc) +bool Module::read(Loc loc) { //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); if (srcfile->read()) @@ -415,9 +417,11 @@ void Module::read(Loc loc) } else fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars()); + fatal(); } - fatal(); + return false; } + return true; } inline unsigned readwordLE(unsigned short *p) @@ -684,7 +688,15 @@ void Module::parse() if (md) { this->ident = md->id; - dst = Package::resolve(md->packages, &this->parent, NULL); + this->safe = md->safe; + Package *ppack = NULL; + dst = Package::resolve(md->packages, &this->parent, &ppack); + if (ppack && ppack->isModule()) + { + error(loc, "package name '%s' in file %s conflicts with usage as a module name in file %s", + ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars()); + dst = modules; + } } else { @@ -709,7 +721,7 @@ void Module::parse() { Package *pkg = prev->isPackage(); assert(pkg); - error(loc, "from file %s conflicts with package name %s", + error(pkg->loc, "from file %s conflicts with package name %s", srcname, pkg->toChars()); } } @@ -1216,19 +1228,24 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package else { assert(p->isPackage()); -#if TARGET_NET //dot net needs modules and packages with same name -#else - if (p->isModule()) - { p->error("module and package have the same name"); - fatal(); - break; - } -#endif + // It might already be a module, not a package, but that needs + // to be checked at a higher level, where a nice error message + // can be generated. + // dot net needs modules and packages with same name } parent = p; dst = ((Package *)p)->symtab; if (ppkg && !*ppkg) *ppkg = (Package *)p; +#if TARGET_NET +#else + if (p->isModule()) + { // Return the module so that a nice error message can be generated + if (ppkg) + *ppkg = (Package *)p; + break; + } +#endif } if (pparent) { diff --git a/dmd/module.h b/dmd/module.h index bea6e17d..6e998ee6 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -134,10 +134,11 @@ struct Module : Package void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toJsonBuffer(OutBuffer *buf); const char *kind(); - void read(Loc loc); // read file + bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise. #if IN_LLVM void parse(bool gen_docs = false); // syntactic parse #elif IN_GCC + void setDocfile(); // set docfile member void parse(bool dump_source = false); // syntactic parse #else void parse(); // syntactic parse diff --git a/dmd/mtype.c b/dmd/mtype.c index 34a1627f..729a3fd5 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -1451,7 +1451,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) case Timaginary64: t = tfloat64; goto L2; case Timaginary80: t = tfloat80; goto L2; L2: - e = new RealExp(0, 0.0, t); + e = new RealExp(e->loc, 0.0, t); break; default: @@ -1481,7 +1481,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) case Tfloat32: case Tfloat64: case Tfloat80: - e = new RealExp(0, 0.0, this); + e = new RealExp(e->loc, 0.0, this); break; default: @@ -2645,6 +2645,22 @@ int TypeAArray::checkBoolean() return TRUE; } +Expression *TypeAArray::toExpression() +{ + Expression *e = next->toExpression(); + if (e) + { + Expression *ei = index->toExpression(); + if (ei) + { + Expressions *arguments = new Expressions(); + arguments->push(ei); + return new ArrayExp(0, e, arguments); + } + } + return NULL; +} + int TypeAArray::hasPointers() { return TRUE; @@ -3184,13 +3200,25 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) error(loc, "cannot have parameter of type %s", fparam->type->toChars()); if (fparam->defaultArg) - { - fparam->defaultArg = fparam->defaultArg->semantic(argsc); - fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg); - fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type); + { Expression *e = fparam->defaultArg; + e = e->semantic(argsc); + e = resolveProperties(argsc, e); + if (e->op == TOKfunction) // see Bugzilla 4820 + { FuncExp *fe = (FuncExp *)e; + if (fe->fd) + { // Replace function literal with a function symbol, + // since default arg expression must be copied when used + // and copying the literal itself is wrong. + e = new VarExp(e->loc, fe->fd); + e = new AddrExp(e->loc, e); + e = e->semantic(argsc); + } + } + e = e->implicitCastTo(argsc, fparam->type); + fparam->defaultArg = e; } - /* If arg turns out to be a tuple, the number of parameters may + /* If fparam after semantic() turns out to be a tuple, the number of parameters may * change. */ if (t->ty == Ttuple) @@ -3650,7 +3678,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, else { Lerror: - error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); + if (id->dyncast() == DYNCAST_DSYMBOL) + { // searchX already handles errors for template instances + assert(global.errors); + } + else + { + sm = s->search_correct(id); + if (sm) + error(loc, "identifier '%s' of '%s' is not defined, did you mean '%s %s'?", + id->toChars(), toChars(), sm->kind(), sm->toChars()); + else + error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); + } *pe = new ErrorExp(); } return; @@ -4131,14 +4171,19 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) else #endif { - sc->intypeof++; - exp = exp->semantic(sc); + Scope *sc2 = sc->push(); + sc2->intypeof++; + unsigned oldspecgag = global.speculativeGag; + if (global.gag) + global.speculativeGag = global.gag; + exp = exp->semantic(sc2); + global.speculativeGag = oldspecgag; #if DMDV2 if (exp->type && exp->type->ty == Tfunction && ((TypeFunction *)exp->type)->isproperty) - exp = resolveProperties(sc, exp); + exp = resolveProperties(sc2, exp); #endif - sc->intypeof--; + sc2->pop(); if (exp->op == TOKtype) { error(loc, "argument %s to typeof is not an expression", exp->toChars()); @@ -4959,8 +5004,8 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) e = vd->init->toExpression(); } else - e = vd->type->defaultInitLiteral(); - structelems->tdata()[j] = e; + e = vd->type->defaultInitLiteral(loc); + (*structelems)[j] = e; } StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems); // Why doesn't the StructLiteralExp constructor do this, when diff --git a/dmd/mtype.h b/dmd/mtype.h index a54607fd..9e4979c7 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -254,7 +254,8 @@ struct Type : Object virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); virtual unsigned memalign(unsigned salign); virtual Expression *defaultInit(Loc loc = 0); - virtual Expression *defaultInitLiteral(Loc loc = 0); + virtual Expression *defaultInitLiteral(Loc loc); + virtual Expression *voidInitLiteral(VarDeclaration *var); virtual int isZeroInit(Loc loc = 0); // if initializer is 0 #if IN_DMD virtual dt_t **toDt(dt_t **pdt); @@ -391,6 +392,7 @@ struct TypeSArray : TypeArray MATCH implicitConvTo(Type *to); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); + Expression *voidInitLiteral(VarDeclaration *var); #if IN_DMD dt_t **toDt(dt_t **pdt); dt_t **toDtElem(dt_t **pdt, Expression *e); @@ -451,6 +453,7 @@ struct TypeAArray : TypeArray int isZeroInit(Loc loc); int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); + Expression *toExpression(); int hasPointers(); TypeTuple *toArgTypes(); @@ -644,6 +647,7 @@ struct TypeStruct : Type unsigned memalign(unsigned salign); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); + Expression *voidInitLiteral(VarDeclaration *var); int isZeroInit(Loc loc); int checkBoolean(); #if IN_DMD diff --git a/dmd/parse.c b/dmd/parse.c index 3bf1b96b..2aedae31 100644 --- a/dmd/parse.c +++ b/dmd/parse.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -129,7 +129,7 @@ Dsymbols *Parser::parseModule() decldefs = parseDeclDefs(0); if (token.value != TOKeof) - { error("unrecognized declaration"); + { error(loc, "unrecognized declaration"); goto Lerr; } return decldefs; @@ -5565,6 +5565,7 @@ void initPrecedence() precedence[TOKtraits] = PREC_primary; precedence[TOKdefault] = PREC_primary; precedence[TOKoverloadset] = PREC_primary; + precedence[TOKvoid] = PREC_primary; #endif // post diff --git a/dmd/root/aav.c b/dmd/root/aav.c index 67ff2585..ca685d42 100644 --- a/dmd/root/aav.c +++ b/dmd/root/aav.c @@ -1,188 +1,188 @@ -/** - * Implementation of associative arrays. - * - */ - -#include -#include -#include - -#include "aav.h" - -static const size_t prime_list[] = { - 31UL, - 97UL, 389UL, - 1543UL, 6151UL, - 24593UL, 98317UL, - 393241UL, 1572869UL, - 6291469UL, 25165843UL, - 100663319UL, 402653189UL, - 1610612741UL, 4294967291UL, -}; - -struct aaA -{ - aaA *next; - Key key; - Value value; -}; - -struct AA -{ - aaA* *b; - size_t b_length; - size_t nodes; // total number of aaA nodes - aaA* binit[4]; // initial value of b[] -}; - -static const AA bbinit = { NULL, }; - -/**************************************************** - * Determine number of entries in associative array. - */ - -size_t _aaLen(AA* aa) -{ - return aa ? aa->nodes : 0; -} - - -/************************************************* - * Get pointer to value in associative array indexed by key. - * Add entry for key if it is not already there. - */ - -Value* _aaGet(AA** paa, Key key) -{ - //printf("paa = %p\n", paa); - - if (!*paa) - { AA *a = new AA(); - *a = bbinit; - a->b = a->binit; - a->b_length = sizeof(a->binit) / sizeof(a->binit[0]); - *paa = a; - assert((*paa)->b_length == 4); - } - //printf("paa = %p, *paa = %p\n", paa, *paa); - - assert((*paa)->b_length); - size_t i = (size_t)key % (*paa)->b_length; - aaA** pe = &(*paa)->b[i]; - aaA *e; - while ((e = *pe) != NULL) - { - if (key == e->key) - return &e->value; - pe = &e->next; - } - - // Not found, create new elem - //printf("create new one\n"); - e = new aaA(); - e->next = NULL; - e->key = key; - e->value = NULL; - *pe = e; - - size_t nodes = ++(*paa)->nodes; - //printf("length = %d, nodes = %d\n", paa.a.b.length, nodes); - if (nodes > (*paa)->b_length * 4) - { - //printf("rehash\n"); - _aaRehash(paa); - } - - return &e->value; -} - - -/************************************************* - * Get value in associative array indexed by key. - * Returns NULL if it is not already there. - */ - -Value _aaGetRvalue(AA* aa, Key key) -{ - //printf("_aaGetRvalue(key = %p)\n", key); - if (!aa) - return NULL; - - size_t len = aa->b_length; - - if (len) - { - size_t i = (size_t)key % len; - aaA* e = aa->b[i]; - while (e) - { - if (key == e->key) - return e->value; - e = e->next; - } - } - return NULL; // not found -} - - -/******************************************** - * Rehash an array. - */ - -void _aaRehash(AA** paa) -{ - //printf("Rehash\n"); - if (*paa) - { - AA newb = bbinit; - AA *aa = *paa; - size_t len = _aaLen(*paa); - if (len) - { size_t i; - - for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++) - { - if (len <= prime_list[i]) - break; - } - len = prime_list[i]; - newb.b = new aaA*[len]; - memset(newb.b, 0, len * sizeof(aaA*)); - newb.b_length = len; - - for (size_t k = 0; k < aa->b_length; k++) - { aaA *e = aa->b[k]; - while (e) - { aaA* enext = e->next; - size_t j = (size_t)e->key % len; - e->next = newb.b[j]; - newb.b[j] = e; - e = enext; - } - } - if (aa->b != aa->binit) - delete[] aa->b; - - newb.nodes = aa->nodes; - } - - **paa = newb; - } -} - - -#if UNITTEST - -void unittest_aa() -{ - AA* aa = NULL; - Value v = _aaGetRvalue(aa, NULL); - assert(!v); - Value *pv = _aaGet(&aa, NULL); - assert(pv); - *pv = (void *)3; - v = _aaGetRvalue(aa, NULL); - assert(v == (void *)3); -} - -#endif +/** + * Implementation of associative arrays. + * + */ + +#include +#include +#include + +#include "aav.h" + +static const size_t prime_list[] = { + 31UL, + 97UL, 389UL, + 1543UL, 6151UL, + 24593UL, 98317UL, + 393241UL, 1572869UL, + 6291469UL, 25165843UL, + 100663319UL, 402653189UL, + 1610612741UL, 4294967291UL, +}; + +struct aaA +{ + aaA *next; + Key key; + Value value; +}; + +struct AA +{ + aaA* *b; + size_t b_length; + size_t nodes; // total number of aaA nodes + aaA* binit[4]; // initial value of b[] +}; + +static const AA bbinit = { NULL, }; + +/**************************************************** + * Determine number of entries in associative array. + */ + +size_t _aaLen(AA* aa) +{ + return aa ? aa->nodes : 0; +} + + +/************************************************* + * Get pointer to value in associative array indexed by key. + * Add entry for key if it is not already there. + */ + +Value* _aaGet(AA** paa, Key key) +{ + //printf("paa = %p\n", paa); + + if (!*paa) + { AA *a = new AA(); + *a = bbinit; + a->b = a->binit; + a->b_length = sizeof(a->binit) / sizeof(a->binit[0]); + *paa = a; + assert((*paa)->b_length == 4); + } + //printf("paa = %p, *paa = %p\n", paa, *paa); + + assert((*paa)->b_length); + size_t i = (size_t)key % (*paa)->b_length; + aaA** pe = &(*paa)->b[i]; + aaA *e; + while ((e = *pe) != NULL) + { + if (key == e->key) + return &e->value; + pe = &e->next; + } + + // Not found, create new elem + //printf("create new one\n"); + e = new aaA(); + e->next = NULL; + e->key = key; + e->value = NULL; + *pe = e; + + size_t nodes = ++(*paa)->nodes; + //printf("length = %d, nodes = %d\n", paa.a.b.length, nodes); + if (nodes > (*paa)->b_length * 4) + { + //printf("rehash\n"); + _aaRehash(paa); + } + + return &e->value; +} + + +/************************************************* + * Get value in associative array indexed by key. + * Returns NULL if it is not already there. + */ + +Value _aaGetRvalue(AA* aa, Key key) +{ + //printf("_aaGetRvalue(key = %p)\n", key); + if (!aa) + return NULL; + + size_t len = aa->b_length; + + if (len) + { + size_t i = (size_t)key % len; + aaA* e = aa->b[i]; + while (e) + { + if (key == e->key) + return e->value; + e = e->next; + } + } + return NULL; // not found +} + + +/******************************************** + * Rehash an array. + */ + +void _aaRehash(AA** paa) +{ + //printf("Rehash\n"); + if (*paa) + { + AA newb = bbinit; + AA *aa = *paa; + size_t len = _aaLen(*paa); + if (len) + { size_t i; + + for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++) + { + if (len <= prime_list[i]) + break; + } + len = prime_list[i]; + newb.b = new aaA*[len]; + memset(newb.b, 0, len * sizeof(aaA*)); + newb.b_length = len; + + for (size_t k = 0; k < aa->b_length; k++) + { aaA *e = aa->b[k]; + while (e) + { aaA* enext = e->next; + size_t j = (size_t)e->key % len; + e->next = newb.b[j]; + newb.b[j] = e; + e = enext; + } + } + if (aa->b != aa->binit) + delete[] aa->b; + + newb.nodes = aa->nodes; + } + + **paa = newb; + } +} + + +#if UNITTEST + +void unittest_aa() +{ + AA* aa = NULL; + Value v = _aaGetRvalue(aa, NULL); + assert(!v); + Value *pv = _aaGet(&aa, NULL); + assert(pv); + *pv = (void *)3; + v = _aaGetRvalue(aa, NULL); + assert(v == (void *)3); +} + +#endif diff --git a/dmd/root/aav.h b/dmd/root/aav.h index 5f8f56eb..266b5a83 100644 --- a/dmd/root/aav.h +++ b/dmd/root/aav.h @@ -1,11 +1,11 @@ - -typedef void* Value; -typedef void* Key; - -struct AA; - -size_t _aaLen(AA* aa); -Value* _aaGet(AA** aa, Key key); -Value _aaGetRvalue(AA* aa, Key key); -void _aaRehash(AA** paa); - + +typedef void* Value; +typedef void* Key; + +struct AA; + +size_t _aaLen(AA* aa); +Value* _aaGet(AA** aa, Key key); +Value _aaGetRvalue(AA* aa, Key key); +void _aaRehash(AA** paa); + diff --git a/dmd/root/array.c b/dmd/root/array.c index 3630654a..f3440445 100644 --- a/dmd/root/array.c +++ b/dmd/root/array.c @@ -1,257 +1,257 @@ - -// Copyright (c) 1999-2010 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#include -#include -#include -#include -#include - -#if (defined (__SVR4) && defined (__sun)) -#include -#endif - -#if _MSC_VER || __MINGW32__ -#include -#endif - -#if IN_GCC -#include "gdc_alloca.h" -#endif - -#if _WIN32 -#include -#endif - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#endif - -#include "port.h" -#include "root.h" -#include "dchar.h" -#include "rmem.h" - - -/********************************* Array ****************************/ - -Array::Array() -{ - data = SMALLARRAYCAP ? &smallarray[0] : NULL; - dim = 0; - allocdim = SMALLARRAYCAP; -} - -Array::~Array() -{ - if (data != &smallarray[0]) - mem.free(data); -} - -void Array::mark() -{ unsigned u; - - mem.mark(data); - for (u = 0; u < dim; u++) - mem.mark(data[u]); // BUG: what if arrays of Object's? -} - -void Array::reserve(unsigned nentries) -{ - //printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries); - if (allocdim - dim < nentries) - { - 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)); - } - } -} - -void Array::setDim(unsigned newdim) -{ - if (dim < newdim) - { - reserve(newdim - dim); - } - dim = newdim; -} - -void Array::fixDim() -{ - if (dim != allocdim) - { - 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; - } -} - -void Array::push(void *ptr) -{ - reserve(1); - data[dim++] = ptr; -} - -void *Array::pop() -{ - return data[--dim]; -} - -void Array::shift(void *ptr) -{ - reserve(1); - memmove(data + 1, data, dim * sizeof(*data)); - data[0] = ptr; - dim++; -} - -void Array::insert(unsigned index, void *ptr) -{ - reserve(1); - memmove(data + index + 1, data + index, (dim - index) * sizeof(*data)); - data[index] = ptr; - dim++; -} - - -void Array::insert(unsigned index, Array *a) -{ - if (a) - { unsigned d; - - d = a->dim; - reserve(d); - if (dim != index) - memmove(data + index + d, data + index, (dim - index) * sizeof(*data)); - memcpy(data + index, a->data, d * sizeof(*data)); - dim += d; - } -} - - -/*********************************** - * Append array a to this array. - */ - -void Array::append(Array *a) -{ - insert(dim, a); -} - -void Array::remove(unsigned i) -{ - if (dim - i - 1) - memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0])); - dim--; -} - -char *Array::toChars() -{ - unsigned len; - unsigned u; - char **buf; - char *str; - char *p; - - buf = (char **)malloc(dim * sizeof(char *)); - assert(buf); - len = 2; - for (u = 0; u < dim; u++) - { - buf[u] = ((Object *)data[u])->toChars(); - len += strlen(buf[u]) + 1; - } - str = (char *)mem.malloc(len); - - str[0] = '['; - p = str + 1; - for (u = 0; u < dim; u++) - { - if (u) - *p++ = ','; - len = strlen(buf[u]); - memcpy(p,buf[u],len); - p += len; - } - *p++ = ']'; - *p = 0; - free(buf); - return str; -} - -void Array::zero() -{ - memset(data,0,dim * sizeof(data[0])); -} - -void *Array::tos() -{ - return dim ? data[dim - 1] : NULL; -} - -int -#if _WIN32 - __cdecl -#endif - Array_sort_compare(const void *x, const void *y) -{ - Object *ox = *(Object **)x; - Object *oy = *(Object **)y; - - return ox->compare(oy); -} - -void Array::sort() -{ - if (dim) - { - qsort(data, dim, sizeof(Object *), Array_sort_compare); - } -} - -Array *Array::copy() -{ - Array *a = new Array(); - - a->setDim(dim); - memcpy(a->data, data, dim * sizeof(void *)); - return a; -} - + +// Copyright (c) 1999-2010 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#include +#include +#include +#include +#include + +#if (defined (__SVR4) && defined (__sun)) +#include +#endif + +#if _MSC_VER || __MINGW32__ +#include +#endif + +#if IN_GCC +#include "gdc_alloca.h" +#endif + +#if _WIN32 +#include +#endif + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#endif + +#include "port.h" +#include "root.h" +#include "dchar.h" +#include "rmem.h" + + +/********************************* Array ****************************/ + +Array::Array() +{ + data = SMALLARRAYCAP ? &smallarray[0] : NULL; + dim = 0; + allocdim = SMALLARRAYCAP; +} + +Array::~Array() +{ + if (data != &smallarray[0]) + mem.free(data); +} + +void Array::mark() +{ unsigned u; + + mem.mark(data); + for (u = 0; u < dim; u++) + mem.mark(data[u]); // BUG: what if arrays of Object's? +} + +void Array::reserve(unsigned nentries) +{ + //printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries); + if (allocdim - dim < nentries) + { + 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)); + } + } +} + +void Array::setDim(unsigned newdim) +{ + if (dim < newdim) + { + reserve(newdim - dim); + } + dim = newdim; +} + +void Array::fixDim() +{ + if (dim != allocdim) + { + 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; + } +} + +void Array::push(void *ptr) +{ + reserve(1); + data[dim++] = ptr; +} + +void *Array::pop() +{ + return data[--dim]; +} + +void Array::shift(void *ptr) +{ + reserve(1); + memmove(data + 1, data, dim * sizeof(*data)); + data[0] = ptr; + dim++; +} + +void Array::insert(unsigned index, void *ptr) +{ + reserve(1); + memmove(data + index + 1, data + index, (dim - index) * sizeof(*data)); + data[index] = ptr; + dim++; +} + + +void Array::insert(unsigned index, Array *a) +{ + if (a) + { unsigned d; + + d = a->dim; + reserve(d); + if (dim != index) + memmove(data + index + d, data + index, (dim - index) * sizeof(*data)); + memcpy(data + index, a->data, d * sizeof(*data)); + dim += d; + } +} + + +/*********************************** + * Append array a to this array. + */ + +void Array::append(Array *a) +{ + insert(dim, a); +} + +void Array::remove(unsigned i) +{ + if (dim - i - 1) + memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0])); + dim--; +} + +char *Array::toChars() +{ + unsigned len; + unsigned u; + char **buf; + char *str; + char *p; + + buf = (char **)malloc(dim * sizeof(char *)); + assert(buf); + len = 2; + for (u = 0; u < dim; u++) + { + buf[u] = ((Object *)data[u])->toChars(); + len += strlen(buf[u]) + 1; + } + str = (char *)mem.malloc(len); + + str[0] = '['; + p = str + 1; + for (u = 0; u < dim; u++) + { + if (u) + *p++ = ','; + len = strlen(buf[u]); + memcpy(p,buf[u],len); + p += len; + } + *p++ = ']'; + *p = 0; + free(buf); + return str; +} + +void Array::zero() +{ + memset(data,0,dim * sizeof(data[0])); +} + +void *Array::tos() +{ + return dim ? data[dim - 1] : NULL; +} + +int +#if _WIN32 + __cdecl +#endif + Array_sort_compare(const void *x, const void *y) +{ + Object *ox = *(Object **)x; + Object *oy = *(Object **)y; + + return ox->compare(oy); +} + +void Array::sort() +{ + if (dim) + { + qsort(data, dim, sizeof(Object *), Array_sort_compare); + } +} + +Array *Array::copy() +{ + Array *a = new Array(); + + a->setDim(dim); + memcpy(a->data, data, dim * sizeof(void *)); + return a; +} + diff --git a/dmd/root/async.c b/dmd/root/async.c index 8699e961..78f17c68 100644 --- a/dmd/root/async.c +++ b/dmd/root/async.c @@ -1,325 +1,325 @@ - -#define _MT 1 - -#include -#include -#include - -#if _WIN32 - -#include -#include -#include - -#include "root.h" - -static unsigned __stdcall startthread(void *p); - -struct FileData -{ - File *file; - int result; - HANDLE event; -}; - -struct AsyncRead -{ - static AsyncRead *create(size_t nfiles); - void addFile(File *file); - void start(); - int read(size_t i); - static void dispose(AsyncRead *); - - HANDLE hThread; - - size_t filesdim; - size_t filesmax; - FileData files[1]; -}; - - -AsyncRead *AsyncRead::create(size_t nfiles) -{ - AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + - (nfiles - 1) * sizeof(FileData)); - aw->filesmax = nfiles; - return aw; -} - -void AsyncRead::addFile(File *file) -{ - //printf("addFile(file = %p)\n", file); - //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); - assert(filesdim < filesmax); - files[filesdim].file = file; - files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); - ResetEvent(files[filesdim].event); - filesdim++; -} - -void AsyncRead::start() -{ - //printf("aw->filesdim = %p %d\n", this, filesdim); - if (filesdim) - { - unsigned threadaddr; - hThread = (HANDLE) _beginthreadex(NULL, - 0, - &startthread, - this, - 0, - (unsigned *)&threadaddr); - - if (hThread) - { - SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); - } - else - { - assert(0); - } - } -} - -int AsyncRead::read(size_t i) -{ - FileData *f = &files[i]; - WaitForSingleObject(f->event, INFINITE); - Sleep(0); // give up time slice - return f->result; -} - -void AsyncRead::dispose(AsyncRead *aw) -{ - free(aw); -} - - - -unsigned __stdcall startthread(void *p) -{ - AsyncRead *aw = (AsyncRead *)p; - - //printf("aw->filesdim = %p %d\n", aw, aw->filesdim); - for (size_t i = 0; i < aw->filesdim; i++) - { FileData *f = &aw->files[i]; - - f->result = f->file->read(); - SetEvent(f->event); - } - _endthreadex(EXIT_SUCCESS); - return EXIT_SUCCESS; // if skidding -} - -#elif linux // Posix - -#include -#include -#include - -#include "root.h" - -void *startthread(void *arg); - -void err_abort(int status, const char *msg) -{ - fprintf(stderr, "fatal error = %d, %s\n", status, msg); - exit(EXIT_FAILURE); -} - -struct FileData -{ - File *file; - int result; - - pthread_mutex_t mutex; - pthread_cond_t cond; - int value; -}; - -struct AsyncRead -{ - static AsyncRead *create(size_t nfiles); - void addFile(File *file); - void start(); - int read(size_t i); - static void dispose(AsyncRead *); - - size_t filesdim; - size_t filesmax; - FileData files[1]; -}; - - -AsyncRead *AsyncRead::create(size_t nfiles) -{ - AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + - (nfiles - 1) * sizeof(FileData)); - aw->filesmax = nfiles; - return aw; -} - -void AsyncRead::addFile(File *file) -{ - //printf("addFile(file = %p)\n", file); - //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); - assert(filesdim < filesmax); - FileData *f = &files[filesdim]; - f->file = file; - - int status = pthread_mutex_init(&f->mutex, NULL); - if (status != 0) - err_abort(status, "init mutex"); - status = pthread_cond_init(&f->cond, NULL); - if (status != 0) - err_abort(status, "init cond"); - - filesdim++; -} - -void AsyncRead::start() -{ - //printf("aw->filesdim = %p %d\n", this, filesdim); - if (filesdim) - { - pthread_t thread_id; - int status = pthread_create(&thread_id, - NULL, - &startthread, - this); - if (status != 0) - err_abort(status, "create thread"); - } -} - -int AsyncRead::read(size_t i) -{ - FileData *f = &files[i]; - - // Wait for the event - int status = pthread_mutex_lock(&f->mutex); - if (status != 0) - err_abort(status, "lock mutex"); - while (f->value == 0) - { - status = pthread_cond_wait(&f->cond, &f->mutex); - if (status != 0) - err_abort(status, "wait on condition"); - } - status = pthread_mutex_unlock(&f->mutex); - if (status != 0) - err_abort(status, "unlock mutex"); - - return f->result; -} - -void AsyncRead::dispose(AsyncRead *aw) -{ - //printf("AsyncRead::dispose()\n"); - for (int i = 0; i < aw->filesdim; i++) - { - FileData *f = &aw->files[i]; - int status = pthread_cond_destroy(&f->cond); - if (status != 0) - err_abort(status, "cond destroy"); - status = pthread_mutex_destroy(&f->mutex); - if (status != 0) - err_abort(status, "mutex destroy"); - } - free(aw); -} - - -void *startthread(void *p) -{ - AsyncRead *aw = (AsyncRead *)p; - - //printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim); - size_t dim = aw->filesdim; - for (size_t i = 0; i < dim; i++) - { FileData *f = &aw->files[i]; - - f->result = f->file->read(); - - // Set event - int status = pthread_mutex_lock(&f->mutex); - if (status != 0) - err_abort(status, "lock mutex"); - f->value = 1; - status = pthread_cond_signal(&f->cond); - if (status != 0) - err_abort(status, "signal condition"); - status = pthread_mutex_unlock(&f->mutex); - if (status != 0) - err_abort(status, "unlock mutex"); - } - - return NULL; // end thread -} - -#else - -#include -#include - -#include "root.h" - -struct FileData -{ - File *file; - int result; - //HANDLE event; -}; - -struct AsyncRead -{ - static AsyncRead *create(size_t nfiles); - void addFile(File *file); - void start(); - int read(size_t i); - static void dispose(AsyncRead *); - - //HANDLE hThread; - - size_t filesdim; - size_t filesmax; - FileData files[1]; -}; - - -AsyncRead *AsyncRead::create(size_t nfiles) -{ - AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + - (nfiles - 1) * sizeof(FileData)); - aw->filesmax = nfiles; - return aw; -} - -void AsyncRead::addFile(File *file) -{ - //printf("addFile(file = %p)\n", file); - //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); - assert(filesdim < filesmax); - files[filesdim].file = file; - //files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); - //ResetEvent(files[filesdim].event); - filesdim++; -} - -void AsyncRead::start() -{ -} - -int AsyncRead::read(size_t i) -{ - FileData *f = &files[i]; - f->result = f->file->read(); - return f->result; -} - -void AsyncRead::dispose(AsyncRead *aw) -{ - free(aw); -} - -#endif + +#define _MT 1 + +#include +#include +#include + +#if _WIN32 + +#include +#include +#include + +#include "root.h" + +static unsigned __stdcall startthread(void *p); + +struct FileData +{ + File *file; + int result; + HANDLE event; +}; + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); + + HANDLE hThread; + + size_t filesdim; + size_t filesmax; + FileData files[1]; +}; + + +AsyncRead *AsyncRead::create(size_t nfiles) +{ + AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + + (nfiles - 1) * sizeof(FileData)); + aw->filesmax = nfiles; + return aw; +} + +void AsyncRead::addFile(File *file) +{ + //printf("addFile(file = %p)\n", file); + //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); + assert(filesdim < filesmax); + files[filesdim].file = file; + files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); + ResetEvent(files[filesdim].event); + filesdim++; +} + +void AsyncRead::start() +{ + //printf("aw->filesdim = %p %d\n", this, filesdim); + if (filesdim) + { + unsigned threadaddr; + hThread = (HANDLE) _beginthreadex(NULL, + 0, + &startthread, + this, + 0, + (unsigned *)&threadaddr); + + if (hThread) + { + SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); + } + else + { + assert(0); + } + } +} + +int AsyncRead::read(size_t i) +{ + FileData *f = &files[i]; + WaitForSingleObject(f->event, INFINITE); + Sleep(0); // give up time slice + return f->result; +} + +void AsyncRead::dispose(AsyncRead *aw) +{ + free(aw); +} + + + +unsigned __stdcall startthread(void *p) +{ + AsyncRead *aw = (AsyncRead *)p; + + //printf("aw->filesdim = %p %d\n", aw, aw->filesdim); + for (size_t i = 0; i < aw->filesdim; i++) + { FileData *f = &aw->files[i]; + + f->result = f->file->read(); + SetEvent(f->event); + } + _endthreadex(EXIT_SUCCESS); + return EXIT_SUCCESS; // if skidding +} + +#elif linux // Posix + +#include +#include +#include + +#include "root.h" + +void *startthread(void *arg); + +void err_abort(int status, const char *msg) +{ + fprintf(stderr, "fatal error = %d, %s\n", status, msg); + exit(EXIT_FAILURE); +} + +struct FileData +{ + File *file; + int result; + + pthread_mutex_t mutex; + pthread_cond_t cond; + int value; +}; + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); + + size_t filesdim; + size_t filesmax; + FileData files[1]; +}; + + +AsyncRead *AsyncRead::create(size_t nfiles) +{ + AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + + (nfiles - 1) * sizeof(FileData)); + aw->filesmax = nfiles; + return aw; +} + +void AsyncRead::addFile(File *file) +{ + //printf("addFile(file = %p)\n", file); + //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); + assert(filesdim < filesmax); + FileData *f = &files[filesdim]; + f->file = file; + + int status = pthread_mutex_init(&f->mutex, NULL); + if (status != 0) + err_abort(status, "init mutex"); + status = pthread_cond_init(&f->cond, NULL); + if (status != 0) + err_abort(status, "init cond"); + + filesdim++; +} + +void AsyncRead::start() +{ + //printf("aw->filesdim = %p %d\n", this, filesdim); + if (filesdim) + { + pthread_t thread_id; + int status = pthread_create(&thread_id, + NULL, + &startthread, + this); + if (status != 0) + err_abort(status, "create thread"); + } +} + +int AsyncRead::read(size_t i) +{ + FileData *f = &files[i]; + + // Wait for the event + int status = pthread_mutex_lock(&f->mutex); + if (status != 0) + err_abort(status, "lock mutex"); + while (f->value == 0) + { + status = pthread_cond_wait(&f->cond, &f->mutex); + if (status != 0) + err_abort(status, "wait on condition"); + } + status = pthread_mutex_unlock(&f->mutex); + if (status != 0) + err_abort(status, "unlock mutex"); + + return f->result; +} + +void AsyncRead::dispose(AsyncRead *aw) +{ + //printf("AsyncRead::dispose()\n"); + for (int i = 0; i < aw->filesdim; i++) + { + FileData *f = &aw->files[i]; + int status = pthread_cond_destroy(&f->cond); + if (status != 0) + err_abort(status, "cond destroy"); + status = pthread_mutex_destroy(&f->mutex); + if (status != 0) + err_abort(status, "mutex destroy"); + } + free(aw); +} + + +void *startthread(void *p) +{ + AsyncRead *aw = (AsyncRead *)p; + + //printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim); + size_t dim = aw->filesdim; + for (size_t i = 0; i < dim; i++) + { FileData *f = &aw->files[i]; + + f->result = f->file->read(); + + // Set event + int status = pthread_mutex_lock(&f->mutex); + if (status != 0) + err_abort(status, "lock mutex"); + f->value = 1; + status = pthread_cond_signal(&f->cond); + if (status != 0) + err_abort(status, "signal condition"); + status = pthread_mutex_unlock(&f->mutex); + if (status != 0) + err_abort(status, "unlock mutex"); + } + + return NULL; // end thread +} + +#else + +#include +#include + +#include "root.h" + +struct FileData +{ + File *file; + int result; + //HANDLE event; +}; + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); + + //HANDLE hThread; + + size_t filesdim; + size_t filesmax; + FileData files[1]; +}; + + +AsyncRead *AsyncRead::create(size_t nfiles) +{ + AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + + (nfiles - 1) * sizeof(FileData)); + aw->filesmax = nfiles; + return aw; +} + +void AsyncRead::addFile(File *file) +{ + //printf("addFile(file = %p)\n", file); + //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); + assert(filesdim < filesmax); + files[filesdim].file = file; + //files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); + //ResetEvent(files[filesdim].event); + filesdim++; +} + +void AsyncRead::start() +{ +} + +int AsyncRead::read(size_t i) +{ + FileData *f = &files[i]; + f->result = f->file->read(); + return f->result; +} + +void AsyncRead::dispose(AsyncRead *aw) +{ + free(aw); +} + +#endif diff --git a/dmd/root/async.h b/dmd/root/async.h index cbecd25e..6f25f367 100644 --- a/dmd/root/async.h +++ b/dmd/root/async.h @@ -1,33 +1,33 @@ - -// Copyright (c) 2009-2009 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef ASYNC_H -#define ASYNC_H - -#if __DMC__ -#pragma once -#endif - - -/******************* - * Simple interface to read files asynchronously in another - * thread. - */ - -struct AsyncRead -{ - static AsyncRead *create(size_t nfiles); - void addFile(File *file); - void start(); - int read(size_t i); - static void dispose(AsyncRead *); -}; - - -#endif + +// Copyright (c) 2009-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#ifndef ASYNC_H +#define ASYNC_H + +#if __DMC__ +#pragma once +#endif + + +/******************* + * Simple interface to read files asynchronously in another + * thread. + */ + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); +}; + + +#endif diff --git a/dmd/root/dchar.c b/dmd/root/dchar.c index db90916f..0b11a8a4 100644 --- a/dmd/root/dchar.c +++ b/dmd/root/dchar.c @@ -1,482 +1,482 @@ - -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - - -#include -#include -#include -#include - -#include "dchar.h" -#include "rmem.h" - -#if M_UNICODE - -// Converts a char string to Unicode - -dchar *Dchar::dup(char *p) -{ - dchar *s; - size_t len; - - if (!p) - return NULL; - len = strlen(p); - s = (dchar *)mem.malloc((len + 1) * sizeof(dchar)); - for (unsigned i = 0; i < len; i++) - { - s[i] = (dchar)(p[i] & 0xFF); - } - s[len] = 0; - return s; -} - -dchar *Dchar::memchr(dchar *p, int c, int count) -{ - int u; - - for (u = 0; u < count; u++) - { - if (p[u] == c) - return p + u; - } - return NULL; -} - -#if _WIN32 && __DMC__ -__declspec(naked) -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - __asm - { - mov ECX,4[ESP] - mov EDX,8[ESP] - xor EAX,EAX - test EDX,EDX - je L92 - -LC8: cmp EDX,1 - je L98 - cmp EDX,2 - je LAE - - add EAX,[ECX] -// imul EAX,EAX,025h - lea EAX,[EAX][EAX*8] - add ECX,4 - sub EDX,2 - jmp LC8 - -L98: mov DX,[ECX] - and EDX,0FFFFh - add EAX,EDX - ret - -LAE: add EAX,[ECX] -L92: ret - } -} -#else -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - unsigned hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(const uint16_t *)str; - return hash; - - case 2: - hash += *(const uint32_t *)str; - return hash; - - default: - hash += *(const uint32_t *)str; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} -#endif - -hash_t Dchar::icalcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(const uint16_t *)str | 0x20; - return hash; - - case 2: - hash += *(const uint32_t *)str | 0x200020; - return hash; - - default: - hash += *(const uint32_t *)str | 0x200020; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} - -#elif MCBS - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; - hash += *(const uint16_t *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(const uint32_t *)str; - str += 4; - len -= 4; - break; - } - } -} - -#elif UTF8 - -// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335 - -char Dchar::mblen[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1, -}; - -dchar *Dchar::dec(dchar *pstart, dchar *p) -{ - while ((p[-1] & 0xC0) == 0x80) - p--; - return p; -} - -int Dchar::get(dchar *p) -{ - unsigned c; - unsigned char *q = (unsigned char *)p; - - c = q[0]; - switch (mblen[c]) - { - case 2: - c = ((c - 0xC0) << 6) | - (q[1] - 0x80); - break; - - case 3: - c = ((c - 0xE0) << 12) | - ((q[1] - 0x80) << 6) | - (q[2] - 0x80); - break; - - case 4: - c = ((c - 0xF0) << 18) | - ((q[1] - 0x80) << 12) | - ((q[2] - 0x80) << 6) | - (q[3] - 0x80); - break; - - case 5: - c = ((c - 0xF8) << 24) | - ((q[1] - 0x80) << 18) | - ((q[2] - 0x80) << 12) | - ((q[3] - 0x80) << 6) | - (q[4] - 0x80); - break; - - case 6: - c = ((c - 0xFC) << 30) | - ((q[1] - 0x80) << 24) | - ((q[2] - 0x80) << 18) | - ((q[3] - 0x80) << 12) | - ((q[4] - 0x80) << 6) | - (q[5] - 0x80); - break; - } - return c; -} - -dchar *Dchar::put(dchar *p, unsigned c) -{ - if (c <= 0x7F) - { - *p++ = c; - } - else if (c <= 0x7FF) - { - p[0] = 0xC0 + (c >> 6); - p[1] = 0x80 + (c & 0x3F); - p += 2; - } - else if (c <= 0xFFFF) - { - p[0] = 0xE0 + (c >> 12); - p[1] = 0x80 + ((c >> 6) & 0x3F); - p[2] = 0x80 + (c & 0x3F); - p += 3; - } - else if (c <= 0x1FFFFF) - { - p[0] = 0xF0 + (c >> 18); - p[1] = 0x80 + ((c >> 12) & 0x3F); - p[2] = 0x80 + ((c >> 6) & 0x3F); - p[3] = 0x80 + (c & 0x3F); - p += 4; - } - else if (c <= 0x3FFFFFF) - { - p[0] = 0xF8 + (c >> 24); - p[1] = 0x80 + ((c >> 18) & 0x3F); - p[2] = 0x80 + ((c >> 12) & 0x3F); - p[3] = 0x80 + ((c >> 6) & 0x3F); - p[4] = 0x80 + (c & 0x3F); - p += 5; - } - else if (c <= 0x7FFFFFFF) - { - p[0] = 0xFC + (c >> 30); - p[1] = 0x80 + ((c >> 24) & 0x3F); - p[2] = 0x80 + ((c >> 18) & 0x3F); - p[3] = 0x80 + ((c >> 12) & 0x3F); - p[4] = 0x80 + ((c >> 6) & 0x3F); - p[5] = 0x80 + (c & 0x3F); - p += 6; - } - else - assert(0); // not a UCS-4 character - return p; -} - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint16_t *)str; -#else - hash += str[0] * 256 + str[1]; -#endif - return hash; - - case 3: - hash *= 37; -#if LITTLE_ENDIAN - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; -#else - hash += (str[0] * 256 + str[1]) * 256 + str[2]; -#endif - return hash; - - default: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint32_t *)str; -#else - hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -#endif - - str += 4; - len -= 4; - break; - } - } -} - -#else // ascii - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint16_t *)str; -#else - hash += str[0] * 256 + str[1]; -#endif - return hash; - - case 3: - hash *= 37; -#if LITTLE_ENDIAN - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; -#else - hash += (str[0] * 256 + str[1]) * 256 + str[2]; -#endif - return hash; - - default: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint32_t *)str; -#else - hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -#endif - str += 4; - len -= 4; - break; - } - } -} - -hash_t Dchar::icalcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str | 0x20; - return hash; - - case 2: - hash *= 37; - hash += *(const uint16_t *)str | 0x2020; - return hash; - - case 3: - hash *= 37; - hash += ((*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]) | 0x202020; - return hash; - - default: - hash *= 37; - hash += *(const uint32_t *)str | 0x20202020; - str += 4; - len -= 4; - break; - } - } -} - -#endif - -#if 0 -#include - -void main() -{ - // Print out values to hardcode into Dchar::mblen[] - int c; - int s; - - for (c = 0; c < 256; c++) - { - s = 1; - if (c >= 0xC0 && c <= 0xDF) - s = 2; - if (c >= 0xE0 && c <= 0xEF) - s = 3; - if (c >= 0xF0 && c <= 0xF7) - s = 4; - if (c >= 0xF8 && c <= 0xFB) - s = 5; - if (c >= 0xFC && c <= 0xFD) - s = 6; - - printf("%d", s); - if ((c & 15) == 15) - printf(",\n"); - else - printf(","); - } -} -#endif + +// Copyright (c) 1999-2006 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + + +#include +#include +#include +#include + +#include "dchar.h" +#include "rmem.h" + +#if M_UNICODE + +// Converts a char string to Unicode + +dchar *Dchar::dup(char *p) +{ + dchar *s; + size_t len; + + if (!p) + return NULL; + len = strlen(p); + s = (dchar *)mem.malloc((len + 1) * sizeof(dchar)); + for (unsigned i = 0; i < len; i++) + { + s[i] = (dchar)(p[i] & 0xFF); + } + s[len] = 0; + return s; +} + +dchar *Dchar::memchr(dchar *p, int c, int count) +{ + int u; + + for (u = 0; u < count; u++) + { + if (p[u] == c) + return p + u; + } + return NULL; +} + +#if _WIN32 && __DMC__ +__declspec(naked) +unsigned Dchar::calcHash(const dchar *str, unsigned len) +{ + __asm + { + mov ECX,4[ESP] + mov EDX,8[ESP] + xor EAX,EAX + test EDX,EDX + je L92 + +LC8: cmp EDX,1 + je L98 + cmp EDX,2 + je LAE + + add EAX,[ECX] +// imul EAX,EAX,025h + lea EAX,[EAX][EAX*8] + add ECX,4 + sub EDX,2 + jmp LC8 + +L98: mov DX,[ECX] + and EDX,0FFFFh + add EAX,EDX + ret + +LAE: add EAX,[ECX] +L92: ret + } +} +#else +hash_t Dchar::calcHash(const dchar *str, size_t len) +{ + unsigned hash = 0; + + for (;;) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash += *(const uint16_t *)str; + return hash; + + case 2: + hash += *(const uint32_t *)str; + return hash; + + default: + hash += *(const uint32_t *)str; + hash *= 37; + str += 2; + len -= 2; + break; + } + } +} +#endif + +hash_t Dchar::icalcHash(const dchar *str, size_t len) +{ + hash_t hash = 0; + + for (;;) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash += *(const uint16_t *)str | 0x20; + return hash; + + case 2: + hash += *(const uint32_t *)str | 0x200020; + return hash; + + default: + hash += *(const uint32_t *)str | 0x200020; + hash *= 37; + str += 2; + len -= 2; + break; + } + } +} + +#elif MCBS + +hash_t Dchar::calcHash(const dchar *str, size_t len) +{ + hash_t hash = 0; + + while (1) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash *= 37; + hash += *(const uint8_t *)str; + return hash; + + case 2: + hash *= 37; + hash += *(const uint16_t *)str; + return hash; + + case 3: + hash *= 37; + hash += (*(const uint16_t *)str << 8) + + ((const uint8_t *)str)[2]; + return hash; + + default: + hash *= 37; + hash += *(const uint32_t *)str; + str += 4; + len -= 4; + break; + } + } +} + +#elif UTF8 + +// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335 + +char Dchar::mblen[256] = +{ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1, +}; + +dchar *Dchar::dec(dchar *pstart, dchar *p) +{ + while ((p[-1] & 0xC0) == 0x80) + p--; + return p; +} + +int Dchar::get(dchar *p) +{ + unsigned c; + unsigned char *q = (unsigned char *)p; + + c = q[0]; + switch (mblen[c]) + { + case 2: + c = ((c - 0xC0) << 6) | + (q[1] - 0x80); + break; + + case 3: + c = ((c - 0xE0) << 12) | + ((q[1] - 0x80) << 6) | + (q[2] - 0x80); + break; + + case 4: + c = ((c - 0xF0) << 18) | + ((q[1] - 0x80) << 12) | + ((q[2] - 0x80) << 6) | + (q[3] - 0x80); + break; + + case 5: + c = ((c - 0xF8) << 24) | + ((q[1] - 0x80) << 18) | + ((q[2] - 0x80) << 12) | + ((q[3] - 0x80) << 6) | + (q[4] - 0x80); + break; + + case 6: + c = ((c - 0xFC) << 30) | + ((q[1] - 0x80) << 24) | + ((q[2] - 0x80) << 18) | + ((q[3] - 0x80) << 12) | + ((q[4] - 0x80) << 6) | + (q[5] - 0x80); + break; + } + return c; +} + +dchar *Dchar::put(dchar *p, unsigned c) +{ + if (c <= 0x7F) + { + *p++ = c; + } + else if (c <= 0x7FF) + { + p[0] = 0xC0 + (c >> 6); + p[1] = 0x80 + (c & 0x3F); + p += 2; + } + else if (c <= 0xFFFF) + { + p[0] = 0xE0 + (c >> 12); + p[1] = 0x80 + ((c >> 6) & 0x3F); + p[2] = 0x80 + (c & 0x3F); + p += 3; + } + else if (c <= 0x1FFFFF) + { + p[0] = 0xF0 + (c >> 18); + p[1] = 0x80 + ((c >> 12) & 0x3F); + p[2] = 0x80 + ((c >> 6) & 0x3F); + p[3] = 0x80 + (c & 0x3F); + p += 4; + } + else if (c <= 0x3FFFFFF) + { + p[0] = 0xF8 + (c >> 24); + p[1] = 0x80 + ((c >> 18) & 0x3F); + p[2] = 0x80 + ((c >> 12) & 0x3F); + p[3] = 0x80 + ((c >> 6) & 0x3F); + p[4] = 0x80 + (c & 0x3F); + p += 5; + } + else if (c <= 0x7FFFFFFF) + { + p[0] = 0xFC + (c >> 30); + p[1] = 0x80 + ((c >> 24) & 0x3F); + p[2] = 0x80 + ((c >> 18) & 0x3F); + p[3] = 0x80 + ((c >> 12) & 0x3F); + p[4] = 0x80 + ((c >> 6) & 0x3F); + p[5] = 0x80 + (c & 0x3F); + p += 6; + } + else + assert(0); // not a UCS-4 character + return p; +} + +hash_t Dchar::calcHash(const dchar *str, size_t len) +{ + hash_t hash = 0; + + while (1) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash *= 37; + hash += *(const uint8_t *)str; + return hash; + + case 2: + hash *= 37; +#if LITTLE_ENDIAN + hash += *(const uint16_t *)str; +#else + hash += str[0] * 256 + str[1]; +#endif + return hash; + + case 3: + hash *= 37; +#if LITTLE_ENDIAN + hash += (*(const uint16_t *)str << 8) + + ((const uint8_t *)str)[2]; +#else + hash += (str[0] * 256 + str[1]) * 256 + str[2]; +#endif + return hash; + + default: + hash *= 37; +#if LITTLE_ENDIAN + hash += *(const uint32_t *)str; +#else + hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; +#endif + + str += 4; + len -= 4; + break; + } + } +} + +#else // ascii + +hash_t Dchar::calcHash(const dchar *str, size_t len) +{ + hash_t hash = 0; + + while (1) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash *= 37; + hash += *(const uint8_t *)str; + return hash; + + case 2: + hash *= 37; +#if LITTLE_ENDIAN + hash += *(const uint16_t *)str; +#else + hash += str[0] * 256 + str[1]; +#endif + return hash; + + case 3: + hash *= 37; +#if LITTLE_ENDIAN + hash += (*(const uint16_t *)str << 8) + + ((const uint8_t *)str)[2]; +#else + hash += (str[0] * 256 + str[1]) * 256 + str[2]; +#endif + return hash; + + default: + hash *= 37; +#if LITTLE_ENDIAN + hash += *(const uint32_t *)str; +#else + hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; +#endif + str += 4; + len -= 4; + break; + } + } +} + +hash_t Dchar::icalcHash(const dchar *str, size_t len) +{ + hash_t hash = 0; + + while (1) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash *= 37; + hash += *(const uint8_t *)str | 0x20; + return hash; + + case 2: + hash *= 37; + hash += *(const uint16_t *)str | 0x2020; + return hash; + + case 3: + hash *= 37; + hash += ((*(const uint16_t *)str << 8) + + ((const uint8_t *)str)[2]) | 0x202020; + return hash; + + default: + hash *= 37; + hash += *(const uint32_t *)str | 0x20202020; + str += 4; + len -= 4; + break; + } + } +} + +#endif + +#if 0 +#include + +void main() +{ + // Print out values to hardcode into Dchar::mblen[] + int c; + int s; + + for (c = 0; c < 256; c++) + { + s = 1; + if (c >= 0xC0 && c <= 0xDF) + s = 2; + if (c >= 0xE0 && c <= 0xEF) + s = 3; + if (c >= 0xF0 && c <= 0xF7) + s = 4; + if (c >= 0xF8 && c <= 0xFB) + s = 5; + if (c >= 0xFC && c <= 0xFD) + s = 6; + + printf("%d", s); + if ((c & 15) == 15) + printf(",\n"); + else + printf(","); + } +} +#endif diff --git a/dmd/root/dchar.h b/dmd/root/dchar.h index 631c2a35..6ac7994c 100644 --- a/dmd/root/dchar.h +++ b/dmd/root/dchar.h @@ -1,194 +1,194 @@ - -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#ifndef DCHAR_H -#define DCHAR_H - -#if __GNUC__ && !_WIN32 -#include "gnuc.h" -#endif - -#if _MSC_VER - // Disable useless warnings about unreferenced functions - #pragma warning (disable : 4514) -#endif - -//#include "root.h" -typedef size_t hash_t; - -#undef TEXT - -// NOTE: All functions accepting pointer arguments must not be NULL - -#if M_UNICODE - -#include -#include - -typedef wchar_t dchar; -#define TEXT(x) L##x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } - static int len(const dchar *p) { return wcslen(p); } - static dchar get(dchar *p) { return *p; } - static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; } - static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) - { -#if __DMC__ - if (!*s1 && !*s2) // wcscmp is broken - return 0; -#endif - return wcscmp(s1, s2); -#if 0 - return (*s1 == *s2) - ? wcscmp(s1, s2) - : ((int)*s1 - (int)*s2); -#endif - } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return iswalpha(c); } - static int isUpper(dchar c) { return iswupper(c); } - static int isLower(dchar c) { return iswlower(c); } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; } - static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory? - static dchar *dup(char *p); - static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); } - static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); } - static dchar *memchr(dchar *p, int c, int count); - static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); } - static hash_t icalcHash(const dchar *str, size_t len); -}; - -#elif MCBS - -#include -#include - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax MB_LEN_MAX - -#elif UTF8 - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 6 - -struct Dchar -{ - static char mblen[256]; - - static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; } - static dchar *dec(dchar *pstart, dchar *p); - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p); - static int getprev(dchar *pstart, dchar *p) - { return *dec(pstart, p) & 0xFF; } - static dchar *put(dchar *p, unsigned c); - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; } - static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; } - static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); } -}; - -#else - -#include - -#ifndef GCC_SAFE_DMD -#include -#endif - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { return p - 1; } - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p) { return *p & 0xFF; } - static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; } - static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } -#ifndef GCC_SAFE_DMD - static int isAlpha(dchar c) { return isalpha((unsigned char)c); } - static int isUpper(dchar c) { return isupper((unsigned char)c); } - static int isLower(dchar c) { return islower((unsigned char)c); } - static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); } - static int isLocaleLower(dchar c) { return islower((unsigned char)c); } - static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? -#endif - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions -#ifdef __GNUC__ - static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); } -#else - static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); } -#endif - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); } - static hash_t icalcHash(const dchar *str, size_t len); -}; - -#endif -#endif - + +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + + +#ifndef DCHAR_H +#define DCHAR_H + +#if __GNUC__ && !_WIN32 +#include "gnuc.h" +#endif + +#if _MSC_VER + // Disable useless warnings about unreferenced functions + #pragma warning (disable : 4514) +#endif + +//#include "root.h" +typedef size_t hash_t; + +#undef TEXT + +// NOTE: All functions accepting pointer arguments must not be NULL + +#if M_UNICODE + +#include +#include + +typedef wchar_t dchar; +#define TEXT(x) L##x + +#define Dchar_mbmax 1 + +struct Dchar +{ + static dchar *inc(dchar *p) { return p + 1; } + static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } + static int len(const dchar *p) { return wcslen(p); } + static dchar get(dchar *p) { return *p; } + static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; } + static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; } + static int cmp(dchar *s1, dchar *s2) + { +#if __DMC__ + if (!*s1 && !*s2) // wcscmp is broken + return 0; +#endif + return wcscmp(s1, s2); +#if 0 + return (*s1 == *s2) + ? wcscmp(s1, s2) + : ((int)*s1 - (int)*s2); +#endif + } + static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); } + static int isDigit(dchar c) { return '0' <= c && c <= '9'; } + static int isAlpha(dchar c) { return iswalpha(c); } + static int isUpper(dchar c) { return iswupper(c); } + static int isLower(dchar c) { return iswlower(c); } + static int isLocaleUpper(dchar c) { return isUpper(c); } + static int isLocaleLower(dchar c) { return isLower(c); } + static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; } + static int toLower(dchar *p) { return toLower(*p); } + static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; } + static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory? + static dchar *dup(char *p); + static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); } + static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); } + static dchar *memchr(dchar *p, int c, int count); + static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); } + static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); } + static hash_t calcHash(const dchar *str, size_t len); + + // Case insensitive versions + static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); } + static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); } + static hash_t icalcHash(const dchar *str, size_t len); +}; + +#elif MCBS + +#include +#include + +typedef char dchar; +#define TEXT(x) x + +#define Dchar_mbmax MB_LEN_MAX + +#elif UTF8 + +typedef char dchar; +#define TEXT(x) x + +#define Dchar_mbmax 6 + +struct Dchar +{ + static char mblen[256]; + + static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; } + static dchar *dec(dchar *pstart, dchar *p); + static int len(const dchar *p) { return strlen(p); } + static int get(dchar *p); + static int getprev(dchar *pstart, dchar *p) + { return *dec(pstart, p) & 0xFF; } + static dchar *put(dchar *p, unsigned c); + static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } + static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } + static int isDigit(dchar c) { return '0' <= c && c <= '9'; } + static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; } + static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; } + static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; } + static int isLocaleUpper(dchar c) { return isUpper(c); } + static int isLocaleLower(dchar c) { return isLower(c); } + static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; } + static int toLower(dchar *p) { return toLower(*p); } + static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; } + static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? + static dchar *chr(dchar *p, int c) { return strchr(p, c); } + static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } + static dchar *memchr(dchar *p, int c, int count) + { return (dchar *)::memchr(p, c, count); } + static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } + static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } + static hash_t calcHash(const dchar *str, size_t len); + + // Case insensitive versions + static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); } + static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); } +}; + +#else + +#include + +#ifndef GCC_SAFE_DMD +#include +#endif + +typedef char dchar; +#define TEXT(x) x + +#define Dchar_mbmax 1 + +struct Dchar +{ + static dchar *inc(dchar *p) { return p + 1; } + static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } + static int len(const dchar *p) { return strlen(p); } + static int get(dchar *p) { return *p & 0xFF; } + static int getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1] & 0xFF; } + static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; } + static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } + static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } + static int isDigit(dchar c) { return '0' <= c && c <= '9'; } +#ifndef GCC_SAFE_DMD + static int isAlpha(dchar c) { return isalpha((unsigned char)c); } + static int isUpper(dchar c) { return isupper((unsigned char)c); } + static int isLower(dchar c) { return islower((unsigned char)c); } + static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); } + static int isLocaleLower(dchar c) { return islower((unsigned char)c); } + static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; } + static int toLower(dchar *p) { return toLower(*p); } + static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; } + static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? +#endif + static dchar *chr(dchar *p, int c) { return strchr(p, c); } + static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } + static dchar *memchr(dchar *p, int c, int count) + { return (dchar *)::memchr(p, c, count); } + static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } + static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } + static hash_t calcHash(const dchar *str, size_t len); + + // Case insensitive versions +#ifdef __GNUC__ + static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); } +#else + static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); } +#endif + static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); } + static hash_t icalcHash(const dchar *str, size_t len); +}; + +#endif +#endif + diff --git a/dmd/root/longdouble.c b/dmd/root/longdouble.c new file mode 100644 index 00000000..8a0f00e7 --- /dev/null +++ b/dmd/root/longdouble.c @@ -0,0 +1,636 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Rainer Schuetze +// 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. + +// 80 bit floating point value implementation for Microsoft compiler + +#if _MSC_VER +#include "longdouble.h" + +#include "assert.h" + +#include +#include +#include + +extern "C" +{ + // implemented in ldfpu.asm for _WIN64 + int ld_initfpu(int bits, int mask); + void ld_expl(longdouble* ld, int exp); + longdouble ld_add(longdouble ld1, longdouble ld2); + longdouble ld_sub(longdouble ld1, longdouble ld2); + longdouble ld_mul(longdouble ld1, longdouble ld2); + longdouble ld_div(longdouble ld1, longdouble ld2); + longdouble ld_mod(longdouble ld1, longdouble ld2); + bool ld_cmpb(longdouble ld1, longdouble ld2); + bool ld_cmpbe(longdouble ld1, longdouble ld2); + bool ld_cmpa(longdouble ld1, longdouble ld2); + bool ld_cmpae(longdouble ld1, longdouble ld2); + bool ld_cmpe(longdouble ld1, longdouble ld2); + bool ld_cmpne(longdouble ld1, longdouble ld2); + longdouble ld_sqrt(longdouble ld1); + longdouble ld_sin(longdouble ld1); + longdouble ld_cos(longdouble ld1); + longdouble ld_tan(longdouble ld1); +} + +bool initFPU() +{ +#ifdef _WIN64 +// int old_cw = ld_initfpu(_RC_NEAR); + int old_cw = ld_initfpu(0x300 /*_PC_64 | _RC_NEAR*/, // #defines NOT identical to CPU FPU control word! + 0xF00 /*_MCW_PC | _MCW_RC*/); +#else + int old_cw = _control87(_MCW_EM | _PC_64 | _RC_NEAR, + _MCW_EM | _MCW_PC | _MCW_RC); +#endif + return true; +} +static bool doInitFPU = initFPU(); + +#ifndef _WIN64 +extern "C" +{ + +double ld_read(const longdouble* pthis) +{ + double res; + __asm + { + mov eax, pthis + fld tbyte ptr [eax] + fstp res + } + return res; +} +long long ld_readll(const longdouble* pthis) +{ +#if 1 + return ld_readull(pthis); +#elif defined _WIN64 + return ld_readll(this); +#else + longdouble* pthis = this; + long long res; + __asm + { + mov eax, pthis + fld tbyte ptr [eax] + fistp qword ptr res + } + return res; +#endif +} + +unsigned long long ld_readull(const longdouble* pthis) +{ +#if 1 + // somehow the FPU does not respect the CHOP mode of the rounding control + // in 64-bit mode + // so we roll our own conversion (it also allows the usual C wrap-around + // instead of the "invalid value" created by the FPU) + int expo = pthis->exponent - 0x3fff; + unsigned long long u; + if(expo < 0 || expo > 127) + return 0; + if(expo < 64) + u = pthis->mantissa >> (63 - expo); + else + u = pthis->mantissa << (expo - 63); + if(pthis->sign) + u = ~u + 1; + return u; +#else + longdouble* pthis = this; + long long res; // cannot use unsigned, VC will not generate "fistp qword" + longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 }; + __asm + { + mov eax, pthis + fld tbyte ptr [eax] + fld tbyte ptr twoPow63 + fsubp ST(1),ST(0) // move it into signed range + + lea eax, res + fistp qword ptr [eax] + } + res ^= (1LL << 63); + return res; +#endif +} + +void ld_set(longdouble* pthis, double d) +{ + __asm + { + mov eax, pthis + fld d + fstp tbyte ptr [eax] + } +} +void ld_setll(longdouble* pthis, long long d) +{ + __asm + { + fild qword ptr d + mov eax, pthis + fstp tbyte ptr [eax] + } +} +void ld_setull(longdouble* pthis, unsigned long long d) +{ + d ^= (1LL << 63); + longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 }; + __asm + { + fild qword ptr d + fld tbyte ptr twoPow63 + faddp ST(1),ST(0) + mov eax, pthis + fstp tbyte ptr [eax] + } +} + +} // extern "C" +#endif // !_WIN64 + +longdouble ldexpl(longdouble ld, int exp) +{ +#ifdef _WIN64 + ld_expl(&ld, exp); +#else + __asm + { + fild dword ptr exp + fld tbyte ptr ld + fscale // ST(0) = ST(0) * (2**ST(1)) + fstp ST(1) + fstp tbyte ptr ld + } +#endif + return ld; +} + +/////////////////////////////////////////////////////////////////////// +longdouble operator+(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_add(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fadd + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble operator-(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_sub(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fsub + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble operator*(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_mul(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fmul + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble operator/(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_div(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fdiv + fstp tbyte ptr res; + } + return res; +#endif +} + +bool operator< (longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpb(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setb AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator<=(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpbe(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setbe AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator> (longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpa(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + seta AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator>=(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpae(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setae AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator==(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpe(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + sete AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator!=(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpne(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setne AL + setp AH + or AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} + + +int _isnan(longdouble ld) +{ + return (ld.exponent == 0x7fff && ld.mantissa != 0); +} + +longdouble fabsl(longdouble ld) +{ + ld.sign = 0; + return ld; +} + +longdouble sqrtl(longdouble ld) +{ +#ifdef _WIN64 + return ld_sqrt(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fsqrt; + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble sinl (longdouble ld) +{ +#ifdef _WIN64 + return ld_sin(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fsin; // exact for |x|<=PI/4 + fstp tbyte ptr res + } + return res; +#endif +} +longdouble cosl (longdouble ld) +{ +#ifdef _WIN64 + return ld_cos(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fcos; // exact for |x|<=PI/4 + fstp tbyte ptr res; + } + return res; +#endif +} +longdouble tanl (longdouble ld) +{ +#ifdef _WIN64 + return ld_tan(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fptan; + fstp ST(0); // always 1 + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble fmodl(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_mod(x, y); +#else + short sw; + longdouble res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y +FM1: // We don't use fprem1 because for some inexplicable + // reason we get -5 when we do _modulo(15, 10) + fprem // ST = ST % ST1 + fstsw word ptr sw + fwait + mov AH,byte ptr sw+1 // get msb of status word in AH + sahf // transfer to flags + jp FM1 // continue till ST < ST1 + fstp ST(1) // leave remainder on stack + fstp tbyte ptr res; + } + return res; +#endif +} + +////////////////////////////////////////////////////////////// + +longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 }; +longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 }; +longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 }; + +longdouble ld_zero = { 0, 0, 0 }; +longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 }; +longdouble ld_pi = { 0xc90fdaa22168c235ULL, 0x4000, 0 }; +longdouble ld_log2t = { 0xd49a784bcd1b8afeULL, 0x4000, 0 }; +longdouble ld_log2e = { 0xb8aa3b295c17f0bcULL, 0x3fff, 0 }; +longdouble ld_log2 = { 0x9a209a84fbcff799ULL, 0x3ffd, 0 }; +longdouble ld_ln2 = { 0xb17217f7d1cf79acULL, 0x3ffe, 0 }; + +longdouble ld_pi2 = ld_pi*2; +longdouble ld_piOver2 = ld_pi*0.5; +longdouble ld_piOver4 = ld_pi*0.25; + +////////////////////////////////////////////////////////////// + +#define LD_TYPE_OTHER 0 +#define LD_TYPE_ZERO 1 +#define LD_TYPE_INFINITE 2 +#define LD_TYPE_SNAN 3 +#define LD_TYPE_QNAN 4 + +int ld_type(longdouble x) +{ + if(x.exponent == 0) + return x.mantissa == 0 ? LD_TYPE_ZERO : LD_TYPE_OTHER; // dnormal if not zero + if(x.exponent != 0x7fff) + return LD_TYPE_OTHER; + if(x.mantissa == 0) + return LD_TYPE_INFINITE; + if(x.mantissa & (1LL << 63)) + return LD_TYPE_QNAN; + return LD_TYPE_SNAN; +} + +int ld_sprint(char* str, int fmt, longdouble x) +{ + // fmt is 'a','A','f' or 'g' + if(fmt != 'a' && fmt != 'A') + { + char format[] = { '%', fmt, 0 }; + return sprintf(str, format, ld_read(&x)); + } + + unsigned short exp = x.exponent; + unsigned long long mantissa = x.mantissa; + + switch(ld_type(x)) + { + case LD_TYPE_ZERO: + return sprintf(str, "0x0.0L"); + case LD_TYPE_QNAN: + case LD_TYPE_SNAN: + return sprintf(str, "NAN"); + case LD_TYPE_INFINITE: + return sprintf(str, x.sign ? "-INF" : "INF"); + } + + int len = 0; + if(x.sign) + str[len++] = '-'; + len += sprintf(str + len, mantissa & (1LL << 63) ? "0x1." : "0x0."); + mantissa = mantissa << 1; + while(mantissa) + { + int dig = (mantissa >> 60) & 0xf; + dig += dig < 10 ? '0' : fmt - 10; + str[len++] = dig; + mantissa = mantissa << 4; + } + str[len++] = 'p'; + if(exp < 0x3fff) + { + str[len++] = '-'; + exp = 0x3fff - exp; + } + else + { + str[len++] = '+'; + exp = exp - 0x3fff; + } + int exppos = len; + for(int i = 12; i >= 0; i -= 4) + { + int dig = (exp >> i) & 0xf; + if(dig != 0 || len > exppos || i == 0) + str[len++] = dig + (dig < 10 ? '0' : fmt - 10); + } + str[len] = 0; + return len; +} + +////////////////////////////////////////////////////////////// + +#if UNITTEST +static bool unittest() +{ + char buffer[32]; + ld_sprint(buffer, 'a', ld_pi); + assert(strcmp(buffer, "0x1.921fb54442d1846ap+1") == 0); + + longdouble ldb = ldouble(0.4); + long long b = ldb; + assert(b == 0); + + b = ldouble(0.9); + assert(b == 0); + + long long x = 0x12345678abcdef78LL; + longdouble ldx = ldouble(x); + assert(ldx > 0); + long long y = ldx; + assert(x == y); + + x = -0x12345678abcdef78LL; + ldx = ldouble(x); + assert(ldx < 0); + y = ldx; + assert(x == y); + + unsigned long long u = 0x12345678abcdef78LL; + longdouble ldu = ldouble(u); + assert(ldu > 0); + unsigned long long v = ldu; + assert(u == v); + + u = 0xf234567812345678ULL; + ldu = ldouble(u); + assert(ldu > 0); + v = ldu; + assert(u == v); + + u = 0xf2345678; + ldu = ldouble(u); + ldu = ldu * ldu; + ldu = sqrt(ldu); + v = ldu; + assert(u == v); + + u = 0x123456789A; + ldu = ldouble(u); + ldu = ldu * (1LL << 23); + v = ldu; + u = u * (1LL << 23); + assert(u == v); + + return true; +} + +static bool runUnittest = unittest(); + +#endif // UNITTEST + +#endif // _MSC_VER + diff --git a/dmd/root/longdouble.h b/dmd/root/longdouble.h new file mode 100644 index 00000000..d25223a7 --- /dev/null +++ b/dmd/root/longdouble.h @@ -0,0 +1,254 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Rainer Schuetze +// 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. + +// 80 bit floating point value implementation for Microsoft compiler + +#ifndef __LONG_DOUBLE_H__ +#define __LONG_DOUBLE_H__ + +#if IN_GCC +#include "d-gcc-real.h" +typedef real_t longdouble; + +template longdouble ldouble(T x) { return (longdouble) x; } +inline int ld_sprint(char* str, int fmt, longdouble x) +{ + if(fmt == 'a' || fmt == 'A') + return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max + return x.format(buffer, 46); +} + +#elif !_MSC_VER // has native 10 byte doubles +#include +typedef long double longdouble; +typedef volatile long double volatile_longdouble; + +// also used from within C code, so use a #define rather than a template +// template longdouble ldouble(T x) { return (longdouble) x; } +#define ldouble(x) ((longdouble)(x)) + +inline int ld_sprint(char* str, int fmt, longdouble x) +{ + char sfmt[4] = "%Lg"; + sfmt[2] = fmt; + return sprintf(str, sfmt, x); +} + +#else + +#include +#include + +struct longdouble; + +extern "C" +{ + // implemented in ldfpu.asm for _WIN64 + double ld_read(const longdouble* ld); + long long ld_readll(const longdouble* ld); + unsigned long long ld_readull(const longdouble* ld); + void ld_set(longdouble* ld, double d); + void ld_setll(longdouble* ld, long long d); + void ld_setull(longdouble* ld, unsigned long long d); +} + +struct longdouble +{ + unsigned long long mantissa; + unsigned short exponent:15; // bias 0x3fff + unsigned short sign:1; + unsigned short fill:16; // for 12 byte alignment + + // no constructor to be able to use this class in a union + // use ldouble() to explicitely create a longdouble value + + template longdouble& operator=(T x) { set(x); return *this; } + + void set(longdouble ld) { mantissa = ld.mantissa; exponent = ld.exponent; sign = ld.sign; } + + // we need to list all basic types to avoid ambiguities + void set(float d) { ld_set(this, d); } + void set(double d) { ld_set(this, d); } + void set(long double d) { ld_set(this, d); } + + void set(signed char d) { ld_set(this, d); } + void set(short d) { ld_set(this, d); } + void set(int d) { ld_set(this, d); } + void set(long d) { ld_set(this, d); } + void set(long long d) { ld_setll(this, d); } + + void set(unsigned char d) { ld_set(this, d); } + void set(unsigned short d) { ld_set(this, d); } + void set(unsigned int d) { ld_set(this, d); } + void set(unsigned long d) { ld_set(this, d); } + void set(unsigned long long d) { ld_setull(this, d); } + void set(bool d) { ld_set(this, d); } + + operator float () { return ld_read(this); } + operator double () { return ld_read(this); } + + operator signed char () { return ld_read(this); } + operator short () { return ld_read(this); } + operator int () { return ld_read(this); } + operator long () { return ld_read(this); } + operator long long () { return ld_readll(this); } + + operator unsigned char () { return ld_read(this); } + operator unsigned short () { return ld_read(this); } + operator unsigned int () { return ld_read(this); } + operator unsigned long () { return ld_read(this); } + operator unsigned long long() { return ld_readull(this); } + operator bool () { return mantissa != 0 || exponent != 0; } // correct? +}; + +// some optimizations are avoided by adding volatile to the longdouble +// type, but this introduces bad ambiguities when using the class implementation above +// as we are going through asm these optimizations won't kick in anyway, so "volatile" +// is not required. +typedef longdouble volatile_longdouble; + +inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0) +{ + longdouble d; + d.mantissa = mantissa; + d.exponent = exp; + d.sign = sign; + return d; +} +template inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; } +//template inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; } + +longdouble operator+(longdouble ld1, longdouble ld2); +longdouble operator-(longdouble ld1, longdouble ld2); +longdouble operator*(longdouble ld1, longdouble ld2); +longdouble operator/(longdouble ld1, longdouble ld2); + +bool operator< (longdouble ld1, longdouble ld2); +bool operator<=(longdouble ld1, longdouble ld2); +bool operator> (longdouble ld1, longdouble ld2); +bool operator>=(longdouble ld1, longdouble ld2); +bool operator==(longdouble ld1, longdouble ld2); +bool operator!=(longdouble ld1, longdouble ld2); + +inline longdouble operator-(longdouble ld1) { ld1.sign ^= 1; return ld1; } +inline longdouble operator+(longdouble ld1) { return ld1; } + +template inline longdouble operator+(longdouble ld, T x) { return ld + ldouble(x); } +template inline longdouble operator-(longdouble ld, T x) { return ld - ldouble(x); } +template inline longdouble operator*(longdouble ld, T x) { return ld * ldouble(x); } +template inline longdouble operator/(longdouble ld, T x) { return ld / ldouble(x); } + +template inline longdouble operator+(T x, longdouble ld) { return ldouble(x) + ld; } +template inline longdouble operator-(T x, longdouble ld) { return ldouble(x) - ld; } +template inline longdouble operator*(T x, longdouble ld) { return ldouble(x) * ld; } +template inline longdouble operator/(T x, longdouble ld) { return ldouble(x) / ld; } + +template inline longdouble& operator+=(longdouble& ld, T x) { return ld = ld + x; } +template inline longdouble& operator-=(longdouble& ld, T x) { return ld = ld - x; } +template inline longdouble& operator*=(longdouble& ld, T x) { return ld = ld * x; } +template inline longdouble& operator/=(longdouble& ld, T x) { return ld = ld / x; } + +template inline bool operator< (longdouble ld, T x) { return ld < ldouble(x); } +template inline bool operator<=(longdouble ld, T x) { return ld <= ldouble(x); } +template inline bool operator> (longdouble ld, T x) { return ld > ldouble(x); } +template inline bool operator>=(longdouble ld, T x) { return ld >= ldouble(x); } +template inline bool operator==(longdouble ld, T x) { return ld == ldouble(x); } +template inline bool operator!=(longdouble ld, T x) { return ld != ldouble(x); } + +template inline bool operator< (T x, longdouble ld) { return ldouble(x) < ld; } +template inline bool operator<=(T x, longdouble ld) { return ldouble(x) <= ld; } +template inline bool operator> (T x, longdouble ld) { return ldouble(x) > ld; } +template inline bool operator>=(T x, longdouble ld) { return ldouble(x) >= ld; } +template inline bool operator==(T x, longdouble ld) { return ldouble(x) == ld; } +template inline bool operator!=(T x, longdouble ld) { return ldouble(x) != ld; } + +int _isnan(longdouble ld); + +longdouble fabsl(longdouble ld); +longdouble sqrtl(longdouble ld); +longdouble sinl (longdouble ld); +longdouble cosl (longdouble ld); +longdouble tanl (longdouble ld); + +longdouble fmodl(longdouble x, longdouble y); +longdouble ldexpl(longdouble ldval, int exp); // see strtold + +inline longdouble fabs (longdouble ld) { return fabsl(ld); } +inline longdouble sqrt (longdouble ld) { return sqrtl(ld); } + +#undef LDBL_DIG +#undef LDBL_MAX +#undef LDBL_MIN +#undef LDBL_EPSILON +#undef LDBL_MANT_DIG +#undef LDBL_MAX_EXP +#undef LDBL_MIN_EXP +#undef LDBL_MAX_10_EXP +#undef LDBL_MIN_10_EXP + +#define LDBL_DIG 18 +#define LDBL_MAX ldouble(0xffffffffffffffffULL, 0x7ffe) +#define LDBL_MIN ldouble(0x8000000000000000ULL, 1) +#define LDBL_EPSILON ldouble(0x8000000000000000ULL, 0x3fff - 63) // allow denormal? +#define LDBL_MANT_DIG 64 +#define LDBL_MAX_EXP 16384 +#define LDBL_MIN_EXP (-16381) +#define LDBL_MAX_10_EXP 4932 +#define LDBL_MIN_10_EXP (-4932) + +extern longdouble ld_zero; +extern longdouble ld_one; +extern longdouble ld_pi; +extern longdouble ld_log2t; +extern longdouble ld_log2e; +extern longdouble ld_log2; +extern longdouble ld_ln2; + +extern longdouble ld_inf; +extern longdouble ld_qnan; +extern longdouble ld_snan; + +/////////////////////////////////////////////////////////////////////// +// CLASS numeric_limits +template<> class _CRTIMP2_PURE std::numeric_limits +: public _Num_float_base +{ // limits for type long double +public: + typedef longdouble _Ty; + + static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; } + static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; } + static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; } + static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); } + static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); } + static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; } + static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; } + static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; } + + _STCONS(int, digits, LDBL_MANT_DIG); + _STCONS(int, digits10, LDBL_DIG); + _STCONS(int, max_exponent, (int)LDBL_MAX_EXP); + _STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP); + _STCONS(int, min_exponent, (int)LDBL_MIN_EXP); + _STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP); +}; + +//_STCONSDEF(numeric_limits, int, digits) +//_STCONSDEF(numeric_limits, int, digits10) +//_STCONSDEF(numeric_limits, int, max_exponent) +//_STCONSDEF(numeric_limits, int, max_exponent10) +//_STCONSDEF(numeric_limits, int, min_exponent) +//_STCONSDEF(numeric_limits, int, min_exponent10) + +int ld_sprint(char* str, int fmt, longdouble x); + +#endif // !_MSC_VER + +#endif // __LONG_DOUBLE_H__ diff --git a/dmd/root/lstring.c b/dmd/root/lstring.c index c354d4b3..a4e41ed5 100644 --- a/dmd/root/lstring.c +++ b/dmd/root/lstring.c @@ -1,63 +1,63 @@ -// lstring.c - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#include - -#include "dchar.h" -#include "rmem.h" -#include "lstring.h" - -#ifdef _MSC_VER // prevent compiler internal crash -Lstring Lstring::zero; -#else -Lstring Lstring::zero = LSTRING_EMPTY(); -#endif - -Lstring *Lstring::ctor(const dchar *p, unsigned length) -{ - Lstring *s; - - s = alloc(length); - memcpy(s->string, p, length * sizeof(dchar)); - return s; -} - -Lstring *Lstring::alloc(unsigned length) -{ - Lstring *s; - - s = (Lstring *)mem.malloc(size(length)); - s->length = length; - s->string[length] = 0; - return s; -} - -Lstring *Lstring::append(const Lstring *s) -{ - Lstring *t; - - if (!s->length) - return this; - t = alloc(length + s->length); - memcpy(t->string, string, length * sizeof(dchar)); - memcpy(t->string + length, s->string, s->length * sizeof(dchar)); - return t; -} - -Lstring *Lstring::substring(int start, int end) -{ - Lstring *t; - - if (start == end) - return &zero; - t = alloc(end - start); - memcpy(t->string, string + start, (end - start) * sizeof(dchar)); - return t; -} +// lstring.c + +// Copyright (c) 1999-2002 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#include + +#include "dchar.h" +#include "rmem.h" +#include "lstring.h" + +#ifdef _MSC_VER // prevent compiler internal crash +Lstring Lstring::zero; +#else +Lstring Lstring::zero = LSTRING_EMPTY(); +#endif + +Lstring *Lstring::ctor(const dchar *p, unsigned length) +{ + Lstring *s; + + s = alloc(length); + memcpy(s->string, p, length * sizeof(dchar)); + return s; +} + +Lstring *Lstring::alloc(unsigned length) +{ + Lstring *s; + + s = (Lstring *)mem.malloc(size(length)); + s->length = length; + s->string[length] = 0; + return s; +} + +Lstring *Lstring::append(const Lstring *s) +{ + Lstring *t; + + if (!s->length) + return this; + t = alloc(length + s->length); + memcpy(t->string, string, length * sizeof(dchar)); + memcpy(t->string + length, s->string, s->length * sizeof(dchar)); + return t; +} + +Lstring *Lstring::substring(int start, int end) +{ + Lstring *t; + + if (start == end) + return &zero; + t = alloc(end - start); + memcpy(t->string, string + start, (end - start) * sizeof(dchar)); + return t; +} diff --git a/dmd/root/lstring.h b/dmd/root/lstring.h index fed39199..0c545790 100644 --- a/dmd/root/lstring.h +++ b/dmd/root/lstring.h @@ -1,72 +1,74 @@ - -// lstring.h -// length-prefixed strings - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef LSTRING_H -#define LSTRING_H 1 - -#include "dchar.h" - -struct Lstring -{ - unsigned length; - - // Disable warning about nonstandard extension - #pragma warning (disable : 4200) - dchar string[]; - - static Lstring zero; // 0 length string - - // No constructors because we want to be able to statically - // initialize Lstring's, and Lstrings are of variable size. - - #if M_UNICODE - #define LSTRING(p,length) { length, L##p } - #else - #define LSTRING(p,length) { length, p } - #endif - -#if __GNUC__ - #define LSTRING_EMPTY() { 0 } -#else - #define LSTRING_EMPTY() LSTRING("", 0) -#endif - - static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); } - static Lstring *ctor(const dchar *p, unsigned length); - static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); } - static Lstring *alloc(unsigned length); - Lstring *clone(); - - unsigned len() { return length; } - - dchar *toDchars() { return string; } - - hash_t hash() { return Dchar::calcHash(string, length); } - hash_t ihash() { return Dchar::icalcHash(string, length); } - - static int cmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length); - } - - static int icmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length); - } - - Lstring *append(const Lstring *s); - Lstring *substring(int start, int end); -}; - -#endif + +// lstring.h +// length-prefixed strings + +// Copyright (c) 1999-2002 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#ifndef LSTRING_H +#define LSTRING_H 1 + +#include "dchar.h" + +struct Lstring +{ + unsigned length; + +#ifndef IN_GCC + // Disable warning about nonstandard extension + #pragma warning (disable : 4200) +#endif + dchar string[]; + + static Lstring zero; // 0 length string + + // No constructors because we want to be able to statically + // initialize Lstring's, and Lstrings are of variable size. + + #if M_UNICODE + #define LSTRING(p,length) { length, L##p } + #else + #define LSTRING(p,length) { length, p } + #endif + +#if __GNUC__ + #define LSTRING_EMPTY() { 0 } +#else + #define LSTRING_EMPTY() LSTRING("", 0) +#endif + + static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); } + static Lstring *ctor(const dchar *p, unsigned length); + static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); } + static Lstring *alloc(unsigned length); + Lstring *clone(); + + unsigned len() { return length; } + + dchar *toDchars() { return string; } + + hash_t hash() { return Dchar::calcHash(string, length); } + hash_t ihash() { return Dchar::icalcHash(string, length); } + + static int cmp(const Lstring *s1, const Lstring *s2) + { + int c = s2->length - s1->length; + return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length); + } + + static int icmp(const Lstring *s1, const Lstring *s2) + { + int c = s2->length - s1->length; + return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length); + } + + Lstring *append(const Lstring *s); + Lstring *substring(int start, int end); +}; + +#endif diff --git a/dmd/root/man.c b/dmd/root/man.c index 8b2787c4..3770aa96 100644 --- a/dmd/root/man.c +++ b/dmd/root/man.c @@ -1,100 +1,100 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 2008-2009 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - -#include -#include -#include -#include - -#if _WIN32 - -#include - -#pragma comment(lib,"shell32.lib") - -void browse(const char *url) -{ - ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); -} - -#endif - -#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 - -#include -#include -#include - -void browse(const char *url) -{ - pid_t childpid; - const char *args[3]; - - const char *browser = getenv("BROWSER"); - if (browser) - browser = strdup(browser); - else - browser = "x-www-browser"; - - args[0] = browser; - args[1] = url; - args[2] = NULL; - - childpid = fork(); - if (childpid == 0) - { - execvp(args[0], (char**)args); - perror(args[0]); // failed to execute - return; - } -} - -#endif - -#if __APPLE__ - -#include -#include -#include - -void browse(const char *url) -{ - pid_t childpid; - const char *args[5]; - - char *browser = getenv("BROWSER"); - if (browser) - { browser = strdup(browser); - args[0] = browser; - args[1] = url; - args[2] = NULL; - } - else - { - //browser = "/Applications/Safari.app/Contents/MacOS/Safari"; - args[0] = "open"; - args[1] = "-a"; - args[2] = "/Applications/Safari.app"; - args[3] = url; - args[4] = NULL; - } - - childpid = fork(); - if (childpid == 0) - { - execvp(args[0], (char**)args); - perror(args[0]); // failed to execute - return; - } -} - -#endif - - + +// Compiler implementation of the D programming language +// Copyright (c) 2008-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + +#include +#include +#include +#include + +#if _WIN32 + +#include + +#pragma comment(lib,"shell32.lib") + +void browse(const char *url) +{ + ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); +} + +#endif + +#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 + +#include +#include +#include + +void browse(const char *url) +{ + pid_t childpid; + const char *args[3]; + + const char *browser = getenv("BROWSER"); + if (browser) + browser = strdup(browser); + else + browser = "x-www-browser"; + + args[0] = browser; + args[1] = url; + args[2] = NULL; + + childpid = fork(); + if (childpid == 0) + { + execvp(args[0], (char**)args); + perror(args[0]); // failed to execute + return; + } +} + +#endif + +#if __APPLE__ + +#include +#include +#include + +void browse(const char *url) +{ + pid_t childpid; + const char *args[5]; + + char *browser = getenv("BROWSER"); + if (browser) + { browser = strdup(browser); + args[0] = browser; + args[1] = url; + args[2] = NULL; + } + else + { + //browser = "/Applications/Safari.app/Contents/MacOS/Safari"; + args[0] = "open"; + args[1] = "-a"; + args[2] = "/Applications/Safari.app"; + args[3] = url; + args[4] = NULL; + } + + childpid = fork(); + if (childpid == 0) + { + execvp(args[0], (char**)args); + perror(args[0]); // failed to execute + return; + } +} + +#endif + + diff --git a/dmd/root/port.c b/dmd/root/port.c index bc82f7fc..f498885b 100644 --- a/dmd/root/port.c +++ b/dmd/root/port.c @@ -1,796 +1,655 @@ - -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com - -#include "port.h" -#if __DMC__ -#include -#include -#include -#include -#include -#include - -double Port::nan = NAN; -double Port::infinity = INFINITY; -double Port::dbl_max = DBL_MAX; -double Port::dbl_min = DBL_MIN; -long double Port::ldbl_max = LDBL_MAX; - -int Port::isNan(double r) -{ - return ::isnan(r); -} - -int Port::isNan(long double r) -{ - return ::isnan(r); -} - -int Port::isSignallingNan(double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 51 of 0..63 for 64 bit doubles. - */ - return isNan(r) && !((((unsigned char*)&r)[6]) & 8); -} - -int Port::isSignallingNan(long double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 62 of 0..79 for 80 bit reals. - */ - return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); -} - -int Port::isFinite(double r) -{ - return ::isfinite(r); -} - -int Port::isInfinity(double r) -{ - return (::fpclassify(r) == FP_INFINITE); -} - -int Port::Signbit(double r) -{ - return ::signbit(r); -} - -double Port::floor(double d) -{ - return ::floor(d); -} - -double Port::pow(double x, double y) -{ - return ::pow(x, y); -} - -long double Port::fmodl(long double x, long double y) -{ - return ::fmodl(x, y); -} - -unsigned long long Port::strtoull(const char *p, char **pend, int base) -{ - return ::strtoull(p, pend, base); -} - -char *Port::ull_to_string(char *buffer, ulonglong ull) -{ - sprintf(buffer, "%llu", ull); - return buffer; -} - -wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) -{ - swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); - return buffer; -} - -double Port::ull_to_double(ulonglong ull) -{ - return (double) ull; -} - -const char *Port::list_separator() -{ - // LOCALE_SLIST for Windows - return ","; -} - -const wchar_t *Port::wlist_separator() -{ - // LOCALE_SLIST for Windows - return L","; -} - -char *Port::strupr(char *s) -{ - return ::strupr(s); -} - -#endif - -#if _MSC_VER - -// Disable useless warnings about unreferenced functions -#pragma warning (disable : 4514) - -#include -#include -#include -#include -#include -#include -#include -#include // for std::numeric_limits - -static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF }; -//static unsigned long nanarray[2] = {0,0x7FF80000 }; -double Port::nan = (*(double *)nanarray); - -//static unsigned long infinityarray[2] = {0,0x7FF00000 }; -static double zero = 0; -double Port::infinity = 1 / zero; - -double Port::dbl_max = DBL_MAX; -double Port::dbl_min = DBL_MIN; -long double Port::ldbl_max = LDBL_MAX; - -struct PortInitializer -{ - PortInitializer(); -}; - -static PortInitializer portinitializer; - -PortInitializer::PortInitializer() -{ - Port::infinity = std::numeric_limits::infinity(); -} - -int Port::isNan(double r) -{ - return ::_isnan(r); -} - -int Port::isNan(long double r) -{ - return ::_isnan(r); -} - -int Port::isSignallingNan(double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 51 of 0..63 for 64 bit doubles. - */ - return isNan(r) && !((((unsigned char*)&r)[6]) & 8); -} - -int Port::isSignallingNan(long double r) -{ - /* MSVC doesn't have 80 bit long doubles - */ - return isSignallingNan((double) r); -} - -int Port::isFinite(double r) -{ - return ::_finite(r); -} - -int Port::isInfinity(double r) -{ - return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF)); -} - -int Port::Signbit(double r) -{ - return (long)(((long *)&(r))[1] & 0x80000000); -} - -double Port::floor(double d) -{ - return ::floor(d); -} - -double Port::pow(double x, double y) -{ - if (y == 0) - return 1; // even if x is NAN - return ::pow(x, y); -} - -long double Port::fmodl(long double x, long double y) -{ - return ::fmodl(x, y); -} - -unsigned _int64 Port::strtoull(const char *p, char **pend, int base) -{ - unsigned _int64 number = 0; - int c; - int error; -#ifndef ULLONG_MAX - #define ULLONG_MAX ((unsigned _int64)~0I64) -#endif - - while (isspace((unsigned char)*p)) /* skip leading white space */ - p++; - if (*p == '+') - p++; - switch (base) - { case 0: - base = 10; /* assume decimal base */ - if (*p == '0') - { base = 8; /* could be octal */ - p++; - switch (*p) - { case 'x': - case 'X': - base = 16; /* hex */ - p++; - break; -#if BINARY - case 'b': - case 'B': - base = 2; /* binary */ - p++; - break; -#endif - } - } - break; - case 16: /* skip over '0x' and '0X' */ - if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) - p += 2; - break; -#if BINARY - case 2: /* skip over '0b' and '0B' */ - if (*p == '0' && (p[1] == 'b' || p[1] == 'B')) - p += 2; - break; -#endif - } - error = 0; - for (;;) - { c = *p; - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c = (c & ~0x20) - ('A' - 10); - else /* unrecognized character */ - break; - if (c >= base) /* not in number base */ - break; - if ((ULLONG_MAX - c) / base < number) - error = 1; - number = number * base + c; - p++; - } - if (pend) - *pend = (char *)p; - if (error) - { number = ULLONG_MAX; - errno = ERANGE; - } - return number; -} - -char *Port::ull_to_string(char *buffer, ulonglong ull) -{ - _ui64toa(ull, buffer, 10); - return buffer; -} - -wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) -{ - _ui64tow(ull, buffer, 10); - return buffer; -} - -double Port::ull_to_double(ulonglong ull) -{ double d; - - if ((__int64) ull < 0) - { - // MSVC doesn't implement the conversion - d = (double) (__int64)(ull - 0x8000000000000000i64); - d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0; - } - else - d = (double)(__int64)ull; - return d; -} - -const char *Port::list_separator() -{ - // LOCALE_SLIST for Windows - return ","; -} - -const wchar_t *Port::wlist_separator() -{ - // LOCALE_SLIST for Windows - return L","; -} - -char *Port::strupr(char *s) -{ - return ::strupr(s); -} - -#endif - -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __MINGW32__ || __HAIKU__ - -#include -#if linux -#include -#include -#endif -#if __FreeBSD__ && __i386__ -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -static double zero = 0; -double Port::nan = copysign(NAN, 1.0); -double Port::infinity = 1 / zero; -double Port::dbl_max = 1.7976931348623157e308; -double Port::dbl_min = 5e-324; -long double Port::ldbl_max = LDBL_MAX; - -struct PortInitializer -{ - PortInitializer(); -}; - -static PortInitializer portinitializer; - -PortInitializer::PortInitializer() -{ - assert(!signbit(Port::nan)); - -#if __FreeBSD__ && __i386__ - // LDBL_MAX comes out as infinity. Fix. - static unsigned char x[sizeof(long double)] = - { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F }; - Port::ldbl_max = *(long double *)&x[0]; - // FreeBSD defaults to double precision. Switch to extended precision. - fpsetprec(FP_PE); -#endif -} - -int Port::isNan(double r) -{ -#if __APPLE__ - return __inline_isnan(r); -#elif __OpenBSD__ || __MINGW32__ || __HAIKU__ - return isnan(r); -#else - #undef isnan - return ::isnan(r); -#endif -} - -int Port::isNan(long double r) -{ -#if __APPLE__ - return __inline_isnan(r); -#elif __OpenBSD__ || __MINGW32__ || __HAIKU__ - return isnan(r); -#else - #undef isnan - return ::isnan(r); -#endif -} - -int Port::isSignallingNan(double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 51 of 0..63 for 64 bit doubles. - */ - return isNan(r) && !((((unsigned char*)&r)[6]) & 8); -} - -int Port::isSignallingNan(long double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 62 of 0..79 for 80 bit reals. - */ - return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); -} - -#undef isfinite -int Port::isFinite(double r) -{ - return ::finite(r); -} - -int Port::isInfinity(double r) -{ -#if __APPLE__ - return fpclassify(r) == FP_INFINITE; -#elif __OpenBSD__ || __MINGW32__ || __HAIKU__ - return isinf(r); -#else - #undef isinf - return ::isinf(r); -#endif -} - -#undef signbit -int Port::Signbit(double r) -{ - union { double d; long long ll; } u; - u.d = r; - return u.ll < 0; -} - -double Port::floor(double d) -{ - return ::floor(d); -} - -double Port::pow(double x, double y) -{ - return ::pow(x, y); -} - -long double Port::fmodl(long double x, long double y) -{ -#if __FreeBSD__ || __OpenBSD__ - return ::fmod(x, y); // hack for now, fix later -#else - return ::fmodl(x, y); -#endif -} - -unsigned long long Port::strtoull(const char *p, char **pend, int base) -{ - return ::strtoull(p, pend, base); -} - -char *Port::ull_to_string(char *buffer, ulonglong ull) -{ - sprintf(buffer, "%llu", ull); - return buffer; -} - -wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) -{ -#if __OpenBSD__ - assert(0); -#else -#ifndef __MINGW32__ - swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); -#else - _snwprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); -#endif -#endif - return buffer; -} - -double Port::ull_to_double(ulonglong ull) -{ - return (double) ull; -} - -const char *Port::list_separator() -{ - return ","; -} - -const wchar_t *Port::wlist_separator() -{ - return L","; -} - -char *Port::strupr(char *s) -{ - char *t = s; - - while (*s) - { - *s = toupper(*s); - s++; - } - - return t; -} - -#endif - -#if __sun&&__SVR4 - -#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static double zero = 0; -double Port::nan = NAN; -double Port::infinity = 1 / zero; -double Port::dbl_max = 1.7976931348623157e308; -double Port::dbl_min = 5e-324; -long double Port::ldbl_max = LDBL_MAX; - -struct PortInitializer -{ - PortInitializer(); -}; - -static PortInitializer portinitializer; - -PortInitializer::PortInitializer() -{ - // gcc nan's have the sign bit set by default, so turn it off - // Need the volatile to prevent gcc from doing incorrect - // constant folding. - volatile long double foo; - foo = NAN; - if (signbit(foo)) // signbit sometimes, not always, set - foo = -foo; // turn off sign bit - Port::nan = foo; -} - -int Port::isNan(double r) -{ - return isnan(r); -} - -int Port::isNan(long double r) -{ - return isnan(r); -} - -int Port::isSignallingNan(double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 51 of 0..63 for 64 bit doubles. - */ - return isNan(r) && !((((unsigned char*)&r)[6]) & 8); -} - -int Port::isSignallingNan(long double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 62 of 0..79 for 80 bit reals. - */ - return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); -} - -#undef isfinite -int Port::isFinite(double r) -{ - return finite(r); -} - -int Port::isInfinity(double r) -{ - return isinf(r); -} - -#undef signbit -int Port::Signbit(double r) -{ - return (long)(((long *)&r)[1] & 0x80000000); -} - -double Port::floor(double d) -{ - return ::floor(d); -} - -double Port::pow(double x, double y) -{ - return ::pow(x, y); -} - -unsigned long long Port::strtoull(const char *p, char **pend, int base) -{ - return ::strtoull(p, pend, base); -} - -char *Port::ull_to_string(char *buffer, ulonglong ull) -{ - sprintf(buffer, "%llu", ull); - return buffer; -} - -wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) -{ - swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); - return buffer; -} - -double Port::ull_to_double(ulonglong ull) -{ - return (double) ull; -} - -const char *Port::list_separator() -{ - return ","; -} - -const wchar_t *Port::wlist_separator() -{ - return L","; -} - -char *Port::strupr(char *s) -{ - char *t = s; - - while (*s) - { - *s = toupper(*s); - s++; - } - - return t; -} - -#endif - -#if IN_GCC - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static double zero = 0; -double Port::nan = NAN; -double Port::infinity = 1 / zero; -double Port::dbl_max = 1.7976931348623157e308; -double Port::dbl_min = 5e-324; -long double Port::ldbl_max = LDBL_MAX; - -#include "d-gcc-real.h" -extern "C" bool real_isnan (const real_t *); - -struct PortInitializer -{ - PortInitializer(); -}; - -static PortInitializer portinitializer; - -PortInitializer::PortInitializer() -{ - Port::infinity = real_t::getinfinity(); - Port::nan = real_t::getnan(real_t::LongDouble); -} - -#undef isnan -int Port::isNan(double r) -{ -#if __APPLE__ - return __inline_isnan(r); -#else - return ::isnan(r); -#endif -} - -int Port::isNan(long double r) -{ - return real_isnan(&r); -} - -int Port::isSignallingNan(double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 51 of 0..63 for 64 bit doubles. - */ - return isNan(r) && !((((unsigned char*)&r)[6]) & 8); -} - -int Port::isSignallingNan(long double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 62 of 0..79 for 80 bit reals. - */ - return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); -} - -#undef isfinite -int Port::isFinite(double r) -{ - return ::finite(r); -} - -#undef isinf -int Port::isInfinity(double r) -{ - return ::isinf(r); -} - -#undef signbit -int Port::Signbit(double r) -{ - return (long)(((long *)&r)[1] & 0x80000000); -} - -double Port::floor(double d) -{ - return ::floor(d); -} - -double Port::pow(double x, double y) -{ - return ::pow(x, y); -} - -unsigned long long Port::strtoull(const char *p, char **pend, int base) -{ - return ::strtoull(p, pend, base); -} - -char *Port::ull_to_string(char *buffer, ulonglong ull) -{ - sprintf(buffer, "%llu", ull); - return buffer; -} - -wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) -{ - swprintf(buffer, L"%llu", ull); - return buffer; -} - -double Port::ull_to_double(ulonglong ull) -{ - return (double) ull; -} - -const char *Port::list_separator() -{ - return ","; -} - -const wchar_t *Port::wlist_separator() -{ - return L","; -} - -char *Port::strupr(char *s) -{ - char *t = s; - - while (*s) - { - *s = toupper(*s); - s++; - } - - return t; -} - -#endif - + +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com + +#include "port.h" +#if __DMC__ +#include +#include +#include +#include +#include +#include + +double Port::nan = NAN; +double Port::infinity = INFINITY; +double Port::dbl_max = DBL_MAX; +double Port::dbl_min = DBL_MIN; +longdouble Port::ldbl_max = LDBL_MAX; + +int Port::isNan(double r) +{ + return ::isnan(r); +} + +int Port::isNan(longdouble r) +{ + return ::isnan(r); +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(longdouble r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +int Port::isFinite(double r) +{ + return ::isfinite(r); +} + +int Port::isInfinity(double r) +{ + return (::fpclassify(r) == FP_INFINITE); +} + +int Port::Signbit(double r) +{ + return ::signbit(r); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +longdouble Port::fmodl(longdouble x, longdouble y) +{ + return ::fmodl(x, y); +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + // LOCALE_SLIST for Windows + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + // LOCALE_SLIST for Windows + return L","; +} + +char *Port::strupr(char *s) +{ + return ::strupr(s); +} + +#endif + +#if _MSC_VER + +// Disable useless warnings about unreferenced functions +#pragma warning (disable : 4514) + +#include +#include +#include +#include +#include +#include +#include +#include // for std::numeric_limits + +static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF }; +//static unsigned long nanarray[2] = {0,0x7FF80000 }; +double Port::nan = (*(double *)nanarray); + +//static unsigned long infinityarray[2] = {0,0x7FF00000 }; +static double zero = 0; +double Port::infinity = 1 / zero; + +double Port::dbl_max = DBL_MAX; +double Port::dbl_min = DBL_MIN; +longdouble Port::ldbl_max = LDBL_MAX; + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + Port::infinity = std::numeric_limits::infinity(); +} + +int Port::isNan(double r) +{ + return ::_isnan(r); +} + +int Port::isNan(longdouble r) +{ + return ::_isnan(r); +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(longdouble r) +{ + /* MSVC doesn't have 80 bit long doubles + */ + return isSignallingNan((double) r); +} + +int Port::isFinite(double r) +{ + return ::_finite(r); +} + +int Port::isInfinity(double r) +{ + return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF)); +} + +int Port::Signbit(double r) +{ + return (long)(((long *)&(r))[1] & 0x80000000); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + if (y == 0) + return 1; // even if x is NAN + return ::pow(x, y); +} + +longdouble Port::fmodl(longdouble x, longdouble y) +{ + return ::fmodl(x, y); +} + +unsigned _int64 Port::strtoull(const char *p, char **pend, int base) +{ + unsigned _int64 number = 0; + int c; + int error; +#ifndef ULLONG_MAX + #define ULLONG_MAX ((unsigned _int64)~0I64) +#endif + + while (isspace((unsigned char)*p)) /* skip leading white space */ + p++; + if (*p == '+') + p++; + switch (base) + { case 0: + base = 10; /* assume decimal base */ + if (*p == '0') + { base = 8; /* could be octal */ + p++; + switch (*p) + { case 'x': + case 'X': + base = 16; /* hex */ + p++; + break; +#if BINARY + case 'b': + case 'B': + base = 2; /* binary */ + p++; + break; +#endif + } + } + break; + case 16: /* skip over '0x' and '0X' */ + if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) + p += 2; + break; +#if BINARY + case 2: /* skip over '0b' and '0B' */ + if (*p == '0' && (p[1] == 'b' || p[1] == 'B')) + p += 2; + break; +#endif + } + error = 0; + for (;;) + { c = *p; + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c = (c & ~0x20) - ('A' - 10); + else /* unrecognized character */ + break; + if (c >= base) /* not in number base */ + break; + if ((ULLONG_MAX - c) / base < number) + error = 1; + number = number * base + c; + p++; + } + if (pend) + *pend = (char *)p; + if (error) + { number = ULLONG_MAX; + errno = ERANGE; + } + return number; +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + _ui64toa(ull, buffer, 10); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + _ui64tow(ull, buffer, 10); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ double d; + + if ((__int64) ull < 0) + { + // MSVC doesn't implement the conversion + d = (double) (__int64)(ull - 0x8000000000000000i64); + d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0; + } + else + d = (double)(__int64)ull; + return d; +} + +const char *Port::list_separator() +{ + // LOCALE_SLIST for Windows + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + // LOCALE_SLIST for Windows + return L","; +} + +char *Port::strupr(char *s) +{ + return ::strupr(s); +} + +#endif + +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __MINGW32__ || __HAIKU__ + +#include +#if linux +#include +#include +#endif +#if __FreeBSD__ && __i386__ +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +static double zero = 0; +double Port::nan = copysign(NAN, 1.0); +double Port::infinity = 1 / zero; +double Port::dbl_max = 1.7976931348623157e308; +double Port::dbl_min = 5e-324; +longdouble Port::ldbl_max = LDBL_MAX; + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + assert(!signbit(Port::nan)); + +#if __FreeBSD__ && __i386__ + // LDBL_MAX comes out as infinity. Fix. + static unsigned char x[sizeof(longdouble)] = + { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F }; + Port::ldbl_max = *(longdouble *)&x[0]; + // FreeBSD defaults to double precision. Switch to extended precision. + fpsetprec(FP_PE); +#endif +} + +int Port::isNan(double r) +{ +#if __APPLE__ + return __inline_isnan(r); +#elif __OpenBSD__ || __MINGW32__ || __HAIKU__ + return isnan(r); +#else + #undef isnan + return ::isnan(r); +#endif +} + +int Port::isNan(longdouble r) +{ +#if __APPLE__ + return __inline_isnan(r); +#elif __OpenBSD__ || __MINGW32__ || __HAIKU__ + return isnan(r); +#else + #undef isnan + return ::isnan(r); +#endif +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(longdouble r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +#undef isfinite +int Port::isFinite(double r) +{ + return ::finite(r); +} + +int Port::isInfinity(double r) +{ +#if __APPLE__ + return fpclassify(r) == FP_INFINITE; +#elif __OpenBSD__ || __MINGW32__ || __HAIKU__ + return isinf(r); +#else + #undef isinf + return ::isinf(r); +#endif +} + +#undef signbit +int Port::Signbit(double r) +{ + union { double d; long long ll; } u; + u.d = r; + return u.ll < 0; +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +longdouble Port::fmodl(longdouble x, longdouble y) +{ +#if __FreeBSD__ || __OpenBSD__ + return ::fmod(x, y); // hack for now, fix later +#else + return ::fmodl(x, y); +#endif +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ +#if __OpenBSD__ + assert(0); +#else +#ifndef __MINGW32__ + swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); +#else + _snwprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); +#endif +#endif + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + return L","; +} + +char *Port::strupr(char *s) +{ + char *t = s; + + while (*s) + { + *s = toupper(*s); + s++; + } + + return t; +} + +#endif + +#if __sun&&__SVR4 + +#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static double zero = 0; +double Port::nan = NAN; +double Port::infinity = 1 / zero; +double Port::dbl_max = 1.7976931348623157e308; +double Port::dbl_min = 5e-324; +longdouble Port::ldbl_max = LDBL_MAX; + +struct PortInitializer +{ + PortInitializer(); +}; + +static PortInitializer portinitializer; + +PortInitializer::PortInitializer() +{ + // gcc nan's have the sign bit set by default, so turn it off + // Need the volatile to prevent gcc from doing incorrect + // constant folding. + volatile longdouble foo; + foo = NAN; + if (signbit(foo)) // signbit sometimes, not always, set + foo = -foo; // turn off sign bit + Port::nan = foo; +} + +int Port::isNan(double r) +{ + return isnan(r); +} + +int Port::isNan(longdouble r) +{ + return isnan(r); +} + +int Port::isSignallingNan(double r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 51 of 0..63 for 64 bit doubles. + */ + return isNan(r) && !((((unsigned char*)&r)[6]) & 8); +} + +int Port::isSignallingNan(longdouble r) +{ + /* A signalling NaN is a NaN with 0 as the most significant bit of + * its significand, which is bit 62 of 0..79 for 80 bit reals. + */ + return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); +} + +#undef isfinite +int Port::isFinite(double r) +{ + return finite(r); +} + +int Port::isInfinity(double r) +{ + return isinf(r); +} + +#undef signbit +int Port::Signbit(double r) +{ + return (long)(((long *)&r)[1] & 0x80000000); +} + +double Port::floor(double d) +{ + return ::floor(d); +} + +double Port::pow(double x, double y) +{ + return ::pow(x, y); +} + +unsigned long long Port::strtoull(const char *p, char **pend, int base) +{ + return ::strtoull(p, pend, base); +} + +char *Port::ull_to_string(char *buffer, ulonglong ull) +{ + sprintf(buffer, "%llu", ull); + return buffer; +} + +wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) +{ + swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull); + return buffer; +} + +double Port::ull_to_double(ulonglong ull) +{ + return (double) ull; +} + +const char *Port::list_separator() +{ + return ","; +} + +const wchar_t *Port::wlist_separator() +{ + return L","; +} + +char *Port::strupr(char *s) +{ + char *t = s; + + while (*s) + { + *s = toupper(*s); + s++; + } + + return t; +} + +#endif + diff --git a/dmd/root/port.h b/dmd/root/port.h index 0c7e24a4..bcd3dafc 100644 --- a/dmd/root/port.h +++ b/dmd/root/port.h @@ -1,81 +1,83 @@ - -// Copyright (c) 1999-2009 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com - -#ifndef PORT_H -#define PORT_H - -// Portable wrapper around compiler/system specific things. -// The idea is to minimize #ifdef's in the app code. - -#ifndef TYPEDEFS -#define TYPEDEFS - -#include - -#if _MSC_VER -typedef __int64 longlong; -typedef unsigned __int64 ulonglong; - -// According to VC 8.0 docs, long double is the same as double -#define strtold strtod -#define strtof strtod - -#else -typedef long long longlong; -typedef unsigned long long ulonglong; -#endif - -#endif - -typedef double d_time; - -struct Port -{ - static double nan; - static double infinity; - static double dbl_max; - static double dbl_min; - static long double ldbl_max; - -#if __OpenBSD__ -#elif __GNUC__ && !defined __HAIKU__ - // These conflict with macros in math.h, should rename them - #undef isnan - #undef isfinite - #undef isinfinity - #undef signbit -#endif - static int isNan(double); - static int isNan(long double); - - static int isSignallingNan(double); - static int isSignallingNan(long double); - - static int isFinite(double); - static int isInfinity(double); - static int Signbit(double); - - static double floor(double); - static double pow(double x, double y); - - static long double fmodl(long double x, long double y); - - static ulonglong strtoull(const char *p, char **pend, int base); - - static char *ull_to_string(char *buffer, ulonglong ull); - static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull); - - // Convert ulonglong to double - static double ull_to_double(ulonglong ull); - - // Get locale-dependent list separator - static const char *list_separator(); - static const wchar_t *wlist_separator(); - - static char *strupr(char *); -}; - -#endif + +// Copyright (c) 1999-2009 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com + +#ifndef PORT_H +#define PORT_H + +// Portable wrapper around compiler/system specific things. +// The idea is to minimize #ifdef's in the app code. + +#include "longdouble.h" + +#ifndef TYPEDEFS +#define TYPEDEFS + +#include + +#if _MSC_VER +typedef __int64 longlong; +typedef unsigned __int64 ulonglong; + +// According to VC 8.0 docs, long double is the same as double +longdouble strtold(const char *p,char **endp); +#define strtof strtod + +#else +typedef long long longlong; +typedef unsigned long long ulonglong; +#endif + +#endif + +typedef double d_time; + +struct Port +{ + static double nan; + static double infinity; + static double dbl_max; + static double dbl_min; + static longdouble ldbl_max; + +#if __OpenBSD__ +#elif __GNUC__ && !defined __HAIKU__ + // These conflict with macros in math.h, should rename them + #undef isnan + #undef isfinite + #undef isinfinity + #undef signbit +#endif + static int isNan(double); + static int isNan(longdouble); + + static int isSignallingNan(double); + static int isSignallingNan(longdouble); + + static int isFinite(double); + static int isInfinity(double); + static int Signbit(double); + + static double floor(double); + static double pow(double x, double y); + + static longdouble fmodl(longdouble x, longdouble y); + + static ulonglong strtoull(const char *p, char **pend, int base); + + static char *ull_to_string(char *buffer, ulonglong ull); + static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull); + + // Convert ulonglong to double + static double ull_to_double(ulonglong ull); + + // Get locale-dependent list separator + static const char *list_separator(); + static const wchar_t *wlist_separator(); + + static char *strupr(char *); +}; + +#endif diff --git a/dmd/root/root.c b/dmd/root/root.c index b0ed53ec..2ba47eb5 100644 --- a/dmd/root/root.c +++ b/dmd/root/root.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -8,7 +8,7 @@ // See the included readme.txt for details. #ifndef POSIX -#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4) +#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4) #endif #include @@ -35,7 +35,7 @@ #endif #ifdef __HAIKU__ -#include +#include #endif #if POSIX @@ -364,21 +364,21 @@ FileName::FileName(char *path, char *name) } // Split a path into an Array of paths -Strings *FileName::splitPath(const char *path) +Strings *FileName::splitPath(const char *path) { char c = 0; // unnecessary initializer is for VC /W4 const char *p; OutBuffer buf; - Strings *array; + Strings *array; - array = new Strings(); + array = new Strings(); if (path) { p = path; do { char instring = 0; - while (isspace((unsigned char)*p)) // skip leading whitespace + while (isspace((unsigned char)*p)) // skip leading whitespace p++; buf.reserve(strlen(p) + 1); // guess size of path // LDC remember first character @@ -799,7 +799,7 @@ void FileName::CopyTo(FileName *to) * cwd if !=0, search current directory before searching path */ -char *FileName::searchPath(Strings *path, const char *name, int cwd) +char *FileName::searchPath(Strings *path, const char *name, int cwd) { if (absolute(name)) { @@ -815,7 +815,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd) for (i = 0; i < path->dim; i++) { - char *p = path->tdata()[i]; + char *p = path->tdata()[i]; char *n = combine(p, name); if (exists(n)) @@ -839,7 +839,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd) * !=NULL mem.malloc'd file name */ -char *FileName::safeSearchPath(Strings *path, const char *name) +char *FileName::safeSearchPath(Strings *path, const char *name) { #if _WIN32 /* Disallow % / \ : and .. in name characters @@ -876,7 +876,7 @@ char *FileName::safeSearchPath(Strings *path, const char *name) for (i = 0; i < path->dim; i++) { char *cname = NULL; - char *cpath = canonicalName(path->tdata()[i]); + char *cpath = canonicalName(path->tdata()[i]); //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", // name, (char *)path->data[i], cpath); if (cpath == NULL) @@ -966,7 +966,7 @@ void FileName::ensurePathExists(const char *path) { //printf("mkdir(%s)\n", path); #if _WIN32 - if (_mkdir(path)) + if (_mkdir(path)) #endif #if POSIX if (mkdir(path, 0777)) @@ -1088,13 +1088,13 @@ int File::read() //printf("File::read('%s')\n",name); fd = open(name, O_RDONLY); if (fd == -1) - { + { //printf("\topen error, errno = %d\n",errno); goto err1; } if (!ref) - ::free(buffer); + ::free(buffer); ref = 0; // we own the buffer now //printf("\tfile opened\n"); @@ -1104,7 +1104,7 @@ int File::read() goto err2; } size = buf.st_size; - buffer = (unsigned char *) ::malloc(size + 2); + buffer = (unsigned char *) ::malloc(size + 2); if (!buffer) { printf("\tmalloc error, errno = %d\n",errno); @@ -1137,7 +1137,7 @@ int File::read() err2: close(fd); err: - ::free(buffer); + ::free(buffer); buffer = NULL; len = 0; @@ -1158,11 +1158,11 @@ err1: goto err1; if (!ref) - ::free(buffer); + ::free(buffer); ref = 0; size = GetFileSize(h,NULL); - buffer = (unsigned char *) ::malloc(size + 2); + buffer = (unsigned char *) ::malloc(size + 2); if (!buffer) goto err2; @@ -1191,7 +1191,7 @@ err1: err2: CloseHandle(h); err: - ::free(buffer); + ::free(buffer); buffer = NULL; len = 0; @@ -1454,23 +1454,23 @@ void File::remove() #endif } -Files *File::match(char *n) +Files *File::match(char *n) { return match(new FileName(n, 0)); } -Files *File::match(FileName *n) +Files *File::match(FileName *n) { #if POSIX return NULL; #elif _WIN32 HANDLE h; WIN32_FIND_DATAA fileinfo; - Files *a; + Files *a; char *c; char *name; - a = new Files(); + a = new Files(); c = n->toChars(); name = n->name(); h = FindFirstFileA(c,&fileinfo); @@ -1540,7 +1540,7 @@ void File::stat() void File::checkoffset(size_t offset, size_t nbytes) { if (offset > len || offset + nbytes > len) - error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset); + error("Corrupt file '%s': offset x%llx off end of file",toChars(),(ulonglong)offset); } char *File::toChars() @@ -1563,11 +1563,11 @@ OutBuffer::~OutBuffer() mem.free(data); } -char *OutBuffer::extractData() +char *OutBuffer::extractData() { - char *p; + char *p; - p = (char *)data; + p = (char *)data; data = NULL; offset = 0; size = 0; @@ -1813,7 +1813,7 @@ void OutBuffer::align(unsigned size) // The compiler shipped with Visual Studio 2005 (and possible // other versions) does not support C99 printf format specfiers // such as %z and %j -#if _MSC_VER || __MINGW32__ +#if 0 && _MSC_VER using std::string; using std::wstring; @@ -1832,7 +1832,7 @@ search_and_replace(S& str, const S& what, const S& replacement) #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \ S tmp = f; \ search_and_replace(fmt, S("%z"), S("%l")); \ - search_and_replace(fmt, S("%j"), S("%i")); \ + search_and_replace(fmt, S("%j"), S("%l")); \ f = tmp.c_str(); #else #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) diff --git a/dmd/root/root.h b/dmd/root/root.h index 8c2557f0..91d9d9d3 100644 --- a/dmd/root/root.h +++ b/dmd/root/root.h @@ -1,425 +1,428 @@ - - -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef ROOT_H -#define ROOT_H - -#include -#include -#ifdef DEBUG -#include -#endif - -#if __DMC__ -#pragma once -#endif - -#ifndef IS_PRINTF -# ifdef __GNUC__ -# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) )) -# else -# define IS_PRINTF(FMTARG) -# endif -#endif - -typedef size_t hash_t; - -#include "dchar.h" - -char *wchar2ascii(wchar_t *); -int wcharIsAscii(wchar_t *); -char *wchar2ascii(wchar_t *, unsigned len); -int wcharIsAscii(wchar_t *, unsigned len); - -int bstrcmp(unsigned char *s1, unsigned char *s2); -char *bstr2str(unsigned char *b); -void error(const char *format, ...) IS_PRINTF(1); -void error(const wchar_t *format, ...); -void warning(const char *format, ...) IS_PRINTF(1); - -#ifndef TYPEDEFS -#define TYPEDEFS - -#if _MSC_VER -#include // for _isnan -#include // for alloca -// According to VC 8.0 docs, long double is the same as double -#define strtold strtod -#define strtof strtod -#define isnan _isnan - -typedef __int64 longlong; -typedef unsigned __int64 ulonglong; -#else -typedef long long longlong; -typedef unsigned long long ulonglong; -#endif - -#endif - -longlong randomx(); - -/* - * Root of our class library. - */ - -struct OutBuffer; - -// Can't include arraytypes.h here, need to declare these directly. -template struct ArrayBase; -typedef ArrayBase Files; -typedef ArrayBase Strings; - - -struct Object -{ - Object() { } - virtual ~Object() { } - - virtual int equals(Object *o); - - /** - * Returns a hash code, useful for things like building hash tables of Objects. - */ - virtual hash_t hashCode(); - - /** - * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj. - * Useful for sorting Objects. - */ - virtual int compare(Object *obj); - - /** - * Pretty-print an Object. Useful for debugging the old-fashioned way. - */ - virtual void print(); - - virtual char *toChars(); - virtual dchar *toDchars(); - virtual void toBuffer(OutBuffer *buf); - - /** - * Used as a replacement for dynamic_cast. Returns a unique number - * defined by the library user. For Object, the return value is 0. - */ - virtual int dyncast(); - - /** - * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap. - */ - /*virtual*/ // not used, disable for now - void mark(); -}; - -struct String : Object -{ - int ref; // != 0 if this is a reference to someone else's string - char *str; // the string itself - - String(char *str, int ref = 1); - - ~String(); - - static hash_t calcHash(const char *str, size_t len); - static hash_t calcHash(const char *str); - hash_t hashCode(); - unsigned len(); - int equals(Object *obj); - int compare(Object *obj); - char *toChars(); - void print(); - void mark(); -}; - -struct FileName : String -{ - FileName(char *str, int ref); - FileName(char *path, char *name); - hash_t hashCode(); - int equals(Object *obj); - static int equals(const char *name1, const char *name2); - int compare(Object *obj); - static int compare(const char *name1, const char *name2); - static int absolute(const char *name); - static char *ext(const char *); - char *ext(); - static char *removeExt(const char *str); - static char *name(const char *); - char *name(); - static char *path(const char *); - static const char *replaceName(const char *path, const char *name); - - static char *combine(const char *path, const char *name); - static Strings *splitPath(const char *path); - static FileName *defaultExt(const char *name, const char *ext); - static FileName *forceExt(const char *name, const char *ext); - int equalsExt(const char *ext); - - void CopyTo(FileName *to); - static char *searchPath(Strings *path, const char *name, int cwd); - static char *safeSearchPath(Strings *path, const char *name); - static int exists(const char *name); - static void ensurePathExists(const char *path); - static char *canonicalName(const char *name); -}; - -struct File : Object -{ - int ref; // != 0 if this is a reference to someone else's buffer - unsigned char *buffer; // data for our file - unsigned len; // amount of data in buffer[] - void *touchtime; // system time to use for file - - FileName *name; // name of our file - - File(char *); - File(FileName *); - ~File(); - - void mark(); - - char *toChars(); - - /* Read file, return !=0 if error - */ - - int read(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void readv(); - - /* Read file, return !=0 if error - */ - - int mmread(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void mmreadv(); - - /* Write file, return !=0 if error - */ - - int write(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void writev(); - - /* Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - - /* Append to file, return !=0 if error - */ - - int append(); - - /* Append to file, either succeed or fail - * with error message & exit. - */ - - void appendv(); - - /* Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - - int exists(); - - /* Given wildcard filespec, return an array of - * matching File's. - */ - - static Files *match(char *); - static Files *match(FileName *); - - // Compare file times. - // Return <0 this < f - // =0 this == f - // >0 this > f - int compareTime(File *f); - - // Read system file statistics - void stat(); - - /* Set buffer - */ - - void setbuffer(void *buffer, unsigned len) - { - this->buffer = (unsigned char *)buffer; - this->len = len; - } - - void checkoffset(size_t offset, size_t nbytes); - - void remove(); // delete file -}; - -struct OutBuffer : Object -{ - unsigned char *data; - unsigned offset; - unsigned size; - - OutBuffer(); - ~OutBuffer(); - char *extractData(); - void mark(); - - void reserve(unsigned nbytes); - void setsize(unsigned size); - void reset(); - void write(const void *data, unsigned nbytes); - void writebstring(unsigned char *string); - void writestring(const char *string); - void writedstring(const char *string); - void writedstring(const wchar_t *string); - void prependstring(const char *string); - void writenl(); // write newline - void writeByte(unsigned b); - void writebyte(unsigned b) { writeByte(b); } - void writeUTF8(unsigned b); - void writedchar(unsigned b); - void prependbyte(unsigned b); - void writeword(unsigned w); - void writeUTF16(unsigned w); - void write4(unsigned w); - void write(OutBuffer *buf); - void write(Object *obj); - void fill0(unsigned nbytes); - void align(unsigned size); - void vprintf(const char *format, va_list args); - void printf(const char *format, ...) IS_PRINTF(2); -#if M_UNICODE - void vprintf(const unsigned short *format, va_list args); - void printf(const unsigned short *format, ...); -#endif - void bracket(char left, char right); - unsigned bracket(unsigned i, const char *left, unsigned j, const char *right); - void spread(unsigned offset, unsigned nbytes); - unsigned insert(unsigned offset, const void *data, unsigned nbytes); - void remove(unsigned offset, unsigned nbytes); - char *toChars(); - char *extractString(); -}; - -struct Array : Object -{ - unsigned dim; - 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(); - - void reserve(unsigned nentries); - void setDim(unsigned newdim); - void fixDim(); - void push(void *ptr); - void *pop(); - void shift(void *ptr); - void insert(unsigned index, void *ptr); - void insert(unsigned index, Array *a); - void append(Array *a); - void remove(unsigned i); - void zero(); - void *tos(); - void sort(); - Array *copy(); -}; - -template -struct ArrayBase : Array -{ - TYPE **tdata() - { - return (TYPE **)data; - } - - TYPE*& operator[] (size_t index) - { -#ifdef DEBUG - assert(index < dim); -#endif - return ((TYPE **)data)[index]; - } - - void insert(size_t index, TYPE *v) - { - Array::insert(index, (void *)v); - } - - void insert(size_t index, ArrayBase *a) - { - Array::insert(index, (Array *)a); - } - - void append(ArrayBase *a) - { - Array::append((Array *)a); - } - - void push(TYPE *a) - { - Array::push((void *)a); - } - - ArrayBase *copy() - { - return (ArrayBase *)Array::copy(); - } -}; - -struct Bits : Object -{ - unsigned bitdim; - unsigned allocdim; - unsigned *data; - - Bits(); - ~Bits(); - void mark(); - - void resize(unsigned bitdim); - - void set(unsigned bitnum); - void clear(unsigned bitnum); - int test(unsigned bitnum); - - void set(); - void clear(); - void copy(Bits *from); - Bits *clone(); - - void sub(Bits *b); -}; - -#endif + + +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#ifndef ROOT_H +#define ROOT_H + +#include +#include +#ifdef DEBUG +#include +#endif + +#if __DMC__ +#pragma once +#endif + +#ifndef IS_PRINTF +# ifdef __GNUC__ +# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) )) +# else +# define IS_PRINTF(FMTARG) +# endif +#endif + +typedef size_t hash_t; + +#include "longdouble.h" +#include "dchar.h" + +char *wchar2ascii(wchar_t *); +int wcharIsAscii(wchar_t *); +char *wchar2ascii(wchar_t *, unsigned len); +int wcharIsAscii(wchar_t *, unsigned len); + +int bstrcmp(unsigned char *s1, unsigned char *s2); +char *bstr2str(unsigned char *b); +void error(const char *format, ...) IS_PRINTF(1); +#if M_UNICODE +void error(const dchar *format, ...); +#endif +void warning(const char *format, ...) IS_PRINTF(1); + +#ifndef TYPEDEFS +#define TYPEDEFS + +#if _MSC_VER +#include // for _isnan +#include // for alloca +// According to VC 8.0 docs, long double is the same as double +longdouble strtold(const char *p,char **endp); +#define strtof strtod +#define isnan _isnan + +typedef __int64 longlong; +typedef unsigned __int64 ulonglong; +#else +typedef long long longlong; +typedef unsigned long long ulonglong; +#endif + +#endif + +longlong randomx(); + +/* + * Root of our class library. + */ + +struct OutBuffer; + +// Can't include arraytypes.h here, need to declare these directly. +template struct ArrayBase; +typedef ArrayBase Files; +typedef ArrayBase Strings; + + +struct Object +{ + Object() { } + virtual ~Object() { } + + virtual int equals(Object *o); + + /** + * Returns a hash code, useful for things like building hash tables of Objects. + */ + virtual hash_t hashCode(); + + /** + * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj. + * Useful for sorting Objects. + */ + virtual int compare(Object *obj); + + /** + * Pretty-print an Object. Useful for debugging the old-fashioned way. + */ + virtual void print(); + + virtual char *toChars(); + virtual dchar *toDchars(); + virtual void toBuffer(OutBuffer *buf); + + /** + * Used as a replacement for dynamic_cast. Returns a unique number + * defined by the library user. For Object, the return value is 0. + */ + virtual int dyncast(); + + /** + * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap. + */ + /*virtual*/ // not used, disable for now + void mark(); +}; + +struct String : Object +{ + int ref; // != 0 if this is a reference to someone else's string + char *str; // the string itself + + String(char *str, int ref = 1); + + ~String(); + + static hash_t calcHash(const char *str, size_t len); + static hash_t calcHash(const char *str); + hash_t hashCode(); + unsigned len(); + int equals(Object *obj); + int compare(Object *obj); + char *toChars(); + void print(); + void mark(); +}; + +struct FileName : String +{ + FileName(char *str, int ref); + FileName(char *path, char *name); + hash_t hashCode(); + int equals(Object *obj); + static int equals(const char *name1, const char *name2); + int compare(Object *obj); + static int compare(const char *name1, const char *name2); + static int absolute(const char *name); + static char *ext(const char *); + char *ext(); + static char *removeExt(const char *str); + static char *name(const char *); + char *name(); + static char *path(const char *); + static const char *replaceName(const char *path, const char *name); + + static char *combine(const char *path, const char *name); + static Strings *splitPath(const char *path); + static FileName *defaultExt(const char *name, const char *ext); + static FileName *forceExt(const char *name, const char *ext); + int equalsExt(const char *ext); + + void CopyTo(FileName *to); + static char *searchPath(Strings *path, const char *name, int cwd); + static char *safeSearchPath(Strings *path, const char *name); + static int exists(const char *name); + static void ensurePathExists(const char *path); + static char *canonicalName(const char *name); +}; + +struct File : Object +{ + int ref; // != 0 if this is a reference to someone else's buffer + unsigned char *buffer; // data for our file + unsigned len; // amount of data in buffer[] + void *touchtime; // system time to use for file + + FileName *name; // name of our file + + File(char *); + File(FileName *); + ~File(); + + void mark(); + + char *toChars(); + + /* Read file, return !=0 if error + */ + + int read(); + + /* Write file, either succeed or fail + * with error message & exit. + */ + + void readv(); + + /* Read file, return !=0 if error + */ + + int mmread(); + + /* Write file, either succeed or fail + * with error message & exit. + */ + + void mmreadv(); + + /* Write file, return !=0 if error + */ + + int write(); + + /* Write file, either succeed or fail + * with error message & exit. + */ + + void writev(); + + /* Return !=0 if file exists. + * 0: file doesn't exist + * 1: normal file + * 2: directory + */ + + /* Append to file, return !=0 if error + */ + + int append(); + + /* Append to file, either succeed or fail + * with error message & exit. + */ + + void appendv(); + + /* Return !=0 if file exists. + * 0: file doesn't exist + * 1: normal file + * 2: directory + */ + + int exists(); + + /* Given wildcard filespec, return an array of + * matching File's. + */ + + static Files *match(char *); + static Files *match(FileName *); + + // Compare file times. + // Return <0 this < f + // =0 this == f + // >0 this > f + int compareTime(File *f); + + // Read system file statistics + void stat(); + + /* Set buffer + */ + + void setbuffer(void *buffer, unsigned len) + { + this->buffer = (unsigned char *)buffer; + this->len = len; + } + + void checkoffset(size_t offset, size_t nbytes); + + void remove(); // delete file +}; + +struct OutBuffer : Object +{ + unsigned char *data; + unsigned offset; + unsigned size; + + OutBuffer(); + ~OutBuffer(); + char *extractData(); + void mark(); + + void reserve(unsigned nbytes); + void setsize(unsigned size); + void reset(); + void write(const void *data, unsigned nbytes); + void writebstring(unsigned char *string); + void writestring(const char *string); + void writedstring(const char *string); + void writedstring(const wchar_t *string); + void prependstring(const char *string); + void writenl(); // write newline + void writeByte(unsigned b); + void writebyte(unsigned b) { writeByte(b); } + void writeUTF8(unsigned b); + void writedchar(unsigned b); + void prependbyte(unsigned b); + void writeword(unsigned w); + void writeUTF16(unsigned w); + void write4(unsigned w); + void write(OutBuffer *buf); + void write(Object *obj); + void fill0(unsigned nbytes); + void align(unsigned size); + void vprintf(const char *format, va_list args); + void printf(const char *format, ...) IS_PRINTF(2); +#if M_UNICODE + void vprintf(const unsigned short *format, va_list args); + void printf(const unsigned short *format, ...); +#endif + void bracket(char left, char right); + unsigned bracket(unsigned i, const char *left, unsigned j, const char *right); + void spread(unsigned offset, unsigned nbytes); + unsigned insert(unsigned offset, const void *data, unsigned nbytes); + void remove(unsigned offset, unsigned nbytes); + char *toChars(); + char *extractString(); +}; + +struct Array : Object +{ + unsigned dim; + 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(); + + void reserve(unsigned nentries); + void setDim(unsigned newdim); + void fixDim(); + void push(void *ptr); + void *pop(); + void shift(void *ptr); + void insert(unsigned index, void *ptr); + void insert(unsigned index, Array *a); + void append(Array *a); + void remove(unsigned i); + void zero(); + void *tos(); + void sort(); + Array *copy(); +}; + +template +struct ArrayBase : Array +{ + TYPE **tdata() + { + return (TYPE **)data; + } + + TYPE*& operator[] (size_t index) + { +#ifdef DEBUG + assert(index < dim); +#endif + return ((TYPE **)data)[index]; + } + + void insert(size_t index, TYPE *v) + { + Array::insert(index, (void *)v); + } + + void insert(size_t index, ArrayBase *a) + { + Array::insert(index, (Array *)a); + } + + void append(ArrayBase *a) + { + Array::append((Array *)a); + } + + void push(TYPE *a) + { + Array::push((void *)a); + } + + ArrayBase *copy() + { + return (ArrayBase *)Array::copy(); + } +}; + +struct Bits : Object +{ + unsigned bitdim; + unsigned allocdim; + unsigned *data; + + Bits(); + ~Bits(); + void mark(); + + void resize(unsigned bitdim); + + void set(unsigned bitnum); + void clear(unsigned bitnum); + int test(unsigned bitnum); + + void set(); + void clear(); + void copy(Bits *from); + Bits *clone(); + + void sub(Bits *b); +}; + +#endif diff --git a/dmd/root/stringtable.c b/dmd/root/stringtable.c index a50f737d..f1c0044a 100644 --- a/dmd/root/stringtable.c +++ b/dmd/root/stringtable.c @@ -1,139 +1,139 @@ - -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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. - - -#include -#include -#include - -#include "root.h" -#include "rmem.h" -#include "dchar.h" -#include "lstring.h" -#include "stringtable.h" - -void StringTable::init(unsigned size) -{ - table = (void **)mem.calloc(size, sizeof(void *)); - tabledim = size; - count = 0; -} - -StringTable::~StringTable() -{ - unsigned i; - - // Zero out dangling pointers to help garbage collector. - // Should zero out StringEntry's too. - for (i = 0; i < count; i++) - table[i] = NULL; - - mem.free(table); - table = NULL; -} - -struct StringEntry -{ - StringEntry *left; - StringEntry *right; - hash_t hash; - - StringValue value; - - static StringEntry *alloc(const dchar *s, unsigned len); -}; - -StringEntry *StringEntry::alloc(const dchar *s, unsigned len) -{ - StringEntry *se; - - se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len)); - se->value.lstring.length = len; - se->hash = Dchar::calcHash(s,len); - memcpy(se->value.lstring.string, s, len * sizeof(dchar)); - return se; -} - -void **StringTable::search(const dchar *s, unsigned len) -{ - hash_t hash; - unsigned u; - int cmp; - StringEntry **se; - - //printf("StringTable::search(%p,%d)\n",s,len); - hash = Dchar::calcHash(s,len); - u = hash % tabledim; - se = (StringEntry **)&table[u]; - //printf("\thash = %d, u = %d\n",hash,u); - while (*se) - { - cmp = (*se)->hash - hash; - if (cmp == 0) - { - cmp = (*se)->value.lstring.len() - len; - if (cmp == 0) - { - cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len); - if (cmp == 0) - break; - } - } - if (cmp < 0) - se = &(*se)->left; - else - se = &(*se)->right; - } - //printf("\treturn %p, %p\n",se, (*se)); - return (void **)se; -} - -StringValue *StringTable::lookup(const dchar *s, unsigned len) -{ StringEntry *se; - - se = *(StringEntry **)search(s,len); - if (se) - return &se->value; - else - return NULL; -} - -StringValue *StringTable::update(const dchar *s, unsigned len) -{ StringEntry **pse; - StringEntry *se; - - pse = (StringEntry **)search(s,len); - se = *pse; - if (!se) // not in table: so create new entry - { - se = StringEntry::alloc(s, len); - *pse = se; - } - return &se->value; -} - -StringValue *StringTable::insert(const dchar *s, unsigned len) -{ StringEntry **pse; - StringEntry *se; - - pse = (StringEntry **)search(s,len); - se = *pse; - if (se) - return NULL; // error: already in table - else - { - se = StringEntry::alloc(s, len); - *pse = se; - } - return &se->value; -} - - - - + +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// 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. + + +#include +#include +#include + +#include "root.h" +#include "rmem.h" +#include "dchar.h" +#include "lstring.h" +#include "stringtable.h" + +void StringTable::init(unsigned size) +{ + table = (void **)mem.calloc(size, sizeof(void *)); + tabledim = size; + count = 0; +} + +StringTable::~StringTable() +{ + unsigned i; + + // Zero out dangling pointers to help garbage collector. + // Should zero out StringEntry's too. + for (i = 0; i < count; i++) + table[i] = NULL; + + mem.free(table); + table = NULL; +} + +struct StringEntry +{ + StringEntry *left; + StringEntry *right; + hash_t hash; + + StringValue value; + + static StringEntry *alloc(const dchar *s, unsigned len); +}; + +StringEntry *StringEntry::alloc(const dchar *s, unsigned len) +{ + StringEntry *se; + + se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len)); + se->value.lstring.length = len; + se->hash = Dchar::calcHash(s,len); + memcpy(se->value.lstring.string, s, len * sizeof(dchar)); + return se; +} + +void **StringTable::search(const dchar *s, unsigned len) +{ + hash_t hash; + unsigned u; + int cmp; + StringEntry **se; + + //printf("StringTable::search(%p,%d)\n",s,len); + hash = Dchar::calcHash(s,len); + u = hash % tabledim; + se = (StringEntry **)&table[u]; + //printf("\thash = %d, u = %d\n",hash,u); + while (*se) + { + cmp = (*se)->hash - hash; + if (cmp == 0) + { + cmp = (*se)->value.lstring.len() - len; + if (cmp == 0) + { + cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len); + if (cmp == 0) + break; + } + } + if (cmp < 0) + se = &(*se)->left; + else + se = &(*se)->right; + } + //printf("\treturn %p, %p\n",se, (*se)); + return (void **)se; +} + +StringValue *StringTable::lookup(const dchar *s, unsigned len) +{ StringEntry *se; + + se = *(StringEntry **)search(s,len); + if (se) + return &se->value; + else + return NULL; +} + +StringValue *StringTable::update(const dchar *s, unsigned len) +{ StringEntry **pse; + StringEntry *se; + + pse = (StringEntry **)search(s,len); + se = *pse; + if (!se) // not in table: so create new entry + { + se = StringEntry::alloc(s, len); + *pse = se; + } + return &se->value; +} + +StringValue *StringTable::insert(const dchar *s, unsigned len) +{ StringEntry **pse; + StringEntry *se; + + pse = (StringEntry **)search(s,len); + se = *pse; + if (se) + return NULL; // error: already in table + else + { + se = StringEntry::alloc(s, len); + *pse = se; + } + return &se->value; +} + + + + diff --git a/dmd/root/stringtable.h b/dmd/root/stringtable.h index c9ba26c5..ce714587 100644 --- a/dmd/root/stringtable.h +++ b/dmd/root/stringtable.h @@ -1,48 +1,48 @@ -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#ifndef STRINGTABLE_H -#define STRINGTABLE_H - -#if __SC__ -#pragma once -#endif - -#include "root.h" -#include "dchar.h" -#include "lstring.h" - -struct StringValue -{ - union - { int intvalue; - void *ptrvalue; - dchar *string; - }; - Lstring lstring; -}; - -struct StringTable -{ - void **table; - unsigned count; - unsigned tabledim; - - void init(unsigned size = 37); - ~StringTable(); - - StringValue *lookup(const dchar *s, unsigned len); - StringValue *insert(const dchar *s, unsigned len); - StringValue *update(const dchar *s, unsigned len); - -private: - void **search(const dchar *s, unsigned len); -}; - -#endif +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + + +#ifndef STRINGTABLE_H +#define STRINGTABLE_H + +#if __SC__ +#pragma once +#endif + +#include "root.h" +#include "dchar.h" +#include "lstring.h" + +struct StringValue +{ + union + { int intvalue; + void *ptrvalue; + dchar *string; + }; + Lstring lstring; +}; + +struct StringTable +{ + void **table; + unsigned count; + unsigned tabledim; + + void init(unsigned size = 37); + ~StringTable(); + + StringValue *lookup(const dchar *s, unsigned len); + StringValue *insert(const dchar *s, unsigned len); + StringValue *update(const dchar *s, unsigned len); + +private: + void **search(const dchar *s, unsigned len); +}; + +#endif diff --git a/dmd/scope.c b/dmd/scope.c index 86852584..e0971796 100644 --- a/dmd/scope.c +++ b/dmd/scope.c @@ -78,7 +78,6 @@ Scope::Scope() this->parameterSpecialization = 0; this->callSuper = 0; this->flags = 0; - this->anonAgg = NULL; this->lastdc = NULL; this->lastoffset = 0; this->docbuf = NULL; @@ -127,7 +126,6 @@ Scope::Scope(Scope *enclosing) this->parameterSpecialization = enclosing->parameterSpecialization; this->callSuper = enclosing->callSuper; this->flags = 0; - this->anonAgg = NULL; this->lastdc = NULL; this->lastoffset = 0; this->docbuf = enclosing->docbuf; diff --git a/dmd/scope.h b/dmd/scope.h index 7b719d9f..339da7b6 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -64,6 +64,10 @@ struct Scope Statement *scontinue; // enclosing statement that supports "continue" ForeachStatement *fes; // if nested function for ForeachStatement, this is it unsigned offset; // next offset to use in aggregate + // This really shouldn't be a part of Scope, because it requires + // semantic() to be done in the lexical field order. It should be + // set in a pass after semantic() on all fields so they can be + // semantic'd in any order. int inunion; // we're processing members of a union int incontract; // we're inside contract code int nofree; // set if shouldn't free it @@ -95,7 +99,6 @@ struct Scope #define SCOPEstaticif 2 // inside static if #define SCOPEfree 4 // is on free list - AnonymousAggregateDeclaration *anonAgg; // for temporary analysis DocComment *lastdc; // documentation comment for last symbol at this scope unsigned lastoffset; // offset in docbuf of where to insert next dec diff --git a/dmd/speller.c b/dmd/speller.c index d6437379..0a93b0e9 100644 --- a/dmd/speller.c +++ b/dmd/speller.c @@ -4,9 +4,14 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif +#if _MSC_VER +#include +#endif + + #include "speller.h" diff --git a/dmd/statement.c b/dmd/statement.c index e5bd31ef..58673b45 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -1441,7 +1441,13 @@ Statement *ForeachStatement::semantic(Scope *sc) s =((ScopeExp *)e)->sds; if (s) + { var = new AliasDeclaration(loc, arg->ident, s); + } + else if (e->op == TOKtype) + { + var = new AliasDeclaration(loc, arg->ident, e->type); + } else { arg->type = e->type; @@ -3783,6 +3789,8 @@ Statement *SynchronizedStatement::semantic(Scope *sc) { exp = exp->semantic(sc); exp = resolveProperties(sc, exp); + if (exp->op == TOKerror) + goto Lbody; ClassDeclaration *cd = exp->type->isClassHandle(); if (!cd) error("can only synchronize on class objects, not '%s'", exp->type->toChars()); @@ -3797,6 +3805,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc) exp = exp->semantic(sc); } +#if 1 /* Rewrite as: * auto tmp = exp; * _d_monitorenter(tmp); @@ -3827,7 +3836,9 @@ Statement *SynchronizedStatement::semantic(Scope *sc) s = new CompoundStatement(loc, cs); return s->semantic(sc); +#endif } +#if 1 else { /* Generate our own critical section, then rewrite as: * __gshared byte[CriticalSection.sizeof] critsec; @@ -3869,6 +3880,11 @@ Statement *SynchronizedStatement::semantic(Scope *sc) s = new CompoundStatement(loc, cs); return s->semantic(sc); } +#endif +Lbody: + if (body) + body = body->semantic(sc); + return this; } int SynchronizedStatement::hasBreak() @@ -4141,7 +4157,9 @@ Catch *Catch::syntaxCopy() } void Catch::semantic(Scope *sc) -{ ScopeDsymbol *sym; +{ + if (type && type->deco) + return; //printf("Catch::semantic(%s)\n", ident->toChars()); @@ -4158,7 +4176,7 @@ void Catch::semantic(Scope *sc) } #endif - sym = new ScopeDsymbol(); + ScopeDsymbol *sym = new ScopeDsymbol(); sym->parent = sc->scopesym; sc = sc->push(sym); diff --git a/dmd/struct.c b/dmd/struct.c index 81c2a2e8..03e26fa4 100644 --- a/dmd/struct.c +++ b/dmd/struct.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -36,7 +36,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) alignsize = 0; // size of struct for alignment purposes structalign = 0; // struct member alignment in effect hasUnions = 0; - sizeok = 0; // size not determined yet + sizeok = SIZEOKnone; // size not determined yet isdeprecated = 0; inv = NULL; aggNew = NULL; @@ -123,9 +123,9 @@ unsigned AggregateDeclaration::size(Loc loc) //printf("AggregateDeclaration::size() = %d\n", structsize); if (!members) error(loc, "unknown size"); - if (sizeok != 1 && scope) + if (sizeok != SIZEOKdone && scope) semantic(NULL); - if (sizeok != 1) + if (sizeok != SIZEOKdone) { error(loc, "no size yet for forward reference"); //*(char*)0=0; } @@ -169,73 +169,41 @@ void AggregateDeclaration::alignmember( //printf("result = %d\n", *poffset); } - -void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) +/**************************************** + * Place a member (mem) into an aggregate (agg), which can be a struct, union or class + * Returns: + * offset to place field at + */ +unsigned AggregateDeclaration::placeField( + unsigned *nextoffset, // next location in aggregate + unsigned memsize, // size of member + unsigned memalignsize, // size of member for alignment purposes + unsigned memalign, // alignment in effect for this member + unsigned *paggsize, // size of aggregate (updated) + unsigned *paggalignsize, // size of aggregate for alignment purposes (updated) + bool isunion // the aggregate is a union + ) { - unsigned memsize; // size of member - unsigned memalignsize; // size of member for alignment purposes - unsigned xalign; // alignment boundaries - - //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars()); - - // Check for forward referenced types which will fail the size() call - Type *t = v->type->toBasetype(); - if (t->ty == Tstruct /*&& isStructDeclaration()*/) - { TypeStruct *ts = (TypeStruct *)t; -#if DMDV2 - if (ts->sym == this) - { - error("cannot have field %s with same struct type", v->toChars()); - } -#endif - - if (ts->sym->sizeok != 1 && ts->sym->scope) - ts->sym->semantic(NULL); - if (ts->sym->sizeok != 1) - { - sizeok = 2; // cannot finish; flag as forward referenced - return; - } - } - if (t->ty == Tident) - { - sizeok = 2; // cannot finish; flag as forward referenced - return; - } - - 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; + unsigned ofs = *nextoffset; + alignmember(memalign, memalignsize, &ofs); + unsigned memoffset = ofs; ofs += memsize; - if (ofs > structsize) - structsize = ofs; - if (!isUnionDeclaration()) - sc->offset = ofs; -#endif - if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16) + if (ofs > *paggsize) + *paggsize = ofs; + if (!isunion) + *nextoffset = ofs; + if (global.params.is64bit && memalign == 8 && memalignsize == 16) /* Not sure how to handle this */ ; - else if (sc->structalign < memalignsize) - memalignsize = sc->structalign; - if (alignsize < memalignsize) - alignsize = memalignsize; - //printf("\t%s: alignsize = %d\n", toChars(), alignsize); + else if (memalign < memalignsize) + memalignsize = memalign; + if (*paggalignsize < memalignsize) + *paggalignsize = memalignsize; - v->storage_class |= STCfield; - //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); - fields.push(v); + return memoffset; } + /**************************************** * If field[indx] is not part of a union, return indx. * Otherwise, return the lowest field index of the union. @@ -330,7 +298,7 @@ void StructDeclaration::semantic(Scope *sc) return; if (symtab) - { if (sizeok == 1 || !scope) + { if (sizeok == SIZEOKdone || !scope) { //printf("already completed\n"); scope = NULL; return; // semantic() already completed @@ -369,7 +337,7 @@ void StructDeclaration::semantic(Scope *sc) type = type->constOf(); #endif - if (sizeok == 0) // if not already done the addMember step + if (sizeok == SIZEOKnone) // if not already done the addMember step { for (size_t i = 0; i < members->dim; i++) { @@ -379,7 +347,7 @@ void StructDeclaration::semantic(Scope *sc) } } - sizeok = 0; + sizeok = SIZEOKnone; sc2 = sc->push(this); sc2->stc = 0; sc2->parent = this; @@ -394,7 +362,7 @@ void StructDeclaration::semantic(Scope *sc) * resolve individual members like enums. */ for (size_t i = 0; i < members_dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; /* There are problems doing this in the general case because * Scope keeps track of things like 'offset' */ @@ -407,8 +375,13 @@ void StructDeclaration::semantic(Scope *sc) for (size_t i = 0; i < members_dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; + // Ungag errors when not speculative + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging() && !isSpeculative()) + global.gag = 0; s->semantic(sc2); + global.gag = oldgag; #if 0 if (sizeok == 2) { //printf("forward reference\n"); @@ -416,6 +389,7 @@ void StructDeclaration::semantic(Scope *sc) } #endif } + finalizeSize(sc2); #if DMDV1 /* This doesn't work for DMDV2 because (ref S) and (S) parameter @@ -480,44 +454,14 @@ void StructDeclaration::semantic(Scope *sc) } #endif #if DMDV2 - /* Try to find the opEquals function. Build it if necessary. - */ - TypeFunction *tfeqptr; - { // bool opEquals(const T*) const; - Parameters *parameters = new Parameters; -#if STRUCTTHISREF - // bool opEquals(ref const T) const; - Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL); -#else - // bool opEquals(const T*) const; - Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL); -#endif - - parameters->push(param); - tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd); - tfeqptr->mod = MODconst; - tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2); - - Dsymbol *s = search_function(this, Id::eq); - FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; - if (fdx) - { - eq = fdx->overloadExactMatch(tfeqptr); - if (!eq) - fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars()); - } - - TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL; - // BUG: should also check that td is a function template, not just a template - - if (!eq && !td) - eq = buildOpEquals(sc2); - } - dtor = buildDtor(sc2); postblit = buildPostBlit(sc2); cpctor = buildCpCtor(sc2); + buildOpAssign(sc2); + hasIdentityEquals = (buildOpEquals(sc2) != NULL); + + xeq = buildXopEquals(sc2); #endif sc2->pop(); @@ -525,6 +469,12 @@ void StructDeclaration::semantic(Scope *sc) if (sizeok == 2) { // semantic() failed because of forward references. // Unwind what we did, and defer it for later + for (size_t i = 0; i < fields.dim; i++) + { Dsymbol *s = fields[i]; + VarDeclaration *vd = s->isVarDeclaration(); + if (vd) + vd->offset = 0; + } fields.setDim(0); structsize = 0; alignsize = 0; @@ -551,7 +501,7 @@ void StructDeclaration::semantic(Scope *sc) // aligned properly. structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - sizeok = 1; + sizeok = SIZEOKdone; Module::dprogress++; //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); @@ -613,6 +563,36 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) return ScopeDsymbol::search(loc, ident, flags); } +void StructDeclaration::finalizeSize(Scope *sc) +{ + if (sizeok != SIZEOKnone) + return; + + // Set the offsets of the fields and determine the size of the struct + unsigned offset = 0; + bool isunion = isUnionDeclaration() != NULL; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setFieldOffset(this, &offset, isunion); + } + if (sizeok == SIZEOKfwd) + return; + + // 0 sized struct's are set to 1 byte + if (structsize == 0) + { + structsize = 1; + alignsize = 1; + } + + // Round struct size up to next alignsize boundary. + // This will ensure that arrays of structs will get their internals + // aligned properly. + structsize = (structsize + alignsize - 1) & ~(alignsize - 1); + + sizeok = SIZEOKdone; +} + void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->printf("%s ", kind()); diff --git a/dmd/template.c b/dmd/template.c index 9c3305b8..a8989e5c 100644 --- a/dmd/template.c +++ b/dmd/template.c @@ -202,7 +202,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) { if (sc1->scopesym == ti1) { - error("recursive template expansion for template argument %s", t1->toChars()); + tempdecl->error("recursive template expansion for template argument %s", t1->toChars()); return 1; // fake a match } } @@ -381,7 +381,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, this->members = decldefs; this->overnext = NULL; this->overroot = NULL; - this->semanticRun = 0; + this->semanticRun = PASSinit; this->onemember = NULL; // Compute in advance for Ddoc's use @@ -438,7 +438,7 @@ void TemplateDeclaration::semantic(Scope *sc) #endif if (semanticRun) return; // semantic() already run - semanticRun = 1; + semanticRun = PASSsemantic; if (sc->func) { @@ -994,12 +994,17 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi, * now form the tuple argument. */ Tuple *t = new Tuple(); - dedargs->data[parameters->dim - 1] = (void *)t; + dedargs->tdata()[parameters->dim - 1] = t; tuple_dim = nfargs - (nfparams - 1); t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) - { Expression *farg = (Expression *)fargs->data[fptupindex + i]; + { Expression *farg = fargs->tdata()[fptupindex + i]; + + // Check invalid arguments to detect errors early. + if (farg->op == TOKerror || farg->type->ty == Terror) + goto Lnomatch; + t->objects.data[i] = (void *)farg->type; } declareParameter(paramscope, tp, t); @@ -1025,7 +1030,7 @@ L2: { // Match 'ethis' to any TemplateThisParameter's for (size_t i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; + { TemplateParameter *tp = parameters->tdata()[i]; TemplateThisParameter *ttp = tp->isTemplateThisParameter(); if (ttp) { MATCH m; @@ -1101,7 +1106,13 @@ L2: } } else - { Expression *farg = (Expression *)fargs->data[i]; + { + Expression *farg = fargs->tdata()[i]; + + // Check invalid arguments to detect errors early. + if (farg->op == TOKerror || farg->type->ty == Terror) + goto Lnomatch; + #if 0 printf("\tfarg->type = %s\n", farg->type->toChars()); printf("\tfparam->type = %s\n", fparam->type->toChars()); @@ -1121,10 +1132,34 @@ L2: argtype = argtype->invariantOf(); } } + + /* Allow implicit function literals to delegate conversion + */ + if (farg->op == TOKfunction) + { FuncExp *fe = (FuncExp *)farg; + Type *tp = fparam->type; + Expression *e = fe->inferType(tp, 1, parameters); + if (!e) + goto Lvarargs; + farg = e; + argtype = farg->type; + } + + if (!(fparam->storageClass & STClazy) && argtype->ty == Tvoid) + goto Lnomatch; + + /* Remove top const for dynamic array types and pointer types + */ + if ((argtype->ty == Tarray || argtype->ty == Tpointer) && + !argtype->isMutable() && + (!(fparam->storageClass & STCref) || + (fparam->storageClass & STCauto) && !farg->isLvalue())) + { + argtype = argtype->mutableOf(); + } #endif - MATCH m; - m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes); + MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes); //printf("\tdeduceType m = %d\n", m); /* If no match, see if there's a conversion to a delegate @@ -1428,7 +1463,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, } printf(" fargs:\n"); for (size_t i = 0; i < fargs->dim; i++) - { Expression *arg = (Expression *)fargs->data[i]; + { Expression *arg = fargs->tdata()[i]; printf("\t%s %s\n", arg->type->toChars(), arg->toChars()); //printf("\tty = %d\n", arg->type->ty); } @@ -1499,8 +1534,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, } if (td_ambig) { - error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", - toChars(), + ::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", + kind(), parent->toPrettyChars(), ident->toChars(), td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); } @@ -1514,6 +1549,16 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, fd = ti->toAlias()->isFuncDeclaration(); if (!fd) goto Lerror; + + /* As Bugzilla 3682 shows, a template instance can be matched while instantiating + * that same template. Thus, the function type can be incomplete. Complete it. + */ + { TypeFunction *tf = (TypeFunction *)fd->type; + assert(tf->ty == Tfunction); + if (tf->next) + fd->type = tf->semantic(loc, sc); + } + return fd; Lerror: @@ -1530,14 +1575,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, { if (i) bufa.writeByte(','); - Object *oarg = (Object *)args->data[i]; + Object *oarg = args->tdata()[i]; ObjectToCBuffer(&bufa, &hgs, oarg); } } OutBuffer buf; argExpTypesToCBuffer(&buf, fargs, &hgs); - error(loc, "cannot deduce template function from argument types !(%s)(%s)", + if (this->overnext) + ::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)", + kind(), parent->toPrettyChars(), ident->toChars(), + bufa.toChars(), buf.toChars()); + else + error("cannot deduce template function from argument types !(%s)(%s)", bufa.toChars(), buf.toChars()); } return NULL; @@ -1633,7 +1683,7 @@ char *TemplateDeclaration::toChars() int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters) { for (size_t i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; + { TemplateParameter *tp = parameters->tdata()[i]; if (tp->ident->equals(id)) return i; @@ -1662,7 +1712,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters) * Foo!(int*) // template instantiation * Input: * this = int* - * tparam = T + * tparam = T* * parameters = [ T:T* ] // Array of TemplateParameter's * Output: * dedtypes = [ int ] // Array of Expression/Type's @@ -1696,7 +1746,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Loc loc; if (parameters->dim) { - TemplateParameter *tp = (TemplateParameter *)parameters->data[0]; + TemplateParameter *tp = parameters->tdata()[0]; loc = tp->loc; } @@ -1708,7 +1758,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, return deduceType(sc, tparam, parameters, dedtypes); } - TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; + TemplateParameter *tp = parameters->tdata()[i]; // Found the corresponding parameter tp if (!tp->isTemplateTypeParameter()) @@ -2840,14 +2890,14 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, //printf("TemplateAliasParameter::matchArg()\n"); if (i < tiargs->dim) - oarg = (Object *)tiargs->data[i]; + oarg = tiargs->tdata()[i]; else { // Get default argument instead oarg = defaultArg(loc, sc); if (!oarg) { assert(i < dedtypes->dim); // It might have already been deduced - oarg = (Object *)dedtypes->data[i]; + oarg = dedtypes->tdata()[i]; if (!oarg) goto Lnomatch; } @@ -2937,7 +2987,7 @@ Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc) { s = defaultAlias->toDsymbol(sc); if (!s) - error("%s is not a symbol", defaultAlias->toChars()); + error(Loc(0), "%s is not a symbol", defaultAlias->toChars()); } return s; } @@ -2986,7 +3036,13 @@ void TemplateValueParameter::declareParameter(Scope *sc) void TemplateValueParameter::semantic(Scope *sc) { + bool wasSame = (sparam->type == valType); sparam->semantic(sc); + if (sparam->type == Type::terror && wasSame) + { // If sparam has a type error, avoid duplicate errors + valType = Type::terror; + return; + } valType = valType->semantic(loc, sc); if (!(valType->isintegral() || valType->isfloating() || valType->isString()) && valType->ty != Tident) @@ -3344,13 +3400,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->tinst = NULL; this->argsym = NULL; this->aliasdecl = NULL; - this->semanticRun = 0; + this->semanticRun = PASSinit; this->semantictiargsdone = 0; this->withsym = NULL; this->nest = 0; this->havetempdecl = 0; this->isnested = NULL; - this->errors = 0; this->speculative = 0; #if IN_LLVM @@ -3379,13 +3434,12 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->tinst = NULL; this->argsym = NULL; this->aliasdecl = NULL; - this->semanticRun = 0; + this->semanticRun = PASSinit; this->semantictiargsdone = 1; this->withsym = NULL; this->nest = 0; this->havetempdecl = 1; this->isnested = NULL; - this->errors = 0; this->speculative = 0; #if IN_LLVM @@ -3463,7 +3517,7 @@ void TemplateInstance::semantic(Scope *sc) // get the enclosing template instance from the scope tinst tinst = sc->tinst; - if (semanticRun != 0) + if (semanticRun != PASSinit) { #if LOG printf("Recursive template expansion\n"); @@ -3472,7 +3526,7 @@ void TemplateInstance::semantic(Scope *sc) // inst = this; return; } - semanticRun = 1; + semanticRun = PASSsemantic; // get the enclosing template instance from the scope tinst tinst = sc->tinst; @@ -3579,7 +3633,7 @@ void TemplateInstance::semantic(Scope *sc) } #if LOG - printf("\tit's a match with instance %p\n", inst); + printf("\tit's a match with instance %p, %d\n", inst, inst->semanticRun); #endif return; @@ -3866,7 +3920,7 @@ void TemplateInstance::semantic(Scope *sc) assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); target_symbol_list->remove(target_symbol_list_idx); } - semanticRun = 0; + semanticRun = PASSinit; inst = NULL; } } @@ -4208,13 +4262,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc) // Only one template, so we can give better error message error("%s does not match template declaration %s", toChars(), tempdecl->toChars()); else - error("%s does not match any template declaration", toChars()); + ::error(loc, "%s %s.%s does not match any template declaration", + tempdecl->kind(), tempdecl->parent->toPrettyChars(), tempdecl->ident->toChars()); return NULL; } if (td_ambig) { - error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", - toChars(), + ::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", + td_best->kind(), td_best->parent->toPrettyChars(), td_best->ident->toChars(), td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); } @@ -4275,7 +4330,12 @@ int TemplateInstance::hasNestedArgs(Objects *args) sa = ((VarExp *)ea)->var; goto Lsa; } - if (ea->op == TOKfunction) + if (ea->op == TOKthis) + { + sa = ((ThisExp *)ea)->var; + goto Lsa; + } + if (ea->op == TOKfunction) { sa = ((FuncExp *)ea)->fd; goto Lsa; @@ -4472,16 +4532,15 @@ void TemplateInstance::declareParameters(Scope *sc) //printf("TemplateInstance::declareParameters()\n"); for (size_t i = 0; i < tdtypes.dim; i++) { - TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i]; - //Object *o = (Object *)tiargs->data[i]; - Object *o = (Object *)tdtypes.data[i]; // initializer for tp + TemplateParameter *tp = tempdecl->parameters->tdata()[i]; + //Object *o = tiargs->tdata()[i]; + Object *o = tdtypes.tdata()[i]; // initializer for tp //printf("\ttdtypes[%d] = %p\n", i, o); tempdecl->declareParameter(sc, tp, o); } } - /***************************************************** * Determine if template instance is really a template function, * and that template function needs to infer types from the function @@ -4493,6 +4552,7 @@ int TemplateInstance::needsTypeInference(Scope *sc) //printf("TemplateInstance::needsTypeInference() %s\n", toChars()); if (!tempdecl) tempdecl = findTemplateDeclaration(sc); + int multipleMatches = FALSE; for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) { /* If any of the overloaded template declarations need inference, @@ -4518,23 +4578,44 @@ int TemplateInstance::needsTypeInference(Scope *sc) /* Determine if the instance arguments, tiargs, are all that is necessary * to instantiate the template. */ - TemplateTupleParameter *tp = td->isVariadic(); //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim); TypeFunction *fdtype = (TypeFunction *)fd->type; - if (Parameter::dim(fdtype->parameters) && - ((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim)) - return TRUE; + if (Parameter::dim(fdtype->parameters)) + { + TemplateParameter *tp = td->isVariadic(); + if (tp && td->parameters->dim > 1) + return TRUE; + + if (tiargs->dim < td->parameters->dim) + { // Can remain tiargs be filled by default arguments? + for (size_t i = tiargs->dim; i < td->parameters->dim; i++) + { tp = (*td->parameters)[i]; + if (TemplateTypeParameter *ttp = tp->isTemplateTypeParameter()) + { if (!ttp->defaultType) + return TRUE; + } + else if (TemplateAliasParameter *tap = tp->isTemplateAliasParameter()) + { if (!tap->defaultAlias) + return TRUE; + } + else if (TemplateValueParameter *tvp = tp->isTemplateValueParameter()) + { if (!tvp->defaultValue) + return TRUE; + } + } + } + } } //printf("false\n"); - return FALSE; + return multipleMatches; } void TemplateInstance::semantic2(Scope *sc) { int i; - if (semanticRun >= 2) + if (semanticRun >= PASSsemantic2) return; - semanticRun = 2; + semanticRun = PASSsemantic2; #if LOG printf("+TemplateInstance::semantic2('%s')\n", toChars()); #endif @@ -4567,9 +4648,9 @@ void TemplateInstance::semantic3(Scope *sc) printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun); #endif //if (toChars()[0] == 'D') *(char*)0=0; - if (semanticRun >= 3) + if (semanticRun >= PASSsemantic3) return; - semanticRun = 3; + semanticRun = PASSsemantic3; if (!errors && members) { sc = tempdecl->scope; @@ -4752,9 +4833,24 @@ Dsymbol *TemplateInstance::toAlias() printf("TemplateInstance::toAlias()\n"); #endif if (!inst) - { error("cannot resolve forward reference"); - errors = 1; - return this; + { + // Maybe we can resolve it + if (scope) + { + /* Anything that affects scope->offset must be + * done in lexical order. Fwd ref error if it is affected, otherwise allow. + */ + unsigned offset = scope->offset; + Scope *sc = scope; + semantic(scope); +// if (offset != sc->offset) +// inst = NULL; // trigger fwd ref error + } + if (!inst) + { error("cannot resolve forward reference"); + errors = 1; + return this; + } } if (inst != this) @@ -4865,7 +4961,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) ti = (TemplateInstance *)ti->syntaxCopy(NULL); id = (Identifier *)ti; } - ids->data[i] = id; + ids->tdata()[i] = id; } tm = new TemplateMixin(loc, ident, @@ -4886,7 +4982,7 @@ void TemplateMixin::semantic(Scope *sc) // This for when a class/struct contains mixin members, and // is done over because of forward references if (parent && toParent()->isAggregateDeclaration()) - semanticRun = 1; // do over + semanticRun = PASSsemantic; // do over else { #if LOG @@ -4896,7 +4992,7 @@ void TemplateMixin::semantic(Scope *sc) } } if (!semanticRun) - semanticRun = 1; + semanticRun = PASSsemantic; #if LOG printf("\tdo semantic\n"); #endif @@ -4979,10 +5075,10 @@ void TemplateMixin::semantic(Scope *sc) * runDeferred will re-run mixin's semantic outside of the struct's * semantic. */ - semanticRun = 0; + semanticRun = PASSinit; AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); if (ad) - ad->sizeok = 2; + ad->sizeok = SIZEOKfwd; else { // Forward reference @@ -5027,11 +5123,11 @@ void TemplateMixin::semantic(Scope *sc) continue; for (size_t i = 0; i < tiargs->dim; i++) - { Object *o = (Object *)tiargs->data[i]; + { Object *o = (*tiargs)[i]; Type *ta = isType(o); Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); - Object *tmo = (Object *)tm->tiargs->data[i]; + Object *tmo = (*tm->tiargs)[i]; if (ta) { Type *tmta = isType(tmo); @@ -5095,10 +5191,8 @@ void TemplateMixin::semantic(Scope *sc) declareParameters(argscope); // Add members to enclosing scope, as well as this scope - for (unsigned i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = (Dsymbol *)members->data[i]; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; s->addMember(argscope, this, i); //sc->insert(s); //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); @@ -5124,7 +5218,7 @@ void TemplateMixin::semantic(Scope *sc) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (Dsymbol *)members->data[i]; + Dsymbol *s = (*members)[i]; s->semantic(sc2); } @@ -5166,9 +5260,9 @@ void TemplateMixin::semantic(Scope *sc) void TemplateMixin::semantic2(Scope *sc) { - if (semanticRun >= 2) + if (semanticRun >= PASSsemantic2) return; - semanticRun = 2; + semanticRun = PASSsemantic2; #if LOG printf("+TemplateMixin::semantic2('%s')\n", toChars()); #endif @@ -5179,7 +5273,7 @@ void TemplateMixin::semantic2(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (Dsymbol *)members->data[i]; + Dsymbol *s = (*members)[i]; #if LOG printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); #endif @@ -5195,9 +5289,9 @@ void TemplateMixin::semantic2(Scope *sc) void TemplateMixin::semantic3(Scope *sc) { - if (semanticRun >= 3) + if (semanticRun >= PASSsemantic3) return; - semanticRun = 3; + semanticRun = PASSsemantic3; #if LOG printf("TemplateMixin::semantic3('%s')\n", toChars()); #endif @@ -5207,7 +5301,7 @@ void TemplateMixin::semantic3(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (Dsymbol *)members->data[i]; + Dsymbol *s = members->tdata()[i]; s->semantic3(sc); } sc = sc->pop(); @@ -5230,21 +5324,48 @@ int TemplateMixin::oneMember(Dsymbol **ps) return Dsymbol::oneMember(ps); } +int TemplateMixin::apply(Dsymbol_apply_ft_t fp, void *param) +{ + if (members) + { + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + if (s) + { + if (s->apply(fp, param)) + return 1; + } + } + } + return 0; +} + int TemplateMixin::hasPointers() { //printf("TemplateMixin::hasPointers() %s\n", toChars()); if (members) - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *s = (*members)[i]; - //printf(" s = %s %s\n", s->kind(), s->toChars()); - if (s->hasPointers()) + for (size_t i = 0; i < members->dim; i++) { - return 1; + Dsymbol *s = (*members)[i]; + //printf(" s = %s %s\n", s->kind(), s->toChars()); + if (s->hasPointers()) + { + return 1; + } + } + return 0; +} + +void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ + if (members) + { + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setFieldOffset(ad, poffset, isunion); } } - return 0; } char *TemplateMixin::toChars() @@ -5264,7 +5385,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("mixin "); for (size_t i = 0; i < idents->dim; i++) - { Identifier *id = (Identifier *)idents->data[i]; + { Identifier *id = idents->tdata()[i]; if (i) buf->writeByte('.'); diff --git a/dmd/template.h b/dmd/template.h index 77f1cee7..352b5bcd 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -40,6 +40,7 @@ struct AliasDeclaration; struct FuncDeclaration; struct HdrGenState; enum MATCH; +enum PASS; struct Tuple : Object { @@ -60,7 +61,7 @@ struct TemplateDeclaration : ScopeDsymbol TemplateDeclaration *overnext; // next overloaded TemplateDeclaration TemplateDeclaration *overroot; // first in overnext list - int semanticRun; // 1 semantic() run + enum PASS semanticRun; // 1 semantic() run Dsymbol *onemember; // if !=NULL then one member of this template @@ -287,12 +288,11 @@ struct TemplateInstance : ScopeDsymbol AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its // sole member WithScopeSymbol *withsym; // if a member of a with statement - int semanticRun; // has semantic() been done? + enum PASS semanticRun; // has semantic() been done? int semantictiargsdone; // has semanticTiargs() been done? int nest; // for recursion detection int havetempdecl; // 1 if used second constructor Dsymbol *isnested; // if referencing local symbols, this is the context - int errors; // 1 if compiled with errors int speculative; // 1 if only instantiated with errors gagged #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol @@ -356,7 +356,9 @@ struct TemplateMixin : TemplateInstance void inlineScan(); const char *kind(); int oneMember(Dsymbol **ps); + int apply(Dsymbol_apply_ft_t fp, void *param); int hasPointers(); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); char *toChars(); char *mangle(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);